diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000..72e653a --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,5 @@ +.deveco/** +.vscode/** +**/.DS_Store +.remote-sync.json +.ftpconfig* diff --git a/src/LICENSE b/src/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/src/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/src/applications/sample/wifi-iot/.gitee/ISSUE_TEMPLATE.zh-CN.md b/src/applications/sample/wifi-iot/.gitee/ISSUE_TEMPLATE.zh-CN.md new file mode 100644 index 0000000..651e02c --- /dev/null +++ b/src/applications/sample/wifi-iot/.gitee/ISSUE_TEMPLATE.zh-CN.md @@ -0,0 +1,11 @@ +### 该问题是怎么引起的? + + + +### 重现步骤 + + + +### 报错信息 + + diff --git a/src/applications/sample/wifi-iot/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md b/src/applications/sample/wifi-iot/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md new file mode 100644 index 0000000..86dd358 --- /dev/null +++ b/src/applications/sample/wifi-iot/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md @@ -0,0 +1,12 @@ +### 相关的Issue + + +### 原因(目的、解决的问题等) + + +### 描述(做了什么,变更了什么) + + +### 测试用例(新增、改动、可能影响的功能) + + diff --git a/src/applications/sample/wifi-iot/LICENSE b/src/applications/sample/wifi-iot/LICENSE new file mode 100644 index 0000000..4947287 --- /dev/null +++ b/src/applications/sample/wifi-iot/LICENSE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/OAT.xml b/src/applications/sample/wifi-iot/OAT.xml new file mode 100644 index 0000000..56abade --- /dev/null +++ b/src/applications/sample/wifi-iot/OAT.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/applications/sample/wifi-iot/README.md b/src/applications/sample/wifi-iot/README.md new file mode 100644 index 0000000..b606fd4 --- /dev/null +++ b/src/applications/sample/wifi-iot/README.md @@ -0,0 +1,26 @@ +# WIFI\_IOT\_APP + +- [Introduction](#section11660541593) +- [Directory Structure](#section1464106163817) +- [Repositories Involved](#section1718733212019) + +## Introduction + +The WIFI\_IOT\_APP module provides sample code for iothardware, demolink, and samgr. + +## Directory Structure + +``` +applications/sample/wifi-iot/ # Sample code +└── app + ├── BUILD.gn # Build script + ├── demolink # Sample code for integrating demolink + ├── iothardware # Sample code for LED operations + ├── samgr # Sample code for the service framework + └── startup +``` + +## Repositories Involved + +applications\_sample\_wifi-iot + diff --git a/src/applications/sample/wifi-iot/README_zh.md b/src/applications/sample/wifi-iot/README_zh.md new file mode 100644 index 0000000..99e4755 --- /dev/null +++ b/src/applications/sample/wifi-iot/README_zh.md @@ -0,0 +1,26 @@ +# WIFI\_IOT\_APP组件 + +- [简介](#section11660541593) +- [目录](#section1464106163817) +- [涉及仓](#section1718733212019) + +## 简介 + +WIFI\_IOT\_APP组件,提供了iothardware、demolink、samgr等示例代码。 + +## 目录 + +``` +applications/sample/wifi-iot/ # sample模块目录 +└── app + ├── BUILD.gn # 模块构建脚本 + ├── demolink # demolink集成示例代码 + ├── iothardware # LED操作示例代码 + ├── samgr # 服务框架示例代码 + └── startup +``` + +## 涉及仓 + +applications\_sample\_wifi-iot + diff --git a/src/applications/sample/wifi-iot/app/BUILD.gn b/src/applications/sample/wifi-iot/app/BUILD.gn new file mode 100644 index 0000000..7465791 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/BUILD.gn @@ -0,0 +1,18 @@ +# Copyright (c) 2020-2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/lite/config/component/lite_component.gni") + +lite_component("app") { + features = [ "cloud_to_uart:cloud_uart", ] +} diff --git a/src/applications/sample/wifi-iot/app/core/BUILD.gn b/src/applications/sample/wifi-iot/app/core/BUILD.gn new file mode 100644 index 0000000..a2151b3 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/core/BUILD.gn @@ -0,0 +1,41 @@ +# Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +static_library("cloud_uart") { + sources = [ + "app_demo_iot.c", + "cjson_init.c", + "iot_hmac.c", + "iot_log.c", + "iot_main.c", + "iot_profile.c", + "iot_sta.c", + "hal_iot_gpio_ex.c", + "hisignalling_protocol.c", + ] + + include_dirs = [ + "./", + "//utils/native/lite/include", + "//kernel/liteos_m/kal/cmsis", + "//base/iot_hardware/peripheral/interfaces/kits", + "//device/soc/hisilicon/hi3861v100/sdk_liteos/third_party/lwip_sack/include/lwip", + "//third_party/cJSON", + "//device/soc/hisilicon/hi3861v100/sdk_liteos/third_party/mbedtls/include/mbedtls", + "//foundation/communication/wifi_lite/interfaces/wifiservice", + "//device/soc/hisilicon/hi3861v100/sdk_liteos/third_party/paho.mqtt.c/include/mqtt", + "//device/soc/hisilicon/hi3861v100/sdk_liteos/third_party/libcoap/include/coap2", + ] + + defines = [ "WITH_LWIP" ] +} diff --git a/src/applications/sample/wifi-iot/app/core/app_demo_iot.c b/src/applications/sample/wifi-iot/app/core/app_demo_iot.c new file mode 100644 index 0000000..26a81cf --- /dev/null +++ b/src/applications/sample/wifi-iot/app/core/app_demo_iot.c @@ -0,0 +1,507 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "iot_config.h" +#include "iot_log.h" +#include "iot_main.h" +#include "iot_profile.h" +#include "ohos_init.h" +#include "cmsis_os2.h" +#include "iot_gpio.h" +#include +#include +#include +#include +#include +#include "iot_gpio_ex.h" + + + + +/* attribute initiative to report */ +#define TAKE_THE_INITIATIVE_TO_REPORT +#define TWO_SECOND (2000) +/* oc request id */ +#define CN_COMMADN_INDEX "commands/request_id=" +#define WECHAT_SUBSCRIBE_control "slot_num" +#define WECHAT_SUBSCRIBE_channel1 "slot_1" +#define WECHAT_SUBSCRIBE_channel2 "slot_2" +#define WECHAT_SUBSCRIBE_channel3 "slot_3" +#define WECHAT_SUBSCRIBE_channel4 "4" +#define topic_data "YT32IOSCAL/Hi38611_mqtt/data" +#define topic_event "YT32IOSCAL/Hi38611_mqtt/event" +#define topic_control "YT32IOSCAL/Hi38611_mqtt/control" +#define human_detect_io 7 + +int g_ligthStatus = -1; +int control_success = 0; +char *control_flag = "failed"; +char *message = NULL; +UartDefConfig uartDefConfig = {0}; +//int slot1 = 20,slot2 = 20, slot3 = 20, slot4 = 20; +typedef void (*FnMsgCallBack)(hi_gpio_value val); + +typedef struct FunctionCallback { + hi_bool stop; + hi_u32 conLost; + hi_u32 queueID; + hi_u32 iotTaskID; + FnMsgCallBack msgCallBack; +}FunctionCallback; +FunctionCallback g_functinoCallback; + +// uart + +static void Uart1GpioCOnfig(void) +{ +#ifdef ROBOT_BOARD + IoSetFunc(HI_IO_NAME_GPIO_5, IOT_IO_FUNC_GPIO_5_UART1_RXD); + IoSetFunc(HI_IO_NAME_GPIO_6, IOT_IO_FUNC_GPIO_6_UART1_TXD); + /* IOT_BOARD */ +#elif defined (EXPANSION_BOARD) + IoSetFunc(HI_IO_NAME_GPIO_0, IOT_IO_FUNC_GPIO_0_UART1_TXD); + IoSetFunc(HI_IO_NAME_GPIO_1, IOT_IO_FUNC_GPIO_1_UART1_RXD); +#endif +} + +/* CPU Sleep time Set */ +unsigned int TaskMsleep(unsigned int ms) +{ + if (ms <= 0) { + return HI_ERR_FAILURE; + } + return hi_sleep((hi_u32)ms); +} + +static void DeviceConfigInit(hi_gpio_value val) +{ + hi_io_set_func(HI_IO_NAME_GPIO_9, HI_IO_FUNC_GPIO_9_GPIO); + hi_gpio_set_dir(HI_GPIO_IDX_9, HI_GPIO_DIR_OUT); + hi_gpio_set_ouput_val(HI_GPIO_IDX_9, val); +} + +static void engine_control(unsigned int IO){ + IoTGpioInit(IO); + IoSetFunc(IO, 0); + IoTGpioSetDir(IO, IOT_GPIO_DIR_OUT); + IoTGpioSetOutputVal(IO, IOT_GPIO_VALUE1); + IOT_LOG_DEBUG("Engine at GPIO:%u started!\n", IO); + hi_udelay(20000); + IoTGpioSetOutputVal(IO, IOT_GPIO_VALUE0); + IOT_LOG_DEBUG("Engine at GPIO:%u stopped!\n", IO); +} + +static void engine_start(unsigned int IO){ + IoSetFunc(IO, 0); + IoTGpioSetDir(IO, IOT_GPIO_DIR_OUT); + IoTGpioSetOutputVal(IO, IOT_GPIO_VALUE1); + IOT_LOG_DEBUG("Engine at GPIO:%u started!\n", IO); +} + +static void engine_stop(unsigned int IO){ + IoSetFunc(IO, 0); + IoTGpioSetDir(IO, IOT_GPIO_DIR_OUT); + IoTGpioSetOutputVal(IO, IOT_GPIO_VALUE0); + IOT_LOG_DEBUG("Engine at GPIO:%u stopped!\n", IO); +} + +static void engine_reinit(unsigned int IO){ + IoTGpioInit(IO); + IoSetFunc(IO, 0); + IoTGpioSetDir(IO, IOT_GPIO_DIR_OUT); + IoTGpioSetOutputVal(IO, IOT_GPIO_VALUE0); + IOT_LOG_DEBUG("Engine at GPIO:%u initialized!\n", IO); +} + +static void all_engine_reinit(){ + engine_reinit(6); + engine_reinit(7); + engine_reinit(9); + engine_reinit(10); + IOT_LOG_DEBUG("All engines initialized!\n"); +} + +static void Sensor_init(){ + IoTGpioInit(human_detect_io); + IoSetFunc(human_detect_io, 0); + IoTGpioSetDir(human_detect_io, IOT_GPIO_DIR_IN); + IOT_LOG_DEBUG("Sensor initialized!\n"); +} + +static int DeviceMsgCallback(FnMsgCallBack msgCallBack) +{ + g_functinoCallback.msgCallBack = msgCallBack; + return 0; +} + +static void wechatControlDeviceMsg(hi_gpio_value val) +{ + DeviceConfigInit(val); +} + + +// < this is the callback function, set to the mqtt, and if any messages come, it will be called +// < The payload here is the json string +static void DemoMsgRcvCallBack(int qos, const char *topic, const char *payload)/*定义3861接收到json文件后的操作*/ +{ + IOT_LOG_DEBUG("RCVMSG:QOS:%d TOPIC:%s PAYLOAD:%s\r\n", qos, topic, payload); + printf(strstr(payload, WECHAT_SUBSCRIBE_control)); + /* 云端下发命令后,板端的操作处理 */ + if (strstr(payload, WECHAT_SUBSCRIBE_control) != NULL) { + //printf(strstr(payload, WECHAT_SUBSCRIBE_control)); + + all_engine_reinit(); + if (strstr(payload, WECHAT_SUBSCRIBE_channel1) != NULL) { + engine_start(6); + hi_udelay(4000000); + engine_stop(6); + wechatControlDeviceMsg(HI_GPIO_VALUE1); + control_success = 1; + control_flag = payload; + } + else if (strstr(payload, WECHAT_SUBSCRIBE_channel2) != NULL) { + engine_start(7); + hi_udelay(4000000); + engine_stop(7); + wechatControlDeviceMsg(HI_GPIO_VALUE1); + control_success = 1; + control_flag = payload; + } + else if (strstr(payload, WECHAT_SUBSCRIBE_channel3) != NULL) { + engine_start(2); + hi_udelay(4000000); + engine_stop(2); + wechatControlDeviceMsg(HI_GPIO_VALUE1); + control_success = 1; + control_flag = payload; + } + else if (strstr(payload, WECHAT_SUBSCRIBE_channel4) != NULL) { + engine_start(10); + hi_udelay(4000000); + engine_stop(10); + wechatControlDeviceMsg(HI_GPIO_VALUE1); + control_success = 1; + control_flag = payload; + } + + } + + return HI_NULL; +} + +static void DemoMsgRcvsynchronize(int qos, const char *topic, const char *payload) +{ + message = payload; + +} + +/* publish sample */ +/*hi_void IotPublishSample(int slot1, int slot2, int slot3, int slot4) +{ + // reported attribute + WeChatProfile weChatProfile = { + .subscribeType = "type", + .status.subState = "state", + .status.subReport = "reported", + .status.reportVersion = "version", + .status.Token = "clientToken", + // report motor + .reportAction.subDeviceActionMotor = "slot_1", + .reportAction.motorActionStatus = slot1, // 0 : motor off + // report temperature + .reportAction.subDeviceActionTemperature = "slot_2", + .reportAction.temperatureData = slot2, // 30 :temperature data + // report humidity + .reportAction.subDeviceActionHumidity = "slot_3", + .reportAction.humidityActionData = slot3, // humidity data + // report light_intensity + .reportAction.subDeviceActionLightIntensity = "slot_4", + .reportAction.lightIntensityActionData = slot4, // 60 : light_intensity + }; + + // report light + if (g_ligthStatus == HI_TRUE) { + weChatProfile.reportAction.subDeviceActionLight = "light"; + weChatProfile.reportAction.lightActionStatus = 1; // 1: light on + } else if (g_ligthStatus == HI_FALSE) { + weChatProfile.reportAction.subDeviceActionLight = "light"; + weChatProfile.reportAction.lightActionStatus = 0; // 0: light off + } else { + weChatProfile.reportAction.subDeviceActionLight = "light"; + weChatProfile.reportAction.lightActionStatus = 0; // 0: light off + } + //profile report + IoTProfilePropertyReport(CONFIG_USER_ID, &weChatProfile1); +}*/ + +// < this is the demo main task entry,here we will set the wifi/cjson/mqtt ready and +// < wait if any work to do in the while +//static hi_void *DemoEntry(const char *arg) +//{ + + //int feedback = 0; + + + /*6WifiStaReadyWait(); + cJsonInit(); + IoTMain(); + /* 云端下发回调 */ + //IoTSetMsgCallback(DemoMsgRcvCallBack); + + /*if (control_success == 1) + { + //Uart1GpioCOnfig(); + feedback = IoTUartWrite(DEMO_UART_NUM, control_flag, 7); + printf("feedback: %d", feedback); + + }*/ + + /* 主动上报 */ +/*#ifdef TAKE_THE_INITIATIVE_TO_REPORT + while (1) { + // 用户可以在这调用发布函数进行发布,需要用户自己写调用函数 + IotPublishSample(slot1,slot2,slot3,slot4); // 发布例程 +#endif*/ + //TaskMsleep(TWO_SECOND); + + //return NULL; +//} + +/////////////////////////////////////////////////////////////////////////////////////////// +int SetUartRecvFlag(UartRecvDef def) +{ + if (def == UART_RECV_TRUE) { + uartDefConfig.g_uartReceiveFlag = HI_TRUE; + } else { + uartDefConfig.g_uartReceiveFlag = HI_FALSE; + } + + return uartDefConfig.g_uartReceiveFlag; +} + +int GetUartConfig(UartDefType type) +{ + int receive = 0; + + switch (type) { + case UART_RECEIVE_FLAG: + receive = uartDefConfig.g_uartReceiveFlag; + break; + case UART_RECVIVE_LEN: + receive = uartDefConfig.g_uartLen; + break; + default: + break; + } + return receive; +} + +void ResetUartReceiveMsg(void) +{ + (void)memset_s(uartDefConfig.g_receiveUartBuff, sizeof(uartDefConfig.g_receiveUartBuff), + 0x0, sizeof(uartDefConfig.g_receiveUartBuff)); +} + +unsigned char *GetUartReceiveMsg(void) +{ + return uartDefConfig.g_receiveUartBuff; +} + +static hi_void *UartDemoTask(char *param) +{ + hi_u8 uartBuff[UART_BUFF_SIZE] = {0}; + char *recBuff = NULL; + int feedback_1 = 0; + int feedback_2 = 0; + int length = 0; + unsigned char *detect_flag = "start"; + unsigned char *data_send = "jdata"; + IotGpioValue value = IOT_GPIO_VALUE0; + + hi_unref_param(param); + printf("Initialize uart demo successfully, please enter some datas via DEMO_UART_NUM port...\n"); + Uart1GpioCOnfig(); + Sensor_init(); + printf("Please wait for 60 seconds for the system to start...\n"); + TaskMsleep(60000); + printf("Done!\n"); + + for (;;) + { + int isTimeOut = 0; + + IoTGpioGetInputVal(human_detect_io, &value); + + if(value == IOT_GPIO_VALUE1) + { + //get from cloud and send to 3516 + IoTUartWrite(DEMO_UART_NUM, detect_flag, 5); + IoTSetMsgCallback(DemoMsgRcvsynchronize); + //start to work + feedback_1 = IoTUartWrite(DEMO_UART_NUM, detect_flag, 5);// + printf("uart feedback %d\n", feedback_1); + + //TaskMsleep(20); + uartDefConfig.g_uartLen = IoTUartRead(DEMO_UART_NUM, uartBuff, UART_BUFF_SIZE); + int waitCount = 0; + while (!((uartDefConfig.g_uartLen > 0) && (uartBuff[0] == 0xaa) && (uartBuff[1] == 0x55))) { + uartDefConfig.g_uartLen = IoTUartRead(DEMO_UART_NUM, uartBuff, UART_BUFF_SIZE); + TaskMsleep(50); + waitCount += 1; + if(waitCount > 400){ + isTimeOut = 1; + printf("Timeout!\n"); + break; + } + + } + if(isTimeOut) + continue; + if (GetUartConfig(UART_RECEIVE_FLAG) == HI_FALSE) { + (void)memcpy_s(uartDefConfig.g_receiveUartBuff, uartDefConfig.g_uartLen, + uartBuff, uartDefConfig.g_uartLen);/*uartBuff中的信息放到uartDefConfig.g_receiveUartBuff*/ + (void)SetUartRecvFlag(UART_RECV_TRUE); + } + printf("UART start\n"); + printf("len:%d\n", uartDefConfig.g_uartLen); + recBuff = (char*)malloc(uartDefConfig.g_uartLen-3); + + for (int i = 0; i +#include +#include + +static void *cJsonMalloc(size_t sz) +{ + return hi_malloc(0, sz); +} + +static void cJsonFree(const char *p) +{ + hi_free(0, p); +} + +void cJsonInit(void) +{ + cJSON_Hooks hooks; + hooks.malloc_fn = cJsonMalloc; + hooks.free_fn = cJsonFree; + cJSON_InitHooks(&hooks); + + return; +} \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/core/hal_iot_gpio_ex.c b/src/applications/sample/wifi-iot/app/core/hal_iot_gpio_ex.c new file mode 100644 index 0000000..68121d9 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/core/hal_iot_gpio_ex.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "iot_errno.h" +#include "iot_gpio_ex.h" +#include "hi_gpio.h" +#include "hi_io.h" +#include "hi_task.h" +#include "hi_types_base.h" + + +unsigned int IoSetPull(unsigned int id, IotIoPull val) +{ + if (id >= HI_GPIO_IDX_MAX) { + return IOT_FAILURE; + } + return hi_io_set_pull((hi_io_name)id, (hi_io_pull)val); +} + +unsigned int IoSetFunc(unsigned int id, unsigned char val) +{ + if (id >= HI_GPIO_IDX_MAX) { + return IOT_FAILURE; + } + return hi_io_set_func((hi_io_name)id, val); +} + +/*unsigned int TaskMsleep(unsigned int ms) +{ + if (ms <= 0) { + return IOT_FAILURE; + } + return hi_sleep((hi_u32)ms); +}*/ \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/core/hisignalling_protocol.c b/src/applications/sample/wifi-iot/app/core/hisignalling_protocol.c new file mode 100644 index 0000000..d55f4bb --- /dev/null +++ b/src/applications/sample/wifi-iot/app/core/hisignalling_protocol.c @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "ohos_init.h" +#include "cmsis_os2.h" +#include "iot_gpio_ex.h" +#include "hi_io.h" +#include "iot_gpio.h" +#include "hisignalling_protocol.h" + +#define LED_TEST_GPIO 9 +#define LED_INTERVAL_TIME_US 300000 + +hi_u8 g_sendUartBuff[UART_BUFF_SIZE]; + +UartDefConfig recConfig = {0}; + +/* + * crc32 Verification implementation +*/ +static const unsigned int crc32table[] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, + 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, + 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, + 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, + 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, + 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, + 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, + 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, + 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, + 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, + 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, + 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, + 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, + 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, + 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, + 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, + 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, + 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, + 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, + 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, + 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, + 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, + 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, + 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, + 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, + 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, + 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, + 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, + 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, + 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, + 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, + 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, + 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, + 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, + 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, + 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L, + 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, + 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, + 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, + 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, + 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, + 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, + 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, + 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, + 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, + 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, + 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, + 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, + 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, + 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, + 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, + 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL +}; + +static unsigned int crc32(const unsigned char *buf, unsigned int len) +{ + unsigned int i, crc = 0xFFFFFFFF; + + for (i = 0; i < len; i++) { + crc = crc32table[(crc ^ buf[i]) & 0xff] ^ (crc >> 8); /* 8: right move 8 bit */ + } + return crc ^ 0xFFFFFFFF; +} +/* Log level look up table */ +static const char *hisignallingLevelNames[] = { + "TRACE", + "DEBUG", + "INFO", + "WARN", + "ERROR", + "FATAL" +}; +/* get hisignaling log level */ +const char *HisignallingLevelNum (HisignallingLogType hisignallingLevel) +{ + if (hisignallingLevel >= HISIGNALLING_LEVEL_MAX) { + return "NULL"; + } else { + return hisignallingLevelNames[hisignallingLevel]; + } +} +#define RIGHT_MOVE_8_BIT (8) +#define RIGHT_MOVE_16_BIT (16) +#define RIGHT_MOVE_24_BIT (24) +/* hisignal Hi3861 message package */ +static hi_u32 HisignallingDataPackage(HisignallingProtocalType *buf, hi_u32 len, hi_u8 *hisignallingDataBuf) +{ + hi_u32 crcCheckSend = 0; + hi_u32 packageLen = 0; + + memcpy_s(hisignallingDataBuf, HISGNALLING_MSG_FRAME_HEADER_LEN, + buf->frameHeader, HISGNALLING_MSG_FRAME_HEADER_LEN); + memcpy_s(&hisignallingDataBuf[HISGNALLING_MSG_FRAME_HEADER_LEN], + len, buf->hisignallingMsgBuf, len); + memcpy_s(&hisignallingDataBuf[HISGNALLING_MSG_FRAME_HEADER_LEN + len], + HISIGNALLING_MSG_HEADER_LEN, &(buf->endOfFrame), HISIGNALLING_MSG_HEADER_LEN); + crcCheckSend = crc32(hisignallingDataBuf, (len + HISIGNALLING_MSG_HEADER_TAIL_LEN)); + hisignallingDataBuf[len + HISIGNALLING_MSG_HEADER_TAIL_LEN] = + (hi_u8) ((crcCheckSend & 0xff000000)>>RIGHT_MOVE_24_BIT); + hisignallingDataBuf[len + HISIGNALLING_MSG_HEADER_TAIL_LEN + 1] = /* 1: addr offset */ + (hi_u8) ((crcCheckSend & 0x00ff0000)>>RIGHT_MOVE_16_BIT); + hisignallingDataBuf[len + HISIGNALLING_MSG_HEADER_TAIL_LEN + 2] = /* 2: addr offset */ + (hi_u8) ((crcCheckSend & 0x0000ff00)>>RIGHT_MOVE_8_BIT); + hisignallingDataBuf[len + HISIGNALLING_MSG_HEADER_TAIL_LEN + 3] = /* 3: addr offset */ + (hi_u8)crcCheckSend; + packageLen = len + HISIGNALLING_MSG_HEADER_TAIL_LEN + HISGNALLING_MSG_CRC32_LEN; + return packageLen; +} + +/* hisignal Hi3861 message recevice */ +HisignallingErrorType HisignallingMsgReceive(hi_u8 *buf, hi_u32 len) +{ + hi_u32 crcCheckReceived = 0; + unsigned char testBuff[7] = {0xaa, 0x55, 0x0, 0x2, 0x0, 0x8, 0xff}; + if (buf == HI_NULL && len > 0) { + HISIGNALLING_LOG_FATAL("received buf is null"); + return HISGNALLING_RET_VAL_MAX; + } + printf("length:%u\n", len); + + /* 校验crc */ + if (len > HISGNALLING_MSG_CRC32_LEN) { + crcCheckReceived = crc32(buf, len - HISGNALLING_MSG_CRC32_LEN); + if (((hi_u8)((crcCheckReceived & 0xff000000)>>RIGHT_MOVE_24_BIT) != buf[len - 4]) && /* 4: addr offset */ + ((hi_u8)((crcCheckReceived & 0x00ff0000)>>RIGHT_MOVE_16_BIT) != buf[len - 3]) && /* 3: addr offset */ + ((hi_u8)((crcCheckReceived & 0x0000ff00)>>RIGHT_MOVE_8_BIT) != buf[len - 2]) && /* 2: addr offset */ + ((hi_u8)crcCheckReceived != buf[len - 1])) { + HISIGNALLING_LOG_ERROR(": crc32 Verification failed!"); + HISIGNALLING_LOG_ERROR(":crc_4=0x%x, crc_3=0x%x, crc_2=0x%x, crc_1=0x%x", + buf[len - 4], buf[len - 3], buf[len - 2], buf[len - 1]); /* 4,3,2,1 addr offset */ + return HISIGNALLING_RET_VAL_ERROR; + } + } + IoTGpioSetOutputVal(LED_TEST_GPIO, 0); + usleep(LED_INTERVAL_TIME_US); + IoTGpioSetOutputVal(LED_TEST_GPIO, 1); + usleep(LED_INTERVAL_TIME_US); + /* 输出回显收到的数据 */ + /*if ((buf[0] == HISIGNALLING_MSG_FRAME_HEADER_1) && (buf[1] == HISIGNALLING_MSG_FRAME_HEADER_2)) { + for (int i = 0; i < len; i++) { + HISIGNALLING_LOG_INFO("0x%x", buf[i]); + } + }*/ + return HISIGNALLING_RET_VAL_CORRECT; +} +/* hisignal Hi3861 message send */ +hi_u32 HisignallingMsgSend(char *buf, hi_u32 dataLen) +{ + HisignallingProtocalType hisignallingMsg = {0}; + hi_u8 hisignallingSendBuf[HISIGNALLING_MSG_BUFF_LEN] = {0}; + hi_u32 hisignallingPackageLen = 0; + hi_u32 writeDataLen = 0; + + hisignallingMsg.frameHeader[0]= HISIGNALLING_MSG_FRAME_HEADER_1; + hisignallingMsg.frameHeader[1]= HISIGNALLING_MSG_FRAME_HEADER_2; + (void)memcpy_s(hisignallingMsg.hisignallingMsgBuf, dataLen, buf, dataLen); + hisignallingMsg.endOfFrame = HISIGNALLING_MSG_FRAME_TAIL; + + hisignallingPackageLen = HisignallingDataPackage(&hisignallingMsg, dataLen, hisignallingSendBuf); + if (!hisignallingPackageLen) { + HISIGNALLING_LOG_ERROR("hisignaling_data_package failed\r\n"); + return HI_ERR_FAILURE; + } + if (*hisignallingSendBuf == NULL) { + HISIGNALLING_LOG_ERROR("hisignal send buf is null!\r\n"); + return HI_ERR_FAILURE; + } + writeDataLen = IoTUartWrite(HI_UART_IDX_1, hisignallingSendBuf, hisignallingPackageLen); + if (!writeDataLen) { + HISIGNALLING_LOG_ERROR("hi_uart_write failed\r\n"); + return HI_ERR_FAILURE; + } + return HI_ERR_SUCCESS; +} + +int SetUartReceiveFlag(void) +{ + return recConfig.g_uartReceiveFlag; +} + +hi_void *HisignallingMsgHandle(char *param) +{ + unsigned char *recBuff = NULL; + int len; + + while (1) { + /*g_sendUartBuff清零*/ + (void)memset_s(g_sendUartBuff, sizeof(g_sendUartBuff) / sizeof(g_sendUartBuff[0]), + 0x0, sizeof(g_sendUartBuff)/sizeof(g_sendUartBuff[0])); + /*GetUartConfig得到data的flag和length*/ + if (GetUartConfig(UART_RECEIVE_FLAG) == HI_TRUE) { + /* 接收数据 */ + HisignallingMsgReceive(GetUartReceiveMsg(), GetUartConfig(UART_RECVIVE_LEN)); + /* 回显数据组包 */ + if (GetUartConfig(UART_RECVIVE_LEN) > (HISGNALLING_MSG_CRC32_LEN + HISIGNALLING_MSG_HEADER_TAIL_LEN)) { + len = GetUartConfig(UART_RECVIVE_LEN); + recBuff = GetUartReceiveMsg(); + for (int i = 0; i < len ; i++ ){ + HISIGNALLING_LOG_INFO("0x%x", recBuff[i]); + } + printf("end\n"); + (void)memcpy_s(g_sendUartBuff, + (GetUartConfig(UART_RECVIVE_LEN) - HISGNALLING_MSG_CRC32_LEN - HISIGNALLING_MSG_HEADER_TAIL_LEN), + &recBuff[HISGNALLING_MSG_FRAME_HEADER_LEN], + (GetUartConfig(UART_RECVIVE_LEN) - HISGNALLING_MSG_CRC32_LEN - HISIGNALLING_MSG_HEADER_TAIL_LEN)); + /* 接收到Hi3516DV300数据后,发送回显 */ + HisignallingMsgSend(g_sendUartBuff, + (GetUartConfig(UART_RECVIVE_LEN) - HISGNALLING_MSG_CRC32_LEN - HISIGNALLING_MSG_HEADER_TAIL_LEN)); + } + (void)SetUartRecvFlag(UART_RECV_FALSE); + ResetUartReceiveMsg(); + } + TaskMsleep(HISGNALLING_FREE_TASK_TIME); + } +} + +hi_u32 HisignalingMsgTask(hi_void) +{ + hi_u32 ret = 0; + IoTGpioInit(LED_TEST_GPIO); + IoTGpioSetDir(LED_TEST_GPIO, IOT_GPIO_DIR_OUT); + osThreadAttr_t hisignallingAttr = {0}; + + hisignallingAttr.stack_size = HISIGNALLING_MSG_TASK_STACK_SIZE; + hisignallingAttr.priority = HISIGNALLING_MSG_TASK_PRIO; + hisignallingAttr.name = (hi_char*)"hisignal msg task"; + + if (osThreadNew((osThreadFunc_t)HisignallingMsgHandle, NULL, &hisignallingAttr) == NULL) { + HISIGNALLING_LOG_ERROR("Failed to create hisignaling msg task\r\n"); + return HI_ERR_FAILURE; + } + return HI_ERR_SUCCESS; +} +//SYS_RUN(HisignalingMsgTask); diff --git a/src/applications/sample/wifi-iot/app/core/hisignalling_protocol.h b/src/applications/sample/wifi-iot/app/core/hisignalling_protocol.h new file mode 100644 index 0000000..efe68fa --- /dev/null +++ b/src/applications/sample/wifi-iot/app/core/hisignalling_protocol.h @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HISIGNALLING_PROTOCOL_H +#define HISIGNALLING_PROTOCOL_H +#include +#include +#include +#include +#include +/** +* @brief : hisignalling Macro definition +*/ +#define HISIGNALLING_MSG_HEADER_LEN (1) +#define HISGNALLING_MSG_FRAME_HEADER_LEN (2) +#define HISIGNALLING_MSG_HEADER_TAIL_LEN (3) +#define HISGNALLING_MSG_CRC32_LEN (4) +#define HISIGNALLING_MSG_PAYLOAD_INDEX (5) +#define HISGNALLING_FREE_TASK_TIME (20) +#define HISIGNALLING_MSG_TASK_PRIO (28) +#define HISIGNALLING_UART_MSG_LEN (32) +#define HISIGNALLING_MSG_BUFF_LEN (512) +#define HISIGNALLING_MSG_TASK_STACK_SIZE (4096) + +/* hisgnalling protocol frame header and tail */ +#define HISIGNALLING_MSG_FRAME_HEADER_1 ((hi_u8)0xAA) +#define HISIGNALLING_MSG_FRAME_HEADER_2 ((hi_u8)0x55) +#define HISIGNALLING_MSG_FRAME_TAIL ((hi_u8)0xFF) +/** +* @brief Adapter plate selection +* 使用时选择打开宏,使用外设扩展板打开#define BOARD_SELECT_IS_EXPANSION_BOARD这个宏 +* 使用Robot板自己定义#define BOARD_SELECT_IS_ROBOT_BOARD这个宏,注释掉#define BOARD_SELECT_IS_EXPANSION_BOARD +**/ + +#define BOARD_SELECT_IS_EXPANSION_BOARD +#ifdef BOARD_SELECT_IS_EXPANSION_BOARD +#define EXPANSION_BOARD +#else +#define ROBOT_BOARD +#endif +/** + * @brief:this defines for the log module, and HISIGNALING_LOG_TRACE/HISIGNALING_LOG_DEBUG... + * will not participate the compile in the release version + * */ +typedef enum { + HISIGNALLING_LEVEL_TRACE = 0, + HISIGNALLING_LEVEL_DEBUG, + HISIGNALLING_LEVEL_INFO, + HISIGNALLING_LEVEL_WARN, + HISIGNALLING_LEVEL_ERROR, + HISIGNALLING_LEVEL_FATAL, + HISIGNALLING_LEVEL_MAX +} HisignallingLogType; +/** + * @brief: use this function to get the hisignalling log level name + * + * @parameter[in]:level, the level to get + * + * @return: the mapped level name + * */ +const char *HisignallingLevelNum (HisignallingLogType hisignallingLevel); +/** + * @brief: this is a weak function ,and you could rewrite one + * + * @param fmt: same use as the fmt for printf + * + * @param unfixed: same use for printf + * + * @return: don't care about it + * + * @attention: and the components should not call this function directly, you'd better + * + * call HISIGNALING_LOG groups + * + * */ +#define HISIGNALLING_PRINT(fmt, ...) \ + do \ + { \ + printf(fmt, ##__VA_ARGS__); \ + } while (0) + +#define HISIGNALLING_LOG(level, fmt, ...) \ + do \ + { \ + HISIGNALLING_PRINT("<%s>, <%s>, <%d> "fmt" \r\n", \ + HisignallingLevelNum((level)), __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + } while (0) + +#define HISIGNALLING_LOG_TRACE(fmt, ...) \ + do \ + { \ + HISIGNALLING_LOG (HISIGNALLING_LEVEL_TRACE, fmt, ##__VA_ARGS__); \ + } while (0) + +#define HISIGNALLING_LOG_DEBUG(fmt, ...) \ + do \ + { \ + HISIGNALLING_LOG (HISIGNALLING_LEVEL_DEBUG, fmt, ##__VA_ARGS__); \ + } while (0) + +#define HISIGNALLING_LOG_INFO(fmt, ...) \ + do \ + { \ + HISIGNALLING_LOG (HISIGNALLING_LEVEL_INFO, fmt, ##__VA_ARGS__); \ + } while (0) + +#define HISIGNALLING_LOG_WARN(fmt, ...) \ + do \ + { \ + HISIGNALLING_LOG (HISIGNALLING_LEVEL_WARN, fmt, ##__VA_ARGS__); \ + } while (0) + +#define HISIGNALLING_LOG_ERROR(fmt, ...) \ + do \ + { \ + HISIGNALLING_LOG (HISIGNALLING_LEVEL_ERROR, fmt, ##__VA_ARGS__); \ + } while (0) + +#define HISIGNALLING_LOG_FATAL(fmt, ...) \ + do \ + { \ + HISIGNALLING_LOG (HISIGNALLING_LEVEL_FATAL, fmt, ##__VA_ARGS__); \ + } while (0) +/** + * @brief: use this hisignalling Transmission protocol frame format + * + * @param frameHeader: Transmission protocol frame header + * + * @param hisignallingMsgBuf: Transmission protocol frame buffer + * + * @param hisigallingMsgLen: Transmission protocol frame buffer len + * + * @param endOfFrame: Transmission protocol frame tail + * + * @param hisignallingCrc32Check: Transmission protocol crc32 check + * + * */ +typedef struct { + hi_u8 frameHeader[HISGNALLING_MSG_FRAME_HEADER_LEN]; + hi_u8 hisignallingMsgBuf[HISIGNALLING_MSG_BUFF_LEN]; + hi_u32 hisigallingMsgLen; + hi_u8 endOfFrame; + hi_u32 hisignallingCrc32Check; +}HisignallingProtocalType; +/** + * @brief: use this hisignalling return type + * + * @param HISIGNALLING_RET_VAL_CORRECT: return type is correct + * + * @param HISIGNALLING_RET_VAL_ERROR: return type is error + * + * @param HISIGNALLING_RET_VAL_ERROR: return type is unknown type + * */ +typedef enum { + HISIGNALLING_RET_VAL_CORRECT = 0, + HISIGNALLING_RET_VAL_ERROR, + HISGNALLING_RET_VAL_MAX +}HisignallingErrorType; +/** + * @brief: use this hisignalling sample:Access peripheral enumeration type + * + * @param MOTOR_GO_FORWARD: peripheral motor go forward + * + * @param MOTOR_GO_BACK: peripheral motor go back + * + * @param STEERING_ENGINE_MOVEMENT/STEERING_ENGINE_AND_MOTOR_MOVEMENT/STEERING_ENGINE_AND_MOTOR_STOP + * the same use for peripheral + * */ +typedef enum { + MOTOR_GO_FORWARD = 0, + MOTOR_GO_BACK, + STEERING_ENGINE_MOVEMENT, + STEERING_ENGINE_AND_MOTOR_MOVEMENT, + STEERING_ENGINE_AND_MOTOR_STOP, + TRASH_CAN_LID_OPEN, + TRASH_CAN_LID_COLSE +}HisignallingDataType; +/** +* @brief:hisignalling protocal Function declaration +**/ +hi_u32 hisignallingMsgTask(hi_void); +/** +* @brief:hisignalling uart message receive API +* @param buf: uart receive buffer +* @param len: uart receive buffer len +*/ +HisignallingErrorType hisignallingMsgReceive(hi_u8 *buf, hi_u32 len); +/** +* @brief:hisignalling uart send API +* @param buf: uart message send buffer +* @param len: uart message send buffer len +*/ +hi_u32 hisignallingMsgSend(hi_void *buf, hi_u32 dataLen); +int SetUartReceiveFlag(void); +#endif /* HISIGNALING_PROTOCOL_H */ \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/core/iot_config.h b/src/applications/sample/wifi-iot/app/core/iot_config.h new file mode 100644 index 0000000..b307f05 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/core/iot_config.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IOT_CONFIG_H +#define IOT_CONFIG_H + +// +#include +#include +#include +#include "md.h" +#include "md_internal.h" + +#define CN_HMAC256_LEN_MAX (65) +#define CN_HMAC256_LEN 32 +#define RIGHT_MOVE_BIT_4 (4) +#define NUMBER_9 (9) +#define DECIMAL_BASE (10) +#define STRING_LEN_TIMES (2) +#define LEN_TIMES (2) +#define OFFSET (1) +// make a byte to 2 ascii hex +static int byte2hexstr(unsigned char *bufin, int len, char *bufout) +{ + int i = 0; + unsigned char tmp_l = 0x0; + unsigned char tmp_h = 0; + if ((bufin == NULL)||(len <= 0)||(bufout == NULL)) { + return -1; + } + for (i = 0; i < len; i++) { + tmp_h = (bufin[i] >> RIGHT_MOVE_BIT_4) & 0X0F; + tmp_l = bufin[i] & 0x0F; + bufout[STRING_LEN_TIMES * i] = (tmp_h > NUMBER_9) ? + (tmp_h - DECIMAL_BASE + 'a'):(tmp_h +'0'); + bufout[STRING_LEN_TIMES * i + OFFSET] = (tmp_l > NUMBER_9) ? + (tmp_l - DECIMAL_BASE + 'a'):(tmp_l +'0'); + } + bufout[STRING_LEN_TIMES * len] = '\0'; + + return 0; +} + +int HmacGeneratePwd(const unsigned char *content, int contentLen, const unsigned char *key, + int keyLen, unsigned char *buf) +{ + int ret = -1; + mbedtls_md_context_t mbedtls_md_ctx; + const mbedtls_md_info_t *md_info; + unsigned char hash[CN_HMAC256_LEN]; + + if ((key == NULL)||(content == NULL)||(buf == NULL)|| + (keyLen == 0)||(contentLen == 0)|| + (CN_HMAC256_LEN_MAX < (CN_HMAC256_LEN * LEN_TIMES + OFFSET))) { + return ret; + } + + md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); + if ((md_info == NULL)||((size_t)md_info->size > CN_HMAC256_LEN)) { + return ret; + } + + mbedtls_md_init(&mbedtls_md_ctx); + ret = mbedtls_md_setup(&mbedtls_md_ctx, md_info, 1); + if (ret != 0) { + mbedtls_md_free(&mbedtls_md_ctx); + return ret; + } + + (void)mbedtls_md_hmac_starts(&mbedtls_md_ctx, key, keyLen); + (void)mbedtls_md_hmac_update(&mbedtls_md_ctx, content, contentLen); + (void)mbedtls_md_hmac_finish(&mbedtls_md_ctx, hash); + + // + +static EnIotLogLevel gIoTLogLevel = EN_IOT_LOG_LEVEL_TRACE; +static const char *gIoTLogLevelNames[] = { + "TRACE", + "DEBUG", + "INFO ", + "WARN ", + "ERROR", + "FATAL" +}; + +int IoTLogLevelSet(EnIotLogLevel level) +{ + int ret = -1; + if (level < EN_IOT_LOG_LEVEL_MAX) { + gIoTLogLevel = level; + ret = 0; + } + return ret; +} + +EnIotLogLevel IoTLogLevelGet(void) +{ + return gIoTLogLevel; +} + +const char *IoTLogLevelGetName(EnIotLogLevel logLevel) +{ + if (logLevel >= EN_IOT_LOG_LEVEL_MAX) { + return "NULL "; + } else { + return gIoTLogLevelNames[logLevel]; + } +} diff --git a/src/applications/sample/wifi-iot/app/core/iot_log.h b/src/applications/sample/wifi-iot/app/core/iot_log.h new file mode 100644 index 0000000..a0532b7 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/core/iot_log.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IOT_LOG_H_ +#define IOT_LOG_H_ +/** + * @brief:this defines for the log module, + * and IOT_LOG_TRACE/IOT_LOG_DEBUG will not participate the compile in the release version + * + * + * */ +typedef enum { + // < this is used as the trace function,like the function enter and function out + EN_IOT_LOG_LEVEL_TRACE = 0, + // < this is used as the debug, you could add any debug as you wish + EN_IOT_LOG_LEVEL_DEBUG, + // < which means it is import message, and you should known + EN_IOT_LOG_LEVEL_INFO, + // < this is used as the executed result,which means the status is not what we expected + EN_IOT_LOG_LEVEL_WARN, + // < this is used as the executed result,which means the status is not what we expected + EN_IOT_LOG_LEVEL_ERROR, + // < this is used as the parameters input for the api interface, which could not accepted + EN_IOT_LOG_LEVEL_FATAL, + EN_IOT_LOG_LEVEL_MAX, +}EnIotLogLevel; +/** + * @brief:use this function to get the current output log + * + * @return: the current output mask log, defined by en_iot_log_level_t + * */ +EnIotLogLevel IoTLogLevelGet(void); +/** + * @brief: use this function to get the debug level name + * + * @parameter[in]:level, the level to get + * + * @return: the mapped level name + * */ +const char *IoTLogLevelGetName(EnIotLogLevel logLevel); +/** + * @brief:use this function to set the current output log + * + * @parameter[in] level:defined by en_iot_log_level_t + * + * @return: 0 success while -1 failed + * */ +int IoTLogLevelSet(EnIotLogLevel level); +/* + * @brief: this is a weak function ,and you could rewrite one + * + * @param fmt: same use as the fmt for printf + * + * @param unfixed: same use for printf + * + * @return: don't care about it + * + * @attention: and the components should not call this function directly, you'd better + * + * call IOT_LOG groups + * + * */ +#ifndef IOT_PRINT +#define IOT_PRINT(fmt, ...) \ + do \ + { \ + printf(fmt, ##__VA_ARGS__); \ + }while (0) +#endif + +#ifdef CONFIG_LINKLOG_ENABLE + +#define IOT_LOG(level, fmt, ...) \ + do \ + { \ + IOT_PRINT("[%s][%s] " fmt "\r\n", \ + IoTLogLevelGetName((level)), __FUNCTION__, ##__VA_ARGS__); \ + } while (0) + +#define IOT_LOG_TRACE(fmt, ...) \ + do \ + { \ + if ((EN_IOT_LOG_LEVEL_TRACE) >= IoTLogLevelGet()) \ + { \ + IOT_LOG(EN_IOT_LOG_LEVEL_TRACE, fmt, ##__VA_ARGS__); \ + } \ + } while (0) + +#define IOT_LOG_DEBUG(fmt, ...) \ + do \ + { \ + if ((EN_IOT_LOG_LEVEL_DEBUG) >= IoTLogLevelGet()) \ + { \ + IOT_LOG(EN_IOT_LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__); \ + } \ + } while (0) + +#else +#define IOT_LOG(level, fmt, ...) +#define IOT_LOG_TRACE(fmt, ...) +#define IOT_LOG_DEBUG(fmt, ...) +#endif + +#define IOT_LOG_TRACE(fmt, ...) IOT_LOG(EN_IOT_LOG_LEVEL_TRACE, fmt, ##__VA_ARGS__) +#define IOT_LOG_INFO(fmt, ...) IOT_LOG(EN_IOT_LOG_LEVEL_INFO, fmt, ##__VA_ARGS__) +#define IOT_LOG_WARN(fmt, ...) IOT_LOG(EN_IOT_LOG_LEVEL_WARN, fmt, ##__VA_ARGS__) +#define IOT_LOG_ERROR(fmt, ...) IOT_LOG(EN_IOT_LOG_LEVEL_ERROR, fmt, ##__VA_ARGS__) +#define IOT_LOG_FATAL(fmt, ...) IOT_LOG(EN_IOT_LOG_LEVEL_FATAL, fmt, ##__VA_ARGS__) + +#endif /* IOT_LOG_H_ */ \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/core/iot_main.c b/src/applications/sample/wifi-iot/app/core/iot_main.c new file mode 100644 index 0000000..8bdb873 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/core/iot_main.c @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * STEPS: + * 1, CONNECT TO THE IOT SERVER + * 2, SUBSCRIBE THE DEFAULT TOPIC + * 3, WAIT FOR ANY MESSAGE COMES OR ANY MESSAGE TO SEND +*/ + +#include +#include +#include +#include +#include +#include +#include "iot_config.h" +#include "iot_log.h" +#include "iot_hmac.h" +#include "ohos_init.h" +#include "cmsis_os2.h" +#include "iot_watchdog.h" +#include "MQTTClient.h" +#include "iot_errno.h" +#include "iot_main.h" +#include "iot_gpio.h" + + +// < this is the configuration head +#define CN_IOT_SERVER "tcp://106.55.124.154:1883" // Tencent iot cloud address +#define CONFIG_COMMAND_TIMEOUT 10000L +#define CN_KEEPALIVE_TIME 50 +#define CN_CLEANSESSION 1 +#define CN_HMAC_PWD_LEN 65 // < SHA256 IS 32 BYTES AND END APPEND '\0' +#define CN_EVENT_TIME "1970000100" +#define CN_CLIENTID_FMT "%s_0_0_%s" // < This is the cient ID format, deviceID_0_0_TIME +#define CN_QUEUE_WAITTIMEOUT 1000 +#define CN_QUEUE_MSGNUM 16 +#define CN_QUEUE_MSGSIZE (sizeof(hi_pvoid)) + +#define CN_TASK_PRIOR 28 +#define CN_TASK_STACKSIZE 0X2000 +#define CN_TASK_NAME "IoTMain" +#define Signal_LED_IO 12 + +typedef enum { + EN_IOT_MSG_PUBLISH = 0, + EN_IOT_MSG_RECV, +}EnIotMsg; + +typedef struct { + EnIotMsg type; + int qos; + const char *topic; + const char *payload; +}IoTMsg_t; + +typedef struct { + bool stop; + unsigned int conLost; + unsigned int queueID; + unsigned int iotTaskID; + fnMsgCallBack msgCallBack; + MQTTClient_deliveryToken tocken; +}IotAppCb_t; +static IotAppCb_t gIoTAppCb; + +static const char *gDefaultSubscribeTopic[] = { + /* Tencent iot cloud topic */ + "YT32IOSCAL/Hi38611_mqtt/data", + "YT32IOSCAL/Hi38611_mqtt/event", + "YT32IOSCAL/Hi38611_mqtt/control", +}; + +#define CN_TOPIC_SUBSCRIBE_NUM (sizeof(gDefaultSubscribeTopic) / sizeof(const char *)) +static int MsgRcvCallBack(char *context, char *topic, int topicLen, MQTTClient_message *message) +{ + IoTMsg_t *msg; + char *buf; + unsigned int bufSize; + int topiLen = topicLen; + + if (topiLen == 0) { + topiLen = strlen(topic); + } + bufSize = topiLen + 1 + message->payloadlen + 1 + sizeof(IoTMsg_t); + buf = hi_malloc(0, bufSize); + if (buf != NULL) { + msg = (IoTMsg_t *)buf; + buf += sizeof(IoTMsg_t); + bufSize -= sizeof(IoTMsg_t); + msg->qos = message->qos; + msg->type = EN_IOT_MSG_RECV; + (void)memcpy_s(buf, bufSize, topic, topiLen); + buf[topiLen] = '\0'; + msg->topic = buf; + buf += topiLen + 1; + bufSize -= (topiLen + 1); + (void)memcpy_s(buf, bufSize, message->payload, message->payloadlen); + buf[message->payloadlen] = '\0'; + msg->payload = buf; + IOT_LOG_DEBUG("RCVMSG:QOS:%d TOPIC:%s PAYLOAD:%s\r\n", msg->qos, msg->topic, msg->payload); + if (IOT_SUCCESS != osMessageQueuePut(gIoTAppCb.queueID, &msg, 0, CN_QUEUE_WAITTIMEOUT)) { + IOT_LOG_ERROR("Wrie queue failed\r\n"); + hi_free(0, msg); + } + } + + MQTTClient_freeMessage(&message); + MQTTClient_free(topic); + return 1; +} + +// < when the connect lost and this callback will be called +static void ConnLostCallBack(char *context, char *cause) +{ + IOT_LOG_DEBUG("Connection lost:caused by:%s\r\n", cause == NULL? "Unknown" : cause); + return; +} + +static int MqttProcessQueueMsg(MQTTClient client, IoTMsg_t *msg, MQTTClient_message pubMsg) +{ + int ret = 0; + + switch (msg->type) { + case EN_IOT_MSG_PUBLISH: + pubMsg.payload = (void *)msg->payload; + pubMsg.payloadlen = (int)strlen(msg->payload); + pubMsg.qos = msg->qos; + pubMsg.retained = 0; + ret = MQTTClient_publishMessage(client, msg->topic, &pubMsg, &gIoTAppCb.tocken); + if (ret != MQTTCLIENT_SUCCESS) { + IOT_LOG_ERROR("MSGSEND:failed\r\n"); + } + IOT_LOG_DEBUG("MSGSEND:SUCCESS\r\n"); + gIoTAppCb.tocken++; + break; + case EN_IOT_MSG_RECV: + if (gIoTAppCb.msgCallBack != NULL) { + gIoTAppCb.msgCallBack(msg->qos, msg->topic, msg->payload); /*接受信息并进行相应的操作,函数体在IoTSetMsgCallback中定义*/ + } + break; + default: + break; + } +} + +// qos, msg->topic, msg->payload); + MqttProcessQueueMsg(client, msg, pubmsg); + hi_free(0, msg); + } + timeout = 0; // < continous to deal the message without wait here + } while (ret == IOT_SUCCESS); + + return 0; +} + +int MqttDestory(int ret, MQTTClient client) +{ + if (ret != MQTTCLIENT_SUCCESS) { + MQTTClient_destroy(&client); + return -1; + } + return MQTTCLIENT_SUCCESS; +} + +static void MainEntryProcess(void) +{ + int rc = 0, subQos[CN_TOPIC_SUBSCRIBE_NUM] = {1}; + + MQTTClient client = NULL; + MQTTClient_connectOptions connOpts = MQTTClient_connectOptions_initializer; + char *clientID = CN_CLIENTID; + char *userID = CONFIG_USER_ID; + char *userPwd = hi_malloc(0, CN_HMAC_PWD_LEN); + if (userPwd == NULL) { + hi_free(0, clientID); + return; + } + userPwd = CONFIG_USER_PWD; + connOpts.keepAliveInterval = CN_KEEPALIVE_TIME; + connOpts.cleansession = CN_CLEANSESSION; + connOpts.username = userID; + connOpts.password = userPwd; + connOpts.MQTTVersion = MQTTVERSION_3_1_1; + IOT_LOG_DEBUG("CLIENTID:%s USERID:%s USERPWD:%s, IOTSERVER:%s\r\n", + clientID, userID, userPwd==NULL?"NULL" : userPwd, CN_IOT_SERVER); + rc = MQTTClient_create(&client, CN_IOT_SERVER, clientID, MQTTCLIENT_PERSISTENCE_NONE, NULL); + if (rc != MQTTCLIENT_SUCCESS) { + if (userPwd != NULL) { + hi_free(0, userPwd); + } + return; + } + rc = MQTTClient_setCallbacks(client, NULL, ConnLostCallBack, MsgRcvCallBack, NULL); + if (MqttDestory(rc, client) != MQTTCLIENT_SUCCESS) { + return; + } + rc = MQTTClient_connect(client, &connOpts); + if (MqttDestory(rc, client) != MQTTCLIENT_SUCCESS) { + return; + } + for (int i = 0; i < CN_TOPIC_SUBSCRIBE_NUM; i++) { + rc = MQTTClient_subscribeMany(client, CN_TOPIC_SUBSCRIBE_NUM, + (char *const *)gDefaultSubscribeTopic, (int *)&subQos[0]); + if (MqttDestory(rc, client) != MQTTCLIENT_SUCCESS) { + return; + } + } + IOT_LOG_DEBUG ("Connect success and Subscribe success\r\n"); + IoTGpioSetOutputVal(Signal_LED_IO, IOT_GPIO_VALUE1); + while (MQTTClient_isConnected(client)) { + ProcessQueueMsg(client); // < do the job here + MQTTClient_yield(); // < make the keepalive done + } + MQTTClient_disconnect(client, CONFIG_COMMAND_TIMEOUT); + return; +} + +/* MQTT processing entry */ +static hi_void *MainEntry(char *arg) +{ + (void)arg; + while (gIoTAppCb.stop == false) { + MainEntryProcess(); + IOT_LOG_DEBUG("The connection lost and we will try another connect\r\n"); + IoTGpioSetOutputVal(Signal_LED_IO, IOT_GPIO_VALUE0); + hi_sleep(1000); /* 1000: cpu sleep 1000ms */ + } + return NULL; +} +static void engine_init(unsigned int IO){ + IoTGpioInit(IO); + IoSetFunc(IO, 0); + IoTGpioSetDir(IO, IOT_GPIO_DIR_OUT); + IoTGpioSetOutputVal(IO, IOT_GPIO_VALUE0); + IOT_LOG_DEBUG("GPIO:%u initialized!", IO); +} +int IoTMain(void) +{ + unsigned int ret = 0; + hi_task_attr attr = {0}; + engine_init(6); + engine_init(7); + engine_init(9); + engine_init(10); + IoTGpioInit(Signal_LED_IO); + IoSetFunc(Signal_LED_IO, 0); + IoTGpioSetDir(Signal_LED_IO, IOT_GPIO_DIR_OUT); + IoTGpioSetOutputVal(Signal_LED_IO, IOT_GPIO_VALUE0); + + gIoTAppCb.queueID = osMessageQueueNew(CN_QUEUE_MSGNUM, CN_QUEUE_MSGSIZE, NULL); + if (ret != IOT_SUCCESS) { + IOT_LOG_ERROR("Create the msg queue Failed\r\n"); + } + + attr.stack_size = CN_TASK_STACKSIZE; + attr.task_prio = CN_TASK_PRIOR; + attr.task_name = CN_TASK_NAME; + ret = hi_task_create(&gIoTAppCb.iotTaskID, &attr, MainEntry, NULL); + if (ret != IOT_SUCCESS) { + IOT_LOG_ERROR("Create the Main Entry Failed\r\n"); + } + + return 0; +} + +int IoTSetMsgCallback(fnMsgCallBack msgCallback) +{ + gIoTAppCb.msgCallBack = msgCallback;/*赋予函数*/ + return 0; +} + +int IotSendMsg(int qos, const char *topic, const char *payload) +{ + int rc = -1; + IoTMsg_t *msg; + char *buf; + unsigned int bufSize; + + bufSize = strlen(topic) + 1 +strlen(payload) + 1 + sizeof(IoTMsg_t); + buf = hi_malloc(0, bufSize); + if (buf != NULL) { + msg = (IoTMsg_t *)buf; + buf += sizeof(IoTMsg_t); + bufSize -= sizeof(IoTMsg_t); + msg->qos = qos; + msg->type = EN_IOT_MSG_PUBLISH; + (void)memcpy_s(buf, bufSize, topic, strlen(topic)); + buf[strlen(topic)] = '\0'; + msg->topic = buf; + buf += strlen(topic) + 1; + bufSize -= (strlen(topic) + 1); + (void)memcpy_s(buf, bufSize, payload, strlen(payload)); + buf[strlen(payload)] = '\0'; + msg->payload = buf; + IOT_LOG_DEBUG("SNDMSG:QOS:%d TOPIC:%s PAYLOAD:%s\r\n", msg->qos, msg->topic, msg->payload); + if (IOT_SUCCESS != osMessageQueuePut(gIoTAppCb.queueID, &msg, 0, CN_QUEUE_WAITTIMEOUT)) { + IOT_LOG_ERROR("Write queue failed\r\n"); + hi_free(0, msg); + } else { + rc = 0; + } + } + return rc; +} \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/core/iot_main.h b/src/applications/sample/wifi-iot/app/core/iot_main.h new file mode 100644 index 0000000..75d0664 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/core/iot_main.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IOT_MAIN_H +#define IOT_MAIN_H + +typedef void (*fnMsgCallBack)(int qos, const char *topic, const char *payload); + +/** + * This is the iot main function. Please call this function first +*/ +int IoTMain(void); +/** + * Use this function to set the message call back function, when some messages comes, + * the callback will be called, if you don't care about the message, set it to NULL +*/ +int IoTSetMsgCallback(fnMsgCallBack msgCallback); +/** + * When you want to send some messages to the iot server(including the response message), + * please call this api + * @param qos: the mqtt qos,:0,1,2 + * @param topic: the iot mqtt topic + * @param payload: the mqtt payload + * + * @return 0 success while others failed + * + * @instruction: if success means we write the message to the queue susccess, + * not means communicate with the server success +*/ +int IotSendMsg(int qos, const char *topic, const char *payload); + +#endif /* IOT_MAIN_H_ */ \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/core/iot_profile.c b/src/applications/sample/wifi-iot/app/core/iot_profile.c new file mode 100644 index 0000000..a763b97 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/core/iot_profile.c @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "iot_main.h" +#include "iot_log.h" +#include "iot_config.h" +#include "iot_profile.h" + +// < format the report data to json string mode +static cJSON *FormateProflleValue(IoTProfileKV_t *kv) +{ + cJSON *ret = NULL; + switch (kv->type) { + case EN_IOT_DATATYPE_INT: + ret = cJSON_CreateNumber(kv->iValue); + break; + case EN_IOT_DATATYPE_LONG: + ret = cJSON_CreateNumber((double)(*(long *)kv->value)); + break; + case EN_IOT_DATATYPE_STRING: + ret = cJSON_CreateString((const char *)kv->value); + break; + default: + break; + } + return ret; +} + +static cJSON *MakeKvs(IoTProfileKV_t *kvlst) +{ + cJSON *root; + cJSON *kv; + IoTProfileKV_t *kvInfo; + + // < build a root node + root = cJSON_CreateObject(); + if (root == NULL) { + cJSON_Delete(root); + root = NULL; + return root; + } + // < add all the property to the properties + kvInfo = kvlst; + while (kvInfo != NULL) { + kv = FormateProflleValue(kvInfo); + if (kv == NULL) { + if (root != NULL) { + cJSON_Delete(root); + root = NULL; + } + return root; + } + cJSON_AddItemToObject(root, kvInfo->key, kv); + kvInfo = kvInfo->nxt; + } + // < OK, now we return it + return root; +} + +#define CN_PROFILE_SERVICE_KEY_SERVICEID "service_id" +#define CN_PROFILE_SERVICE_KEY_PROPERTIIES "properties" +#define CN_PROFILE_SERVICE_KEY_EVENTTIME "event_time" +#define CN_PROFILE_KEY_SERVICES "services" +static cJSON *MakeService(IoTProfileService_t *serviceInfo) +{ + cJSON *root; + cJSON *serviceID; + cJSON *properties; + cJSON *eventTime; + + // < build a root node + root = cJSON_CreateObject(); + if (root == NULL) { + cJSON_Delete(root); + root = NULL; + return root; + } + // < add the serviceID node to the root node + serviceID = cJSON_CreateString(serviceInfo->serviceID); + if (serviceID == NULL) { + if (root != NULL) { + cJSON_Delete(root); + root = NULL; + } + return root; + } + cJSON_AddItemToObjectCS(root, CN_PROFILE_SERVICE_KEY_SERVICEID, serviceID); + // < add the properties node to the root + properties = MakeKvs(serviceInfo->serviceProperty); + if (properties == NULL) { + if (root != NULL) { + cJSON_Delete(root); + root = NULL; + } + return root; + } + cJSON_AddItemToObjectCS(root, CN_PROFILE_SERVICE_KEY_PROPERTIIES, properties); + // < add the event time (optional) to the root + if (serviceInfo->eventTime != NULL) { + eventTime = cJSON_CreateString(serviceInfo->eventTime); + if (eventTime == NULL) { + if (root != NULL) { + cJSON_Delete(root); + root = NULL; + } + return root; + } + cJSON_AddItemToObjectCS(root, CN_PROFILE_SERVICE_KEY_EVENTTIME, eventTime); + } + // < OK, now we return it + cJSON_Delete(properties); + return root; +} + +static cJSON *MakeServices(IoTProfileService_t *serviceInfo) +{ + cJSON *services = NULL; + cJSON *service; + IoTProfileService_t *serviceTmp; + + // < create the services array node + services = cJSON_CreateArray(); + if (services == NULL) { + cJSON_Delete(services); + services = NULL; + return services; + } + + serviceTmp = serviceInfo; + while (serviceTmp != NULL) { + service = MakeService(serviceTmp); + if (service == NULL) { + if (services != NULL) { + cJSON_Delete(services); + services = NULL; + } + return services; + } + cJSON_AddItemToArray(services, service); + serviceTmp = serviceTmp->nxt; + } + // < now we return the services + return services; +} + +// < use this function to make a topic to publish +// < if request_id is needed depends on the fmt +static char *MakeTopic(const char *fmt, const char *deviceID, const char *requestID) +{ + int len; + char *ret = NULL; + + len = strlen(fmt) + strlen(deviceID); + if (requestID != NULL) { + len += strlen(requestID); + } + + ret = hi_malloc(0, len); + if (ret != NULL) { + if (requestID != NULL) { + (void)snprintf_s(ret, len, len, fmt, deviceID, requestID); + } else { + (void)snprintf_s(ret, len, len, fmt, deviceID); + } + } + return ret; +} + +#define CN_PROFILE_CMDRESP_KEY_RETCODE "result_code" +#define CN_PROFILE_CMDRESP_KEY_RESPNAME "response_name" +#define CN_PROFILE_CMDRESP_KEY_PARAS "paras" +static char *MakeProfileCmdResp(IoTCmdResp_t *payload) +{ + char *ret = NULL; + cJSON *root; + cJSON *retCode; + cJSON *respName; + cJSON *paras; + + // < create the root node + root = cJSON_CreateObject(); + if (root == NULL) { + cJSON_Delete(root); + return ret; + } + // < create retcode and retdesc and add it to the root + retCode = cJSON_CreateNumber(payload->retCode); + if (retCode == NULL) { + if (root != NULL) { + cJSON_Delete(root); + } + return ret; + } + cJSON_AddItemToObjectCS(root, CN_PROFILE_CMDRESP_KEY_RETCODE, retCode); + if (payload->respName != NULL) { + respName = cJSON_CreateString(payload->respName); + if (respName == NULL) { + if (root != NULL) { + cJSON_Delete(root); + } + return ret; + } + cJSON_AddItemToObjectCS(root, CN_PROFILE_CMDRESP_KEY_RESPNAME, respName); + } + + if (payload->paras != NULL) { + paras = MakeKvs(payload->paras); + if (paras == NULL) { + if (root != NULL) { + cJSON_Delete(root); + } + return ret; + } + cJSON_AddItemToObjectCS(root, CN_PROFILE_CMDRESP_KEY_PARAS, paras); + } + // < OK, now we make it to a buffer + ret = cJSON_PrintUnformatted(root); + cJSON_Delete(root); + return ret; +} + +static char *MakeProfilePropertyReport(IoTProfileService_t *payload) +{ + char *ret = NULL; + cJSON *root; + cJSON *services; + + // < create the root node + root = cJSON_CreateObject(); + if (root == NULL) { + cJSON_Delete(root); + return ret; + } + // < create the services array node to the root + services = MakeServices(payload); + if (services == NULL) { + if (root != NULL) { + cJSON_Delete(root); + } + return ret; + } + cJSON_AddItemToObjectCS(root, CN_PROFILE_KEY_SERVICES, services); + // < OK, now we make it to a buffer + ret = cJSON_PrintUnformatted(root); + cJSON_Delete(root); + return ret; +} + +#define WECHAT_SUBSCRIBE_TYPE "update" +#define WECHAT_SUBSCRIBE_VERSION "1.0.0" +#define WECHAT_SUBSCRIBE_TOKEN "DeviceSubscribe" +static char *MakeProfileReport(WeChatProfile *payload) +{ + char *ret = NULL; + cJSON *root; + cJSON *state; + cJSON *reported; + + /* create json root node */ + root = cJSON_CreateObject(); + if (root == NULL) { + return; + } + /* state create */ + state = cJSON_CreateObject(); + if (state == NULL) { + return; + } + /* reported create */ + reported = cJSON_CreateObject(); + if (reported == NULL) { + return; + } + /* add root object */ + cJSON_AddItemToObject(root, payload->subscribeType, cJSON_CreateString(WECHAT_SUBSCRIBE_TYPE)); + cJSON_AddItemToObject(root, payload->status.subState, state); + cJSON_AddItemToObject(state, payload->status.subReport, reported); + cJSON_AddItemToObject(root, payload->status.reportVersion, cJSON_CreateString(WECHAT_SUBSCRIBE_VERSION)); + cJSON_AddItemToObject(root, payload->status.Token, cJSON_CreateString(WECHAT_SUBSCRIBE_TOKEN)); + /* add reported item */ + cJSON_AddNumberToObject(reported, payload->reportAction.subDeviceActionLight, + payload->reportAction.lightActionStatus); + cJSON_AddNumberToObject(reported, payload->reportAction.subDeviceActionMotor, + payload->reportAction.motorActionStatus); + cJSON_AddNumberToObject(reported, payload->reportAction.subDeviceActionTemperature, + payload->reportAction.temperatureData); + cJSON_AddNumberToObject(reported, payload->reportAction.subDeviceActionHumidity, + payload->reportAction.humidityActionData); + cJSON_AddNumberToObject(reported, payload->reportAction.subDeviceActionLightIntensity, + payload->reportAction.lightIntensityActionData); + ret = cJSON_PrintUnformatted(root); + cJSON_Delete(state); + cJSON_Delete(reported); + cJSON_Delete(root); + return ret; +} + +#define CN_PROFILE_TOPICFMT_TOPIC "YT32IOSCAL/Hi38611_mqtt/event" +/*int IoTProfilePropertyReport(char *deviceID, WeChatProfile *payload) +{ + int ret = -1; + char *topic; + char *msg; + + if ((deviceID == NULL) || (payload== NULL)) { + return ret; + } + topic = MakeTopic(CN_PROFILE_TOPICFMT_TOPIC, deviceID, NULL); + if (topic == NULL) { + return; + } + msg = MakeProfileReport(payload); + if ((topic != NULL) && (msg != NULL)) { + ret = IotSendMsg(0, topic, msg); + } + + hi_free(0, topic); + cJSON_free(msg); + + return ret; +}*/ + +int IoTProfilePropertyReport_uart(char *deviceID, char *msg) +{ + int ret = -1; + char *topic; + //char *msg; + + if ((deviceID == NULL) || (msg == NULL)) { + return ret; + } + topic = MakeTopic(CN_PROFILE_TOPICFMT_TOPIC, deviceID, NULL); + if (topic == NULL) { + return; + } + //msg = MakeProfileReport(payload); + if ((topic != NULL) && (msg != NULL)) { + ret = IotSendMsg(0, topic, msg); + printf("send success\n"); + } + + hi_free(0, topic); + //cJSON_free(msg); + + return ret; +} \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/core/iot_profile.h b/src/applications/sample/wifi-iot/app/core/iot_profile.h new file mode 100644 index 0000000..6c1b065 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/core/iot_profile.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IOT_PROFILE_H +#define IOT_PROFILE_H + +#include +#include "iot_config.h" + +#define OC_BEEP_STATUS_ON ((hi_u8) 0x01) +#define OC_BEEP_STATUS_OFF ((hi_u8) 0x00) + +// < enum all the data type for the oc profile +typedef enum { + EN_IOT_DATATYPE_INT = 0, + EN_IOT_DATATYPE_LONG, + EN_IOT_DATATYPE_FLOAT, + EN_IOT_DATATYPE_DOUBLE, + EN_IOT_DATATYPE_STRING, // < must be ended with '\0' + EN_IOT_DATATYPE_LAST, +}IoTDataType_t; + +typedef enum { + OC_LED_ON = 1, + OC_LED_OFF +}OcLedValue; + +typedef struct { + void *nxt; // < ponit to the next key + const char *key; + const char *value; + hi_u32 iValue; + IoTDataType_t type; +}IoTProfileKV_t; + +typedef struct { + void *nxt; + char *serviceID; + char *eventTime; + IoTProfileKV_t *serviceProperty; +}IoTProfileService_t; + +typedef struct { + int retCode; // < response code, 0 success while others failed + const char *respName; // < response name + const char *requestID; // < specified by the message command + IoTProfileKV_t *paras; // < the command paras +}IoTCmdResp_t; + +typedef struct { + const char *subState; + const char *subReport; + const char *reportVersion; + const char *Token; +}WeChatProfileStatus; + +typedef struct { + int lightActionStatus; + int motorActionStatus; + int temperatureData; + int humidityActionData; + int lightIntensityActionData; + const char *subDeviceActionLight; + const char *subDeviceActionMotor; + const char *subDeviceActionTemperature; + const char *subDeviceActionHumidity; + const char *subDeviceActionLightIntensity; +}WeChatProfileReporte; + +typedef struct { + const char *subscribeType; + WeChatProfileStatus status; + WeChatProfileReporte reportAction; +}WeChatProfile; + +/** + * use this function to report the property to the iot platform +*/ +//int IoTProfilePropertyReport(char *deviceID, WeChatProfile *payload); +int IoTProfilePropertyReport_uart(char *deviceID, char *msg); +void cJsonInit(void); +void WifiStaReadyWait(void); +#endif \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/core/iot_sta.c b/src/applications/sample/wifi-iot/app/core/iot_sta.c new file mode 100644 index 0000000..aed1be3 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/core/iot_sta.c @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// < this demo make the wifi to connect to the specified AP +#include +#include +#include +#include +#include +#include +#include +#include "iot_config.h" +#include "iot_log.h" +#include "wifi_device.h" +#include "cmsis_os2.h" +#include "wifi_device_config.h" +#include "lwip/api_shell.h" + +#define APP_INIT_VAP_NUM 2 +#define APP_INIT_USR_NUM 2 + +static struct netif *gLwipNetif = NULL; +static hi_bool gScanDone = HI_FALSE; +unsigned char wifiStatus = 0; + +unsigned char wifiFirstConnecting = 0; +unsigned char wifiSecondConnecting = 0; +unsigned char wifiSecondConnected = 0; +static struct netif* g_iface = NULL; +void WifiStopSta(int netId); +static int WifiStartSta(void); +int cnetId = -1; +int g_connected = 0; + +#define WIFI_CONNECT_STATUS ((unsigned char)0x02) + +void wifiReconnected(int netId) +{ + int recnetId = netId; + if (wifiFirstConnecting == WIFI_CONNECT_STATUS) { + wifiSecondConnecting = HI_TRUE; + wifiFirstConnecting = HI_FALSE; + WifiStopSta(recnetId); + ip4_addr_t ipAddr; + ip4_addr_t ipAny; + IP4_ADDR(&ipAny, 0, 0, 0, 0); + IP4_ADDR(&ipAddr, 0, 0, 0, 0); + recnetId = WifiStartSta(); + netifapi_dhcp_start(gLwipNetif); + while (0 == memcmp(&ipAddr, &ipAny, sizeof(ip4_addr_t))) { + IOT_LOG_DEBUG(":Wait the DHCP READY"); + netifapi_netif_get_addr(gLwipNetif, &ipAddr, NULL, NULL); + hi_sleep(1000); /* 1000: cpu sleep 1000 ms */ + } + wifiSecondConnected = HI_FALSE; + wifiFirstConnecting = WIFI_CONNECT_STATUS; + wifiStatus = HI_WIFI_EVT_CONNECTED; + } +} +/* clear netif's ip, gateway and netmask */ +static void StaResetAddr(struct netif *lwipNetif) +{ + ip4_addr_t st_gw; + ip4_addr_t st_ipaddr; + ip4_addr_t st_netmask; + + if (lwipNetif == NULL) { + IOT_LOG_ERROR("hisi_reset_addr::Null param of netdev"); + return; + } + + IP4_ADDR(&st_gw, 0, 0, 0, 0); + IP4_ADDR(&st_ipaddr, 0, 0, 0, 0); + IP4_ADDR(&st_netmask, 0, 0, 0, 0); + + netifapi_netif_set_addr(lwipNetif, &st_ipaddr, &st_netmask, &st_gw); +} + +static void WpaEventCB(const hi_wifi_event *hisiEvent) +{ + if (hisiEvent == NULL) + return; + IOT_LOG_DEBUG("EVENT_TYPE:%d", hisiEvent->event); + switch (hisiEvent->event) { + case HI_WIFI_EVT_SCAN_DONE: + IOT_LOG_DEBUG("WiFi: Scan results available"); + gScanDone = HI_TRUE; + break; + case HI_WIFI_EVT_CONNECTED: + IOT_LOG_DEBUG("WiFi: Connected"); + netifapi_dhcp_start(gLwipNetif); + wifiStatus = HI_WIFI_EVT_CONNECTED; + if (wifiSecondConnected) { + wifiSecondConnected = HI_FALSE; + wifiFirstConnecting = WIFI_CONNECT_STATUS; + } + break; + case HI_WIFI_EVT_DISCONNECTED: + IOT_LOG_DEBUG("WiFi: Disconnected"); + netifapi_dhcp_stop(gLwipNetif); + StaResetAddr(gLwipNetif); + wifiStatus = HI_WIFI_EVT_DISCONNECTED; + wifiReconnected(cnetId); + break; + case HI_WIFI_EVT_WPS_TIMEOUT: + IOT_LOG_DEBUG("WiFi: wps is timeout"); + wifiStatus = HI_WIFI_EVT_WPS_TIMEOUT; + break; + default: + break; + } +} + +static int StaStartConnect(void) +{ + int ret; + errno_t rc; + hi_wifi_assoc_request assoc_req = {0}; + + /* copy SSID to assoc_req */ + rc = memcpy_s(assoc_req.ssid, HI_WIFI_MAX_SSID_LEN + 1, CONFIG_AP_SSID, strlen(CONFIG_AP_SSID)); + if (rc != EOK) { + return -1; + } + + /* + * OPEN mode + * for WPA2-PSK mode: + * set assoc_req.auth as HI_WIFI_SECURITY_WPA2PSK, + * then memcpy(assoc_req.key, "12345678", 8). + */ + assoc_req.auth = HI_WIFI_SECURITY_WPA2PSK; + rc = memcpy_s(assoc_req.key, HI_WIFI_MAX_KEY_LEN + 1, CONFIG_AP_PWD, strlen(CONFIG_AP_PWD)); + if (rc != EOK) { + return -1; + } + + ret = hi_wifi_sta_connect(&assoc_req); + if (ret != HISI_OK) { + return -1; + } + + return 0; +} + +static void PrintLinkedInfo(WifiLinkedInfo* info) +{ + int ret = 0; + if (!info) { + return; + } + + static char macAddress[32] = {0}; + unsigned char* mac = info->bssid; + if (snprintf_s(macAddress, sizeof(macAddress) + 1, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]) < 0) { /* mac地址从0,1,2,3,4,5位 */ + return; + } +} + +static void OnWifiConnectionChanged(int state, WifiLinkedInfo* info) +{ + if (!info) { + return; + } + + printf("%s %d, state = %d, info = \r\n", __FUNCTION__, __LINE__, state); + PrintLinkedInfo(info); + + if (state == WIFI_STATE_AVALIABLE) { + g_connected = 1; + } else { + g_connected = 0; + } +} + +static void OnWifiScanStateChanged(int state, int size) +{ + printf("%s %d, state = %X, size = %d\r\n", __FUNCTION__, __LINE__, state, size); +} + +static WifiEvent g_defaultWifiEventListener = { + .OnWifiConnectionChanged = OnWifiConnectionChanged, + .OnWifiScanStateChanged = OnWifiScanStateChanged +}; + +static int WifiStartSta(void) +{ + WifiDeviceConfig apConfig = {0}; + strcpy_s(apConfig.ssid, sizeof(CONFIG_AP_SSID), CONFIG_AP_SSID); + strcpy_s(apConfig.preSharedKey, sizeof(CONFIG_AP_PWD), CONFIG_AP_PWD); + apConfig.securityType = WIFI_SEC_TYPE_PSK; + + WifiErrorCode errCode; + int netId = -1; + + errCode = RegisterWifiEvent(&g_defaultWifiEventListener); + printf("RegisterWifiEvent: %d\r\n", errCode); + + errCode = EnableWifi(); + printf("EnableWifi: %d\r\n", errCode); + + errCode = AddDeviceConfig(&apConfig, &netId); + printf("AddDeviceConfig: %d\r\n", errCode); + + g_connected = 0; + errCode = ConnectTo(netId); + printf("ConnectTo(%d): %d\r\n", netId, errCode); + + while (!g_connected) { // wait until connect to AP + osDelay(10); /* 10: os sleep 10ms */ + } + printf("g_connected: %d\r\n", g_connected); + + g_iface = netifapi_netif_find("wlan0"); + if (g_iface) { + err_t ret = netifapi_dhcp_start(g_iface); + printf("netifapi_dhcp_start: %d\r\n", ret); + + osDelay(100); // 100: os sleep 100ms wait DHCP server give me IP + ret = netifapi_netif_common(g_iface, dhcp_clients_info_show, NULL); + printf("netifapi_netif_common: %d\r\n", ret); + } + return netId; +} + +void WifiStopSta(int netId) +{ + int stopNetId = netId; + + if (g_iface) { + err_t ret = netifapi_dhcp_stop(g_iface); + printf("netifapi_dhcp_stop: %d\r\n", ret); + } + + WifiErrorCode errCode = Disconnect(); // disconnect with your AP + printf("Disconnect: %d\r\n", errCode); + + errCode = UnRegisterWifiEvent(&g_defaultWifiEventListener); + printf("UnRegisterWifiEvent: %d\r\n", errCode); + + RemoveDevice(stopNetId); // remove AP config + printf("RemoveDevice: %d\r\n", errCode); + + errCode = DisableWifi(); + printf("DisableWifi: %d\r\n", errCode); +} + +void WifiStaReadyWait(void) +{ + ip4_addr_t ipAddr; + ip4_addr_t ipAny; + IP4_ADDR(&ipAny, 0, 0, 0, 0); + IP4_ADDR(&ipAddr, 0, 0, 0, 0); + cnetId = WifiStartSta(); + IOT_LOG_DEBUG("wifi sta dhcp done"); +} \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/interconnection_client/BUILD.gn b/src/applications/sample/wifi-iot/app/interconnection_client/BUILD.gn new file mode 100644 index 0000000..be2620d --- /dev/null +++ b/src/applications/sample/wifi-iot/app/interconnection_client/BUILD.gn @@ -0,0 +1,27 @@ +# Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +static_library("interconnectionClient") { + sources = [ + "app_demo_uart.c", + "hal_iot_gpio_ex.c", + "hisignalling_protocol.c", + ] + + include_dirs = [ + "./", + "//utils/native/lite/include", + "//kernel/liteos_m/kal/cmsis", + "//base/iot_hardware/peripheral/interfaces/kits", + ] +} diff --git a/src/applications/sample/wifi-iot/app/interconnection_client/README.md b/src/applications/sample/wifi-iot/app/interconnection_client/README.md new file mode 100644 index 0000000..74d888c --- /dev/null +++ b/src/applications/sample/wifi-iot/app/interconnection_client/README.md @@ -0,0 +1,86 @@ +# Pegasus与Taurus串口互联通信 + +## 硬件环境搭建 +- 硬件要求:Hi3861V100核心板、底板、外设扩展板或者机器人板;硬件搭建如下图所示。注意这里需要跟Taurus同时使用,详情可以参考[串口互联server](http://gitee.com/openharmony/device_soc_hisilicon/blob/master/hi3516dv300/sdk_linux/sample/taurus/ai_sample/interconnection_server/README.md)端。 +- 外设扩展板使用的是Hi3861的GPIO0和GPIO1作为串口1复用功能,请在程序初始化时注意管脚复用关系。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E4%BA%92%E8%81%94/10.jpg) + +- 注意:Robot板使用的串口1复用端口是Hi3861的GPIO5和GPIO6,其中GPIO6要在程序烧录启动后才能使用,如果用户在还没烧录和启动之前就将串口线与硬件连接上,这时Hi3861将无法烧录和重启。GPIO6(TX)引脚影响Hi3861烧录和启动,用户在使用Robot板时,先拔掉Robot上4pin串口连接线,在程序烧录启动后,再将4pin串口连接线插回Robot板,此时串口可以正常通信。如果用户在使用Robot板的过程中觉得频繁插拔串口线麻烦,用户可在串口线上做一个开关,当Hi3861烧录或复位启动前关闭开关,单板启动后打开开关。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E4%BA%92%E8%81%94/11.jpg) + +## 串口通信控制协议HiSignalling介绍 +- 为了便于Taurus与Pegasus开发套件之间进行通信和控制,定义了一套简易的HiSignalling通信控制协议,数据帧格式如下表所示,并提供相关参考代码,大家也可以根据自己的需要使用其他协议。 + +| 帧头(2Byte) | Payload Len (2Byte) | payload | 帧尾(1Byte) | CRC32(4Byte) | +|---|---|---|---|---| +| 0xAA,0x55 | | | 0xFF | CRC32 | + +例如一组数据帧为:AA5500020003FF8ED2BEDF (十六进制不区分大小写) +- 0AA55: 帧头 +- 0002: Payload Len +- 0003: Payload +- FF: 帧尾 +- 8ED2BEDF: CRC32校验码 + +## 软件介绍 +- 注意这里需要跟Taurus同时使用,Taurus软件介绍详情可以参考串口互联server端。 +- 1.代码目录结构及相应接口功能介绍 +- UART API + +| API | 接口说明 | +| ------------------------------------------------------------ | ------------------------ | +| unsigned int UartInit(WifiIotUartIdx id, const WifiIotUartAttribute *param, const WifiIotUartExtraAttr *extraAttr); | 初始化,配置一个UART设备 | +| int UartRead(WifiIotUartIdx id, unsigned char *data, unsigned int dataLen) | 从UART设备中读取数据 | +| int UartWrite(WifiIotUartIdx id, const unsigned char *data, unsigned int dataLen) | 将数据写入UART设备 | + +- 2.工程编译 + - 将源码./vendor/hisilicon/hispark_pegasus/demo目录下的interconnection_client_demo整个文件夹及内容复制到源码./applications/sample/wifi-iot/app/下,如图。 + ``` + . + └── applications + └── sample + └── wifi-iot + └── app + └──interconnection_client_demo + └── 代码 + ``` + + - 在hisignalling.h文件中,如果是想使用硬件扩展板,请将BOARD_SELECT_IS_EXPANSION_BOARD这个宏打开,如果是想使用Robot板,请将BOARD_SELECT_IS_ROBOT_BOARD 这个宏打开。 + ``` + /** + * @brief Adapter plate selection + * 使用时选择打开宏,使用外设扩展板打开#define BOARD_SELECT_IS_EXPANSION_BOARD这个宏 + * 使用Robot板打开#define BOARD_SELECT_IS_ROBOT_BOARD这个宏 + **/ + //#define BOARD_SELECT_IS_ROBOT_BOARD + #define BOARD_SELECT_IS_EXPANSION_BOARD + #ifdef BOARD_SELECT_IS_EXPANSION_BOARD + #define EXPANSION_BOARD + #else + #define ROBOT_BOARD + #endif + ``` + + - 修改源码./applications/sample/wifi-iot/app/BUILD.gn文件,在features字段中增加索引,使目标模块参与编译。features字段指定业务模块的路径和目标,features字段配置如下。 + ``` + import("//build/lite/config/component/lite_component.gni") + + lite_component("app") { + features = [ + "interconnection_client_demo:interconnectionClientDemo", + ] + } + ``` + + - 工程相关配置完成后,然后编译。 +- 3.烧录 + - 编译成功后,点击DevEco Home->配置工程->hi3861->upload_port->选择对应串口端口号->选择upload_protocol->选择hiburn-serial->点击save保存,在保存成功后点击upload进行烧录,出现connecting, please reset device..字样复位开发板等待烧录完成。 + - 烧录成功后,再次点击Hi3861核心板上的“RST”复位键,此时开发板的系统会运行起来。运行结果:打开串口工具,可以看到如下打印,同时3861主板灯闪亮一下。 + + ![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E4%BA%92%E8%81%94/6.png) + + ![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E4%BA%92%E8%81%94/7.png) + + ![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E4%BA%92%E8%81%94/8.jpg) \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/interconnection_client/app_demo_uart.c b/src/applications/sample/wifi-iot/app/interconnection_client/app_demo_uart.c new file mode 100644 index 0000000..1771b35 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/interconnection_client/app_demo_uart.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "iot_gpio_ex.h" +#include "ohos_init.h" +#include "cmsis_os2.h" + +UartDefConfig uartDefConfig = {0}; + +static void Uart1GpioCOnfig(void) +{ +#ifdef ROBOT_BOARD + IoSetFunc(HI_IO_NAME_GPIO_5, IOT_IO_FUNC_GPIO_5_UART1_RXD); + IoSetFunc(HI_IO_NAME_GPIO_6, IOT_IO_FUNC_GPIO_6_UART1_TXD); + /* IOT_BOARD */ +#elif defined (EXPANSION_BOARD) + IoSetFunc(HI_IO_NAME_GPIO_0, IOT_IO_FUNC_GPIO_0_UART1_TXD); + IoSetFunc(HI_IO_NAME_GPIO_1, IOT_IO_FUNC_GPIO_1_UART1_RXD); +#endif +} + +int SetUartRecvFlag(UartRecvDef def) +{ + if (def == UART_RECV_TRUE) { + uartDefConfig.g_uartReceiveFlag = HI_TRUE; + } else { + uartDefConfig.g_uartReceiveFlag = HI_FALSE; + } + + return uartDefConfig.g_uartReceiveFlag; +} + +int GetUartConfig(UartDefType type) +{ + int receive = 0; + + switch (type) { + case UART_RECEIVE_FLAG: + receive = uartDefConfig.g_uartReceiveFlag; + break; + case UART_RECVIVE_LEN: + receive = uartDefConfig.g_uartLen; + break; + default: + break; + } + return receive; +} + +void ResetUartReceiveMsg(void) +{ + (void)memset_s(uartDefConfig.g_receiveUartBuff, sizeof(uartDefConfig.g_receiveUartBuff), + 0x0, sizeof(uartDefConfig.g_receiveUartBuff)); +} + +unsigned char *GetUartReceiveMsg(void) +{ + return uartDefConfig.g_receiveUartBuff; +} + +static hi_void *UartDemoTask(char *param) +{ + hi_u8 uartBuff[UART_BUFF_SIZE] = {0}; + hi_unref_param(param); + printf("Initialize uart demo successfully, please enter some datas via DEMO_UART_NUM port...\n"); + Uart1GpioCOnfig(); + for (;;) { + uartDefConfig.g_uartLen = IoTUartRead(DEMO_UART_NUM, uartBuff, UART_BUFF_SIZE); + if ((uartDefConfig.g_uartLen > 0) && (uartBuff[0] == 0xaa) && (uartBuff[1] == 0x55)) { + if (GetUartConfig(UART_RECEIVE_FLAG) == HI_FALSE) { + (void)memcpy_s(uartDefConfig.g_receiveUartBuff, uartDefConfig.g_uartLen, + uartBuff, uartDefConfig.g_uartLen);/*uartBuff中的信息放到uartDefConfig.g_receiveUartBuff*/ + (void)SetUartRecvFlag(UART_RECV_TRUE); + } + } + printf("len:%d\n", uartDefConfig.g_uartLen); + + for (int i = 0; i= HI_GPIO_IDX_MAX) { + return IOT_FAILURE; + } + return hi_io_set_pull((hi_io_name)id, (hi_io_pull)val); +} + +unsigned int IoSetFunc(unsigned int id, unsigned char val) /* 复用功能 */ +{ + if (id >= HI_GPIO_IDX_MAX) { + return IOT_FAILURE; + } + return hi_io_set_func((hi_io_name)id, val); +} + +unsigned int TaskMsleep(unsigned int ms) +{ + if (ms <= 0) { + return IOT_FAILURE; + } + return hi_sleep((hi_u32)ms); +} \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/interconnection_client/hisignalling_protocol.c b/src/applications/sample/wifi-iot/app/interconnection_client/hisignalling_protocol.c new file mode 100644 index 0000000..d55f4bb --- /dev/null +++ b/src/applications/sample/wifi-iot/app/interconnection_client/hisignalling_protocol.c @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "ohos_init.h" +#include "cmsis_os2.h" +#include "iot_gpio_ex.h" +#include "hi_io.h" +#include "iot_gpio.h" +#include "hisignalling_protocol.h" + +#define LED_TEST_GPIO 9 +#define LED_INTERVAL_TIME_US 300000 + +hi_u8 g_sendUartBuff[UART_BUFF_SIZE]; + +UartDefConfig recConfig = {0}; + +/* + * crc32 Verification implementation +*/ +static const unsigned int crc32table[] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, + 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, + 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, + 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, + 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, + 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, + 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, + 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, + 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, + 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, + 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, + 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, + 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, + 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, + 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, + 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, + 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, + 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, + 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, + 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, + 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, + 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, + 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, + 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, + 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, + 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, + 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, + 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, + 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, + 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, + 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, + 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, + 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, + 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, + 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, + 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L, + 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, + 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, + 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, + 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, + 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, + 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, + 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, + 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, + 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, + 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, + 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, + 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, + 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, + 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, + 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, + 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL +}; + +static unsigned int crc32(const unsigned char *buf, unsigned int len) +{ + unsigned int i, crc = 0xFFFFFFFF; + + for (i = 0; i < len; i++) { + crc = crc32table[(crc ^ buf[i]) & 0xff] ^ (crc >> 8); /* 8: right move 8 bit */ + } + return crc ^ 0xFFFFFFFF; +} +/* Log level look up table */ +static const char *hisignallingLevelNames[] = { + "TRACE", + "DEBUG", + "INFO", + "WARN", + "ERROR", + "FATAL" +}; +/* get hisignaling log level */ +const char *HisignallingLevelNum (HisignallingLogType hisignallingLevel) +{ + if (hisignallingLevel >= HISIGNALLING_LEVEL_MAX) { + return "NULL"; + } else { + return hisignallingLevelNames[hisignallingLevel]; + } +} +#define RIGHT_MOVE_8_BIT (8) +#define RIGHT_MOVE_16_BIT (16) +#define RIGHT_MOVE_24_BIT (24) +/* hisignal Hi3861 message package */ +static hi_u32 HisignallingDataPackage(HisignallingProtocalType *buf, hi_u32 len, hi_u8 *hisignallingDataBuf) +{ + hi_u32 crcCheckSend = 0; + hi_u32 packageLen = 0; + + memcpy_s(hisignallingDataBuf, HISGNALLING_MSG_FRAME_HEADER_LEN, + buf->frameHeader, HISGNALLING_MSG_FRAME_HEADER_LEN); + memcpy_s(&hisignallingDataBuf[HISGNALLING_MSG_FRAME_HEADER_LEN], + len, buf->hisignallingMsgBuf, len); + memcpy_s(&hisignallingDataBuf[HISGNALLING_MSG_FRAME_HEADER_LEN + len], + HISIGNALLING_MSG_HEADER_LEN, &(buf->endOfFrame), HISIGNALLING_MSG_HEADER_LEN); + crcCheckSend = crc32(hisignallingDataBuf, (len + HISIGNALLING_MSG_HEADER_TAIL_LEN)); + hisignallingDataBuf[len + HISIGNALLING_MSG_HEADER_TAIL_LEN] = + (hi_u8) ((crcCheckSend & 0xff000000)>>RIGHT_MOVE_24_BIT); + hisignallingDataBuf[len + HISIGNALLING_MSG_HEADER_TAIL_LEN + 1] = /* 1: addr offset */ + (hi_u8) ((crcCheckSend & 0x00ff0000)>>RIGHT_MOVE_16_BIT); + hisignallingDataBuf[len + HISIGNALLING_MSG_HEADER_TAIL_LEN + 2] = /* 2: addr offset */ + (hi_u8) ((crcCheckSend & 0x0000ff00)>>RIGHT_MOVE_8_BIT); + hisignallingDataBuf[len + HISIGNALLING_MSG_HEADER_TAIL_LEN + 3] = /* 3: addr offset */ + (hi_u8)crcCheckSend; + packageLen = len + HISIGNALLING_MSG_HEADER_TAIL_LEN + HISGNALLING_MSG_CRC32_LEN; + return packageLen; +} + +/* hisignal Hi3861 message recevice */ +HisignallingErrorType HisignallingMsgReceive(hi_u8 *buf, hi_u32 len) +{ + hi_u32 crcCheckReceived = 0; + unsigned char testBuff[7] = {0xaa, 0x55, 0x0, 0x2, 0x0, 0x8, 0xff}; + if (buf == HI_NULL && len > 0) { + HISIGNALLING_LOG_FATAL("received buf is null"); + return HISGNALLING_RET_VAL_MAX; + } + printf("length:%u\n", len); + + /* 校验crc */ + if (len > HISGNALLING_MSG_CRC32_LEN) { + crcCheckReceived = crc32(buf, len - HISGNALLING_MSG_CRC32_LEN); + if (((hi_u8)((crcCheckReceived & 0xff000000)>>RIGHT_MOVE_24_BIT) != buf[len - 4]) && /* 4: addr offset */ + ((hi_u8)((crcCheckReceived & 0x00ff0000)>>RIGHT_MOVE_16_BIT) != buf[len - 3]) && /* 3: addr offset */ + ((hi_u8)((crcCheckReceived & 0x0000ff00)>>RIGHT_MOVE_8_BIT) != buf[len - 2]) && /* 2: addr offset */ + ((hi_u8)crcCheckReceived != buf[len - 1])) { + HISIGNALLING_LOG_ERROR(": crc32 Verification failed!"); + HISIGNALLING_LOG_ERROR(":crc_4=0x%x, crc_3=0x%x, crc_2=0x%x, crc_1=0x%x", + buf[len - 4], buf[len - 3], buf[len - 2], buf[len - 1]); /* 4,3,2,1 addr offset */ + return HISIGNALLING_RET_VAL_ERROR; + } + } + IoTGpioSetOutputVal(LED_TEST_GPIO, 0); + usleep(LED_INTERVAL_TIME_US); + IoTGpioSetOutputVal(LED_TEST_GPIO, 1); + usleep(LED_INTERVAL_TIME_US); + /* 输出回显收到的数据 */ + /*if ((buf[0] == HISIGNALLING_MSG_FRAME_HEADER_1) && (buf[1] == HISIGNALLING_MSG_FRAME_HEADER_2)) { + for (int i = 0; i < len; i++) { + HISIGNALLING_LOG_INFO("0x%x", buf[i]); + } + }*/ + return HISIGNALLING_RET_VAL_CORRECT; +} +/* hisignal Hi3861 message send */ +hi_u32 HisignallingMsgSend(char *buf, hi_u32 dataLen) +{ + HisignallingProtocalType hisignallingMsg = {0}; + hi_u8 hisignallingSendBuf[HISIGNALLING_MSG_BUFF_LEN] = {0}; + hi_u32 hisignallingPackageLen = 0; + hi_u32 writeDataLen = 0; + + hisignallingMsg.frameHeader[0]= HISIGNALLING_MSG_FRAME_HEADER_1; + hisignallingMsg.frameHeader[1]= HISIGNALLING_MSG_FRAME_HEADER_2; + (void)memcpy_s(hisignallingMsg.hisignallingMsgBuf, dataLen, buf, dataLen); + hisignallingMsg.endOfFrame = HISIGNALLING_MSG_FRAME_TAIL; + + hisignallingPackageLen = HisignallingDataPackage(&hisignallingMsg, dataLen, hisignallingSendBuf); + if (!hisignallingPackageLen) { + HISIGNALLING_LOG_ERROR("hisignaling_data_package failed\r\n"); + return HI_ERR_FAILURE; + } + if (*hisignallingSendBuf == NULL) { + HISIGNALLING_LOG_ERROR("hisignal send buf is null!\r\n"); + return HI_ERR_FAILURE; + } + writeDataLen = IoTUartWrite(HI_UART_IDX_1, hisignallingSendBuf, hisignallingPackageLen); + if (!writeDataLen) { + HISIGNALLING_LOG_ERROR("hi_uart_write failed\r\n"); + return HI_ERR_FAILURE; + } + return HI_ERR_SUCCESS; +} + +int SetUartReceiveFlag(void) +{ + return recConfig.g_uartReceiveFlag; +} + +hi_void *HisignallingMsgHandle(char *param) +{ + unsigned char *recBuff = NULL; + int len; + + while (1) { + /*g_sendUartBuff清零*/ + (void)memset_s(g_sendUartBuff, sizeof(g_sendUartBuff) / sizeof(g_sendUartBuff[0]), + 0x0, sizeof(g_sendUartBuff)/sizeof(g_sendUartBuff[0])); + /*GetUartConfig得到data的flag和length*/ + if (GetUartConfig(UART_RECEIVE_FLAG) == HI_TRUE) { + /* 接收数据 */ + HisignallingMsgReceive(GetUartReceiveMsg(), GetUartConfig(UART_RECVIVE_LEN)); + /* 回显数据组包 */ + if (GetUartConfig(UART_RECVIVE_LEN) > (HISGNALLING_MSG_CRC32_LEN + HISIGNALLING_MSG_HEADER_TAIL_LEN)) { + len = GetUartConfig(UART_RECVIVE_LEN); + recBuff = GetUartReceiveMsg(); + for (int i = 0; i < len ; i++ ){ + HISIGNALLING_LOG_INFO("0x%x", recBuff[i]); + } + printf("end\n"); + (void)memcpy_s(g_sendUartBuff, + (GetUartConfig(UART_RECVIVE_LEN) - HISGNALLING_MSG_CRC32_LEN - HISIGNALLING_MSG_HEADER_TAIL_LEN), + &recBuff[HISGNALLING_MSG_FRAME_HEADER_LEN], + (GetUartConfig(UART_RECVIVE_LEN) - HISGNALLING_MSG_CRC32_LEN - HISIGNALLING_MSG_HEADER_TAIL_LEN)); + /* 接收到Hi3516DV300数据后,发送回显 */ + HisignallingMsgSend(g_sendUartBuff, + (GetUartConfig(UART_RECVIVE_LEN) - HISGNALLING_MSG_CRC32_LEN - HISIGNALLING_MSG_HEADER_TAIL_LEN)); + } + (void)SetUartRecvFlag(UART_RECV_FALSE); + ResetUartReceiveMsg(); + } + TaskMsleep(HISGNALLING_FREE_TASK_TIME); + } +} + +hi_u32 HisignalingMsgTask(hi_void) +{ + hi_u32 ret = 0; + IoTGpioInit(LED_TEST_GPIO); + IoTGpioSetDir(LED_TEST_GPIO, IOT_GPIO_DIR_OUT); + osThreadAttr_t hisignallingAttr = {0}; + + hisignallingAttr.stack_size = HISIGNALLING_MSG_TASK_STACK_SIZE; + hisignallingAttr.priority = HISIGNALLING_MSG_TASK_PRIO; + hisignallingAttr.name = (hi_char*)"hisignal msg task"; + + if (osThreadNew((osThreadFunc_t)HisignallingMsgHandle, NULL, &hisignallingAttr) == NULL) { + HISIGNALLING_LOG_ERROR("Failed to create hisignaling msg task\r\n"); + return HI_ERR_FAILURE; + } + return HI_ERR_SUCCESS; +} +//SYS_RUN(HisignalingMsgTask); diff --git a/src/applications/sample/wifi-iot/app/interconnection_client/hisignalling_protocol.h b/src/applications/sample/wifi-iot/app/interconnection_client/hisignalling_protocol.h new file mode 100644 index 0000000..efe68fa --- /dev/null +++ b/src/applications/sample/wifi-iot/app/interconnection_client/hisignalling_protocol.h @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HISIGNALLING_PROTOCOL_H +#define HISIGNALLING_PROTOCOL_H +#include +#include +#include +#include +#include +/** +* @brief : hisignalling Macro definition +*/ +#define HISIGNALLING_MSG_HEADER_LEN (1) +#define HISGNALLING_MSG_FRAME_HEADER_LEN (2) +#define HISIGNALLING_MSG_HEADER_TAIL_LEN (3) +#define HISGNALLING_MSG_CRC32_LEN (4) +#define HISIGNALLING_MSG_PAYLOAD_INDEX (5) +#define HISGNALLING_FREE_TASK_TIME (20) +#define HISIGNALLING_MSG_TASK_PRIO (28) +#define HISIGNALLING_UART_MSG_LEN (32) +#define HISIGNALLING_MSG_BUFF_LEN (512) +#define HISIGNALLING_MSG_TASK_STACK_SIZE (4096) + +/* hisgnalling protocol frame header and tail */ +#define HISIGNALLING_MSG_FRAME_HEADER_1 ((hi_u8)0xAA) +#define HISIGNALLING_MSG_FRAME_HEADER_2 ((hi_u8)0x55) +#define HISIGNALLING_MSG_FRAME_TAIL ((hi_u8)0xFF) +/** +* @brief Adapter plate selection +* 使用时选择打开宏,使用外设扩展板打开#define BOARD_SELECT_IS_EXPANSION_BOARD这个宏 +* 使用Robot板自己定义#define BOARD_SELECT_IS_ROBOT_BOARD这个宏,注释掉#define BOARD_SELECT_IS_EXPANSION_BOARD +**/ + +#define BOARD_SELECT_IS_EXPANSION_BOARD +#ifdef BOARD_SELECT_IS_EXPANSION_BOARD +#define EXPANSION_BOARD +#else +#define ROBOT_BOARD +#endif +/** + * @brief:this defines for the log module, and HISIGNALING_LOG_TRACE/HISIGNALING_LOG_DEBUG... + * will not participate the compile in the release version + * */ +typedef enum { + HISIGNALLING_LEVEL_TRACE = 0, + HISIGNALLING_LEVEL_DEBUG, + HISIGNALLING_LEVEL_INFO, + HISIGNALLING_LEVEL_WARN, + HISIGNALLING_LEVEL_ERROR, + HISIGNALLING_LEVEL_FATAL, + HISIGNALLING_LEVEL_MAX +} HisignallingLogType; +/** + * @brief: use this function to get the hisignalling log level name + * + * @parameter[in]:level, the level to get + * + * @return: the mapped level name + * */ +const char *HisignallingLevelNum (HisignallingLogType hisignallingLevel); +/** + * @brief: this is a weak function ,and you could rewrite one + * + * @param fmt: same use as the fmt for printf + * + * @param unfixed: same use for printf + * + * @return: don't care about it + * + * @attention: and the components should not call this function directly, you'd better + * + * call HISIGNALING_LOG groups + * + * */ +#define HISIGNALLING_PRINT(fmt, ...) \ + do \ + { \ + printf(fmt, ##__VA_ARGS__); \ + } while (0) + +#define HISIGNALLING_LOG(level, fmt, ...) \ + do \ + { \ + HISIGNALLING_PRINT("<%s>, <%s>, <%d> "fmt" \r\n", \ + HisignallingLevelNum((level)), __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + } while (0) + +#define HISIGNALLING_LOG_TRACE(fmt, ...) \ + do \ + { \ + HISIGNALLING_LOG (HISIGNALLING_LEVEL_TRACE, fmt, ##__VA_ARGS__); \ + } while (0) + +#define HISIGNALLING_LOG_DEBUG(fmt, ...) \ + do \ + { \ + HISIGNALLING_LOG (HISIGNALLING_LEVEL_DEBUG, fmt, ##__VA_ARGS__); \ + } while (0) + +#define HISIGNALLING_LOG_INFO(fmt, ...) \ + do \ + { \ + HISIGNALLING_LOG (HISIGNALLING_LEVEL_INFO, fmt, ##__VA_ARGS__); \ + } while (0) + +#define HISIGNALLING_LOG_WARN(fmt, ...) \ + do \ + { \ + HISIGNALLING_LOG (HISIGNALLING_LEVEL_WARN, fmt, ##__VA_ARGS__); \ + } while (0) + +#define HISIGNALLING_LOG_ERROR(fmt, ...) \ + do \ + { \ + HISIGNALLING_LOG (HISIGNALLING_LEVEL_ERROR, fmt, ##__VA_ARGS__); \ + } while (0) + +#define HISIGNALLING_LOG_FATAL(fmt, ...) \ + do \ + { \ + HISIGNALLING_LOG (HISIGNALLING_LEVEL_FATAL, fmt, ##__VA_ARGS__); \ + } while (0) +/** + * @brief: use this hisignalling Transmission protocol frame format + * + * @param frameHeader: Transmission protocol frame header + * + * @param hisignallingMsgBuf: Transmission protocol frame buffer + * + * @param hisigallingMsgLen: Transmission protocol frame buffer len + * + * @param endOfFrame: Transmission protocol frame tail + * + * @param hisignallingCrc32Check: Transmission protocol crc32 check + * + * */ +typedef struct { + hi_u8 frameHeader[HISGNALLING_MSG_FRAME_HEADER_LEN]; + hi_u8 hisignallingMsgBuf[HISIGNALLING_MSG_BUFF_LEN]; + hi_u32 hisigallingMsgLen; + hi_u8 endOfFrame; + hi_u32 hisignallingCrc32Check; +}HisignallingProtocalType; +/** + * @brief: use this hisignalling return type + * + * @param HISIGNALLING_RET_VAL_CORRECT: return type is correct + * + * @param HISIGNALLING_RET_VAL_ERROR: return type is error + * + * @param HISIGNALLING_RET_VAL_ERROR: return type is unknown type + * */ +typedef enum { + HISIGNALLING_RET_VAL_CORRECT = 0, + HISIGNALLING_RET_VAL_ERROR, + HISGNALLING_RET_VAL_MAX +}HisignallingErrorType; +/** + * @brief: use this hisignalling sample:Access peripheral enumeration type + * + * @param MOTOR_GO_FORWARD: peripheral motor go forward + * + * @param MOTOR_GO_BACK: peripheral motor go back + * + * @param STEERING_ENGINE_MOVEMENT/STEERING_ENGINE_AND_MOTOR_MOVEMENT/STEERING_ENGINE_AND_MOTOR_STOP + * the same use for peripheral + * */ +typedef enum { + MOTOR_GO_FORWARD = 0, + MOTOR_GO_BACK, + STEERING_ENGINE_MOVEMENT, + STEERING_ENGINE_AND_MOTOR_MOVEMENT, + STEERING_ENGINE_AND_MOTOR_STOP, + TRASH_CAN_LID_OPEN, + TRASH_CAN_LID_COLSE +}HisignallingDataType; +/** +* @brief:hisignalling protocal Function declaration +**/ +hi_u32 hisignallingMsgTask(hi_void); +/** +* @brief:hisignalling uart message receive API +* @param buf: uart receive buffer +* @param len: uart receive buffer len +*/ +HisignallingErrorType hisignallingMsgReceive(hi_u8 *buf, hi_u32 len); +/** +* @brief:hisignalling uart send API +* @param buf: uart message send buffer +* @param len: uart message send buffer len +*/ +hi_u32 hisignallingMsgSend(hi_void *buf, hi_u32 dataLen); +int SetUartReceiveFlag(void); +#endif /* HISIGNALING_PROTOCOL_H */ \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/interconnection_client/iot_gpio_ex.h b/src/applications/sample/wifi-iot/app/interconnection_client/iot_gpio_ex.h new file mode 100644 index 0000000..f621c98 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/interconnection_client/iot_gpio_ex.h @@ -0,0 +1,394 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file iot_gpio_ex.h + * + * @brief Declares the extended GPIO interface functions. + * + * These functions are used for settings GPIO pulls and driver strength. \n + * + * @since 1.0 + * @version 1.0 + */ + +#ifndef IOT_GPIO_EX_H +#define IOT_GPIO_EX_H + +/** + * @brief Enumerates GPIO pull-up or pull-down settings. + */ +typedef enum { + /** No pull */ + IOT_IO_PULL_NONE, + /** Pull-up */ + IOT_IO_PULL_UP, + /** Pull-down */ + IOT_IO_PULL_DOWN, + /** Maximum value */ + IOT_IO_PULL_MAX, +} IotIoPull; + +/** + * @ingroup iot_io + * + * GPIO pin ID. CNcomment:IO硬件管脚编号。CNend + */ +typedef enum { + IOT_IO_NAME_GPIO_0, /* +#include +#include "ohos_init.h" +#include "cmsis_os2.h" +#include "iot_gpio.h" + +#define LED_INTERVAL_TIME_US 300000 +#define LED_TASK_STACK_SIZE 512 +#define LED_TASK_PRIO 25 +#define LED_TEST_GPIO 9 // for hispark_pegasus + +enum LedState { + LED_ON = 0, + LED_OFF, + LED_SPARK, +}; + +enum LedState g_ledState = LED_SPARK; + +static void *LedTask(const char *arg) +{ + (void)arg; + while (1) { + switch (g_ledState) { + case LED_ON: + IoTGpioSetOutputVal(LED_TEST_GPIO, 1); + usleep(LED_INTERVAL_TIME_US); + break; + case LED_OFF: + IoTGpioSetOutputVal(LED_TEST_GPIO, 0); + usleep(LED_INTERVAL_TIME_US); + break; + case LED_SPARK: + IoTGpioSetOutputVal(LED_TEST_GPIO, 0); + usleep(LED_INTERVAL_TIME_US); + IoTGpioSetOutputVal(LED_TEST_GPIO, 1); + usleep(LED_INTERVAL_TIME_US); + break; + default: + usleep(LED_INTERVAL_TIME_US); + break; + } + } + + return NULL; +} + +static void LedExampleEntry(void) +{ + osThreadAttr_t attr; + + IoTGpioInit(LED_TEST_GPIO); + IoTGpioSetDir(LED_TEST_GPIO, IOT_GPIO_DIR_OUT); + + attr.name = "LedTask"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = LED_TASK_STACK_SIZE; + attr.priority = LED_TASK_PRIO; + + if (osThreadNew((osThreadFunc_t)LedTask, NULL, &attr) == NULL) { + printf("[LedExample] Failed to create LedTask!\n"); + } +} + +SYS_RUN(LedExampleEntry); diff --git a/src/applications/sample/wifi-iot/app/iottencent/BUILD.gn b/src/applications/sample/wifi-iot/app/iottencent/BUILD.gn new file mode 100644 index 0000000..d8e2952 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/iottencent/BUILD.gn @@ -0,0 +1,40 @@ +# Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +static_library("AppDemoIot") { + sources = [ + "app_demo_iot.c", + "cjson_init.c", + "iot_hmac.c", + "iot_log.c", + "iot_main.c", + "iot_profile.c", + "iot_sta.c", + "hal_iot_gpio_ex.c", + ] + + include_dirs = [ + "./", + "//utils/native/lite/include", + "//kernel/liteos_m/kal/cmsis", + "//base/iot_hardware/peripheral/interfaces/kits", + "//device/soc/hisilicon/hi3861v100/sdk_liteos/third_party/lwip_sack/include/lwip", + "//third_party/cJSON", + "//device/soc/hisilicon/hi3861v100/sdk_liteos/third_party/mbedtls/include/mbedtls", + "//foundation/communication/wifi_lite/interfaces/wifiservice", + "//device/soc/hisilicon/hi3861v100/sdk_liteos/third_party/paho.mqtt.c/include/mqtt", + "//device/soc/hisilicon/hi3861v100/sdk_liteos/third_party/libcoap/include/coap2", + ] + + defines = [ "WITH_LWIP" ] +} diff --git a/src/applications/sample/wifi-iot/app/iottencent/README.md b/src/applications/sample/wifi-iot/app/iottencent/README.md new file mode 100644 index 0000000..e863290 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/iottencent/README.md @@ -0,0 +1,226 @@ +# 腾讯云的微信小程序开发及Hi3861板端互联 +## 硬件环境搭建 +- 硬件要求:Hi3861V100核心板、扩展板;硬件搭建如下图所示。 +- [Hi3861V100核心板参考:HiSpark_WiFi_IoT智能开发套件_原理图硬件资料\原理图\HiSpark_WiFi-IoT_Hi3861_CH340G_VER.B.pdf](http://gitee.com/hihope_iot/embedded-race-hisilicon-track-2022/blob/master/%E7%A1%AC%E4%BB%B6%E8%B5%84%E6%96%99/HiSpark_WiFi_IoT%E6%99%BA%E8%83%BD%E5%AE%B6%E5%B1%85%E5%BC%80%E5%8F%91%E5%A5%97%E4%BB%B6_%E5%8E%9F%E7%90%86%E5%9B%BE.rar) +- [扩展板参考:HiSpark_WiFi_IoT智能开发套件_原理图硬件资料\原理图\HiSpark_WiFi-IoT_Hi3861_CH340G_VER.B.pdf](http://gitee.com/hihope_iot/embedded-race-hisilicon-track-2022/blob/master/%E7%A1%AC%E4%BB%B6%E8%B5%84%E6%96%99/HiSpark_WiFi_IoT%E6%99%BA%E8%83%BD%E5%AE%B6%E5%B1%85%E5%BC%80%E5%8F%91%E5%A5%97%E4%BB%B6_%E5%8E%9F%E7%90%86%E5%9B%BE.rar) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/260.jpg) + +## 软件介绍 +- 1.代码目录结构及相应接口功能介绍 +``` +vendor_hisilicon/hispark_pegasus/demo/iottencent_demo +├── app_demo_iot.c #IoSetPull();IoSetFunc();TaskMsleep()。 +├── BUILD.gn # BUILD.gn文件由三部分内容(目标、源文件、头文件路径)构成,开发者根据需要填写,static_library中指定业务模块的编译结果,为静态库文件led_example,开发者根据实际情况完成填写。 +| sources中指定静态库.a所依赖的.c文件及其路径,若路径中包含"//"则表示绝对路径(此处为代码根路径),若不包含"//"则表示相对路径。include_dirs中指定source所需要依赖的.h文件路径。 +├── cjson_init.c # +├── iot_config.h # +├── iot_hmac.c # +├── iot_hmac.h # +├── iot_log.c # +├── iot_log.h # +├── iot_main.c # +├── iot_main.h # +├── iot_profile.c # +├── iot_sta.c # +└── iot_profile.h # +``` +- 2.Mqtt协议第三方软件与腾讯云之间的通信 + +2.1 浏览器搜索腾讯云,在腾讯云界面创建产品和设备,登录腾讯云后搜索“物联网通信”,进入页面后,物联网通信选择立即使用。进入页面后,选择产品列表栏->创建新产品->产品名称:xxx,认证方式:密钥认证,点击确定。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8717.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8720.png) + +2.2 在产品列表栏进入刚刚创建的新产品->设备列表->添加设备->创建新设备:设备名称,设备备注(选填),使用物联网通信提供密钥->保存->复制保存生成的密钥->开始管理设备(可以看到设备相应信息)。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8721.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8722.png) + +2.3 添加设备,同时查看设备相应信息。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F/800.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F/801.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F/802.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F/803.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F/804.png) + +2.4 返回设备列表可以看到设备并未激活,接下来激活设备;下载[MQTT.fx-1.7.1 ](https://www.jensd.de/wordpress/?p=2746),下载完成后打开工具,点击设备图标,进入到设备界面配置ClientID,username,password 等参数。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F/806.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8730.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8731.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8732.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8733.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8734.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8735.png) + +2.5 完成2.3步骤后,可以在腾讯云设备列表里面看到设备状态显示已激活,开始腾讯云与MQTT工具之间的通信。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8736.png) + +2.6 MQTT.fx-1.7.1工具订阅腾讯云的topic,腾讯云下发指令。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8737.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8738.png) + +2.7 在腾讯云网页端点击“在线调试”。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8739.png) + +2.8 可以在MQTT.fx-1.7.1工具中看到腾讯云网页端发过来的消息。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8740.png) + +2.9 MQTT.fx-1.7.1工具发布腾讯云到的topic,在设备影子中查看发布到腾讯云的消息。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8741.png) + +``` +{ + "type":"update", + "state":{ + "reported":{ + "light":1, + "motor":1, + "temperature":25, + "humidity":60, + "light_intensity":50 + } + }, +"version":0, +"clientToken":"clientToken" +} +``` + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8742.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8743.png) + +- 3.微信小程序开发环境搭建及与腾讯云之间通信 + +3.1 注册申请小程序账号:https://mp.weixin.qq.com/wxopen/waregister?action=step1。 + +3.2 登录小程序后(选择IOT字样的账号),在“开发”->“开发设置”页面可以看到小程序的AppID,如下图所示,详情请查看微信官方文档: +https://developers.weixin.qq.com/miniprogram/dev/framework/quickstart/getstart.html#%E7%94%B3%E8%AF%B7%E5%B8%90%E5%8F%B7。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8744.png) + +3.3 开发者工具下载与安装:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8745.png) + +3.4 下载安装完成后,打开微信开发工具,导入提供的微信小程序软件包[获取微信小程序代码](https://gitee.com/leo593362220/Hi3861OpenHarmony)。并填入自己的APPID,后端服务选择微信云开发。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%87102.jpg) + +3.5 使用微信开发者工具打开工程后需要修改project.config.json文件中appid,projectname修改成自己的。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8747.png) + +3.6 获取secretId和secretKey,在腾讯云->产品列表->搜索栏搜索访问密钥->访问密钥->继续使用->可以看到secretId和secretKey,复制在xxxx.txt文件,后面需要。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8749.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8750.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8751.png) + +3.7 环境ID配置并获取环境ID,复制在xxx.txt文件,后面需要。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8752.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8753.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8754.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8755.png)![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8747.png) + +3.8 需要修改app.js文件中productId(腾讯云上设备信息上产品ID),deviceName(腾讯云上设备信息上产品名称),secretId和secretKey(3.6步骤获取到的secretId和secretKey),env(3.7步骤获取到的环境ID)。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8748.png) + +3.9 配置当前云环境 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8756.png) + +注意:第一次部署环境,图片里面的上传并部署会变成新建并部署。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8757.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/228.jpg) + +等待大概1分钟左右,直到出现上传云函数成功:(注意:上传并部署由于网络问题可能会失败,看到上传云函数等字样代表上传部署成功,这里以iothub-publish为例)。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8758.png) + +3.10 环境部署完成后,点击编译,然后真机调试会出现如下界面,上面两个都要出现 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8761.png) + +- 4.Hi3861V100与微信小程序之间通信 + - 将源码./vendor/hisilicon/hispark_pegasus/demo目录下的iottencent_demo整个文件夹及内容复制到源码./applications/sample/wifi-iot/app/下。 + ``` + . + └── applications + └── sample + └── wifi-iot + └── app + └──iottencent_demo + └── 代码 + ``` + + - 配置源码./applications/sample/wifi-iot/app/iottencent_demo/iot_config.h中CONFIG_AP_SSID,CONFIG_AP_PWD为WiFi名称和WiFi密码。CONFIG_USER_ID为腾讯云设备信息上MQTT Username,CONFIG_USER_PWD为腾讯云上设备的MQTT Password,CN_CLIENTID为腾讯云上clientID。 + ``` + #define CONFIG_AP_SSID "XXXXXXXX" // WIFI SSID + #define CONFIG_AP_PWD "XXXXX" // WIFI PWD + /* Tencent iot Cloud user ID , password */ + #define CONFIG_USER_ID "XXXXXXXXXXXXX" + #define CONFIG_USER_PWD "XXXXXXXXXXXX" + #define CN_CLIENTID "xxxxxxxx" // Tencent cloud ClientID format: Product ID + device name + ``` + + - 更改源码./applications/sample/wifi-iot/app/iottencent_demo/iot_main.c文件中搜索g_defaultSubscribeTopic字段,将腾讯云上的Topic列表中自定义Topic添加到字段里。 + ``` + static const char *g_defaultSubscribeTopic[] = { + "76VQ4ZASTL/mqtt/data", + "76VQ4ZASTL/mqtt/event", + "76VQ4ZASTL/mqtt/control", + }; + ``` + - 更改源码./applications/sample/wifi-iot/app/iottencent_demo/iot_profile.c文件中搜索CN_PROFILE_TOPICFMT_TOPIC字段,将腾讯云上的产品名,设备名称添加到字段里。 + ``` + #define CN_PROFILE_TOPICFMT_TOPIC "$shadow/operation/xxxxx/XXXX" //xxxx为产品名和设备名称,如:76VQ4ZASTL + ``` + + - 修改源码./applications/sample/wifi-iot/app/BUILD.gn文件,在features字段中增加索引,使目标模块参与编译。features字段指定业务模块的路径和目标,features字段配置如下。 + ``` + import("//build/lite/config/component/lite_component.gni") + + lite_component("app") { + features = [ + "iottencent_demo:appDemoIot", + ] + } + ``` + + - 工程相关配置完成后,然后编译。 +- 5.烧录 + - 编译成功后,点击DevEco Home->配置工程->hi3861->upload_port->选择对应串口端口号->选择upload_protocol->选择hiburn-serial->点击save保存,在保存成功后点击upload进行烧录,出现connecting, please reset device..字样复位开发板等待烧录完成。烧录成功后,再次点击Hi3861核心板上的“RST”复位键,此时开发板的系统会运行起来。 + - 注意:一定要断开MQTT工具的连接。 + - 微信小程序上选择已连接Wifi,跳过配网->云端互联->看到设备互联界面->点击刷新按钮,运行结果出现如下图代表成功,点击照明,主板灯会亮。 + + ![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8762.png) \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/iottencent/app_demo_iot.c b/src/applications/sample/wifi-iot/app/iottencent/app_demo_iot.c new file mode 100644 index 0000000..4c42976 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/iottencent/app_demo_iot.c @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include "iot_config.h" +#include "iot_log.h" +#include "iot_main.h" +#include "iot_profile.h" +#include "ohos_init.h" +#include "cmsis_os2.h" +#include "iot_gpio.h" + + +/* attribute initiative to report */ +#define TAKE_THE_INITIATIVE_TO_REPORT +#define TWO_SECOND (2000) +/* oc request id */ +#define CN_COMMADN_INDEX "commands/request_id=" +#define WECHAT_SUBSCRIBE_control "chosen_slot" +#define WECHAT_SUBSCRIBE_channel1 "slot_1" +#define WECHAT_SUBSCRIBE_channel2 "slot_2" +#define WECHAT_SUBSCRIBE_channel3 "slot_3" +#define WECHAT_SUBSCRIBE_channel4 "slot_4" +#define topic_data "YT32IOSCAL/Hi38611_mqtt/data" +#define topic_event "YT32IOSCAL/Hi38611_mqtt/event" +#define topic_control "YT32IOSCAL/Hi38611_mqtt/control" + +int g_ligthStatus = -1; +int slot1 = 20,slot2 = 20, slot3 = 20, slot4 = 20; +typedef void (*FnMsgCallBack)(hi_gpio_value val); + +typedef struct FunctionCallback { + hi_bool stop; + hi_u32 conLost; + hi_u32 queueID; + hi_u32 iotTaskID; + FnMsgCallBack msgCallBack; +}FunctionCallback; +FunctionCallback g_functinoCallback; + +/* CPU Sleep time Set */ +unsigned int TaskMsleep(unsigned int ms) +{ + if (ms <= 0) { + return HI_ERR_FAILURE; + } + return hi_sleep((hi_u32)ms); +} + +static void DeviceConfigInit(hi_gpio_value val) +{ + hi_io_set_func(HI_IO_NAME_GPIO_9, HI_IO_FUNC_GPIO_9_GPIO); + hi_gpio_set_dir(HI_GPIO_IDX_9, HI_GPIO_DIR_OUT); + hi_gpio_set_ouput_val(HI_GPIO_IDX_9, val); +} + +static void engine_control(unsigned int IO){ + IoTGpioInit(IO); + IoSetFunc(IO, 0); + IoTGpioSetDir(IO, IOT_GPIO_DIR_OUT); + IoTGpioSetOutputVal(IO, IOT_GPIO_VALUE1); + IOT_LOG_DEBUG("Engine at GPIO:%u started!", IO); + hi_udelay(20000); + IoTGpioSetOutputVal(IO, IOT_GPIO_VALUE0); + IOT_LOG_DEBUG("Engine at GPIO:%u stopped!", IO); +} + +static void engine_start(unsigned int IO){ + IoSetFunc(IO, 0); + IoTGpioSetDir(IO, IOT_GPIO_DIR_OUT); + IoTGpioSetOutputVal(IO, IOT_GPIO_VALUE1); + IOT_LOG_DEBUG("Engine at GPIO:%u started!", IO); +} + +static void engine_stop(unsigned int IO){ + IoSetFunc(IO, 0); + IoTGpioSetDir(IO, IOT_GPIO_DIR_OUT); + IoTGpioSetOutputVal(IO, IOT_GPIO_VALUE0); + IOT_LOG_DEBUG("Engine at GPIO:%u stopped!", IO); +} + +static void engine_reinit(unsigned int IO){ + IoTGpioInit(IO); + IoSetFunc(IO, 0); + IoTGpioSetDir(IO, IOT_GPIO_DIR_OUT); + IoTGpioSetOutputVal(IO, IOT_GPIO_VALUE0); + IOT_LOG_DEBUG("Engine at GPIO:%u initialized!", IO); +} + +static void all_engine_reinit(){ + engine_reinit(6); + engine_reinit(7); + engine_reinit(9); + engine_reinit(10); + IOT_LOG_DEBUG("All engines initialized!"); +} + +static int DeviceMsgCallback(FnMsgCallBack msgCallBack) +{ + g_functinoCallback.msgCallBack = msgCallBack; + return 0; +} + +static void wechatControlDeviceMsg(hi_gpio_value val) +{ + DeviceConfigInit(val); +} + + +// < this is the callback function, set to the mqtt, and if any messages come, it will be called +// < The payload here is the json string +static void DemoMsgRcvCallBack(int qos, const char *topic, const char *payload)/*定义3861接收到json文件后的操作*/ +{ + IOT_LOG_DEBUG("RCVMSG:QOS:%d TOPIC:%s PAYLOAD:%s\r\n", qos, topic, payload); + int IO = 0; + /* 云端下发命令后,板端的操作处理 */ + //if (strcmp(topic, topic_data)==0){ + + if (strstr(payload, WECHAT_SUBSCRIBE_control) != NULL) { + all_engine_reinit(); + if (strstr(payload, WECHAT_SUBSCRIBE_channel1) != NULL) { + engine_start(6); + hi_udelay(4000000); + engine_stop(6); + slot1--; + wechatControlDeviceMsg(HI_GPIO_VALUE1); + } + else if (strstr(payload, WECHAT_SUBSCRIBE_channel2) != NULL) { + engine_start(7); + hi_udelay(4000000); + engine_stop(7); + slot2--; + wechatControlDeviceMsg(HI_GPIO_VALUE1); + } + else if (strstr(payload, WECHAT_SUBSCRIBE_channel3) != NULL) { + engine_start(2); + hi_udelay(4000000); + engine_stop(2); + slot3--; + wechatControlDeviceMsg(HI_GPIO_VALUE1); + } + else if (strstr(payload, WECHAT_SUBSCRIBE_channel4) != NULL) { + engine_start(10); + hi_udelay(4000000); + engine_stop(10); + slot4--; + wechatControlDeviceMsg(HI_GPIO_VALUE1); + } + + } + + //} + return HI_NULL; +} + +/* publish sample */ +hi_void IotPublishSample(int slot1, int slot2, int slot3, int slot4) +{ + /* reported attribute */ + WeChatProfile weChatProfile = { + .subscribeType = "type", + .status.subState = "state", + .status.subReport = "reported", + .status.reportVersion = "version", + .status.Token = "clientToken", + /* report motor */ + .reportAction.subDeviceActionMotor = "slot_1", + .reportAction.motorActionStatus = slot1, /* 0 : motor off */ + /* report temperature */ + .reportAction.subDeviceActionTemperature = "slot_2", + .reportAction.temperatureData = slot2, /* 30 :temperature data */ + /* report humidity */ + .reportAction.subDeviceActionHumidity = "slot_3", + .reportAction.humidityActionData = slot3, /* humidity data */ + /* report light_intensity */ + .reportAction.subDeviceActionLightIntensity = "slot_4", + .reportAction.lightIntensityActionData = slot4, /* 60 : light_intensity */ + }; + + /* report light */ + if (g_ligthStatus == HI_TRUE) { + weChatProfile.reportAction.subDeviceActionLight = "light"; + weChatProfile.reportAction.lightActionStatus = 1; /* 1: light on */ + } else if (g_ligthStatus == HI_FALSE) { + weChatProfile.reportAction.subDeviceActionLight = "light"; + weChatProfile.reportAction.lightActionStatus = 0; /* 0: light off */ + } else { + weChatProfile.reportAction.subDeviceActionLight = "light"; + weChatProfile.reportAction.lightActionStatus = 0; /* 0: light off */ + } + /* profile report */ + IoTProfilePropertyReport(CONFIG_USER_ID, &weChatProfile); +} + +// < this is the demo main task entry,here we will set the wifi/cjson/mqtt ready and +// < wait if any work to do in the while +static hi_void *DemoEntry(const char *arg) +{ + + + WifiStaReadyWait(); + cJsonInit(); + IoTMain(); + /* 云端下发回调 */ + IoTSetMsgCallback(DemoMsgRcvCallBack); + + /* 主动上报 */ +#ifdef TAKE_THE_INITIATIVE_TO_REPORT + while (1) { + /* 用户可以在这调用发布函数进行发布,需要用户自己写调用函数 */ + IotPublishSample(slot1,slot2,slot3,slot4); // 发布例程 +#endif + TaskMsleep(TWO_SECOND); + } + return NULL; +} + +// < This is the demo entry, we create a task here, +// and all the works has been done in the demo_entry +#define CN_IOT_TASK_STACKSIZE 0x1000 +#define CN_IOT_TASK_PRIOR 25 +#define CN_IOT_TASK_NAME "IOTDEMO" + +static void AppDemoIot(void) +{ + osThreadAttr_t attr; + IoTWatchDogDisable(); + + attr.name = "IOTDEMO"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = CN_IOT_TASK_STACKSIZE; + attr.priority = CN_IOT_TASK_PRIOR; + + if (osThreadNew((osThreadFunc_t)DemoEntry, NULL, &attr) == NULL) { + printf("[mqtt] Falied to create IOTDEMO!\n"); + } +} + +SYS_RUN(AppDemoIot); \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/iottencent/cjson_init.c b/src/applications/sample/wifi-iot/app/iottencent/cjson_init.c new file mode 100644 index 0000000..6ad1e78 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/iottencent/cjson_init.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static void *cJsonMalloc(size_t sz) +{ + return hi_malloc(0, sz); +} + +static void cJsonFree(const char *p) +{ + hi_free(0, p); +} + +void cJsonInit(void) +{ + cJSON_Hooks hooks; + hooks.malloc_fn = cJsonMalloc; + hooks.free_fn = cJsonFree; + cJSON_InitHooks(&hooks); + + return; +} \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/iottencent/hal_iot_gpio_ex.c b/src/applications/sample/wifi-iot/app/iottencent/hal_iot_gpio_ex.c new file mode 100644 index 0000000..68121d9 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/iottencent/hal_iot_gpio_ex.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "iot_errno.h" +#include "iot_gpio_ex.h" +#include "hi_gpio.h" +#include "hi_io.h" +#include "hi_task.h" +#include "hi_types_base.h" + + +unsigned int IoSetPull(unsigned int id, IotIoPull val) +{ + if (id >= HI_GPIO_IDX_MAX) { + return IOT_FAILURE; + } + return hi_io_set_pull((hi_io_name)id, (hi_io_pull)val); +} + +unsigned int IoSetFunc(unsigned int id, unsigned char val) +{ + if (id >= HI_GPIO_IDX_MAX) { + return IOT_FAILURE; + } + return hi_io_set_func((hi_io_name)id, val); +} + +/*unsigned int TaskMsleep(unsigned int ms) +{ + if (ms <= 0) { + return IOT_FAILURE; + } + return hi_sleep((hi_u32)ms); +}*/ \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/iottencent/iot_config.h b/src/applications/sample/wifi-iot/app/iottencent/iot_config.h new file mode 100644 index 0000000..d548570 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/iottencent/iot_config.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IOT_CONFIG_H +#define IOT_CONFIG_H + +// +#include +#include +#include +#include "md.h" +#include "md_internal.h" + +#define CN_HMAC256_LEN_MAX (65) +#define CN_HMAC256_LEN 32 +#define RIGHT_MOVE_BIT_4 (4) +#define NUMBER_9 (9) +#define DECIMAL_BASE (10) +#define STRING_LEN_TIMES (2) +#define LEN_TIMES (2) +#define OFFSET (1) +// make a byte to 2 ascii hex +static int byte2hexstr(unsigned char *bufin, int len, char *bufout) +{ + int i = 0; + unsigned char tmp_l = 0x0; + unsigned char tmp_h = 0; + if ((bufin == NULL)||(len <= 0)||(bufout == NULL)) { + return -1; + } + for (i = 0; i < len; i++) { + tmp_h = (bufin[i] >> RIGHT_MOVE_BIT_4) & 0X0F; + tmp_l = bufin[i] & 0x0F; + bufout[STRING_LEN_TIMES * i] = (tmp_h > NUMBER_9) ? + (tmp_h - DECIMAL_BASE + 'a'):(tmp_h +'0'); + bufout[STRING_LEN_TIMES * i + OFFSET] = (tmp_l > NUMBER_9) ? + (tmp_l - DECIMAL_BASE + 'a'):(tmp_l +'0'); + } + bufout[STRING_LEN_TIMES * len] = '\0'; + + return 0; +} + +int HmacGeneratePwd(const unsigned char *content, int contentLen, const unsigned char *key, + int keyLen, unsigned char *buf) +{ + int ret = -1; + mbedtls_md_context_t mbedtls_md_ctx; + const mbedtls_md_info_t *md_info; + unsigned char hash[CN_HMAC256_LEN]; + + if ((key == NULL)||(content == NULL)||(buf == NULL)|| + (keyLen == 0)||(contentLen == 0)|| + (CN_HMAC256_LEN_MAX < (CN_HMAC256_LEN * LEN_TIMES + OFFSET))) { + return ret; + } + + md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); + if ((md_info == NULL)||((size_t)md_info->size > CN_HMAC256_LEN)) { + return ret; + } + + mbedtls_md_init(&mbedtls_md_ctx); + ret = mbedtls_md_setup(&mbedtls_md_ctx, md_info, 1); + if (ret != 0) { + mbedtls_md_free(&mbedtls_md_ctx); + return ret; + } + + (void)mbedtls_md_hmac_starts(&mbedtls_md_ctx, key, keyLen); + (void)mbedtls_md_hmac_update(&mbedtls_md_ctx, content, contentLen); + (void)mbedtls_md_hmac_finish(&mbedtls_md_ctx, hash); + + // + +static EnIotLogLevel gIoTLogLevel = EN_IOT_LOG_LEVEL_TRACE; +static const char *gIoTLogLevelNames[] = { + "TRACE", + "DEBUG", + "INFO ", + "WARN ", + "ERROR", + "FATAL" +}; + +int IoTLogLevelSet(EnIotLogLevel level) +{ + int ret = -1; + if (level < EN_IOT_LOG_LEVEL_MAX) { + gIoTLogLevel = level; + ret = 0; + } + return ret; +} + +EnIotLogLevel IoTLogLevelGet(void) +{ + return gIoTLogLevel; +} + +const char *IoTLogLevelGetName(EnIotLogLevel logLevel) +{ + if (logLevel >= EN_IOT_LOG_LEVEL_MAX) { + return "NULL "; + } else { + return gIoTLogLevelNames[logLevel]; + } +} diff --git a/src/applications/sample/wifi-iot/app/iottencent/iot_log.h b/src/applications/sample/wifi-iot/app/iottencent/iot_log.h new file mode 100644 index 0000000..a0532b7 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/iottencent/iot_log.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IOT_LOG_H_ +#define IOT_LOG_H_ +/** + * @brief:this defines for the log module, + * and IOT_LOG_TRACE/IOT_LOG_DEBUG will not participate the compile in the release version + * + * + * */ +typedef enum { + // < this is used as the trace function,like the function enter and function out + EN_IOT_LOG_LEVEL_TRACE = 0, + // < this is used as the debug, you could add any debug as you wish + EN_IOT_LOG_LEVEL_DEBUG, + // < which means it is import message, and you should known + EN_IOT_LOG_LEVEL_INFO, + // < this is used as the executed result,which means the status is not what we expected + EN_IOT_LOG_LEVEL_WARN, + // < this is used as the executed result,which means the status is not what we expected + EN_IOT_LOG_LEVEL_ERROR, + // < this is used as the parameters input for the api interface, which could not accepted + EN_IOT_LOG_LEVEL_FATAL, + EN_IOT_LOG_LEVEL_MAX, +}EnIotLogLevel; +/** + * @brief:use this function to get the current output log + * + * @return: the current output mask log, defined by en_iot_log_level_t + * */ +EnIotLogLevel IoTLogLevelGet(void); +/** + * @brief: use this function to get the debug level name + * + * @parameter[in]:level, the level to get + * + * @return: the mapped level name + * */ +const char *IoTLogLevelGetName(EnIotLogLevel logLevel); +/** + * @brief:use this function to set the current output log + * + * @parameter[in] level:defined by en_iot_log_level_t + * + * @return: 0 success while -1 failed + * */ +int IoTLogLevelSet(EnIotLogLevel level); +/* + * @brief: this is a weak function ,and you could rewrite one + * + * @param fmt: same use as the fmt for printf + * + * @param unfixed: same use for printf + * + * @return: don't care about it + * + * @attention: and the components should not call this function directly, you'd better + * + * call IOT_LOG groups + * + * */ +#ifndef IOT_PRINT +#define IOT_PRINT(fmt, ...) \ + do \ + { \ + printf(fmt, ##__VA_ARGS__); \ + }while (0) +#endif + +#ifdef CONFIG_LINKLOG_ENABLE + +#define IOT_LOG(level, fmt, ...) \ + do \ + { \ + IOT_PRINT("[%s][%s] " fmt "\r\n", \ + IoTLogLevelGetName((level)), __FUNCTION__, ##__VA_ARGS__); \ + } while (0) + +#define IOT_LOG_TRACE(fmt, ...) \ + do \ + { \ + if ((EN_IOT_LOG_LEVEL_TRACE) >= IoTLogLevelGet()) \ + { \ + IOT_LOG(EN_IOT_LOG_LEVEL_TRACE, fmt, ##__VA_ARGS__); \ + } \ + } while (0) + +#define IOT_LOG_DEBUG(fmt, ...) \ + do \ + { \ + if ((EN_IOT_LOG_LEVEL_DEBUG) >= IoTLogLevelGet()) \ + { \ + IOT_LOG(EN_IOT_LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__); \ + } \ + } while (0) + +#else +#define IOT_LOG(level, fmt, ...) +#define IOT_LOG_TRACE(fmt, ...) +#define IOT_LOG_DEBUG(fmt, ...) +#endif + +#define IOT_LOG_TRACE(fmt, ...) IOT_LOG(EN_IOT_LOG_LEVEL_TRACE, fmt, ##__VA_ARGS__) +#define IOT_LOG_INFO(fmt, ...) IOT_LOG(EN_IOT_LOG_LEVEL_INFO, fmt, ##__VA_ARGS__) +#define IOT_LOG_WARN(fmt, ...) IOT_LOG(EN_IOT_LOG_LEVEL_WARN, fmt, ##__VA_ARGS__) +#define IOT_LOG_ERROR(fmt, ...) IOT_LOG(EN_IOT_LOG_LEVEL_ERROR, fmt, ##__VA_ARGS__) +#define IOT_LOG_FATAL(fmt, ...) IOT_LOG(EN_IOT_LOG_LEVEL_FATAL, fmt, ##__VA_ARGS__) + +#endif /* IOT_LOG_H_ */ \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/iottencent/iot_main.c b/src/applications/sample/wifi-iot/app/iottencent/iot_main.c new file mode 100644 index 0000000..31fc22f --- /dev/null +++ b/src/applications/sample/wifi-iot/app/iottencent/iot_main.c @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * STEPS: + * 1, CONNECT TO THE IOT SERVER + * 2, SUBSCRIBE THE DEFAULT TOPIC + * 3, WAIT FOR ANY MESSAGE COMES OR ANY MESSAGE TO SEND +*/ + +#include +#include +#include +#include +#include +#include +#include "iot_config.h" +#include "iot_log.h" +#include "iot_hmac.h" +#include "ohos_init.h" +#include "cmsis_os2.h" +#include "iot_watchdog.h" +#include "MQTTClient.h" +#include "iot_errno.h" +#include "iot_main.h" +#include "iot_gpio.h" + + +// < this is the configuration head +#define CN_IOT_SERVER "tcp://106.55.124.154:1883" // Tencent iot cloud address +#define CONFIG_COMMAND_TIMEOUT 10000L +#define CN_KEEPALIVE_TIME 50 +#define CN_CLEANSESSION 1 +#define CN_HMAC_PWD_LEN 65 // < SHA256 IS 32 BYTES AND END APPEND '\0' +#define CN_EVENT_TIME "1970000100" +#define CN_CLIENTID_FMT "%s_0_0_%s" // < This is the cient ID format, deviceID_0_0_TIME +#define CN_QUEUE_WAITTIMEOUT 1000 +#define CN_QUEUE_MSGNUM 16 +#define CN_QUEUE_MSGSIZE (sizeof(hi_pvoid)) + +#define CN_TASK_PRIOR 28 +#define CN_TASK_STACKSIZE 0X2000 +#define CN_TASK_NAME "IoTMain" + +typedef enum { + EN_IOT_MSG_PUBLISH = 0, + EN_IOT_MSG_RECV, +}EnIotMsg; + +typedef struct { + EnIotMsg type; + int qos; + const char *topic; + const char *payload; +}IoTMsg_t; + +typedef struct { + bool stop; + unsigned int conLost; + unsigned int queueID; + unsigned int iotTaskID; + fnMsgCallBack msgCallBack; + MQTTClient_deliveryToken tocken; +}IotAppCb_t; +static IotAppCb_t gIoTAppCb; + +static const char *gDefaultSubscribeTopic[] = { + /* Tencent iot cloud topic */ + "YT32IOSCAL/Hi38611_mqtt/data", + "YT32IOSCAL/Hi38611_mqtt/event", + "YT32IOSCAL/Hi38611_mqtt/control", +}; + +#define CN_TOPIC_SUBSCRIBE_NUM (sizeof(gDefaultSubscribeTopic) / sizeof(const char *)) +static int MsgRcvCallBack(char *context, char *topic, int topicLen, MQTTClient_message *message) +{ + IoTMsg_t *msg; + char *buf; + unsigned int bufSize; + int topiLen = topicLen; + + if (topiLen == 0) { + topiLen = strlen(topic); + } + bufSize = topiLen + 1 + message->payloadlen + 1 + sizeof(IoTMsg_t); + buf = hi_malloc(0, bufSize); + if (buf != NULL) { + msg = (IoTMsg_t *)buf; + buf += sizeof(IoTMsg_t); + bufSize -= sizeof(IoTMsg_t); + msg->qos = message->qos; + msg->type = EN_IOT_MSG_RECV; + (void)memcpy_s(buf, bufSize, topic, topiLen); + buf[topiLen] = '\0'; + msg->topic = buf; + buf += topiLen + 1; + bufSize -= (topiLen + 1); + (void)memcpy_s(buf, bufSize, message->payload, message->payloadlen); + buf[message->payloadlen] = '\0'; + msg->payload = buf; + IOT_LOG_DEBUG("RCVMSG:QOS:%d TOPIC:%s PAYLOAD:%s\r\n", msg->qos, msg->topic, msg->payload); + if (IOT_SUCCESS != osMessageQueuePut(gIoTAppCb.queueID, &msg, 0, CN_QUEUE_WAITTIMEOUT)) { + IOT_LOG_ERROR("Wrie queue failed\r\n"); + hi_free(0, msg); + } + } + + MQTTClient_freeMessage(&message); + MQTTClient_free(topic); + return 1; +} + +// < when the connect lost and this callback will be called +static void ConnLostCallBack(char *context, char *cause) +{ + IOT_LOG_DEBUG("Connection lost:caused by:%s\r\n", cause == NULL? "Unknown" : cause); + return; +} + +static int MqttProcessQueueMsg(MQTTClient client, IoTMsg_t *msg, MQTTClient_message pubMsg) +{ + int ret = 0; + + switch (msg->type) { + case EN_IOT_MSG_PUBLISH: + pubMsg.payload = (void *)msg->payload; + pubMsg.payloadlen = (int)strlen(msg->payload); + pubMsg.qos = msg->qos; + pubMsg.retained = 0; + ret = MQTTClient_publishMessage(client, msg->topic, &pubMsg, &gIoTAppCb.tocken); + if (ret != MQTTCLIENT_SUCCESS) { + IOT_LOG_ERROR("MSGSEND:failed\r\n"); + } + IOT_LOG_DEBUG("MSGSEND:SUCCESS\r\n"); + gIoTAppCb.tocken++; + break; + case EN_IOT_MSG_RECV: + if (gIoTAppCb.msgCallBack != NULL) { + gIoTAppCb.msgCallBack(msg->qos, msg->topic, msg->payload); /*接受信息并进行相应的操作,函数体在IoTSetMsgCallback中定义*/ + } + break; + default: + break; + } +} + +// qos, msg->topic, msg->payload); + MqttProcessQueueMsg(client, msg, pubmsg); + hi_free(0, msg); + } + timeout = 0; // < continous to deal the message without wait here + } while (ret == IOT_SUCCESS); + + return 0; +} + +int MqttDestory(int ret, MQTTClient client) +{ + if (ret != MQTTCLIENT_SUCCESS) { + MQTTClient_destroy(&client); + return -1; + } + return MQTTCLIENT_SUCCESS; +} + +static void MainEntryProcess(void) +{ + int rc = 0, subQos[CN_TOPIC_SUBSCRIBE_NUM] = {1}; + + MQTTClient client = NULL; + MQTTClient_connectOptions connOpts = MQTTClient_connectOptions_initializer; + char *clientID = CN_CLIENTID; + char *userID = CONFIG_USER_ID; + char *userPwd = hi_malloc(0, CN_HMAC_PWD_LEN); + if (userPwd == NULL) { + hi_free(0, clientID); + return; + } + userPwd = CONFIG_USER_PWD; + connOpts.keepAliveInterval = CN_KEEPALIVE_TIME; + connOpts.cleansession = CN_CLEANSESSION; + connOpts.username = userID; + connOpts.password = userPwd; + connOpts.MQTTVersion = MQTTVERSION_3_1_1; + IOT_LOG_DEBUG("CLIENTID:%s USERID:%s USERPWD:%s, IOTSERVER:%s\r\n", + clientID, userID, userPwd==NULL?"NULL" : userPwd, CN_IOT_SERVER); + rc = MQTTClient_create(&client, CN_IOT_SERVER, clientID, MQTTCLIENT_PERSISTENCE_NONE, NULL); + if (rc != MQTTCLIENT_SUCCESS) { + if (userPwd != NULL) { + hi_free(0, userPwd); + } + return; + } + rc = MQTTClient_setCallbacks(client, NULL, ConnLostCallBack, MsgRcvCallBack, NULL); + if (MqttDestory(rc, client) != MQTTCLIENT_SUCCESS) { + return; + } + rc = MQTTClient_connect(client, &connOpts); + if (MqttDestory(rc, client) != MQTTCLIENT_SUCCESS) { + return; + } + for (int i = 0; i < CN_TOPIC_SUBSCRIBE_NUM; i++) { + rc = MQTTClient_subscribeMany(client, CN_TOPIC_SUBSCRIBE_NUM, + (char *const *)gDefaultSubscribeTopic, (int *)&subQos[0]); + if (MqttDestory(rc, client) != MQTTCLIENT_SUCCESS) { + return; + } + } + IOT_LOG_DEBUG ("Connect success and Subscribe success\r\n"); + while (MQTTClient_isConnected(client)) { + ProcessQueueMsg(client); // < do the job here + MQTTClient_yield(); // < make the keepalive done + } + MQTTClient_disconnect(client, CONFIG_COMMAND_TIMEOUT); + return; +} + +/* MQTT processing entry */ +static hi_void *MainEntry(char *arg) +{ + (void)arg; + while (gIoTAppCb.stop == false) { + MainEntryProcess(); + IOT_LOG_DEBUG("The connection lost and we will try another connect\r\n"); + hi_sleep(1000); /* 1000: cpu sleep 1000ms */ + } + return NULL; +} +static void engine_init(unsigned int IO){ + IoTGpioInit(IO); + IoSetFunc(IO, 0); + IoTGpioSetDir(IO, IOT_GPIO_DIR_OUT); + IoTGpioSetOutputVal(IO, IOT_GPIO_VALUE0); + IOT_LOG_DEBUG("GPIO:%u initialized!", IO); +} +int IoTMain(void) +{ + unsigned int ret = 0; + hi_task_attr attr = {0}; + engine_init(6); + engine_init(7); + engine_init(9); + engine_init(10); + gIoTAppCb.queueID = osMessageQueueNew(CN_QUEUE_MSGNUM, CN_QUEUE_MSGSIZE, NULL); + if (ret != IOT_SUCCESS) { + IOT_LOG_ERROR("Create the msg queue Failed\r\n"); + } + + attr.stack_size = CN_TASK_STACKSIZE; + attr.task_prio = CN_TASK_PRIOR; + attr.task_name = CN_TASK_NAME; + ret = hi_task_create(&gIoTAppCb.iotTaskID, &attr, MainEntry, NULL); + if (ret != IOT_SUCCESS) { + IOT_LOG_ERROR("Create the Main Entry Failed\r\n"); + } + + return 0; +} + +int IoTSetMsgCallback(fnMsgCallBack msgCallback) +{ + gIoTAppCb.msgCallBack = msgCallback;/*赋予函数*/ + return 0; +} + +int IotSendMsg(int qos, const char *topic, const char *payload) +{ + int rc = -1; + IoTMsg_t *msg; + char *buf; + unsigned int bufSize; + + bufSize = strlen(topic) + 1 +strlen(payload) + 1 + sizeof(IoTMsg_t); + buf = hi_malloc(0, bufSize); + if (buf != NULL) { + msg = (IoTMsg_t *)buf; + buf += sizeof(IoTMsg_t); + bufSize -= sizeof(IoTMsg_t); + msg->qos = qos; + msg->type = EN_IOT_MSG_PUBLISH; + (void)memcpy_s(buf, bufSize, topic, strlen(topic)); + buf[strlen(topic)] = '\0'; + msg->topic = buf; + buf += strlen(topic) + 1; + bufSize -= (strlen(topic) + 1); + (void)memcpy_s(buf, bufSize, payload, strlen(payload)); + buf[strlen(payload)] = '\0'; + msg->payload = buf; + IOT_LOG_DEBUG("SNDMSG:QOS:%d TOPIC:%s PAYLOAD:%s\r\n", msg->qos, msg->topic, msg->payload); + if (IOT_SUCCESS != osMessageQueuePut(gIoTAppCb.queueID, &msg, 0, CN_QUEUE_WAITTIMEOUT)) { + IOT_LOG_ERROR("Write queue failed\r\n"); + hi_free(0, msg); + } else { + rc = 0; + } + } + return rc; +} \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/iottencent/iot_main.h b/src/applications/sample/wifi-iot/app/iottencent/iot_main.h new file mode 100644 index 0000000..75d0664 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/iottencent/iot_main.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IOT_MAIN_H +#define IOT_MAIN_H + +typedef void (*fnMsgCallBack)(int qos, const char *topic, const char *payload); + +/** + * This is the iot main function. Please call this function first +*/ +int IoTMain(void); +/** + * Use this function to set the message call back function, when some messages comes, + * the callback will be called, if you don't care about the message, set it to NULL +*/ +int IoTSetMsgCallback(fnMsgCallBack msgCallback); +/** + * When you want to send some messages to the iot server(including the response message), + * please call this api + * @param qos: the mqtt qos,:0,1,2 + * @param topic: the iot mqtt topic + * @param payload: the mqtt payload + * + * @return 0 success while others failed + * + * @instruction: if success means we write the message to the queue susccess, + * not means communicate with the server success +*/ +int IotSendMsg(int qos, const char *topic, const char *payload); + +#endif /* IOT_MAIN_H_ */ \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/iottencent/iot_profile.c b/src/applications/sample/wifi-iot/app/iottencent/iot_profile.c new file mode 100644 index 0000000..0f54112 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/iottencent/iot_profile.c @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "iot_main.h" +#include "iot_log.h" +#include "iot_config.h" +#include "iot_profile.h" + +// < format the report data to json string mode +static cJSON *FormateProflleValue(IoTProfileKV_t *kv) +{ + cJSON *ret = NULL; + switch (kv->type) { + case EN_IOT_DATATYPE_INT: + ret = cJSON_CreateNumber(kv->iValue); + break; + case EN_IOT_DATATYPE_LONG: + ret = cJSON_CreateNumber((double)(*(long *)kv->value)); + break; + case EN_IOT_DATATYPE_STRING: + ret = cJSON_CreateString((const char *)kv->value); + break; + default: + break; + } + return ret; +} + +static cJSON *MakeKvs(IoTProfileKV_t *kvlst) +{ + cJSON *root; + cJSON *kv; + IoTProfileKV_t *kvInfo; + + // < build a root node + root = cJSON_CreateObject(); + if (root == NULL) { + cJSON_Delete(root); + root = NULL; + return root; + } + // < add all the property to the properties + kvInfo = kvlst; + while (kvInfo != NULL) { + kv = FormateProflleValue(kvInfo); + if (kv == NULL) { + if (root != NULL) { + cJSON_Delete(root); + root = NULL; + } + return root; + } + cJSON_AddItemToObject(root, kvInfo->key, kv); + kvInfo = kvInfo->nxt; + } + // < OK, now we return it + return root; +} + +#define CN_PROFILE_SERVICE_KEY_SERVICEID "service_id" +#define CN_PROFILE_SERVICE_KEY_PROPERTIIES "properties" +#define CN_PROFILE_SERVICE_KEY_EVENTTIME "event_time" +#define CN_PROFILE_KEY_SERVICES "services" +static cJSON *MakeService(IoTProfileService_t *serviceInfo) +{ + cJSON *root; + cJSON *serviceID; + cJSON *properties; + cJSON *eventTime; + + // < build a root node + root = cJSON_CreateObject(); + if (root == NULL) { + cJSON_Delete(root); + root = NULL; + return root; + } + // < add the serviceID node to the root node + serviceID = cJSON_CreateString(serviceInfo->serviceID); + if (serviceID == NULL) { + if (root != NULL) { + cJSON_Delete(root); + root = NULL; + } + return root; + } + cJSON_AddItemToObjectCS(root, CN_PROFILE_SERVICE_KEY_SERVICEID, serviceID); + // < add the properties node to the root + properties = MakeKvs(serviceInfo->serviceProperty); + if (properties == NULL) { + if (root != NULL) { + cJSON_Delete(root); + root = NULL; + } + return root; + } + cJSON_AddItemToObjectCS(root, CN_PROFILE_SERVICE_KEY_PROPERTIIES, properties); + // < add the event time (optional) to the root + if (serviceInfo->eventTime != NULL) { + eventTime = cJSON_CreateString(serviceInfo->eventTime); + if (eventTime == NULL) { + if (root != NULL) { + cJSON_Delete(root); + root = NULL; + } + return root; + } + cJSON_AddItemToObjectCS(root, CN_PROFILE_SERVICE_KEY_EVENTTIME, eventTime); + } + // < OK, now we return it + cJSON_Delete(properties); + return root; +} + +static cJSON *MakeServices(IoTProfileService_t *serviceInfo) +{ + cJSON *services = NULL; + cJSON *service; + IoTProfileService_t *serviceTmp; + + // < create the services array node + services = cJSON_CreateArray(); + if (services == NULL) { + cJSON_Delete(services); + services = NULL; + return services; + } + + serviceTmp = serviceInfo; + while (serviceTmp != NULL) { + service = MakeService(serviceTmp); + if (service == NULL) { + if (services != NULL) { + cJSON_Delete(services); + services = NULL; + } + return services; + } + cJSON_AddItemToArray(services, service); + serviceTmp = serviceTmp->nxt; + } + // < now we return the services + return services; +} + +// < use this function to make a topic to publish +// < if request_id is needed depends on the fmt +static char *MakeTopic(const char *fmt, const char *deviceID, const char *requestID) +{ + int len; + char *ret = NULL; + + len = strlen(fmt) + strlen(deviceID); + if (requestID != NULL) { + len += strlen(requestID); + } + + ret = hi_malloc(0, len); + if (ret != NULL) { + if (requestID != NULL) { + (void)snprintf_s(ret, len, len, fmt, deviceID, requestID); + } else { + (void)snprintf_s(ret, len, len, fmt, deviceID); + } + } + return ret; +} + +#define CN_PROFILE_CMDRESP_KEY_RETCODE "result_code" +#define CN_PROFILE_CMDRESP_KEY_RESPNAME "response_name" +#define CN_PROFILE_CMDRESP_KEY_PARAS "paras" +static char *MakeProfileCmdResp(IoTCmdResp_t *payload) +{ + char *ret = NULL; + cJSON *root; + cJSON *retCode; + cJSON *respName; + cJSON *paras; + + // < create the root node + root = cJSON_CreateObject(); + if (root == NULL) { + cJSON_Delete(root); + return ret; + } + // < create retcode and retdesc and add it to the root + retCode = cJSON_CreateNumber(payload->retCode); + if (retCode == NULL) { + if (root != NULL) { + cJSON_Delete(root); + } + return ret; + } + cJSON_AddItemToObjectCS(root, CN_PROFILE_CMDRESP_KEY_RETCODE, retCode); + if (payload->respName != NULL) { + respName = cJSON_CreateString(payload->respName); + if (respName == NULL) { + if (root != NULL) { + cJSON_Delete(root); + } + return ret; + } + cJSON_AddItemToObjectCS(root, CN_PROFILE_CMDRESP_KEY_RESPNAME, respName); + } + + if (payload->paras != NULL) { + paras = MakeKvs(payload->paras); + if (paras == NULL) { + if (root != NULL) { + cJSON_Delete(root); + } + return ret; + } + cJSON_AddItemToObjectCS(root, CN_PROFILE_CMDRESP_KEY_PARAS, paras); + } + // < OK, now we make it to a buffer + ret = cJSON_PrintUnformatted(root); + cJSON_Delete(root); + return ret; +} + +static char *MakeProfilePropertyReport(IoTProfileService_t *payload) +{ + char *ret = NULL; + cJSON *root; + cJSON *services; + + // < create the root node + root = cJSON_CreateObject(); + if (root == NULL) { + cJSON_Delete(root); + return ret; + } + // < create the services array node to the root + services = MakeServices(payload); + if (services == NULL) { + if (root != NULL) { + cJSON_Delete(root); + } + return ret; + } + cJSON_AddItemToObjectCS(root, CN_PROFILE_KEY_SERVICES, services); + // < OK, now we make it to a buffer + ret = cJSON_PrintUnformatted(root); + cJSON_Delete(root); + return ret; +} + +#define WECHAT_SUBSCRIBE_TYPE "update" +#define WECHAT_SUBSCRIBE_VERSION "1.0.0" +#define WECHAT_SUBSCRIBE_TOKEN "DeviceSubscribe" +static char *MakeProfileReport(WeChatProfile *payload) +{ + char *ret = NULL; + cJSON *root; + cJSON *state; + cJSON *reported; + + /* create json root node */ + root = cJSON_CreateObject(); + if (root == NULL) { + return; + } + /* state create */ + state = cJSON_CreateObject(); + if (state == NULL) { + return; + } + /* reported create */ + reported = cJSON_CreateObject(); + if (reported == NULL) { + return; + } + /* add root object */ + cJSON_AddItemToObject(root, payload->subscribeType, cJSON_CreateString(WECHAT_SUBSCRIBE_TYPE)); + cJSON_AddItemToObject(root, payload->status.subState, state); + cJSON_AddItemToObject(state, payload->status.subReport, reported); + cJSON_AddItemToObject(root, payload->status.reportVersion, cJSON_CreateString(WECHAT_SUBSCRIBE_VERSION)); + cJSON_AddItemToObject(root, payload->status.Token, cJSON_CreateString(WECHAT_SUBSCRIBE_TOKEN)); + /* add reported item */ + cJSON_AddNumberToObject(reported, payload->reportAction.subDeviceActionLight, + payload->reportAction.lightActionStatus); + cJSON_AddNumberToObject(reported, payload->reportAction.subDeviceActionMotor, + payload->reportAction.motorActionStatus); + cJSON_AddNumberToObject(reported, payload->reportAction.subDeviceActionTemperature, + payload->reportAction.temperatureData); + cJSON_AddNumberToObject(reported, payload->reportAction.subDeviceActionHumidity, + payload->reportAction.humidityActionData); + cJSON_AddNumberToObject(reported, payload->reportAction.subDeviceActionLightIntensity, + payload->reportAction.lightIntensityActionData); + ret = cJSON_PrintUnformatted(root); + cJSON_Delete(state); + cJSON_Delete(reported); + cJSON_Delete(root); + return ret; +} + +#define CN_PROFILE_TOPICFMT_TOPIC "YT32IOSCAL/Hi38611_mqtt/data" +int IoTProfilePropertyReport(char *deviceID, WeChatProfile *payload) +{ + int ret = -1; + char *topic; + char *msg; + + if ((deviceID == NULL) || (payload== NULL)) { + return ret; + } + topic = MakeTopic(CN_PROFILE_TOPICFMT_TOPIC, deviceID, NULL); + if (topic == NULL) { + return; + } + msg = MakeProfileReport(payload); + if ((topic != NULL) && (msg != NULL)) { + ret = IotSendMsg(0, topic, msg); + } + + hi_free(0, topic); + cJSON_free(msg); + + return ret; +} \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/iottencent/iot_profile.h b/src/applications/sample/wifi-iot/app/iottencent/iot_profile.h new file mode 100644 index 0000000..39d9e78 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/iottencent/iot_profile.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IOT_PROFILE_H +#define IOT_PROFILE_H + +#include +#include "iot_config.h" + +#define OC_BEEP_STATUS_ON ((hi_u8) 0x01) +#define OC_BEEP_STATUS_OFF ((hi_u8) 0x00) + +// < enum all the data type for the oc profile +typedef enum { + EN_IOT_DATATYPE_INT = 0, + EN_IOT_DATATYPE_LONG, + EN_IOT_DATATYPE_FLOAT, + EN_IOT_DATATYPE_DOUBLE, + EN_IOT_DATATYPE_STRING, // < must be ended with '\0' + EN_IOT_DATATYPE_LAST, +}IoTDataType_t; + +typedef enum { + OC_LED_ON = 1, + OC_LED_OFF +}OcLedValue; + +typedef struct { + void *nxt; // < ponit to the next key + const char *key; + const char *value; + hi_u32 iValue; + IoTDataType_t type; +}IoTProfileKV_t; + +typedef struct { + void *nxt; + char *serviceID; + char *eventTime; + IoTProfileKV_t *serviceProperty; +}IoTProfileService_t; + +typedef struct { + int retCode; // < response code, 0 success while others failed + const char *respName; // < response name + const char *requestID; // < specified by the message command + IoTProfileKV_t *paras; // < the command paras +}IoTCmdResp_t; + +typedef struct { + const char *subState; + const char *subReport; + const char *reportVersion; + const char *Token; +}WeChatProfileStatus; + +typedef struct { + int lightActionStatus; + int motorActionStatus; + int temperatureData; + int humidityActionData; + int lightIntensityActionData; + const char *subDeviceActionLight; + const char *subDeviceActionMotor; + const char *subDeviceActionTemperature; + const char *subDeviceActionHumidity; + const char *subDeviceActionLightIntensity; +}WeChatProfileReporte; + +typedef struct { + const char *subscribeType; + WeChatProfileStatus status; + WeChatProfileReporte reportAction; +}WeChatProfile; + +/** + * use this function to report the property to the iot platform +*/ +int IoTProfilePropertyReport(char *deviceID, WeChatProfile *payload); +void cJsonInit(void); +void WifiStaReadyWait(void); +#endif \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/iottencent/iot_sta.c b/src/applications/sample/wifi-iot/app/iottencent/iot_sta.c new file mode 100644 index 0000000..aed1be3 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/iottencent/iot_sta.c @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// < this demo make the wifi to connect to the specified AP +#include +#include +#include +#include +#include +#include +#include +#include "iot_config.h" +#include "iot_log.h" +#include "wifi_device.h" +#include "cmsis_os2.h" +#include "wifi_device_config.h" +#include "lwip/api_shell.h" + +#define APP_INIT_VAP_NUM 2 +#define APP_INIT_USR_NUM 2 + +static struct netif *gLwipNetif = NULL; +static hi_bool gScanDone = HI_FALSE; +unsigned char wifiStatus = 0; + +unsigned char wifiFirstConnecting = 0; +unsigned char wifiSecondConnecting = 0; +unsigned char wifiSecondConnected = 0; +static struct netif* g_iface = NULL; +void WifiStopSta(int netId); +static int WifiStartSta(void); +int cnetId = -1; +int g_connected = 0; + +#define WIFI_CONNECT_STATUS ((unsigned char)0x02) + +void wifiReconnected(int netId) +{ + int recnetId = netId; + if (wifiFirstConnecting == WIFI_CONNECT_STATUS) { + wifiSecondConnecting = HI_TRUE; + wifiFirstConnecting = HI_FALSE; + WifiStopSta(recnetId); + ip4_addr_t ipAddr; + ip4_addr_t ipAny; + IP4_ADDR(&ipAny, 0, 0, 0, 0); + IP4_ADDR(&ipAddr, 0, 0, 0, 0); + recnetId = WifiStartSta(); + netifapi_dhcp_start(gLwipNetif); + while (0 == memcmp(&ipAddr, &ipAny, sizeof(ip4_addr_t))) { + IOT_LOG_DEBUG(":Wait the DHCP READY"); + netifapi_netif_get_addr(gLwipNetif, &ipAddr, NULL, NULL); + hi_sleep(1000); /* 1000: cpu sleep 1000 ms */ + } + wifiSecondConnected = HI_FALSE; + wifiFirstConnecting = WIFI_CONNECT_STATUS; + wifiStatus = HI_WIFI_EVT_CONNECTED; + } +} +/* clear netif's ip, gateway and netmask */ +static void StaResetAddr(struct netif *lwipNetif) +{ + ip4_addr_t st_gw; + ip4_addr_t st_ipaddr; + ip4_addr_t st_netmask; + + if (lwipNetif == NULL) { + IOT_LOG_ERROR("hisi_reset_addr::Null param of netdev"); + return; + } + + IP4_ADDR(&st_gw, 0, 0, 0, 0); + IP4_ADDR(&st_ipaddr, 0, 0, 0, 0); + IP4_ADDR(&st_netmask, 0, 0, 0, 0); + + netifapi_netif_set_addr(lwipNetif, &st_ipaddr, &st_netmask, &st_gw); +} + +static void WpaEventCB(const hi_wifi_event *hisiEvent) +{ + if (hisiEvent == NULL) + return; + IOT_LOG_DEBUG("EVENT_TYPE:%d", hisiEvent->event); + switch (hisiEvent->event) { + case HI_WIFI_EVT_SCAN_DONE: + IOT_LOG_DEBUG("WiFi: Scan results available"); + gScanDone = HI_TRUE; + break; + case HI_WIFI_EVT_CONNECTED: + IOT_LOG_DEBUG("WiFi: Connected"); + netifapi_dhcp_start(gLwipNetif); + wifiStatus = HI_WIFI_EVT_CONNECTED; + if (wifiSecondConnected) { + wifiSecondConnected = HI_FALSE; + wifiFirstConnecting = WIFI_CONNECT_STATUS; + } + break; + case HI_WIFI_EVT_DISCONNECTED: + IOT_LOG_DEBUG("WiFi: Disconnected"); + netifapi_dhcp_stop(gLwipNetif); + StaResetAddr(gLwipNetif); + wifiStatus = HI_WIFI_EVT_DISCONNECTED; + wifiReconnected(cnetId); + break; + case HI_WIFI_EVT_WPS_TIMEOUT: + IOT_LOG_DEBUG("WiFi: wps is timeout"); + wifiStatus = HI_WIFI_EVT_WPS_TIMEOUT; + break; + default: + break; + } +} + +static int StaStartConnect(void) +{ + int ret; + errno_t rc; + hi_wifi_assoc_request assoc_req = {0}; + + /* copy SSID to assoc_req */ + rc = memcpy_s(assoc_req.ssid, HI_WIFI_MAX_SSID_LEN + 1, CONFIG_AP_SSID, strlen(CONFIG_AP_SSID)); + if (rc != EOK) { + return -1; + } + + /* + * OPEN mode + * for WPA2-PSK mode: + * set assoc_req.auth as HI_WIFI_SECURITY_WPA2PSK, + * then memcpy(assoc_req.key, "12345678", 8). + */ + assoc_req.auth = HI_WIFI_SECURITY_WPA2PSK; + rc = memcpy_s(assoc_req.key, HI_WIFI_MAX_KEY_LEN + 1, CONFIG_AP_PWD, strlen(CONFIG_AP_PWD)); + if (rc != EOK) { + return -1; + } + + ret = hi_wifi_sta_connect(&assoc_req); + if (ret != HISI_OK) { + return -1; + } + + return 0; +} + +static void PrintLinkedInfo(WifiLinkedInfo* info) +{ + int ret = 0; + if (!info) { + return; + } + + static char macAddress[32] = {0}; + unsigned char* mac = info->bssid; + if (snprintf_s(macAddress, sizeof(macAddress) + 1, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]) < 0) { /* mac地址从0,1,2,3,4,5位 */ + return; + } +} + +static void OnWifiConnectionChanged(int state, WifiLinkedInfo* info) +{ + if (!info) { + return; + } + + printf("%s %d, state = %d, info = \r\n", __FUNCTION__, __LINE__, state); + PrintLinkedInfo(info); + + if (state == WIFI_STATE_AVALIABLE) { + g_connected = 1; + } else { + g_connected = 0; + } +} + +static void OnWifiScanStateChanged(int state, int size) +{ + printf("%s %d, state = %X, size = %d\r\n", __FUNCTION__, __LINE__, state, size); +} + +static WifiEvent g_defaultWifiEventListener = { + .OnWifiConnectionChanged = OnWifiConnectionChanged, + .OnWifiScanStateChanged = OnWifiScanStateChanged +}; + +static int WifiStartSta(void) +{ + WifiDeviceConfig apConfig = {0}; + strcpy_s(apConfig.ssid, sizeof(CONFIG_AP_SSID), CONFIG_AP_SSID); + strcpy_s(apConfig.preSharedKey, sizeof(CONFIG_AP_PWD), CONFIG_AP_PWD); + apConfig.securityType = WIFI_SEC_TYPE_PSK; + + WifiErrorCode errCode; + int netId = -1; + + errCode = RegisterWifiEvent(&g_defaultWifiEventListener); + printf("RegisterWifiEvent: %d\r\n", errCode); + + errCode = EnableWifi(); + printf("EnableWifi: %d\r\n", errCode); + + errCode = AddDeviceConfig(&apConfig, &netId); + printf("AddDeviceConfig: %d\r\n", errCode); + + g_connected = 0; + errCode = ConnectTo(netId); + printf("ConnectTo(%d): %d\r\n", netId, errCode); + + while (!g_connected) { // wait until connect to AP + osDelay(10); /* 10: os sleep 10ms */ + } + printf("g_connected: %d\r\n", g_connected); + + g_iface = netifapi_netif_find("wlan0"); + if (g_iface) { + err_t ret = netifapi_dhcp_start(g_iface); + printf("netifapi_dhcp_start: %d\r\n", ret); + + osDelay(100); // 100: os sleep 100ms wait DHCP server give me IP + ret = netifapi_netif_common(g_iface, dhcp_clients_info_show, NULL); + printf("netifapi_netif_common: %d\r\n", ret); + } + return netId; +} + +void WifiStopSta(int netId) +{ + int stopNetId = netId; + + if (g_iface) { + err_t ret = netifapi_dhcp_stop(g_iface); + printf("netifapi_dhcp_stop: %d\r\n", ret); + } + + WifiErrorCode errCode = Disconnect(); // disconnect with your AP + printf("Disconnect: %d\r\n", errCode); + + errCode = UnRegisterWifiEvent(&g_defaultWifiEventListener); + printf("UnRegisterWifiEvent: %d\r\n", errCode); + + RemoveDevice(stopNetId); // remove AP config + printf("RemoveDevice: %d\r\n", errCode); + + errCode = DisableWifi(); + printf("DisableWifi: %d\r\n", errCode); +} + +void WifiStaReadyWait(void) +{ + ip4_addr_t ipAddr; + ip4_addr_t ipAny; + IP4_ADDR(&ipAny, 0, 0, 0, 0); + IP4_ADDR(&ipAddr, 0, 0, 0, 0); + cnetId = WifiStartSta(); + IOT_LOG_DEBUG("wifi sta dhcp done"); +} \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/iottencent_demo/BUILD.gn b/src/applications/sample/wifi-iot/app/iottencent_demo/BUILD.gn new file mode 100644 index 0000000..734c2e7 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/iottencent_demo/BUILD.gn @@ -0,0 +1,39 @@ +# Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +static_library("appDemoIot") { + sources = [ + "app_demo_iot.c", + "cjson_init.c", + "iot_hmac.c", + "iot_log.c", + "iot_main.c", + "iot_profile.c", + "iot_sta.c", + ] + + include_dirs = [ + "./", + "//utils/native/lite/include", + "//kernel/liteos_m/kal/cmsis", + "//base/iot_hardware/peripheral/interfaces/kits", + "//device/soc/hisilicon/hi3861v100/sdk_liteos/third_party/lwip_sack/include/lwip", + "//third_party/cJSON", + "//device/soc/hisilicon/hi3861v100/sdk_liteos/third_party/mbedtls/include/mbedtls", + "//foundation/communication/wifi_lite/interfaces/wifiservice", + "//device/soc/hisilicon/hi3861v100/sdk_liteos/third_party/paho.mqtt.c/include/mqtt", + "//device/soc/hisilicon/hi3861v100/sdk_liteos/third_party/libcoap/include/coap2", + ] + + defines = [ "WITH_LWIP" ] +} diff --git a/src/applications/sample/wifi-iot/app/iottencent_demo/README.md b/src/applications/sample/wifi-iot/app/iottencent_demo/README.md new file mode 100644 index 0000000..e863290 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/iottencent_demo/README.md @@ -0,0 +1,226 @@ +# 腾讯云的微信小程序开发及Hi3861板端互联 +## 硬件环境搭建 +- 硬件要求:Hi3861V100核心板、扩展板;硬件搭建如下图所示。 +- [Hi3861V100核心板参考:HiSpark_WiFi_IoT智能开发套件_原理图硬件资料\原理图\HiSpark_WiFi-IoT_Hi3861_CH340G_VER.B.pdf](http://gitee.com/hihope_iot/embedded-race-hisilicon-track-2022/blob/master/%E7%A1%AC%E4%BB%B6%E8%B5%84%E6%96%99/HiSpark_WiFi_IoT%E6%99%BA%E8%83%BD%E5%AE%B6%E5%B1%85%E5%BC%80%E5%8F%91%E5%A5%97%E4%BB%B6_%E5%8E%9F%E7%90%86%E5%9B%BE.rar) +- [扩展板参考:HiSpark_WiFi_IoT智能开发套件_原理图硬件资料\原理图\HiSpark_WiFi-IoT_Hi3861_CH340G_VER.B.pdf](http://gitee.com/hihope_iot/embedded-race-hisilicon-track-2022/blob/master/%E7%A1%AC%E4%BB%B6%E8%B5%84%E6%96%99/HiSpark_WiFi_IoT%E6%99%BA%E8%83%BD%E5%AE%B6%E5%B1%85%E5%BC%80%E5%8F%91%E5%A5%97%E4%BB%B6_%E5%8E%9F%E7%90%86%E5%9B%BE.rar) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/260.jpg) + +## 软件介绍 +- 1.代码目录结构及相应接口功能介绍 +``` +vendor_hisilicon/hispark_pegasus/demo/iottencent_demo +├── app_demo_iot.c #IoSetPull();IoSetFunc();TaskMsleep()。 +├── BUILD.gn # BUILD.gn文件由三部分内容(目标、源文件、头文件路径)构成,开发者根据需要填写,static_library中指定业务模块的编译结果,为静态库文件led_example,开发者根据实际情况完成填写。 +| sources中指定静态库.a所依赖的.c文件及其路径,若路径中包含"//"则表示绝对路径(此处为代码根路径),若不包含"//"则表示相对路径。include_dirs中指定source所需要依赖的.h文件路径。 +├── cjson_init.c # +├── iot_config.h # +├── iot_hmac.c # +├── iot_hmac.h # +├── iot_log.c # +├── iot_log.h # +├── iot_main.c # +├── iot_main.h # +├── iot_profile.c # +├── iot_sta.c # +└── iot_profile.h # +``` +- 2.Mqtt协议第三方软件与腾讯云之间的通信 + +2.1 浏览器搜索腾讯云,在腾讯云界面创建产品和设备,登录腾讯云后搜索“物联网通信”,进入页面后,物联网通信选择立即使用。进入页面后,选择产品列表栏->创建新产品->产品名称:xxx,认证方式:密钥认证,点击确定。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8717.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8720.png) + +2.2 在产品列表栏进入刚刚创建的新产品->设备列表->添加设备->创建新设备:设备名称,设备备注(选填),使用物联网通信提供密钥->保存->复制保存生成的密钥->开始管理设备(可以看到设备相应信息)。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8721.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8722.png) + +2.3 添加设备,同时查看设备相应信息。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F/800.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F/801.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F/802.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F/803.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F/804.png) + +2.4 返回设备列表可以看到设备并未激活,接下来激活设备;下载[MQTT.fx-1.7.1 ](https://www.jensd.de/wordpress/?p=2746),下载完成后打开工具,点击设备图标,进入到设备界面配置ClientID,username,password 等参数。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F/806.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8730.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8731.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8732.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8733.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8734.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8735.png) + +2.5 完成2.3步骤后,可以在腾讯云设备列表里面看到设备状态显示已激活,开始腾讯云与MQTT工具之间的通信。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8736.png) + +2.6 MQTT.fx-1.7.1工具订阅腾讯云的topic,腾讯云下发指令。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8737.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8738.png) + +2.7 在腾讯云网页端点击“在线调试”。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8739.png) + +2.8 可以在MQTT.fx-1.7.1工具中看到腾讯云网页端发过来的消息。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8740.png) + +2.9 MQTT.fx-1.7.1工具发布腾讯云到的topic,在设备影子中查看发布到腾讯云的消息。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8741.png) + +``` +{ + "type":"update", + "state":{ + "reported":{ + "light":1, + "motor":1, + "temperature":25, + "humidity":60, + "light_intensity":50 + } + }, +"version":0, +"clientToken":"clientToken" +} +``` + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8742.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8743.png) + +- 3.微信小程序开发环境搭建及与腾讯云之间通信 + +3.1 注册申请小程序账号:https://mp.weixin.qq.com/wxopen/waregister?action=step1。 + +3.2 登录小程序后(选择IOT字样的账号),在“开发”->“开发设置”页面可以看到小程序的AppID,如下图所示,详情请查看微信官方文档: +https://developers.weixin.qq.com/miniprogram/dev/framework/quickstart/getstart.html#%E7%94%B3%E8%AF%B7%E5%B8%90%E5%8F%B7。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8744.png) + +3.3 开发者工具下载与安装:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8745.png) + +3.4 下载安装完成后,打开微信开发工具,导入提供的微信小程序软件包[获取微信小程序代码](https://gitee.com/leo593362220/Hi3861OpenHarmony)。并填入自己的APPID,后端服务选择微信云开发。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%87102.jpg) + +3.5 使用微信开发者工具打开工程后需要修改project.config.json文件中appid,projectname修改成自己的。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8747.png) + +3.6 获取secretId和secretKey,在腾讯云->产品列表->搜索栏搜索访问密钥->访问密钥->继续使用->可以看到secretId和secretKey,复制在xxxx.txt文件,后面需要。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8749.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8750.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8751.png) + +3.7 环境ID配置并获取环境ID,复制在xxx.txt文件,后面需要。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8752.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8753.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8754.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8755.png)![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8747.png) + +3.8 需要修改app.js文件中productId(腾讯云上设备信息上产品ID),deviceName(腾讯云上设备信息上产品名称),secretId和secretKey(3.6步骤获取到的secretId和secretKey),env(3.7步骤获取到的环境ID)。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8748.png) + +3.9 配置当前云环境 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8756.png) + +注意:第一次部署环境,图片里面的上传并部署会变成新建并部署。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8757.png) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/228.jpg) + +等待大概1分钟左右,直到出现上传云函数成功:(注意:上传并部署由于网络问题可能会失败,看到上传云函数等字样代表上传部署成功,这里以iothub-publish为例)。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8758.png) + +3.10 环境部署完成后,点击编译,然后真机调试会出现如下界面,上面两个都要出现 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8761.png) + +- 4.Hi3861V100与微信小程序之间通信 + - 将源码./vendor/hisilicon/hispark_pegasus/demo目录下的iottencent_demo整个文件夹及内容复制到源码./applications/sample/wifi-iot/app/下。 + ``` + . + └── applications + └── sample + └── wifi-iot + └── app + └──iottencent_demo + └── 代码 + ``` + + - 配置源码./applications/sample/wifi-iot/app/iottencent_demo/iot_config.h中CONFIG_AP_SSID,CONFIG_AP_PWD为WiFi名称和WiFi密码。CONFIG_USER_ID为腾讯云设备信息上MQTT Username,CONFIG_USER_PWD为腾讯云上设备的MQTT Password,CN_CLIENTID为腾讯云上clientID。 + ``` + #define CONFIG_AP_SSID "XXXXXXXX" // WIFI SSID + #define CONFIG_AP_PWD "XXXXX" // WIFI PWD + /* Tencent iot Cloud user ID , password */ + #define CONFIG_USER_ID "XXXXXXXXXXXXX" + #define CONFIG_USER_PWD "XXXXXXXXXXXX" + #define CN_CLIENTID "xxxxxxxx" // Tencent cloud ClientID format: Product ID + device name + ``` + + - 更改源码./applications/sample/wifi-iot/app/iottencent_demo/iot_main.c文件中搜索g_defaultSubscribeTopic字段,将腾讯云上的Topic列表中自定义Topic添加到字段里。 + ``` + static const char *g_defaultSubscribeTopic[] = { + "76VQ4ZASTL/mqtt/data", + "76VQ4ZASTL/mqtt/event", + "76VQ4ZASTL/mqtt/control", + }; + ``` + - 更改源码./applications/sample/wifi-iot/app/iottencent_demo/iot_profile.c文件中搜索CN_PROFILE_TOPICFMT_TOPIC字段,将腾讯云上的产品名,设备名称添加到字段里。 + ``` + #define CN_PROFILE_TOPICFMT_TOPIC "$shadow/operation/xxxxx/XXXX" //xxxx为产品名和设备名称,如:76VQ4ZASTL + ``` + + - 修改源码./applications/sample/wifi-iot/app/BUILD.gn文件,在features字段中增加索引,使目标模块参与编译。features字段指定业务模块的路径和目标,features字段配置如下。 + ``` + import("//build/lite/config/component/lite_component.gni") + + lite_component("app") { + features = [ + "iottencent_demo:appDemoIot", + ] + } + ``` + + - 工程相关配置完成后,然后编译。 +- 5.烧录 + - 编译成功后,点击DevEco Home->配置工程->hi3861->upload_port->选择对应串口端口号->选择upload_protocol->选择hiburn-serial->点击save保存,在保存成功后点击upload进行烧录,出现connecting, please reset device..字样复位开发板等待烧录完成。烧录成功后,再次点击Hi3861核心板上的“RST”复位键,此时开发板的系统会运行起来。 + - 注意:一定要断开MQTT工具的连接。 + - 微信小程序上选择已连接Wifi,跳过配网->云端互联->看到设备互联界面->点击刷新按钮,运行结果出现如下图代表成功,点击照明,主板灯会亮。 + + ![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%8762.png) \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/iottencent_demo/app_demo_iot.c b/src/applications/sample/wifi-iot/app/iottencent_demo/app_demo_iot.c new file mode 100644 index 0000000..966f756 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/iottencent_demo/app_demo_iot.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include "iot_config.h" +#include "iot_log.h" +#include "iot_main.h" +#include "iot_profile.h" +#include "ohos_init.h" +#include "cmsis_os2.h" + +/* attribute initiative to report */ +#define TAKE_THE_INITIATIVE_TO_REPORT +#define ONE_SECOND (1000) +/* oc request id */ +#define CN_COMMADN_INDEX "commands/request_id=" +#define WECHAT_SUBSCRIBE_LIGHT "light" +#define WECHAT_SUBSCRIBE_LIGHT_ON_STATE "1" +#define WECHAT_SUBSCRIBE_LIGHT_OFF_STATE "0" + +int g_ligthStatus = -1; +typedef void (*FnMsgCallBack)(hi_gpio_value val); + +typedef struct FunctionCallback { + hi_bool stop; + hi_u32 conLost; + hi_u32 queueID; + hi_u32 iotTaskID; + FnMsgCallBack msgCallBack; +}FunctionCallback; +FunctionCallback g_functinoCallback; + +/* CPU Sleep time Set */ +unsigned int TaskMsleep(unsigned int ms) +{ + if (ms <= 0) { + return HI_ERR_FAILURE; + } + return hi_sleep((hi_u32)ms); +} + +static void DeviceConfigInit(hi_gpio_value val) +{ + hi_io_set_func(HI_IO_NAME_GPIO_9, HI_IO_FUNC_GPIO_9_GPIO); + hi_gpio_set_dir(HI_GPIO_IDX_9, HI_GPIO_DIR_OUT); + hi_gpio_set_ouput_val(HI_GPIO_IDX_9, val); +} + +static int DeviceMsgCallback(FnMsgCallBack msgCallBack) +{ + g_functinoCallback.msgCallBack = msgCallBack; + return 0; +} + +static void wechatControlDeviceMsg(hi_gpio_value val) +{ + DeviceConfigInit(val); +} + +// < this is the callback function, set to the mqtt, and if any messages come, it will be called +// < The payload here is the json string +static void DemoMsgRcvCallBack(int qos, const char *topic, const char *payload) +{ + IOT_LOG_DEBUG("RCVMSG:QOS:%d TOPIC:%s PAYLOAD:%s\r\n", qos, topic, payload); + /* 云端下发命令后,板端的操作处理 */ + if (strstr(payload, WECHAT_SUBSCRIBE_LIGHT) != NULL) { + if (strstr(payload, WECHAT_SUBSCRIBE_LIGHT_OFF_STATE) != NULL) { + wechatControlDeviceMsg(HI_GPIO_VALUE1); + g_ligthStatus = HI_FALSE; + } else { + wechatControlDeviceMsg(HI_GPIO_VALUE0); + g_ligthStatus = HI_TRUE; + } + } + return HI_NULL; +} + +/* publish sample */ +hi_void IotPublishSample(void) +{ + /* reported attribute */ + WeChatProfile weChatProfile = { + .subscribeType = "type", + .status.subState = "state", + .status.subReport = "reported", + .status.reportVersion = "version", + .status.Token = "clientToken", + /* report motor */ + .reportAction.subDeviceActionMotor = "motor", + .reportAction.motorActionStatus = 0, /* 0 : motor off */ + /* report temperature */ + .reportAction.subDeviceActionTemperature = "temperature", + .reportAction.temperatureData = 30, /* 30 :temperature data */ + /* report humidity */ + .reportAction.subDeviceActionHumidity = "humidity", + .reportAction.humidityActionData = 70, /* humidity data */ + /* report light_intensity */ + .reportAction.subDeviceActionLightIntensity = "light_intensity", + .reportAction.lightIntensityActionData = 60, /* 60 : light_intensity */ + }; + + /* report light */ + if (g_ligthStatus == HI_TRUE) { + weChatProfile.reportAction.subDeviceActionLight = "light"; + weChatProfile.reportAction.lightActionStatus = 1; /* 1: light on */ + } else if (g_ligthStatus == HI_FALSE) { + weChatProfile.reportAction.subDeviceActionLight = "light"; + weChatProfile.reportAction.lightActionStatus = 0; /* 0: light off */ + } else { + weChatProfile.reportAction.subDeviceActionLight = "light"; + weChatProfile.reportAction.lightActionStatus = 0; /* 0: light off */ + } + /* profile report */ + IoTProfilePropertyReport(CONFIG_USER_ID, &weChatProfile); +} + +// < this is the demo main task entry,here we will set the wifi/cjson/mqtt ready and +// < wait if any work to do in the while +static hi_void *DemoEntry(const char *arg) +{ + WifiStaReadyWait(); + cJsonInit(); + IoTMain(); + /* 云端下发回调 */ + IoTSetMsgCallback(DemoMsgRcvCallBack); + /* 主动上报 */ +#ifdef TAKE_THE_INITIATIVE_TO_REPORT + while (1) { + /* 用户可以在这调用发布函数进行发布,需要用户自己写调用函数 */ + IotPublishSample(); // 发布例程 +#endif + TaskMsleep(ONE_SECOND); + } + return NULL; +} + +// < This is the demo entry, we create a task here, +// and all the works has been done in the demo_entry +#define CN_IOT_TASK_STACKSIZE 0x1000 +#define CN_IOT_TASK_PRIOR 25 +#define CN_IOT_TASK_NAME "IOTDEMO" + +static void AppDemoIot(void) +{ + osThreadAttr_t attr; + IoTWatchDogDisable(); + + attr.name = "IOTDEMO"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = CN_IOT_TASK_STACKSIZE; + attr.priority = CN_IOT_TASK_PRIOR; + + if (osThreadNew((osThreadFunc_t)DemoEntry, NULL, &attr) == NULL) { + printf("[mqtt] Falied to create IOTDEMO!\n"); + } +} + +SYS_RUN(AppDemoIot); \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/iottencent_demo/cjson_init.c b/src/applications/sample/wifi-iot/app/iottencent_demo/cjson_init.c new file mode 100644 index 0000000..6ad1e78 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/iottencent_demo/cjson_init.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static void *cJsonMalloc(size_t sz) +{ + return hi_malloc(0, sz); +} + +static void cJsonFree(const char *p) +{ + hi_free(0, p); +} + +void cJsonInit(void) +{ + cJSON_Hooks hooks; + hooks.malloc_fn = cJsonMalloc; + hooks.free_fn = cJsonFree; + cJSON_InitHooks(&hooks); + + return; +} \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/iottencent_demo/iot_config.h b/src/applications/sample/wifi-iot/app/iottencent_demo/iot_config.h new file mode 100644 index 0000000..d548570 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/iottencent_demo/iot_config.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IOT_CONFIG_H +#define IOT_CONFIG_H + +// +#include +#include +#include +#include "md.h" +#include "md_internal.h" + +#define CN_HMAC256_LEN_MAX (65) +#define CN_HMAC256_LEN 32 +#define RIGHT_MOVE_BIT_4 (4) +#define NUMBER_9 (9) +#define DECIMAL_BASE (10) +#define STRING_LEN_TIMES (2) +#define LEN_TIMES (2) +#define OFFSET (1) +// make a byte to 2 ascii hex +static int byte2hexstr(unsigned char *bufin, int len, char *bufout) +{ + int i = 0; + unsigned char tmp_l = 0x0; + unsigned char tmp_h = 0; + if ((bufin == NULL)||(len <= 0)||(bufout == NULL)) { + return -1; + } + for (i = 0; i < len; i++) { + tmp_h = (bufin[i] >> RIGHT_MOVE_BIT_4) & 0X0F; + tmp_l = bufin[i] & 0x0F; + bufout[STRING_LEN_TIMES * i] = (tmp_h > NUMBER_9) ? + (tmp_h - DECIMAL_BASE + 'a'):(tmp_h +'0'); + bufout[STRING_LEN_TIMES * i + OFFSET] = (tmp_l > NUMBER_9) ? + (tmp_l - DECIMAL_BASE + 'a'):(tmp_l +'0'); + } + bufout[STRING_LEN_TIMES * len] = '\0'; + + return 0; +} + +int HmacGeneratePwd(const unsigned char *content, int contentLen, const unsigned char *key, + int keyLen, unsigned char *buf) +{ + int ret = -1; + mbedtls_md_context_t mbedtls_md_ctx; + const mbedtls_md_info_t *md_info; + unsigned char hash[CN_HMAC256_LEN]; + + if ((key == NULL)||(content == NULL)||(buf == NULL)|| + (keyLen == 0)||(contentLen == 0)|| + (CN_HMAC256_LEN_MAX < (CN_HMAC256_LEN * LEN_TIMES + OFFSET))) { + return ret; + } + + md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); + if ((md_info == NULL)||((size_t)md_info->size > CN_HMAC256_LEN)) { + return ret; + } + + mbedtls_md_init(&mbedtls_md_ctx); + ret = mbedtls_md_setup(&mbedtls_md_ctx, md_info, 1); + if (ret != 0) { + mbedtls_md_free(&mbedtls_md_ctx); + return ret; + } + + (void)mbedtls_md_hmac_starts(&mbedtls_md_ctx, key, keyLen); + (void)mbedtls_md_hmac_update(&mbedtls_md_ctx, content, contentLen); + (void)mbedtls_md_hmac_finish(&mbedtls_md_ctx, hash); + + // + +static EnIotLogLevel gIoTLogLevel = EN_IOT_LOG_LEVEL_TRACE; +static const char *gIoTLogLevelNames[] = { + "TRACE", + "DEBUG", + "INFO ", + "WARN ", + "ERROR", + "FATAL" +}; + +int IoTLogLevelSet(EnIotLogLevel level) +{ + int ret = -1; + if (level < EN_IOT_LOG_LEVEL_MAX) { + gIoTLogLevel = level; + ret = 0; + } + return ret; +} + +EnIotLogLevel IoTLogLevelGet(void) +{ + return gIoTLogLevel; +} + +const char *IoTLogLevelGetName(EnIotLogLevel logLevel) +{ + if (logLevel >= EN_IOT_LOG_LEVEL_MAX) { + return "NULL "; + } else { + return gIoTLogLevelNames[logLevel]; + } +} diff --git a/src/applications/sample/wifi-iot/app/iottencent_demo/iot_log.h b/src/applications/sample/wifi-iot/app/iottencent_demo/iot_log.h new file mode 100644 index 0000000..a0532b7 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/iottencent_demo/iot_log.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IOT_LOG_H_ +#define IOT_LOG_H_ +/** + * @brief:this defines for the log module, + * and IOT_LOG_TRACE/IOT_LOG_DEBUG will not participate the compile in the release version + * + * + * */ +typedef enum { + // < this is used as the trace function,like the function enter and function out + EN_IOT_LOG_LEVEL_TRACE = 0, + // < this is used as the debug, you could add any debug as you wish + EN_IOT_LOG_LEVEL_DEBUG, + // < which means it is import message, and you should known + EN_IOT_LOG_LEVEL_INFO, + // < this is used as the executed result,which means the status is not what we expected + EN_IOT_LOG_LEVEL_WARN, + // < this is used as the executed result,which means the status is not what we expected + EN_IOT_LOG_LEVEL_ERROR, + // < this is used as the parameters input for the api interface, which could not accepted + EN_IOT_LOG_LEVEL_FATAL, + EN_IOT_LOG_LEVEL_MAX, +}EnIotLogLevel; +/** + * @brief:use this function to get the current output log + * + * @return: the current output mask log, defined by en_iot_log_level_t + * */ +EnIotLogLevel IoTLogLevelGet(void); +/** + * @brief: use this function to get the debug level name + * + * @parameter[in]:level, the level to get + * + * @return: the mapped level name + * */ +const char *IoTLogLevelGetName(EnIotLogLevel logLevel); +/** + * @brief:use this function to set the current output log + * + * @parameter[in] level:defined by en_iot_log_level_t + * + * @return: 0 success while -1 failed + * */ +int IoTLogLevelSet(EnIotLogLevel level); +/* + * @brief: this is a weak function ,and you could rewrite one + * + * @param fmt: same use as the fmt for printf + * + * @param unfixed: same use for printf + * + * @return: don't care about it + * + * @attention: and the components should not call this function directly, you'd better + * + * call IOT_LOG groups + * + * */ +#ifndef IOT_PRINT +#define IOT_PRINT(fmt, ...) \ + do \ + { \ + printf(fmt, ##__VA_ARGS__); \ + }while (0) +#endif + +#ifdef CONFIG_LINKLOG_ENABLE + +#define IOT_LOG(level, fmt, ...) \ + do \ + { \ + IOT_PRINT("[%s][%s] " fmt "\r\n", \ + IoTLogLevelGetName((level)), __FUNCTION__, ##__VA_ARGS__); \ + } while (0) + +#define IOT_LOG_TRACE(fmt, ...) \ + do \ + { \ + if ((EN_IOT_LOG_LEVEL_TRACE) >= IoTLogLevelGet()) \ + { \ + IOT_LOG(EN_IOT_LOG_LEVEL_TRACE, fmt, ##__VA_ARGS__); \ + } \ + } while (0) + +#define IOT_LOG_DEBUG(fmt, ...) \ + do \ + { \ + if ((EN_IOT_LOG_LEVEL_DEBUG) >= IoTLogLevelGet()) \ + { \ + IOT_LOG(EN_IOT_LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__); \ + } \ + } while (0) + +#else +#define IOT_LOG(level, fmt, ...) +#define IOT_LOG_TRACE(fmt, ...) +#define IOT_LOG_DEBUG(fmt, ...) +#endif + +#define IOT_LOG_TRACE(fmt, ...) IOT_LOG(EN_IOT_LOG_LEVEL_TRACE, fmt, ##__VA_ARGS__) +#define IOT_LOG_INFO(fmt, ...) IOT_LOG(EN_IOT_LOG_LEVEL_INFO, fmt, ##__VA_ARGS__) +#define IOT_LOG_WARN(fmt, ...) IOT_LOG(EN_IOT_LOG_LEVEL_WARN, fmt, ##__VA_ARGS__) +#define IOT_LOG_ERROR(fmt, ...) IOT_LOG(EN_IOT_LOG_LEVEL_ERROR, fmt, ##__VA_ARGS__) +#define IOT_LOG_FATAL(fmt, ...) IOT_LOG(EN_IOT_LOG_LEVEL_FATAL, fmt, ##__VA_ARGS__) + +#endif /* IOT_LOG_H_ */ \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/iottencent_demo/iot_main.c b/src/applications/sample/wifi-iot/app/iottencent_demo/iot_main.c new file mode 100644 index 0000000..b24ca88 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/iottencent_demo/iot_main.c @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * STEPS: + * 1, CONNECT TO THE IOT SERVER + * 2, SUBSCRIBE THE DEFAULT TOPIC + * 3, WAIT FOR ANY MESSAGE COMES OR ANY MESSAGE TO SEND +*/ + +#include +#include +#include +#include +#include +#include +#include "iot_config.h" +#include "iot_log.h" +#include "iot_hmac.h" +#include "ohos_init.h" +#include "cmsis_os2.h" +#include "iot_watchdog.h" +#include "MQTTClient.h" +#include "iot_errno.h" +#include "iot_main.h" + +// < this is the configuration head +#define CN_IOT_SERVER "tcp://106.55.124.154:1883" // Tencent iot cloud address +#define CONFIG_COMMAND_TIMEOUT 10000L +#define CN_KEEPALIVE_TIME 50 +#define CN_CLEANSESSION 1 +#define CN_HMAC_PWD_LEN 65 // < SHA256 IS 32 BYTES AND END APPEND '\0' +#define CN_EVENT_TIME "1970000100" +#define CN_CLIENTID_FMT "%s_0_0_%s" // < This is the cient ID format, deviceID_0_0_TIME +#define CN_QUEUE_WAITTIMEOUT 1000 +#define CN_QUEUE_MSGNUM 16 +#define CN_QUEUE_MSGSIZE (sizeof(hi_pvoid)) + +#define CN_TASK_PRIOR 28 +#define CN_TASK_STACKSIZE 0X2000 +#define CN_TASK_NAME "IoTMain" + +typedef enum { + EN_IOT_MSG_PUBLISH = 0, + EN_IOT_MSG_RECV, +}EnIotMsg; + +typedef struct { + EnIotMsg type; + int qos; + const char *topic; + const char *payload; +}IoTMsg_t; + +typedef struct { + bool stop; + unsigned int conLost; + unsigned int queueID; + unsigned int iotTaskID; + fnMsgCallBack msgCallBack; + MQTTClient_deliveryToken tocken; +}IotAppCb_t; +static IotAppCb_t gIoTAppCb; + +static const char *gDefaultSubscribeTopic[] = { + /* Tencent iot cloud topic */ + "YT32IOSCAL/Hi38611_mqtt/data", + "YT32IOSCAL/Hi38611_mqtt/event", + "YT32IOSCAL/Hi38611_mqtt/control", +}; + +//#define CN_TOPIC_SUBSCRIBE_NUM (sizeof(gDefaultSubscribeTopic) / sizeof(const char *)) +#define CN_TOPIC_SUBSCRIBE_NUM 3 +static int MsgRcvCallBack(char *context, char *topic, int topicLen, MQTTClient_message *message) +{ + IoTMsg_t *msg; + char *buf; + unsigned int bufSize; + int topiLen = topicLen; + + if (topiLen == 0) { + topiLen = strlen(topic); + } + bufSize = topiLen + 1 + message->payloadlen + 1 + sizeof(IoTMsg_t); + buf = hi_malloc(0, bufSize); + if (buf != NULL) { + msg = (IoTMsg_t *)buf; + buf += sizeof(IoTMsg_t); + bufSize -= sizeof(IoTMsg_t); + msg->qos = message->qos; + msg->type = EN_IOT_MSG_RECV; + (void)memcpy_s(buf, bufSize, topic, topiLen); + buf[topiLen] = '\0'; + msg->topic = buf; + buf += topiLen + 1; + bufSize -= (topiLen + 1); + (void)memcpy_s(buf, bufSize, message->payload, message->payloadlen); + buf[message->payloadlen] = '\0'; + msg->payload = buf; + IOT_LOG_DEBUG("RCVMSG:QOS:%d TOPIC:%s PAYLOAD:%s\r\n", msg->qos, msg->topic, msg->payload); + if (IOT_SUCCESS != osMessageQueuePut(gIoTAppCb.queueID, &msg, 0, CN_QUEUE_WAITTIMEOUT)) { + IOT_LOG_ERROR("Wrie queue failed\r\n"); + hi_free(0, msg); + } + } + + MQTTClient_freeMessage(&message); + MQTTClient_free(topic); + return 1; +} + +// < when the connect lost and this callback will be called +static void ConnLostCallBack(char *context, char *cause) +{ + IOT_LOG_DEBUG("Connection lost:caused by:%s\r\n", cause == NULL? "Unknown" : cause); + return; +} + +static int MqttProcessQueueMsg(MQTTClient client, IoTMsg_t *msg, MQTTClient_message pubMsg) +{ + int ret = 0; + + switch (msg->type) { + case EN_IOT_MSG_PUBLISH: + pubMsg.payload = (void *)msg->payload; + pubMsg.payloadlen = (int)strlen(msg->payload); + pubMsg.qos = msg->qos; + pubMsg.retained = 0; + ret = MQTTClient_publishMessage(client, msg->topic, &pubMsg, &gIoTAppCb.tocken); + if (ret != MQTTCLIENT_SUCCESS) { + IOT_LOG_ERROR("MSGSEND:failed\r\n"); + } + IOT_LOG_DEBUG("MSGSEND:SUCCESS\r\n"); + gIoTAppCb.tocken++; + break; + case EN_IOT_MSG_RECV: + if (gIoTAppCb.msgCallBack != NULL) { + gIoTAppCb.msgCallBack(msg->qos, msg->topic, msg->payload); + } + break; + default: + break; + } +} + +// qos, msg->topic, msg->payload); + MqttProcessQueueMsg(client, msg, pubmsg); + hi_free(0, msg); + } + timeout = 0; // < continous to deal the message without wait here + } while (ret == IOT_SUCCESS); + + return 0; +} + +int MqttDestory(int ret, MQTTClient client) +{ + if (ret != MQTTCLIENT_SUCCESS) { + MQTTClient_destroy(&client); + return -1; + } + return MQTTCLIENT_SUCCESS; +} + +static void MainEntryProcess(void) +{ + int rc = 0, subQos[CN_TOPIC_SUBSCRIBE_NUM] = {1}; + + MQTTClient client = NULL; + MQTTClient_connectOptions connOpts = MQTTClient_connectOptions_initializer; + char *clientID = CN_CLIENTID; + char *userID = CONFIG_USER_ID; + char *userPwd = hi_malloc(0, CN_HMAC_PWD_LEN); + if (userPwd == NULL) { + hi_free(0, clientID); + return; + } + userPwd = CONFIG_USER_PWD; + connOpts.keepAliveInterval = CN_KEEPALIVE_TIME; + connOpts.cleansession = CN_CLEANSESSION; + connOpts.username = userID; + connOpts.password = userPwd; + connOpts.MQTTVersion = MQTTVERSION_3_1_1; + IOT_LOG_DEBUG("CLIENTID:%s USERID:%s USERPWD:%s, IOTSERVER:%s\r\n", + clientID, userID, userPwd==NULL?"NULL" : userPwd, CN_IOT_SERVER); + rc = MQTTClient_create(&client, CN_IOT_SERVER, clientID, MQTTCLIENT_PERSISTENCE_NONE, NULL); + if (rc != MQTTCLIENT_SUCCESS) { + if (userPwd != NULL) { + hi_free(0, userPwd); + } + return; + } + rc = MQTTClient_setCallbacks(client, NULL, ConnLostCallBack, MsgRcvCallBack, NULL); + if (MqttDestory(rc, client) != MQTTCLIENT_SUCCESS) { + return; + } + rc = MQTTClient_connect(client, &connOpts); + if (MqttDestory(rc, client) != MQTTCLIENT_SUCCESS) { + return; + } + for (int i = 0; i < CN_TOPIC_SUBSCRIBE_NUM; i++) { + rc = MQTTClient_subscribeMany(client, CN_TOPIC_SUBSCRIBE_NUM, + (char *const *)gDefaultSubscribeTopic, (int *)&subQos[0]); + if (MqttDestory(rc, client) != MQTTCLIENT_SUCCESS) { + return; + } + } + IOT_LOG_DEBUG ("Connect success and Subscribe success\r\n"); + while (MQTTClient_isConnected(client)) { + ProcessQueueMsg(client); // < do the job here + MQTTClient_yield(); // < make the keepalive done + } + MQTTClient_disconnect(client, CONFIG_COMMAND_TIMEOUT); + return; +} + +/* MQTT processing entry */ +static hi_void *MainEntry(char *arg) +{ + (void)arg; + while (gIoTAppCb.stop == false) { + MainEntryProcess(); + IOT_LOG_DEBUG("The connection lost and we will try another connect\r\n"); + hi_sleep(1000); /* 1000: cpu sleep 1000ms */ + } + return NULL; +} + +int IoTMain(void) +{ + unsigned int ret = 0; + hi_task_attr attr = {0}; + + gIoTAppCb.queueID = osMessageQueueNew(CN_QUEUE_MSGNUM, CN_QUEUE_MSGSIZE, NULL); + if (ret != IOT_SUCCESS) { + IOT_LOG_ERROR("Create the msg queue Failed\r\n"); + } + + attr.stack_size = CN_TASK_STACKSIZE; + attr.task_prio = CN_TASK_PRIOR; + attr.task_name = CN_TASK_NAME; + ret = hi_task_create(&gIoTAppCb.iotTaskID, &attr, MainEntry, NULL); + if (ret != IOT_SUCCESS) { + IOT_LOG_ERROR("Create the Main Entry Failed\r\n"); + } + + return 0; +} + +int IoTSetMsgCallback(fnMsgCallBack msgCallback) +{ + gIoTAppCb.msgCallBack = msgCallback; + return 0; +} + +int IotSendMsg(int qos, const char *topic, const char *payload) +{ + int rc = -1; + IoTMsg_t *msg; + char *buf; + unsigned int bufSize; + + bufSize = strlen(topic) + 1 +strlen(payload) + 1 + sizeof(IoTMsg_t); + buf = hi_malloc(0, bufSize); + if (buf != NULL) { + msg = (IoTMsg_t *)buf; + buf += sizeof(IoTMsg_t); + bufSize -= sizeof(IoTMsg_t); + msg->qos = qos; + msg->type = EN_IOT_MSG_PUBLISH; + (void)memcpy_s(buf, bufSize, topic, strlen(topic)); + buf[strlen(topic)] = '\0'; + msg->topic = buf; + buf += strlen(topic) + 1; + bufSize -= (strlen(topic) + 1); + (void)memcpy_s(buf, bufSize, payload, strlen(payload)); + buf[strlen(payload)] = '\0'; + msg->payload = buf; + IOT_LOG_DEBUG("SNDMSG:QOS:%d TOPIC:%s PAYLOAD:%s\r\n", msg->qos, msg->topic, msg->payload); + if (IOT_SUCCESS != osMessageQueuePut(gIoTAppCb.queueID, &msg, 0, CN_QUEUE_WAITTIMEOUT)) { + IOT_LOG_ERROR("Write queue failed\r\n"); + hi_free(0, msg); + } else { + rc = 0; + } + } + return rc; +} \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/iottencent_demo/iot_main.h b/src/applications/sample/wifi-iot/app/iottencent_demo/iot_main.h new file mode 100644 index 0000000..75d0664 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/iottencent_demo/iot_main.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IOT_MAIN_H +#define IOT_MAIN_H + +typedef void (*fnMsgCallBack)(int qos, const char *topic, const char *payload); + +/** + * This is the iot main function. Please call this function first +*/ +int IoTMain(void); +/** + * Use this function to set the message call back function, when some messages comes, + * the callback will be called, if you don't care about the message, set it to NULL +*/ +int IoTSetMsgCallback(fnMsgCallBack msgCallback); +/** + * When you want to send some messages to the iot server(including the response message), + * please call this api + * @param qos: the mqtt qos,:0,1,2 + * @param topic: the iot mqtt topic + * @param payload: the mqtt payload + * + * @return 0 success while others failed + * + * @instruction: if success means we write the message to the queue susccess, + * not means communicate with the server success +*/ +int IotSendMsg(int qos, const char *topic, const char *payload); + +#endif /* IOT_MAIN_H_ */ \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/iottencent_demo/iot_profile.c b/src/applications/sample/wifi-iot/app/iottencent_demo/iot_profile.c new file mode 100644 index 0000000..d53475e --- /dev/null +++ b/src/applications/sample/wifi-iot/app/iottencent_demo/iot_profile.c @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "iot_main.h" +#include "iot_log.h" +#include "iot_config.h" +#include "iot_profile.h" + +// < format the report data to json string mode +static cJSON *FormateProflleValue(IoTProfileKV_t *kv) +{ + cJSON *ret = NULL; + switch (kv->type) { + case EN_IOT_DATATYPE_INT: + ret = cJSON_CreateNumber(kv->iValue); + break; + case EN_IOT_DATATYPE_LONG: + ret = cJSON_CreateNumber((double)(*(long *)kv->value)); + break; + case EN_IOT_DATATYPE_STRING: + ret = cJSON_CreateString((const char *)kv->value); + break; + default: + break; + } + return ret; +} + +static cJSON *MakeKvs(IoTProfileKV_t *kvlst) +{ + cJSON *root; + cJSON *kv; + IoTProfileKV_t *kvInfo; + + // < build a root node + root = cJSON_CreateObject(); + if (root == NULL) { + cJSON_Delete(root); + root = NULL; + return root; + } + // < add all the property to the properties + kvInfo = kvlst; + while (kvInfo != NULL) { + kv = FormateProflleValue(kvInfo); + if (kv == NULL) { + if (root != NULL) { + cJSON_Delete(root); + root = NULL; + } + return root; + } + cJSON_AddItemToObject(root, kvInfo->key, kv); + kvInfo = kvInfo->nxt; + } + // < OK, now we return it + return root; +} + +#define CN_PROFILE_SERVICE_KEY_SERVICEID "service_id" +#define CN_PROFILE_SERVICE_KEY_PROPERTIIES "properties" +#define CN_PROFILE_SERVICE_KEY_EVENTTIME "event_time" +#define CN_PROFILE_KEY_SERVICES "services" +static cJSON *MakeService(IoTProfileService_t *serviceInfo) +{ + cJSON *root; + cJSON *serviceID; + cJSON *properties; + cJSON *eventTime; + + // < build a root node + root = cJSON_CreateObject(); + if (root == NULL) { + cJSON_Delete(root); + root = NULL; + return root; + } + // < add the serviceID node to the root node + serviceID = cJSON_CreateString(serviceInfo->serviceID); + if (serviceID == NULL) { + if (root != NULL) { + cJSON_Delete(root); + root = NULL; + } + return root; + } + cJSON_AddItemToObjectCS(root, CN_PROFILE_SERVICE_KEY_SERVICEID, serviceID); + // < add the properties node to the root + properties = MakeKvs(serviceInfo->serviceProperty); + if (properties == NULL) { + if (root != NULL) { + cJSON_Delete(root); + root = NULL; + } + return root; + } + cJSON_AddItemToObjectCS(root, CN_PROFILE_SERVICE_KEY_PROPERTIIES, properties); + // < add the event time (optional) to the root + if (serviceInfo->eventTime != NULL) { + eventTime = cJSON_CreateString(serviceInfo->eventTime); + if (eventTime == NULL) { + if (root != NULL) { + cJSON_Delete(root); + root = NULL; + } + return root; + } + cJSON_AddItemToObjectCS(root, CN_PROFILE_SERVICE_KEY_EVENTTIME, eventTime); + } + // < OK, now we return it + cJSON_Delete(properties); + return root; +} + +static cJSON *MakeServices(IoTProfileService_t *serviceInfo) +{ + cJSON *services = NULL; + cJSON *service; + IoTProfileService_t *serviceTmp; + + // < create the services array node + services = cJSON_CreateArray(); + if (services == NULL) { + cJSON_Delete(services); + services = NULL; + return services; + } + + serviceTmp = serviceInfo; + while (serviceTmp != NULL) { + service = MakeService(serviceTmp); + if (service == NULL) { + if (services != NULL) { + cJSON_Delete(services); + services = NULL; + } + return services; + } + cJSON_AddItemToArray(services, service); + serviceTmp = serviceTmp->nxt; + } + // < now we return the services + return services; +} + +// < use this function to make a topic to publish +// < if request_id is needed depends on the fmt +static char *MakeTopic(const char *fmt, const char *deviceID, const char *requestID) +{ + int len; + char *ret = NULL; + + len = strlen(fmt) + strlen(deviceID); + if (requestID != NULL) { + len += strlen(requestID); + } + + ret = hi_malloc(0, len); + if (ret != NULL) { + if (requestID != NULL) { + (void)snprintf_s(ret, len, len, fmt, deviceID, requestID); + } else { + (void)snprintf_s(ret, len, len, fmt, deviceID); + } + } + return ret; +} + +#define CN_PROFILE_CMDRESP_KEY_RETCODE "result_code" +#define CN_PROFILE_CMDRESP_KEY_RESPNAME "response_name" +#define CN_PROFILE_CMDRESP_KEY_PARAS "paras" +static char *MakeProfileCmdResp(IoTCmdResp_t *payload) +{ + char *ret = NULL; + cJSON *root; + cJSON *retCode; + cJSON *respName; + cJSON *paras; + + // < create the root node + root = cJSON_CreateObject(); + if (root == NULL) { + cJSON_Delete(root); + return ret; + } + // < create retcode and retdesc and add it to the root + retCode = cJSON_CreateNumber(payload->retCode); + if (retCode == NULL) { + if (root != NULL) { + cJSON_Delete(root); + } + return ret; + } + cJSON_AddItemToObjectCS(root, CN_PROFILE_CMDRESP_KEY_RETCODE, retCode); + if (payload->respName != NULL) { + respName = cJSON_CreateString(payload->respName); + if (respName == NULL) { + if (root != NULL) { + cJSON_Delete(root); + } + return ret; + } + cJSON_AddItemToObjectCS(root, CN_PROFILE_CMDRESP_KEY_RESPNAME, respName); + } + + if (payload->paras != NULL) { + paras = MakeKvs(payload->paras); + if (paras == NULL) { + if (root != NULL) { + cJSON_Delete(root); + } + return ret; + } + cJSON_AddItemToObjectCS(root, CN_PROFILE_CMDRESP_KEY_PARAS, paras); + } + // < OK, now we make it to a buffer + ret = cJSON_PrintUnformatted(root); + cJSON_Delete(root); + return ret; +} + +static char *MakeProfilePropertyReport(IoTProfileService_t *payload) +{ + char *ret = NULL; + cJSON *root; + cJSON *services; + + // < create the root node + root = cJSON_CreateObject(); + if (root == NULL) { + cJSON_Delete(root); + return ret; + } + // < create the services array node to the root + services = MakeServices(payload); + if (services == NULL) { + if (root != NULL) { + cJSON_Delete(root); + } + return ret; + } + cJSON_AddItemToObjectCS(root, CN_PROFILE_KEY_SERVICES, services); + // < OK, now we make it to a buffer + ret = cJSON_PrintUnformatted(root); + cJSON_Delete(root); + return ret; +} + +#define WECHAT_SUBSCRIBE_TYPE "update" +#define WECHAT_SUBSCRIBE_VERSION "1.0.0" +#define WECHAT_SUBSCRIBE_TOKEN "DeviceSubscribe" +static char *MakeProfileReport(WeChatProfile *payload) +{ + char *ret = NULL; + cJSON *root; + cJSON *state; + cJSON *reported; + + /* create json root node */ + root = cJSON_CreateObject(); + if (root == NULL) { + return; + } + /* state create */ + state = cJSON_CreateObject(); + if (state == NULL) { + return; + } + /* reported create */ + reported = cJSON_CreateObject(); + if (reported == NULL) { + return; + } + /* add root object */ + cJSON_AddItemToObject(root, payload->subscribeType, cJSON_CreateString(WECHAT_SUBSCRIBE_TYPE)); + cJSON_AddItemToObject(root, payload->status.subState, state); + cJSON_AddItemToObject(state, payload->status.subReport, reported); + cJSON_AddItemToObject(root, payload->status.reportVersion, cJSON_CreateString(WECHAT_SUBSCRIBE_VERSION)); + cJSON_AddItemToObject(root, payload->status.Token, cJSON_CreateString(WECHAT_SUBSCRIBE_TOKEN)); + /* add reported item */ + cJSON_AddNumberToObject(reported, payload->reportAction.subDeviceActionLight, + payload->reportAction.lightActionStatus); + cJSON_AddNumberToObject(reported, payload->reportAction.subDeviceActionMotor, + payload->reportAction.motorActionStatus); + cJSON_AddNumberToObject(reported, payload->reportAction.subDeviceActionTemperature, + payload->reportAction.temperatureData); + cJSON_AddNumberToObject(reported, payload->reportAction.subDeviceActionHumidity, + payload->reportAction.humidityActionData); + cJSON_AddNumberToObject(reported, payload->reportAction.subDeviceActionLightIntensity, + payload->reportAction.lightIntensityActionData); + ret = cJSON_PrintUnformatted(root); + cJSON_Delete(state); + cJSON_Delete(reported); + cJSON_Delete(root); + return ret; +} + +#define CN_PROFILE_TOPICFMT_TOPIC "$shadow/operation/19VUBHD786/mqtt" +int IoTProfilePropertyReport(char *deviceID, WeChatProfile *payload) +{ + int ret = -1; + char *topic; + char *msg; + + if ((deviceID == NULL) || (payload== NULL)) { + return ret; + } + topic = MakeTopic(CN_PROFILE_TOPICFMT_TOPIC, deviceID, NULL); + if (topic == NULL) { + return; + } + msg = MakeProfileReport(payload); + if ((topic != NULL) && (msg != NULL)) { + ret = IotSendMsg(0, topic, msg); + } + + hi_free(0, topic); + cJSON_free(msg); + + return ret; +} \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/iottencent_demo/iot_profile.h b/src/applications/sample/wifi-iot/app/iottencent_demo/iot_profile.h new file mode 100644 index 0000000..39d9e78 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/iottencent_demo/iot_profile.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IOT_PROFILE_H +#define IOT_PROFILE_H + +#include +#include "iot_config.h" + +#define OC_BEEP_STATUS_ON ((hi_u8) 0x01) +#define OC_BEEP_STATUS_OFF ((hi_u8) 0x00) + +// < enum all the data type for the oc profile +typedef enum { + EN_IOT_DATATYPE_INT = 0, + EN_IOT_DATATYPE_LONG, + EN_IOT_DATATYPE_FLOAT, + EN_IOT_DATATYPE_DOUBLE, + EN_IOT_DATATYPE_STRING, // < must be ended with '\0' + EN_IOT_DATATYPE_LAST, +}IoTDataType_t; + +typedef enum { + OC_LED_ON = 1, + OC_LED_OFF +}OcLedValue; + +typedef struct { + void *nxt; // < ponit to the next key + const char *key; + const char *value; + hi_u32 iValue; + IoTDataType_t type; +}IoTProfileKV_t; + +typedef struct { + void *nxt; + char *serviceID; + char *eventTime; + IoTProfileKV_t *serviceProperty; +}IoTProfileService_t; + +typedef struct { + int retCode; // < response code, 0 success while others failed + const char *respName; // < response name + const char *requestID; // < specified by the message command + IoTProfileKV_t *paras; // < the command paras +}IoTCmdResp_t; + +typedef struct { + const char *subState; + const char *subReport; + const char *reportVersion; + const char *Token; +}WeChatProfileStatus; + +typedef struct { + int lightActionStatus; + int motorActionStatus; + int temperatureData; + int humidityActionData; + int lightIntensityActionData; + const char *subDeviceActionLight; + const char *subDeviceActionMotor; + const char *subDeviceActionTemperature; + const char *subDeviceActionHumidity; + const char *subDeviceActionLightIntensity; +}WeChatProfileReporte; + +typedef struct { + const char *subscribeType; + WeChatProfileStatus status; + WeChatProfileReporte reportAction; +}WeChatProfile; + +/** + * use this function to report the property to the iot platform +*/ +int IoTProfilePropertyReport(char *deviceID, WeChatProfile *payload); +void cJsonInit(void); +void WifiStaReadyWait(void); +#endif \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/iottencent_demo/iot_sta.c b/src/applications/sample/wifi-iot/app/iottencent_demo/iot_sta.c new file mode 100644 index 0000000..aed1be3 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/iottencent_demo/iot_sta.c @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// < this demo make the wifi to connect to the specified AP +#include +#include +#include +#include +#include +#include +#include +#include "iot_config.h" +#include "iot_log.h" +#include "wifi_device.h" +#include "cmsis_os2.h" +#include "wifi_device_config.h" +#include "lwip/api_shell.h" + +#define APP_INIT_VAP_NUM 2 +#define APP_INIT_USR_NUM 2 + +static struct netif *gLwipNetif = NULL; +static hi_bool gScanDone = HI_FALSE; +unsigned char wifiStatus = 0; + +unsigned char wifiFirstConnecting = 0; +unsigned char wifiSecondConnecting = 0; +unsigned char wifiSecondConnected = 0; +static struct netif* g_iface = NULL; +void WifiStopSta(int netId); +static int WifiStartSta(void); +int cnetId = -1; +int g_connected = 0; + +#define WIFI_CONNECT_STATUS ((unsigned char)0x02) + +void wifiReconnected(int netId) +{ + int recnetId = netId; + if (wifiFirstConnecting == WIFI_CONNECT_STATUS) { + wifiSecondConnecting = HI_TRUE; + wifiFirstConnecting = HI_FALSE; + WifiStopSta(recnetId); + ip4_addr_t ipAddr; + ip4_addr_t ipAny; + IP4_ADDR(&ipAny, 0, 0, 0, 0); + IP4_ADDR(&ipAddr, 0, 0, 0, 0); + recnetId = WifiStartSta(); + netifapi_dhcp_start(gLwipNetif); + while (0 == memcmp(&ipAddr, &ipAny, sizeof(ip4_addr_t))) { + IOT_LOG_DEBUG(":Wait the DHCP READY"); + netifapi_netif_get_addr(gLwipNetif, &ipAddr, NULL, NULL); + hi_sleep(1000); /* 1000: cpu sleep 1000 ms */ + } + wifiSecondConnected = HI_FALSE; + wifiFirstConnecting = WIFI_CONNECT_STATUS; + wifiStatus = HI_WIFI_EVT_CONNECTED; + } +} +/* clear netif's ip, gateway and netmask */ +static void StaResetAddr(struct netif *lwipNetif) +{ + ip4_addr_t st_gw; + ip4_addr_t st_ipaddr; + ip4_addr_t st_netmask; + + if (lwipNetif == NULL) { + IOT_LOG_ERROR("hisi_reset_addr::Null param of netdev"); + return; + } + + IP4_ADDR(&st_gw, 0, 0, 0, 0); + IP4_ADDR(&st_ipaddr, 0, 0, 0, 0); + IP4_ADDR(&st_netmask, 0, 0, 0, 0); + + netifapi_netif_set_addr(lwipNetif, &st_ipaddr, &st_netmask, &st_gw); +} + +static void WpaEventCB(const hi_wifi_event *hisiEvent) +{ + if (hisiEvent == NULL) + return; + IOT_LOG_DEBUG("EVENT_TYPE:%d", hisiEvent->event); + switch (hisiEvent->event) { + case HI_WIFI_EVT_SCAN_DONE: + IOT_LOG_DEBUG("WiFi: Scan results available"); + gScanDone = HI_TRUE; + break; + case HI_WIFI_EVT_CONNECTED: + IOT_LOG_DEBUG("WiFi: Connected"); + netifapi_dhcp_start(gLwipNetif); + wifiStatus = HI_WIFI_EVT_CONNECTED; + if (wifiSecondConnected) { + wifiSecondConnected = HI_FALSE; + wifiFirstConnecting = WIFI_CONNECT_STATUS; + } + break; + case HI_WIFI_EVT_DISCONNECTED: + IOT_LOG_DEBUG("WiFi: Disconnected"); + netifapi_dhcp_stop(gLwipNetif); + StaResetAddr(gLwipNetif); + wifiStatus = HI_WIFI_EVT_DISCONNECTED; + wifiReconnected(cnetId); + break; + case HI_WIFI_EVT_WPS_TIMEOUT: + IOT_LOG_DEBUG("WiFi: wps is timeout"); + wifiStatus = HI_WIFI_EVT_WPS_TIMEOUT; + break; + default: + break; + } +} + +static int StaStartConnect(void) +{ + int ret; + errno_t rc; + hi_wifi_assoc_request assoc_req = {0}; + + /* copy SSID to assoc_req */ + rc = memcpy_s(assoc_req.ssid, HI_WIFI_MAX_SSID_LEN + 1, CONFIG_AP_SSID, strlen(CONFIG_AP_SSID)); + if (rc != EOK) { + return -1; + } + + /* + * OPEN mode + * for WPA2-PSK mode: + * set assoc_req.auth as HI_WIFI_SECURITY_WPA2PSK, + * then memcpy(assoc_req.key, "12345678", 8). + */ + assoc_req.auth = HI_WIFI_SECURITY_WPA2PSK; + rc = memcpy_s(assoc_req.key, HI_WIFI_MAX_KEY_LEN + 1, CONFIG_AP_PWD, strlen(CONFIG_AP_PWD)); + if (rc != EOK) { + return -1; + } + + ret = hi_wifi_sta_connect(&assoc_req); + if (ret != HISI_OK) { + return -1; + } + + return 0; +} + +static void PrintLinkedInfo(WifiLinkedInfo* info) +{ + int ret = 0; + if (!info) { + return; + } + + static char macAddress[32] = {0}; + unsigned char* mac = info->bssid; + if (snprintf_s(macAddress, sizeof(macAddress) + 1, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]) < 0) { /* mac地址从0,1,2,3,4,5位 */ + return; + } +} + +static void OnWifiConnectionChanged(int state, WifiLinkedInfo* info) +{ + if (!info) { + return; + } + + printf("%s %d, state = %d, info = \r\n", __FUNCTION__, __LINE__, state); + PrintLinkedInfo(info); + + if (state == WIFI_STATE_AVALIABLE) { + g_connected = 1; + } else { + g_connected = 0; + } +} + +static void OnWifiScanStateChanged(int state, int size) +{ + printf("%s %d, state = %X, size = %d\r\n", __FUNCTION__, __LINE__, state, size); +} + +static WifiEvent g_defaultWifiEventListener = { + .OnWifiConnectionChanged = OnWifiConnectionChanged, + .OnWifiScanStateChanged = OnWifiScanStateChanged +}; + +static int WifiStartSta(void) +{ + WifiDeviceConfig apConfig = {0}; + strcpy_s(apConfig.ssid, sizeof(CONFIG_AP_SSID), CONFIG_AP_SSID); + strcpy_s(apConfig.preSharedKey, sizeof(CONFIG_AP_PWD), CONFIG_AP_PWD); + apConfig.securityType = WIFI_SEC_TYPE_PSK; + + WifiErrorCode errCode; + int netId = -1; + + errCode = RegisterWifiEvent(&g_defaultWifiEventListener); + printf("RegisterWifiEvent: %d\r\n", errCode); + + errCode = EnableWifi(); + printf("EnableWifi: %d\r\n", errCode); + + errCode = AddDeviceConfig(&apConfig, &netId); + printf("AddDeviceConfig: %d\r\n", errCode); + + g_connected = 0; + errCode = ConnectTo(netId); + printf("ConnectTo(%d): %d\r\n", netId, errCode); + + while (!g_connected) { // wait until connect to AP + osDelay(10); /* 10: os sleep 10ms */ + } + printf("g_connected: %d\r\n", g_connected); + + g_iface = netifapi_netif_find("wlan0"); + if (g_iface) { + err_t ret = netifapi_dhcp_start(g_iface); + printf("netifapi_dhcp_start: %d\r\n", ret); + + osDelay(100); // 100: os sleep 100ms wait DHCP server give me IP + ret = netifapi_netif_common(g_iface, dhcp_clients_info_show, NULL); + printf("netifapi_netif_common: %d\r\n", ret); + } + return netId; +} + +void WifiStopSta(int netId) +{ + int stopNetId = netId; + + if (g_iface) { + err_t ret = netifapi_dhcp_stop(g_iface); + printf("netifapi_dhcp_stop: %d\r\n", ret); + } + + WifiErrorCode errCode = Disconnect(); // disconnect with your AP + printf("Disconnect: %d\r\n", errCode); + + errCode = UnRegisterWifiEvent(&g_defaultWifiEventListener); + printf("UnRegisterWifiEvent: %d\r\n", errCode); + + RemoveDevice(stopNetId); // remove AP config + printf("RemoveDevice: %d\r\n", errCode); + + errCode = DisableWifi(); + printf("DisableWifi: %d\r\n", errCode); +} + +void WifiStaReadyWait(void) +{ + ip4_addr_t ipAddr; + ip4_addr_t ipAny; + IP4_ADDR(&ipAny, 0, 0, 0, 0); + IP4_ADDR(&ipAddr, 0, 0, 0, 0); + cnetId = WifiStartSta(); + IOT_LOG_DEBUG("wifi sta dhcp done"); +} \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/app/samgr/BUILD.gn b/src/applications/sample/wifi-iot/app/samgr/BUILD.gn new file mode 100644 index 0000000..1a8617e --- /dev/null +++ b/src/applications/sample/wifi-iot/app/samgr/BUILD.gn @@ -0,0 +1,36 @@ +# Copyright (c) 2020-2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +static_library("example_samgr") { + sources = [ + "//test/xts/acts/distributed_schedule_lite/samgr_hal/utils/samgr_maintenance.c", + "bootstrap_example.c", + "broadcast_example.c", + "feature_example.c", + "maintenance_example.c", + "service_example.c", + "service_recovery_example.c", + "specified_task_example.c", + "task_example.c", + ] + + include_dirs = [ + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis", + "//foundation/distributedschedule/samgr_lite/interfaces/kits/samgr", + "//foundation/distributedschedule/samgr_lite/interfaces/kits/communication/broadcast", + "//foundation/distributedschedule/samgr_lite/samgr/adapter", + "//foundation/distributedschedule/samgr_lite/samgr/source", + "//test/xts/acts/distributed_schedule_lite/samgr_hal/utils", + ] +} diff --git a/src/applications/sample/wifi-iot/app/samgr/bootstrap_example.c b/src/applications/sample/wifi-iot/app/samgr/bootstrap_example.c new file mode 100644 index 0000000..a5977d7 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/samgr/bootstrap_example.c @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2020-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "example.h" +#include +#include +#include +#include +#include +#include +#include "time_adapter.h" + +typedef struct BootTestExample { + Service service; + Feature feature; +} BootTestExample; + +static const char *GetName(Service *service); +static BOOL Initialize(Service *service, Identity identity); +static BOOL MessageHandle(Service *service, Request *msg); +static TaskConfig GetTaskConfig(Service *service); +static const char *FEATURE_GetName(Feature *feature); +static void FEATURE_OnInitialize(Feature *feature, Service *parent, Identity identity); +static void FEATURE_OnStop(Feature *feature, Identity identity); +static BOOL FEATURE_OnMessage(Feature *feature, Request *request); +static BootTestExample g_example[] = { + { + .service = {GetName, Initialize, MessageHandle, GetTaskConfig}, + .feature = {FEATURE_GetName, FEATURE_OnInitialize, FEATURE_OnStop, FEATURE_OnMessage} + }, { + .service = {GetName, Initialize, MessageHandle, GetTaskConfig}, + .feature = {FEATURE_GetName, FEATURE_OnInitialize, FEATURE_OnStop, FEATURE_OnMessage} + }, { + .service = {GetName, Initialize, MessageHandle, GetTaskConfig}, + .feature = {FEATURE_GetName, FEATURE_OnInitialize, FEATURE_OnStop, FEATURE_OnMessage} + }, { + .service = {GetName, Initialize, MessageHandle, GetTaskConfig}, + .feature = {FEATURE_GetName, FEATURE_OnInitialize, FEATURE_OnStop, FEATURE_OnMessage} + } +}; + +static uint32_t g_initIndex = 0; + +static const char *FEATURE_GetName(Feature *feature) +{ + // test cases service 0 + if (feature == &g_example[0].feature) { + return BOOT_SYS_FEATURE1; + } + // test cases service 1 + if (feature == &g_example[1].feature) { + return BOOT_SYS_FEATURE2; + } + // test cases service 2 + if (feature == &g_example[2].feature) { + return BOOT_SYSEX_FEATURE1; + } + // test cases service 3 + if (feature == &g_example[3].feature) { + return BOOT_SYSEX_FEATURE2; + } + return NULL; +} + +static void FEATURE_OnInitialize(Feature *feature, Service *parent, Identity identity) +{ + (void)identity; + printf("[Boot Test][TaskID:%u][Step:%u][Reg Finish S:%s, F:%s]Time: %llu!\n", + (int)osThreadGetId(), g_initIndex++, parent->GetName(parent), feature->GetName(feature), + SAMGR_GetProcessTime()); +} + +static void FEATURE_OnStop(Feature *feature, Identity identity) +{ + (void)feature; + (void)identity; +} + +static BOOL FEATURE_OnMessage(Feature *feature, Request *request) +{ + printf("[Boot Test][TaskID:%u][Step:%u][F:%s] msgId<%d> \n", + (int)osThreadGetId(), g_initIndex++, feature->GetName(feature), request->msgId); + return FALSE; +} + +static const char *GetName(Service *service) +{ + // test cases service 0 + if (service == &g_example[0].service) { + return BOOT_SYS_SERVICE1; + } + // test cases service 1 + if (service == &g_example[1].service) { + return BOOT_SYS_SERVICE2; + } + // test cases service 2 + if (service == &g_example[2].service) { + return BOOT_SYSEX_SERVICE1; + } + // test cases service 3 + if (service == &g_example[3].service) { + return BOOT_SYSEX_SERVICE2; + } + return NULL; +} + +static BOOL Initialize(Service *service, Identity identity) +{ + (void)identity; + printf("[Boot Test][TaskID:%u][Step:%u][Reg Finish S:%s]Time: %llu!\n", + (int)osThreadGetId(), g_initIndex++, service->GetName(service), SAMGR_GetProcessTime()); + return TRUE; +} + +static BOOL MessageHandle(Service *service, Request *msg) +{ + printf("[Boot Test][TaskID:%u][Step:%u][S:%s] msgId<%d> \n", + (int)osThreadGetId(), g_initIndex++, service->GetName(service), msg->msgId); + return FALSE; +} + +static TaskConfig GetTaskConfig(Service *service) +{ + (void)service; + TaskConfig config = {LEVEL_HIGH, PRI_ABOVE_NORMAL, + 0x400, 2, SHARED_TASK}; + return config; +} + +static void MInit(void) +{ + printf("[Boot Test][TaskID:%u][Step:%u][CORE INIT]Time: %llu!\n", + (int)osThreadGetId(), g_initIndex++, SAMGR_GetProcessTime()); +} +static void MRun(void) +{ + printf("[Boot Test][TaskID:%u][Step:%u][SYS RUN]Time: %llu!\n", + (int)osThreadGetId(), g_initIndex++, SAMGR_GetProcessTime()); +} + +static void SInit(BootTestExample *demo) +{ + SAMGR_GetInstance()->RegisterService(&demo->service); + + // test cases service 2 + printf((demo < &g_example[2]) ? + "[Boot Test][TaskID:%u][Step:%u][SYS Reg S:%s]Time: %llu!\n" : + "[Boot Test][TaskID:%u][Step:%u][SYSEX Reg S:%s]Time: %llu!\n", + (int)osThreadGetId(), g_initIndex++, demo->service.GetName(&demo->service), SAMGR_GetProcessTime()); +} + +static void FInit(BootTestExample *demo) +{ + SAMGR_GetInstance()->RegisterFeature(demo->service.GetName(&demo->service), &demo->feature); + + // test cases service 2 + printf((demo < &g_example[2]) ? + "[Boot Test][TaskID:%u][Step:%u][SYS Reg S:%s, F:%s]Time: %llu!\n" : + "[Boot Test][TaskID:%u][Step:%u][SYSEX Reg S:%s, F:%s]Time: %llu!\n", + (int)osThreadGetId(), g_initIndex++, demo->service.GetName(&demo->service), + demo->feature.GetName(&demo->feature), SAMGR_GetProcessTime()); +} + +static void S1Init(void) +{ + // test cases service 0 + SInit(&g_example[0]); +} + +static void S2Init(void) +{ + // test cases service 1 + SInit(&g_example[1]); +} + +static void F1Init(void) +{ + // test cases feature 0 + FInit(&g_example[0]); +} + +static void F2Init(void) +{ + // test cases feature 1 + FInit(&g_example[1]); +} + +static void S3Init(void) +{ + // test cases service 2 + SInit(&g_example[2]); +} + +static void S4Init(void) +{ + // test cases service 3 + SInit(&g_example[3]); +} + +static void F3Init(void) +{ + // test cases feature 2 + FInit(&g_example[2]); +} + +static void F4Init(void) +{ + // test cases feature 3 + FInit(&g_example[3]); +} + +CORE_INIT(MInit); +SYS_RUN(MRun); +// init pri first +SYS_SERVICE_INIT_PRI(S1Init, 0); +// init pri second +SYS_SERVICE_INIT_PRI(S2Init, 1); +// init pri first +SYS_FEATURE_INIT_PRI(F1Init, 0); +// init pri second +SYS_FEATURE_INIT_PRI(F2Init, 1); +// init pri first +SYSEX_SERVICE_INIT_PRI(S3Init, 0); +// init pri second +SYSEX_SERVICE_INIT_PRI(S4Init, 1); +// init pri first +SYSEX_FEATURE_INIT_PRI(F3Init, 0); +// init pri second +SYSEX_FEATURE_INIT_PRI(F4Init, 1); diff --git a/src/applications/sample/wifi-iot/app/samgr/broadcast_example.c b/src/applications/sample/wifi-iot/app/samgr/broadcast_example.c new file mode 100644 index 0000000..5449be1 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/samgr/broadcast_example.c @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2020-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "samgr_lite.h" +#include "broadcast_interface.h" +#include +#include +#include +#include +#include "time_adapter.h" + +#define TEST_LEN 10 +#define WAIT_PUB_PROC 1000 +#define BROADCAST_TEST_SERVICE "broadcast test" + +static uint32_t g_callbackStep = 0; + +static void C1Callback(Consumer *consumer, const Topic *topic, const Request *request) +{ + (void)consumer; + (void)topic; + printf("[Broadcast Test][TaskID:%u][Step:%u][C1 Callback]c1 is being called data is :%s \n", + (int)osThreadGetId(), g_callbackStep++, (char *)request->data); +} + +static void C2Callback(Consumer *consumer, const Topic *topic, const Request *request) +{ + (void)consumer; + (void)topic; + printf("[Broadcast Test][TaskID:%u][Step:%u][C2 Callback]c2 is being called data is :%s \n", + (int)osThreadGetId(), g_callbackStep++, (char *)request->data); +} + +static BOOL Equal(const Consumer *current, const Consumer *other) +{ + return (current->Notify == other->Notify); +} + +static const char *GetName(Service *service) +{ + (void)service; + return BROADCAST_TEST_SERVICE; +}; + +static Identity g_identity = { -1, -1, NULL}; +static volatile uint32_t g_broadcastStep = 0; + +static BOOL Initialize(Service *service, Identity identity) +{ + g_identity = identity; + (void)service; + printf("[Broadcast Test][TaskID:%u][Step:%u][Reg Finish S:%s]Time: %llu!\n", + (int)osThreadGetId(), g_broadcastStep++, BROADCAST_TEST_SERVICE, SAMGR_GetProcessTime()); + return TRUE; +}; + +static BOOL MessageHandle(Service *service, Request *msg) +{ + printf("[Broadcast Test][TaskID:%u] msgId<%d>: %s \n", (int)osThreadGetId(), msg->msgId, (char *)msg->data); + (void)service; + return FALSE; +}; + +static TaskConfig GetTaskConfig(Service *service) +{ + TaskConfig config = {LEVEL_HIGH, PRI_ABOVE_NORMAL, 0x800, 20, SHARED_TASK}; + (void)service; + return config; +}; + +static Service g_testService = {GetName, Initialize, MessageHandle, GetTaskConfig}; + +static void Init(void) +{ + SAMGR_GetInstance()->RegisterService(&g_testService); + printf("[Broadcast Test][TaskID:%u][Step:%u][Reg S:%s]Time: %llu!\n", + (int)osThreadGetId(), g_broadcastStep++, BROADCAST_TEST_SERVICE, SAMGR_GetProcessTime()); +} + +SYSEX_SERVICE_INIT(Init); + +static PubSubInterface *CASE_GetIUnknown(void) +{ + PubSubInterface *fapi = NULL; + printf("[Broadcast Test][TaskID:%u][Step:%u][GetIUnknown S:%s]: BEGIN\n", + (int)osThreadGetId(), g_broadcastStep++, BROADCAST_TEST_SERVICE); + IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(BROADCAST_SERVICE, PUB_SUB_FEATURE); + if (iUnknown == NULL) { + printf("[Broadcast Test][TaskID:%u][Step:%u][GetDefaultFeatureApi S:%s]Error is NULL!\n", + (int)osThreadGetId(), g_broadcastStep++, BROADCAST_TEST_SERVICE); + goto END; + } + + int result = iUnknown->QueryInterface(iUnknown, DEFAULT_VERSION, (void **)&fapi); + if (result != 0 || fapi == NULL) { + printf("[Broadcast Test][TaskID:%u][Step:%u][QueryInterface S:%s]Error is NULL!\n", + (int)osThreadGetId(), g_broadcastStep++, BROADCAST_TEST_SERVICE); + goto END; + } + printf("[Broadcast Test][TaskID:%u][Step:%u][GetIUnknown S:%s]Success\n", + (int)osThreadGetId(), g_broadcastStep++, BROADCAST_TEST_SERVICE); +END: + printf("[Broadcast Test][TaskID:%u][Step:%u][GetIUnknown S:%s]: END\n", + (int)osThreadGetId(), g_broadcastStep++, BROADCAST_TEST_SERVICE); + return fapi; +} + +static uint32_t g_addTopicStep = 0; +static uint32_t g_unsubscribeTopicStep = 0; + +static void CASE_AddAndUnsubscribeTopic(PubSubInterface *fapi) +{ + Subscriber *subscriber = &fapi->subscriber; + Provider *provider = &fapi->provider; + static Consumer c1 = {.identity = &g_identity, .Notify = C1Callback, .Equal = Equal}; + static Consumer c2 = {.identity = &g_identity, .Notify = C2Callback, .Equal = Equal}; + // add topic test + printf("[Topic Test][TaskID:%u][Step:%u][Add Topic]: BEGIN\n", (int)osThreadGetId(), g_addTopicStep++); + Topic topic0 = 0; + subscriber->AddTopic((IUnknown *)fapi, &topic0); + subscriber->Subscribe((IUnknown *)fapi, &topic0, &c1); + subscriber->Subscribe((IUnknown *)fapi, &topic0, &c2); + provider->Publish((IUnknown *)fapi, &topic0, (uint8_t *) "==>111<==", TEST_LEN); + Topic topic1 = 0x10000; + subscriber->AddTopic((IUnknown *)fapi, &topic1); + subscriber->Subscribe((IUnknown *)fapi, &topic1, &c1); + subscriber->Subscribe((IUnknown *)fapi, &topic1, &c2); + provider->Publish((IUnknown *)fapi, &topic1, (uint8_t *) "==>444<==", TEST_LEN); + printf("[Topic Test][TaskID:%u][Step:%u][Add Topic]: Success!\n", (int)osThreadGetId(), g_addTopicStep++); + printf("[Topic Test][TaskID:%u][Step:%u][Add Topic]: END\n", (int)osThreadGetId(), g_addTopicStep++); + // unsubscribe topic0 test + printf("[Topic Test][TaskID:%u][Step:%u][Unsubscribe Topic]: BEGIN\n", (int)osThreadGetId(), + g_unsubscribeTopicStep++); + LOS_Msleep(WAIT_PUB_PROC); + subscriber->Unsubscribe((IUnknown *)fapi, &topic0, &c1); + provider->Publish((IUnknown *)fapi, &topic0, (uint8_t *) "@@@222@@@", TEST_LEN); + LOS_Msleep(WAIT_PUB_PROC); + subscriber->Unsubscribe((IUnknown *)fapi, &topic0, &c2); + provider->Publish((IUnknown *)fapi, &topic0, (uint8_t *) "@@@333@@@", TEST_LEN); + provider->Publish((IUnknown *)fapi, &topic1, (uint8_t *) "@@@444@@@", TEST_LEN); + printf("[Topic Test][TaskID:%u][Step:%u][Unsubscribe Topic]: Success!\n", + (int)osThreadGetId(), g_unsubscribeTopicStep++); + printf("[Topic Test][TaskID:%u][Step:%u][Unsubscribe Topic]: END\n", (int)osThreadGetId(), + g_unsubscribeTopicStep++); +} + +static uint32_t g_modifyConsumerStep = 0; + +static void CASE_ModifyConsumer(PubSubInterface *fapi) +{ + Subscriber *subscriber = &fapi->subscriber; + Provider *provider = &fapi->provider; + static Consumer c1 = {.identity = &g_identity, .Notify = C1Callback, .Equal = Equal}; + static Consumer c2 = {.identity = &g_identity, .Notify = C2Callback, .Equal = Equal}; + // modify consumer test + printf("[Topic Test][TaskID:%u][Step:%u][Modify Consumer]: BEGIN\n", (int)osThreadGetId(), + g_modifyConsumerStep++); + Topic topic2 = 0x100; + subscriber->AddTopic((IUnknown *)fapi, &topic2); + subscriber->Subscribe((IUnknown *)fapi, &topic2, &c1); + provider->Publish((IUnknown *)fapi, &topic2, (uint8_t *) "==>555<==", TEST_LEN); + LOS_Msleep(WAIT_PUB_PROC); + subscriber->ModifyConsumer((IUnknown *)fapi, &topic2, &c1, &c2); + provider->Publish((IUnknown *)fapi, &topic2, (uint8_t *) "@@@555@@@", TEST_LEN); + printf("[Topic Test][TaskID:%u][Step:%u][Modify Consumer]: Success!\n", (int)osThreadGetId(), + g_modifyConsumerStep++); + printf("[Topic Test][TaskID:%u][Step:%u][Modify Consumer]: END\n", (int)osThreadGetId(), + g_modifyConsumerStep++); +} + +static uint32_t g_reUnsubscribeTopic = 0; + +static void CASE_ReUnsubscribeTopic(PubSubInterface *fapi) +{ + Subscriber *subscriber = &fapi->subscriber; + Provider *provider = &fapi->provider; + static Consumer c1 = {.identity = &g_identity, .Notify = C1Callback, .Equal = Equal}; + printf("[Topic Test][TaskID:%u][Step:%u][ReUnsubscribe Topic]: BEGIN\n", (int)osThreadGetId(), + g_reUnsubscribeTopic++); + Topic topic3 = 0x1000; + subscriber->AddTopic((IUnknown *)fapi, &topic3); + subscriber->Subscribe((IUnknown *)fapi, &topic3, &c1); + provider->Publish((IUnknown *)fapi, &topic3, (uint8_t *) "==>666<==", TEST_LEN); + LOS_Msleep(WAIT_PUB_PROC); + Consumer *retConsumer = subscriber->Unsubscribe((IUnknown *)fapi, &topic3, &c1); + if (retConsumer == NULL) { + printf("[Topic Test][TaskID:%u][Step:%u][ReUnsubscribe Topic]: Unsubscribe Topic lead to NULL return value\n", + (int)osThreadGetId(), g_reUnsubscribeTopic++); + } + retConsumer = subscriber->Unsubscribe((IUnknown *)fapi, &topic3, &c1); + if (retConsumer == NULL) { + printf("[Topic Test][TaskID:%u][Step:%u][ReUnsubscribe Topic]: ReUnsubscribe Topic lead to NULL return value\n", + (int)osThreadGetId(), g_reUnsubscribeTopic++); + } + provider->Publish((IUnknown *)fapi, &topic3, (uint8_t *) "@@@666@@@", TEST_LEN); + printf("[Topic Test][TaskID:%u][Step:%u][ReUnsubscribe Topic]: Success!\n", + (int)osThreadGetId(), g_reUnsubscribeTopic++); + printf("[Topic Test][TaskID:%u][Step:%u][ReUnsubscribe Topic]: END\n", (int)osThreadGetId(), + g_reUnsubscribeTopic++); +} + +static void CASE_ReleaseIUnknown(PubSubInterface *fapi) +{ + printf("[Broadcast Test][TaskID:%u][Step:%u][ReleaseIUnknown S:%s]: BEGIN\n", + (int)osThreadGetId(), g_broadcastStep++, BROADCAST_TEST_SERVICE); + int32 ref = fapi->Release((IUnknown *)fapi); + if (ref <= 0) { + printf("[Broadcast Test][TaskID:%u][Step:%u][ReleaseIUnknown S:%s]Error ref is %d!\n", + (int)osThreadGetId(), g_broadcastStep++, BROADCAST_TEST_SERVICE, ref); + goto END; + } + printf("[Broadcast Test][TaskID:%u][Step:%u][ReleaseIUnknown S:%s]Success\n", + (int)osThreadGetId(), g_broadcastStep++, BROADCAST_TEST_SERVICE); +END: + printf("[Broadcast Test][TaskID:%u][Step:%u][ReleaseIUnknown S:%s]: END\n", + (int)osThreadGetId(), g_broadcastStep++, BROADCAST_TEST_SERVICE); +} + +static void RunTestCase(void) +{ + PubSubInterface *fapi = CASE_GetIUnknown(); + CASE_AddAndUnsubscribeTopic(fapi); + CASE_ModifyConsumer(fapi); + CASE_ReUnsubscribeTopic(fapi); + CASE_ReleaseIUnknown(fapi); +} + +LAYER_INITCALL_DEF(RunTestCase, test, "test"); diff --git a/src/applications/sample/wifi-iot/app/samgr/example.h b/src/applications/sample/wifi-iot/app/samgr/example.h new file mode 100644 index 0000000..ebecce6 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/samgr/example.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2020-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef LITE_EXAMPLE_H +#define LITE_EXAMPLE_H + +#define EXAMPLE_SERVICE "example" +#define EXAMPLE_FEATURE "example" + +#define BOOT_SYS_SERVICE1 "sys_s1" +#define BOOT_SYS_SERVICE2 "sys_s2" +#define BOOT_SYS_FEATURE1 "sys_f1" +#define BOOT_SYS_FEATURE2 "sys_f2" + +#define BOOT_SYSEX_SERVICE1 "sysex_s1" +#define BOOT_SYSEX_SERVICE2 "sysex_s2" +#define BOOT_SYSEX_FEATURE1 "sysex_f1" +#define BOOT_SYSEX_FEATURE2 "sysex_f2" + +#define TASK_SERVICE1 "task_s1" +#define TASK_SERVICE2 "task_s2" +#define TASK_SERVICE3 "task_s3" +#define TASK_SERVICE4 "task_s4" + +#endif // LITE_EXAMPLE_H diff --git a/src/applications/sample/wifi-iot/app/samgr/feature_example.c b/src/applications/sample/wifi-iot/app/samgr/feature_example.c new file mode 100644 index 0000000..692f469 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/samgr/feature_example.c @@ -0,0 +1,320 @@ +/* + * Copyright (c) 2020-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "example.h" +#include +#include +#include +#include +#include +#include +#include "iunknown.h" +#include "feature.h" +#include "service.h" +#include "samgr_lite.h" +#include "time_adapter.h" + +#define WAIT_FEATURE_PROC 1000 + +enum MessageId { + MSG_PROC, + MSG_TIME_PROC, +}; + +struct Payload { + int id; + const char *name; + int value; +}; + +typedef struct DemoApi { + INHERIT_IUNKNOWN; + BOOL (*AsyncCall)(IUnknown *iUnknown, const char *buff); + BOOL (*AsyncTimeCall)(IUnknown *iUnknown); + BOOL (*SyncCall)(IUnknown *iUnknown, struct Payload *payload); + BOOL (*AsyncCallBack)(IUnknown *iUnknown, const char *buff, Handler handler); +} DemoApi; + +typedef struct DemoFeature { + INHERIT_FEATURE; + INHERIT_IUNKNOWNENTRY(DemoApi); + Identity identity; +} DemoFeature; + +static BOOL AsyncCall(IUnknown *iUnknown, const char *body); +static BOOL AsyncTimeCall(IUnknown *iUnknown); +static BOOL SyncCall(IUnknown *iUnknown, struct Payload *payload); +static BOOL AsyncCallBack(IUnknown *iUnknown, const char *body, Handler handler); +static const char *FEATURE_GetName(Feature *feature); +static void FEATURE_OnInitialize(Feature *feature, Service *parent, Identity identity); +static void FEATURE_OnStop(Feature *feature, Identity identity); +static BOOL FEATURE_OnMessage(Feature *feature, Request *request); +static DemoFeature g_example = { + .GetName = FEATURE_GetName, + .OnInitialize = FEATURE_OnInitialize, + .OnStop = FEATURE_OnStop, + .OnMessage = FEATURE_OnMessage, + DEFAULT_IUNKNOWN_ENTRY_BEGIN, + .AsyncCall = AsyncCall, + .AsyncTimeCall = AsyncTimeCall, + .SyncCall = SyncCall, + .AsyncCallBack = AsyncCallBack, + DEFAULT_IUNKNOWN_ENTRY_END, + .identity = {-1, -1, NULL}, +}; +static uint32_t g_regStep = 0; + +static const char *FEATURE_GetName(Feature *feature) +{ + (void)feature; + return EXAMPLE_FEATURE; +} + +static void FEATURE_OnInitialize(Feature *feature, Service *parent, Identity identity) +{ + DemoFeature *demoFeature = (DemoFeature *)feature; + demoFeature->identity = identity; + printf("[Register Test][TaskID:%u][Step:%u][Reg Finish S:%s, F:%s]Time: %llu!\n", + (int)osThreadGetId(), g_regStep++, parent->GetName(parent), feature->GetName(feature), + SAMGR_GetProcessTime()); +} + +static void FEATURE_OnStop(Feature *feature, Identity identity) +{ + (void)feature; + (void)identity; + g_example.identity.queueId = NULL; + g_example.identity.featureId = -1; + g_example.identity.serviceId = -1; +} + +static volatile uint32 g_asyncStep = 0; + +static BOOL FEATURE_OnMessage(Feature *feature, Request *request) +{ + (void)feature; + if (request->msgId == MSG_PROC) { + printf("[LPC Test][TaskID:%u][Step:%u][OnMessage: S:%s, F:%s] msgId %s \n", + (int)osThreadGetId(), g_asyncStep++, EXAMPLE_SERVICE, feature->GetName(feature), + (char *)request->data); + Response response = {.data = "Yes, you did!", .len = 0}; + SAMGR_SendResponse(request, &response); + return TRUE; + } else { + if (request->msgId == MSG_TIME_PROC) { + LOS_Msleep(WAIT_FEATURE_PROC * 11); // sleep 11 seconds + printf("[LPC Test][TaskID:%u][OnMessage: S:%s, F:%s] Time Message Get Value<%s>!", + (int)osThreadGetId(), EXAMPLE_SERVICE, feature->GetName(feature), + request->msgValue ? "TRUE" : "FALSE"); + AsyncTimeCall(GET_IUNKNOWN(g_example)); + return FALSE; + } + } + printf("[LPC Test][TaskID:%u][Step:%u][OnMessage S:%s, F:%s] Inner Error! \n", + (int)osThreadGetId(), g_asyncStep++, EXAMPLE_SERVICE, feature->GetName(feature)); + return FALSE; +} + +static BOOL SyncCall(IUnknown *iUnknown, struct Payload *payload) +{ + (void)iUnknown; + if (payload != NULL && payload->id >= 0 && payload->name != NULL) { + printf("[LPC Test][TaskID:%u][Step:%u][SyncCall API] Id:%d, name:%s, value:%d \n", + (int)osThreadGetId(), g_asyncStep++, payload->id, payload->name, payload->value); + return TRUE; + } + printf("[LPC Test][TaskID:%u][Step:%u][SyncCall API] Input Error! \n", (int)osThreadGetId(), g_asyncStep++); + return FALSE; +} + +static BOOL AsyncCall(IUnknown *iUnknown, const char *body) +{ + Request request = {.msgId = MSG_PROC, .msgValue = 0}; + request.len = (uint32_t)(strlen(body) + 1); + request.data = malloc(request.len); + if (request.data == NULL) { + return FALSE; + } + if (strcpy_s(request.data, request.len, body) != EOK) { + free(request.data); + return FALSE; + } + DemoFeature *feature = GET_OBJECT(iUnknown, DemoFeature, iUnknown); + printf("[LPC Test][TaskID:%u][Step:%u][AsyncCall API] Send request! \n", (int)osThreadGetId(), g_asyncStep++); + return SAMGR_SendRequest(&feature->identity, &request, NULL); +} + +static BOOL AsyncTimeCall(IUnknown *iUnknown) +{ + static int8 cnt = 0; + cnt = (cnt + 1) % 2; // mod 2 to get async status + Request request = {.msgId = MSG_TIME_PROC, .msgValue = cnt}; + DemoFeature *feature = GET_OBJECT(iUnknown, DemoFeature, iUnknown); + return SAMGR_SendRequest(&feature->identity, &request, NULL); +} + +static BOOL AsyncCallBack(IUnknown *iUnknown, const char *body, Handler handler) +{ + Request request = {.msgId = MSG_PROC, .msgValue = 0}; + request.len = (uint32_t)(strlen(body) + 1); + request.data = malloc(request.len); + if (request.data == NULL) { + return FALSE; + } + if (strcpy_s(request.data, request.len, body) != EOK) { + free(request.data); + return FALSE; + } + DemoFeature *feature = GET_OBJECT(iUnknown, DemoFeature, iUnknown); + printf("[LPC Test][TaskID:%u][Step:%u][AsyncCallBack API] Send request! \n", + (int)osThreadGetId(), g_asyncStep++); + return SAMGR_SendRequest(&feature->identity, &request, handler); +} + +static void Init(void) +{ + SAMGR_GetInstance()->RegisterFeature(EXAMPLE_SERVICE, (Feature *)&g_example); + SAMGR_GetInstance()->RegisterFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE, GET_IUNKNOWN(g_example)); + printf("[Register Test][TaskID:%u][Step:%u][Reg S:%s, F:%s]Time: %llu!\n", + (int)osThreadGetId(), g_regStep++, EXAMPLE_SERVICE, EXAMPLE_FEATURE, SAMGR_GetProcessTime()); +} + +SYSEX_FEATURE_INIT(Init); + +static uint32_t g_discoverStep = 0; + +static DemoApi *CASE_GetIUnknown(void) +{ + DemoApi *demoApi = NULL; + printf("[Discover Test][TaskID:%u][Step:%u][GetIUnknown S:%s, F:%s]: BEGIN\n", + (int)osThreadGetId(), g_discoverStep++, EXAMPLE_SERVICE, EXAMPLE_FEATURE); + IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE); + if (iUnknown == NULL) { + printf("[Discover Test][TaskID:%u][Step:%u][GetFeatureApi S:%s, F:%s]Error is NULL!\n", + (int)osThreadGetId(), g_discoverStep++, EXAMPLE_SERVICE, EXAMPLE_FEATURE); + goto END; + } + int result = iUnknown->QueryInterface(iUnknown, DEFAULT_VERSION, (void **)&demoApi); + if (result != 0 || demoApi == NULL) { + printf("[Discover Test][TaskID:%u][Step:%u][QueryInterface S:%s, F:%s]Error is NULL!\n", + (int)osThreadGetId(), g_discoverStep++, EXAMPLE_SERVICE, EXAMPLE_FEATURE); + goto END; + } + printf("[Discover Test][TaskID:%u][Step:%u][GetIUnknown S:%s, F:%s]Success\n", + (int)osThreadGetId(), g_discoverStep++, EXAMPLE_SERVICE, EXAMPLE_FEATURE); +END: + printf("[Discover Test][TaskID:%u][Step:%u][GetIUnknown S:%s, F:%s]: END\n", + (int)osThreadGetId(), g_discoverStep++, EXAMPLE_SERVICE, EXAMPLE_FEATURE); + return demoApi; +} + +static void CASE_SyncCall(DemoApi *demoApi) +{ + if (demoApi->SyncCall == NULL) { + return; + } + printf("[LPC Test][TaskID:%u][Step:%u][SyncCall]: BEGIN! \n", (int)osThreadGetId(), g_asyncStep++); + struct Payload payload = { + .id = 0, + .name = "I want to sync call good result!", + .value = 1 + }; + if (!demoApi->SyncCall((IUnknown *)demoApi, &payload)) { + printf("[LPC Test][TaskID:%u][Step:%u][SyncCall]Error return false! \n", + (int)osThreadGetId(), g_asyncStep++); + goto END; + } + printf("[LPC Test][TaskID:%u][Step:%u][SyncCall]Success!\n", + (int)osThreadGetId(), g_asyncStep++); +END: + printf("[LPC Test][TaskID:%u][Step:%u][SyncCall]: END\n", + (int)osThreadGetId(), g_asyncStep++); +} + + +static void CASE_AsyncCall(DemoApi *demoApi) +{ + if (demoApi->AsyncCall == NULL) { + return; + } + printf("[LPC Test][TaskID:%u][Step:%u][AsyncCall]: BEGIN! \n", (int)osThreadGetId(), g_asyncStep++); + uint32 count = g_asyncStep; + demoApi->AsyncCall((IUnknown *)demoApi, "I want to async call good result!"); + LOS_Msleep(WAIT_FEATURE_PROC); + if (count == g_asyncStep) { + printf("[LPC Test][TaskID:%u][Step:%u][AsyncCall] result is failed! \n", (int)osThreadGetId(), + g_asyncStep++); + goto END; + } + printf("[LPC Test][TaskID:%u][Step:%u][AsyncCall]Success! \n", (int)osThreadGetId(), g_asyncStep++); +END: + printf("[LPC Test][TaskID:%u][Step:%u][AsyncCall]: END! \n", (int)osThreadGetId(), g_asyncStep++); +} + +static void CASE_AsyncTimeCall(DemoApi *demoApi) +{ + if (demoApi->AsyncCall == NULL) { + return; + } + demoApi->AsyncTimeCall((IUnknown *)demoApi); +} + +void AsyncHandler(const Request *request, const Response *response) +{ + (void)request; + printf("[LPC Test][TaskID:%u][Step:%u][AsyncCallBack]Success! Response:%s \n", + (int)osThreadGetId(), g_asyncStep++, (char *)response->data); + printf("[LPC Test][TaskID:%u][Step:%u][AsyncCallBack]: END! \n", (int)osThreadGetId(), g_asyncStep++); +} + +static void CASE_AsyncCallBack(DemoApi *demoApi) +{ + if (demoApi->AsyncCallBack == NULL) { + return; + } + printf("[LPC Test][TaskID:%u][Step:%u][AsyncCallBack]: BEGIN! \n", (int)osThreadGetId(), g_asyncStep++); + demoApi->AsyncCallBack((IUnknown *)demoApi, "I want to async call callback good result!", AsyncHandler); + printf("[LPC Test][TaskID:%u][Step:%u][AsyncCallBack]Wait for response! \n", + (int)osThreadGetId(), g_asyncStep++); +} + +static void CASE_ReleaseIUnknown(DemoApi *demoApi) +{ + printf("[Discover Test][TaskID:%u][Step:%u][ReleaseIUnknown S:%s, F:%s]: BEGIN\n", + (int)osThreadGetId(), g_discoverStep++, EXAMPLE_SERVICE, EXAMPLE_FEATURE); + int32 ref = demoApi->Release((IUnknown *)demoApi); + if (ref <= 0) { + printf("[Discover Test][TaskID:%u][Step:%u][ReleaseIUnknown S:%s, F:%s]Error ref is %d!\n", + (int)osThreadGetId(), g_discoverStep++, EXAMPLE_SERVICE, EXAMPLE_FEATURE, ref); + goto END; + } + printf("[Discover Test][TaskID:%u][Step:%u][ReleaseIUnknown S:%s, F:%s]Success\n", + (int)osThreadGetId(), g_discoverStep++, EXAMPLE_SERVICE, EXAMPLE_FEATURE); +END: + printf("[Discover Test][TaskID:%u][Step:%u][ReleaseIUnknown S:%s, F:%s]: END\n", + (int)osThreadGetId(), g_discoverStep++, EXAMPLE_SERVICE, EXAMPLE_FEATURE); +} + +static void RunTestCase(void) +{ + DemoApi *demoApi = CASE_GetIUnknown(); + CASE_SyncCall(demoApi); + CASE_AsyncCall(demoApi); + CASE_AsyncCallBack(demoApi); + CASE_AsyncTimeCall(demoApi); + CASE_ReleaseIUnknown(demoApi); +} + +LAYER_INITCALL_DEF(RunTestCase, test, "test"); diff --git a/src/applications/sample/wifi-iot/app/samgr/maintenance_example.c b/src/applications/sample/wifi-iot/app/samgr/maintenance_example.c new file mode 100644 index 0000000..b75240a --- /dev/null +++ b/src/applications/sample/wifi-iot/app/samgr/maintenance_example.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2020-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include "service.h" +#include "feature.h" +#include "samgr_lite.h" + +#define MAINTEN_SERVICE1 "mntn_s1" +#define MAINTEN_SERVICE2 "mntn_s2" +#define MAINTEN_SERVICE3 "mntn_s3" +#define MAINTEN_SERVICE4 "mntn_s4" +#define MAINTEN_FEATURE1 "mntn_f1" +#define MAINTEN_FEATURE2 "mntn_f2" + +static const char *GetName(Service *service); +static BOOL Initialize(Service *service, Identity identity); +static BOOL MessageHandle(Service *service, Request *msg); +static TaskConfig GetTaskConfig(Service *service); +static const char *FEATURE_GetName(Feature *feature); +static void FEATURE_OnInitialize(Feature *feature, Service *parent, Identity identity); +static void FEATURE_OnStop(Feature *feature, Identity identity); +static BOOL FEATURE_OnMessage(Feature *feature, Request *request); + +Service g_maintenExample1 = {GetName, Initialize, MessageHandle, GetTaskConfig}; +Service g_maintenExample2 = {GetName, Initialize, MessageHandle, GetTaskConfig}; +Service g_maintenExample3 = {GetName, Initialize, MessageHandle, GetTaskConfig}; +Service g_maintenExample4 = {GetName, Initialize, MessageHandle, GetTaskConfig}; +Feature g_maintenFeature1 = {FEATURE_GetName, FEATURE_OnInitialize, FEATURE_OnStop, FEATURE_OnMessage}; +Feature g_maintenFeature2 = {FEATURE_GetName, FEATURE_OnInitialize, FEATURE_OnStop, FEATURE_OnMessage}; +IUnknownEntry g_demoApi = {DEFAULT_IUNKNOWN_ENTRY_BEGIN, DEFAULT_IUNKNOWN_ENTRY_END}; + +static const char *FEATURE_GetName(Feature *feature) +{ + if (feature == &g_maintenFeature1) { + return MAINTEN_FEATURE1; + } + if (feature == &g_maintenFeature2) { + return MAINTEN_FEATURE2; + } + return NULL; +} + +static void FEATURE_OnInitialize(Feature *feature, Service *parent, Identity identity) +{ + (void)feature; + (void)parent; + (void)identity; +} + +static void FEATURE_OnStop(Feature *feature, Identity identity) +{ + (void)feature; + (void)identity; +} + +static BOOL FEATURE_OnMessage(Feature *feature, Request *request) +{ + (void)feature; + (void)request; + return FALSE; +} + +static const char *GetName(Service *service) +{ + if (service == &g_maintenExample1) { + return MAINTEN_SERVICE1; + } + if (service == &g_maintenExample2) { + return MAINTEN_SERVICE2; + } + if (service == &g_maintenExample3) { + return MAINTEN_SERVICE3; + } + if (service == &g_maintenExample4) { + return MAINTEN_SERVICE4; + } + return NULL; +} + +static BOOL Initialize(Service *service, Identity identity) +{ + (void)identity; + (void)service; + return TRUE; +} + +static BOOL MessageHandle(Service *service, Request *msg) +{ + (void)service; + (void)msg; + return FALSE; +} + +static TaskConfig GetTaskConfig(Service *service) +{ + (void)service; + TaskConfig config = {LEVEL_HIGH, PRI_NORMAL, + 0x800, 16, SHARED_TASK}; + if (service == &g_maintenExample4) { + config.priority = PRI_ABOVE_NORMAL; + config.stackSize = 0x400; + } + return config; +} + +static void SInit(Service *service) +{ + if (service == &g_maintenExample4) { + printf("[Maintenance Test][Before App Service Init]Print Uninitialized App Service\n"); + SAMGR_PrintServices(); + } + SAMGR_GetInstance()->RegisterService(service); +} + +static void FInit(Feature *feature) +{ + if (feature == &g_maintenFeature1) { + SAMGR_GetInstance()->RegisterFeature(MAINTEN_SERVICE1, feature); + SAMGR_GetInstance()->RegisterFeatureApi(MAINTEN_SERVICE1, MAINTEN_FEATURE1, GET_IUNKNOWN(g_demoApi)); + } + if (feature == &g_maintenFeature2) { + SAMGR_GetInstance()->RegisterFeature(MAINTEN_SERVICE2, feature); + SAMGR_GetInstance()->RegisterDefaultFeatureApi(MAINTEN_SERVICE2, GET_IUNKNOWN(g_demoApi)); + } +} + +static void S1Init(void) +{ + SInit(&g_maintenExample1); +} + +static void S2Init(void) +{ + SInit(&g_maintenExample2); +} + +static void S3Init(void) +{ + SInit(&g_maintenExample3); +} + +static void S4Init(void) +{ + SInit(&g_maintenExample4); +} + +static void F1Init(void) +{ + FInit(&g_maintenFeature1); +} + +static void F2Init(void) +{ + FInit(&g_maintenFeature2); +} + +SYSEX_SERVICE_INIT(S1Init); +SYSEX_SERVICE_INIT(S2Init); +SYSEX_SERVICE_INIT(S3Init); +SYSEX_SERVICE_INIT(S4Init); +SYSEX_FEATURE_INIT(F1Init); +SYSEX_FEATURE_INIT(F2Init); diff --git a/src/applications/sample/wifi-iot/app/samgr/service_example.c b/src/applications/sample/wifi-iot/app/samgr/service_example.c new file mode 100644 index 0000000..de411f0 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/samgr/service_example.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2020-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "example.h" +#include +#include +#include +#include +#include +#include "iunknown.h" +#include "feature.h" +#include "service.h" +#include "samgr_lite.h" +#include "time_adapter.h" + +typedef struct DefaultFeatureApi { + INHERIT_IUNKNOWN; + void (*SyncCall)(IUnknown *iUnknown); +} DefaultFeatureApi; + +typedef struct ExampleService { + INHERIT_SERVICE; + INHERIT_IUNKNOWNENTRY(DefaultFeatureApi); + Identity identity; +} ExampleService; + +static const char *GetName(Service *service) +{ + (void)service; + return EXAMPLE_SERVICE; +} + +static uint32_t g_regStep = 0; + +static BOOL Initialize(Service *service, Identity identity) +{ + ExampleService *example = (ExampleService *)service; + example->identity = identity; + printf("[Register Test][TaskID:%u][Step:%u][Reg Finish S:%s]Time: %llu!\n", + (int)osThreadGetId(), g_regStep++, service->GetName(service), SAMGR_GetProcessTime()); + return TRUE; +} + +static BOOL MessageHandle(Service *service, Request *msg) +{ + printf("[LPC Test][TaskID:%u] msgId<%d>: %s \n", (int)osThreadGetId(), msg->msgId, (char *)msg->data); + (void)service; + return FALSE; +} + +static TaskConfig GetTaskConfig(Service *service) +{ + (void)service; + TaskConfig config = {LEVEL_HIGH, PRI_BELOW_NORMAL, + 0x800, 20, SHARED_TASK}; + return config; +} + +static volatile uint32 g_asyncStep = 0; + +static void SyncCall(IUnknown *iUnknown) +{ + (void)iUnknown; + printf("[LPC Test][TaskID:%u][Step:%u][SyncCall API] Default Success!\n", (int)osThreadGetId(), + g_asyncStep++); +} + +static ExampleService g_example = { + .GetName = GetName, + .Initialize = Initialize, + .MessageHandle = MessageHandle, + .GetTaskConfig = GetTaskConfig, + DEFAULT_IUNKNOWN_ENTRY_BEGIN, + .SyncCall = SyncCall, + DEFAULT_IUNKNOWN_ENTRY_END, +}; + +static void Init(void) +{ + SAMGR_GetInstance()->RegisterService((Service *)&g_example); + SAMGR_GetInstance()->RegisterDefaultFeatureApi(EXAMPLE_SERVICE, GET_IUNKNOWN(g_example)); + printf("[Register Test][TaskID:%u][Step:%u][Reg S:%s]Time: %llu!\n", + (int)osThreadGetId(), g_regStep++, EXAMPLE_SERVICE, SAMGR_GetProcessTime()); +} + +SYSEX_SERVICE_INIT(Init); + +static uint32_t g_discoverStep = 0; + +static DefaultFeatureApi *CASE_GetIUnknown(void) +{ + DefaultFeatureApi *demoApi = NULL; + printf("[Discover Test][TaskID:%u][Step:%u][GetIUnknown S:%s]: BEGIN\n", + (int)osThreadGetId(), g_discoverStep++, EXAMPLE_SERVICE); + IUnknown *iUnknown = SAMGR_GetInstance()->GetDefaultFeatureApi(EXAMPLE_SERVICE); + if (iUnknown == NULL) { + printf("[Discover Test][TaskID:%u][Step:%u][GetDefaultFeatureApi S:%s]Error is NULL!\n", + (int)osThreadGetId(), g_discoverStep++, EXAMPLE_SERVICE); + goto END; + } + int result = iUnknown->QueryInterface(iUnknown, DEFAULT_VERSION, (void **)&demoApi); + if (result != 0 || demoApi == NULL) { + printf("[Discover Test][TaskID:%u][Step:%u][QueryInterface S:%s]Error is NULL!\n", + (int)osThreadGetId(), g_discoverStep++, EXAMPLE_SERVICE); + goto END; + } + printf("[Discover Test][TaskID:%u][Step:%u][GetIUnknown S:%s]Success\n", + (int)osThreadGetId(), g_discoverStep++, EXAMPLE_SERVICE); +END: + printf("[Discover Test][TaskID:%u][Step:%u][GetIUnknown S:%s]: END\n", + (int)osThreadGetId(), g_discoverStep++, EXAMPLE_SERVICE); + return demoApi; +} + +static void CASE_SyncCall(DefaultFeatureApi *defaultApi) +{ + printf("[LPC Test][TaskID:%u][Step:%u][DefaultFeature SyncCall]: BEGIN\n", (int)osThreadGetId(), + g_asyncStep++); + defaultApi->SyncCall((IUnknown *)defaultApi); + printf("[LPC Test][TaskID:%u][Step:%u][DefaultFeature SyncCall]: END\n", (int)osThreadGetId(), + g_asyncStep++); +} + +static void CASE_ReleaseIUnknown(DefaultFeatureApi *demoApi) +{ + printf("[Discover Test][TaskID:%u][Step:%u][ReleaseIUnknown S:%s]: BEGIN\n", + (int)osThreadGetId(), g_discoverStep++, EXAMPLE_SERVICE); + int32 ref = demoApi->Release((IUnknown *)demoApi); + if (ref <= 0) { + printf("[Discover Test][TaskID:%u][Step:%u][ReleaseIUnknown S:%s]Error ref is %d!\n", + (int)osThreadGetId(), g_discoverStep++, EXAMPLE_SERVICE, ref); + goto END; + } + printf("[Discover Test][TaskID:%u][Step:%u][ReleaseIUnknown S:%s]Success\n", + (int)osThreadGetId(), g_discoverStep++, EXAMPLE_SERVICE); +END: + printf("[Discover Test][TaskID:%u][Step:%u][ReleaseIUnknown S:%s]: END\n", + (int)osThreadGetId(), g_discoverStep++, EXAMPLE_SERVICE); +} + +static void CASE_RegisterInvalidService(void) +{ + Service service = {.GetName = NULL, .GetTaskConfig = NULL, .Initialize = NULL, .MessageHandle = NULL}; + BOOL ret = SAMGR_GetInstance()->RegisterService(&service); + printf("Register Invalid Service %s\n", ret ? "TRUE" : "FALSE"); + + Feature feature = {.GetName = NULL, .OnInitialize = NULL, .OnMessage = NULL, .OnStop = NULL}; + ret = SAMGR_GetInstance()->RegisterFeature(EXAMPLE_SERVICE, &feature); + printf("Register Invalid Feature %s\n", ret ? "TRUE" : "FALSE"); + + IUnknownEntry entry = { + .ver = DEFAULT_VERSION, + .ref = 1, + .iUnknown = { + .QueryInterface = NULL, + .Release = NULL, + .AddRef = NULL + } + }; + ret = SAMGR_GetInstance()->RegisterDefaultFeatureApi(EXAMPLE_SERVICE, GET_IUNKNOWN(entry)); + printf("Register Invalid Default Api %s\n", ret ? "TRUE" : "FALSE"); + + ret = SAMGR_GetInstance()->RegisterFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE "2", GET_IUNKNOWN(entry)); + printf("Register Invalid " EXAMPLE_FEATURE "2 Api %s\n", ret ? "TRUE" : "FALSE"); +} + +static void RunTestCase(void) +{ + DefaultFeatureApi *defaultApi = CASE_GetIUnknown(); + CASE_RegisterInvalidService(); + CASE_SyncCall(defaultApi); + CASE_ReleaseIUnknown(defaultApi); +} + +LAYER_INITCALL_DEF(RunTestCase, test, "test"); diff --git a/src/applications/sample/wifi-iot/app/samgr/service_recovery_example.c b/src/applications/sample/wifi-iot/app/samgr/service_recovery_example.c new file mode 100644 index 0000000..fecc33b --- /dev/null +++ b/src/applications/sample/wifi-iot/app/samgr/service_recovery_example.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2020-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include "service.h" +#include "samgr_lite.h" + +#define TIME_UNLIMITED_CASE 0 +#define WAIT_BOOT_PROC ((1000) * (11)) +#define TEST_SYS_SERVICE1 "tst_sys1" +#define TEST_SYS_SERVICE2 "tst_sys2" +#define TEST_APP_SERVICE1 "tst_app1" +#define TEST_APP_SERVICE2 "tst_app2" + +static const char *GetName(Service *service); +static BOOL Initialize(Service *service, Identity identity); +static BOOL MessageHandle(Service *service, Request *msg); +static TaskConfig GetTaskConfig(Service *service); +static Service g_testSys1 = {GetName, Initialize, MessageHandle, GetTaskConfig}; +static Service g_testSys2 = {GetName, Initialize, MessageHandle, GetTaskConfig}; +static Service g_testApp1 = {GetName, Initialize, MessageHandle, GetTaskConfig}; +static Service g_testApp2 = {GetName, Initialize, MessageHandle, GetTaskConfig}; + +static const char *GetName(Service *service) +{ + if (service == &g_testSys1) { + return TEST_SYS_SERVICE1; + } + if (service == &g_testSys2) { + return TEST_SYS_SERVICE2; + } + if (service == &g_testApp1) { + return TEST_APP_SERVICE1; + } + if (service == &g_testApp2) { + return TEST_APP_SERVICE2; + } + return NULL; +} + +static BOOL Initialize(Service *service, Identity identity) +{ + (void)identity; + if (service == &g_testSys1 || service == &g_testApp1) { + printf("[Recovery Test][Initialize]Time Out Case Running\n"); + LOS_Msleep(WAIT_BOOT_PROC); + return TRUE; + } +#if TIME_UNLIMITED_CASE + if (service == &g_testSys2 || service == &g_testApp2) { + printf("[Recovery Test][Initialize]Time Unlimited Case Running\n\n"); + while (1) { + (void)identity; + } + return TRUE; + } +#endif + return TRUE; +} + +static BOOL MessageHandle(Service *service, Request *msg) +{ + (void)service; + (void)msg; + return FALSE; +} + +static TaskConfig GetTaskConfig(Service *service) +{ + (void)service; + TaskConfig config = {LEVEL_HIGH, PRI_NORMAL, + 0x400, 16, SHARED_TASK}; + return config; +} + +static void SInit(Service *demo) +{ + SAMGR_GetInstance()->RegisterService(demo); +} + +static void SS1Init(void) +{ + SInit(&g_testSys1); +} + +static void SS2Init(void) +{ + SInit(&g_testSys2); +} + +static void AS1Init(void) +{ + SInit(&g_testApp1); +} + +static void AS2Init(void) +{ + SInit(&g_testApp2); +} + +SYS_SERVICE_INIT(SS1Init); +SYS_SERVICE_INIT(SS2Init); +SYSEX_SERVICE_INIT(AS1Init); +SYSEX_SERVICE_INIT(AS2Init); diff --git a/src/applications/sample/wifi-iot/app/samgr/specified_task_example.c b/src/applications/sample/wifi-iot/app/samgr/specified_task_example.c new file mode 100644 index 0000000..e146227 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/samgr/specified_task_example.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2020-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include "service.h" +#include "samgr_lite.h" +#include "time_adapter.h" + +#define TOTAL_SPEC_TASK_NUM 19 + +static const char *g_specTaskService[] = { + "ltsk_s1", "ltsk_s2", "ltsk_s3", + "otsk_s1", "otsk_s2", "otsk_s3", "otsk_s4", + "otsk_s5", "otsk_s6", "otsk_s7", "otsk_s8", + "otsk_s9", "otsk_s10", "otsk_s11", "otsk_s12", + "otsk_s13", "otsk_s14", "otsk_s15", "otsk_s16", +}; +static const char *g_specServiceName1[] = { + "l6tsk_s1", "l6tsk_s2" +}; +static const char *g_specServiceName2[] = { + "l7tsk_s1", "l7tsk_s2", "l7tsk_s3" +}; +static const char *g_specServiceName3[] = { + "l8tsk_s1", "l8tsk_s2", "l8tsk_s3", "l8tsk_s4" +}; +static const char *GetName(Service *service); +static const char *GetSpec1Name(Service *service); +static const char *GetSpec2Name(Service *service); +static const char *GetSpec3Name(Service *service); +static BOOL Initialize(Service *service, Identity identity); +static BOOL MessageHandle(Service *service, Request *msg); +static TaskConfig GetLowTagTaskConfig(Service *service); +static TaskConfig GetHighTagTaskConfig(Service *service); +static TaskConfig GetSpec1TagTaskConfig(Service *service); +static TaskConfig GetSpec2TagTaskConfig(Service *service); +static TaskConfig GetSpec3TagTaskConfig(Service *service); +static Service g_example[] = { + {GetName, Initialize, MessageHandle, GetLowTagTaskConfig}, + {GetName, Initialize, MessageHandle, GetLowTagTaskConfig}, + {GetName, Initialize, MessageHandle, GetLowTagTaskConfig}, + {GetName, Initialize, MessageHandle, GetHighTagTaskConfig}, + {GetName, Initialize, MessageHandle, GetHighTagTaskConfig}, + {GetName, Initialize, MessageHandle, GetHighTagTaskConfig}, + {GetName, Initialize, MessageHandle, GetHighTagTaskConfig}, + {GetName, Initialize, MessageHandle, GetHighTagTaskConfig}, + {GetName, Initialize, MessageHandle, GetHighTagTaskConfig}, + {GetName, Initialize, MessageHandle, GetHighTagTaskConfig}, + {GetName, Initialize, MessageHandle, GetHighTagTaskConfig}, + {GetName, Initialize, MessageHandle, GetHighTagTaskConfig}, + {GetName, Initialize, MessageHandle, GetHighTagTaskConfig}, + {GetName, Initialize, MessageHandle, GetHighTagTaskConfig}, + {GetName, Initialize, MessageHandle, GetHighTagTaskConfig}, + {GetName, Initialize, MessageHandle, GetHighTagTaskConfig}, + {GetName, Initialize, MessageHandle, GetHighTagTaskConfig}, + {GetName, Initialize, MessageHandle, GetHighTagTaskConfig}, + {GetName, Initialize, MessageHandle, GetHighTagTaskConfig} +}; +static Service g_exampleSpec1[] = { + {GetSpec1Name, Initialize, MessageHandle, GetSpec1TagTaskConfig}, + {GetSpec1Name, Initialize, MessageHandle, GetSpec1TagTaskConfig} +}; +static Service g_exampleSpec2[] = { + {GetSpec2Name, Initialize, MessageHandle, GetSpec2TagTaskConfig}, + {GetSpec2Name, Initialize, MessageHandle, GetSpec2TagTaskConfig}, + {GetSpec2Name, Initialize, MessageHandle, GetSpec2TagTaskConfig} +}; +static Service g_exampleSpec3[] = { + {GetSpec3Name, Initialize, MessageHandle, GetSpec3TagTaskConfig}, + {GetSpec3Name, Initialize, MessageHandle, GetSpec3TagTaskConfig}, + {GetSpec3Name, Initialize, MessageHandle, GetSpec3TagTaskConfig}, + {GetSpec3Name, Initialize, MessageHandle, GetSpec3TagTaskConfig} +}; +static uint32_t g_initIndex = 0; + +static const char *GetName(Service *service) +{ + int i; + for (i = 0; i < TOTAL_SPEC_TASK_NUM; ++i) { + if (service == &g_example[i]) { + return g_specTaskService[i]; + } + } + return NULL; +} + +static const char *GetSpec1Name(Service *service) +{ + int i; + // g_exampleSpec1 has 2 services + for (i = 0; i < 2; ++i) { + if (service == &g_exampleSpec1[i]) { + return g_specServiceName1[i]; + } + } + return NULL; +} + +static const char *GetSpec2Name(Service *service) +{ + int i; + // g_exampleSpec2 has 3 services + for (i = 0; i < 3; ++i) { + if (service == &g_exampleSpec2[i]) { + return g_specServiceName2[i]; + } + } + return NULL; +} + +static const char *GetSpec3Name(Service *service) +{ + int i; + // g_exampleSpec3 has 4 services + for (i = 0; i < 4; ++i) { + if (service == &g_exampleSpec3[i]) { + return g_specServiceName3[i]; + } + } + return NULL; +} + +static BOOL Initialize(Service *service, Identity identity) +{ + (void)identity; + printf("[Specified Task Test][TaskID:%u][Step:%u][Reg Finish S:%s]Time: %llu!\n", + (int)osThreadGetId(), g_initIndex++, service->GetName(service), SAMGR_GetProcessTime()); + return TRUE; +} + +static BOOL MessageHandle(Service *service, Request *msg) +{ + printf("[Specified Task Test][TaskID:%u][Step:%u][S:%s] msgId<%d> \n", + (int)osThreadGetId(), g_initIndex++, service->GetName(service), msg->msgId); + return FALSE; +} + +static TaskConfig GetLowTagTaskConfig(Service *service) +{ + (void)service; + int16 customLevelLow = LEVEL_CUSTOM_BEGIN + 1; + TaskConfig config = {customLevelLow, PRI_NORMAL, + 0x400, 16, SPECIFIED_TASK}; + return config; +} + +static TaskConfig GetHighTagTaskConfig(Service *service) +{ + (void)service; + int16 customLevelHigh = LEVEL_CUSTOM_BEGIN + 2; // Custom level 2 + TaskConfig config = {customLevelHigh, PRI_NORMAL, + 0x400, 16, SPECIFIED_TASK}; + return config; +} + +static TaskConfig GetSpec1TagTaskConfig(Service *service) +{ + (void)service; + int16 customLevelSpec1 = LEVEL_CUSTOM_BEGIN + 3; // Custom level 3 + TaskConfig config = {customLevelSpec1, PRI_NORMAL, + 0x400, 16, SPECIFIED_TASK}; + return config; +} + +static TaskConfig GetSpec2TagTaskConfig(Service *service) +{ + (void)service; + int16 customLevelSpec2 = LEVEL_CUSTOM_BEGIN + 4; // Custom level 4 + TaskConfig config = {customLevelSpec2, PRI_NORMAL, + 0x400, 16, SPECIFIED_TASK}; + return config; +} + +static TaskConfig GetSpec3TagTaskConfig(Service *service) +{ + (void)service; + int16 customLevelSpec3 = LEVEL_CUSTOM_BEGIN + 5; // Custom level 5 + TaskConfig config = {customLevelSpec3, PRI_NORMAL, + 0x400, 16, SPECIFIED_TASK}; + return config; +} + +static void SInit(Service *demo) +{ + SAMGR_GetInstance()->RegisterService(demo); + + printf("[Specified Task Test][TaskID:%u][Step:%u][SYSEX Reg S:%s]Time: %llu!\n", + (int)osThreadGetId(), g_initIndex++, demo->GetName(demo), SAMGR_GetProcessTime()); +} + +static void SSInit(void) +{ + int i; + for (i = 0; i < TOTAL_SPEC_TASK_NUM; ++i) { + SInit(&g_example[i]); + } + + // g_exampleSpec1 has 2 services + for (i = 0; i < 2; ++i) { + SInit(&g_exampleSpec1[i]); + } + // g_exampleSpec2 has 3 services + for (i = 0; i < 3; ++i) { + SInit(&g_exampleSpec2[i]); + } + // g_exampleSpec3 has 4 services + for (i = 0; i < 4; ++i) { + SInit(&g_exampleSpec3[i]); + } +} + +SYSEX_SERVICE_INIT(SSInit); diff --git a/src/applications/sample/wifi-iot/app/samgr/task_example.c b/src/applications/sample/wifi-iot/app/samgr/task_example.c new file mode 100644 index 0000000..cec0622 --- /dev/null +++ b/src/applications/sample/wifi-iot/app/samgr/task_example.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2020-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "example.h" +#include +#include +#include +#include +#include +#include +#include "time_adapter.h" + +static const char *GetName(Service *service); +static BOOL Initialize(Service *service, Identity identity); +static BOOL MessageHandle(Service *service, Request *msg); +static TaskConfig GetTaskConfig(Service *service); +static Service g_example[] = { + {GetName, Initialize, MessageHandle, GetTaskConfig}, + {GetName, Initialize, MessageHandle, GetTaskConfig}, + {GetName, Initialize, MessageHandle, GetTaskConfig}, + {GetName, Initialize, MessageHandle, GetTaskConfig} +}; +static int g_initIndex = 0; + +static const char *GetName(Service *service) +{ + // test cases demo 0 + if (service == &g_example[0]) { + return TASK_SERVICE1; + } + // test cases demo 1 + if (service == &g_example[1]) { + return TASK_SERVICE2; + } + // test cases demo 2 + if (service == &g_example[2]) { + return TASK_SERVICE3; + } + // test cases demo 3 + if (service == &g_example[3]) { + return TASK_SERVICE4; + } + return NULL; +} + +static BOOL Initialize(Service *service, Identity identity) +{ + (void)identity; + printf("[Task Test][TaskID:%u][Step:%u][Reg Finish S:%s]Time: %llu!\n", + (int)osThreadGetId(), g_initIndex++, service->GetName(service), SAMGR_GetProcessTime()); + return TRUE; +} + +static BOOL MessageHandle(Service *service, Request *msg) +{ + printf("[Task Test][TaskID:%u][Step:%u][S:%s] msgId<%d> \n", + (int)osThreadGetId(), g_initIndex++, service->GetName(service), msg->msgId); + return FALSE; +} + +static TaskConfig GetTaskConfig(Service *service) +{ + TaskConfig config = {LEVEL_HIGH, PRI_NORMAL, + 0x800, 5, SHARED_TASK}; + // test cases demo 0 + if (service == &g_example[0]) { + config.taskFlags = SINGLE_TASK; + } + // test cases demo 3 + if (service == &g_example[3]) { + config.priority = PRI_ABOVE_NORMAL; + } + return config; +} + +static void SInit(Service *demo) +{ + SAMGR_GetInstance()->RegisterService(demo); + + printf("[Task Test][TaskID:%u][Step:%u][SYSEX Reg S:%s]Time: %llu!\n", + (int)osThreadGetId(), g_initIndex++, demo->GetName(demo), SAMGR_GetProcessTime()); +} + +static void S1Init(void) +{ + // test cases demo 0 + SInit(&g_example[0]); +} + +static void S2Init(void) +{ + // test cases demo 1 + SInit(&g_example[1]); +} + +static void S3Init(void) +{ + // test cases demo 2 + SInit(&g_example[2]); +} + +static void S4Init(void) +{ + // test cases demo 3 + SInit(&g_example[3]); +} + +SYSEX_SERVICE_INIT(S1Init); +SYSEX_SERVICE_INIT(S2Init); +SYSEX_SERVICE_INIT(S3Init); +SYSEX_SERVICE_INIT(S4Init); diff --git a/src/applications/sample/wifi-iot/screenshot/audiotest/audiorendertest.wav b/src/applications/sample/wifi-iot/screenshot/audiotest/audiorendertest.wav new file mode 100644 index 0000000..82fc8d9 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/audiotest/audiorendertest.wav differ diff --git a/src/applications/sample/wifi-iot/screenshot/audiotest/hdf_audio_hdi_server_function_test b/src/applications/sample/wifi-iot/screenshot/audiotest/hdf_audio_hdi_server_function_test new file mode 100644 index 0000000..b8163d3 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/audiotest/hdf_audio_hdi_server_function_test differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/airquality.png b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/airquality.png new file mode 100644 index 0000000..ce26221 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/airquality.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/airquality.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/airquality.pngraw new file mode 100644 index 0000000..988c85e Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/airquality.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/app_capture_screen_test_config.json b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/app_capture_screen_test_config.json new file mode 100644 index 0000000..6ce2540 --- /dev/null +++ b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/app_capture_screen_test_config.json @@ -0,0 +1,90 @@ +[ + { + "return-x-y":[199, 1262], + "recent-x-y":[500, 1262], + "home-x-y":[350, 1262], + "recent_del-x-y":[350, 1140], + "permisson_ok-x-y":[495, 690], + "permisson_no-x-y":[241, 690], + "shot_cmd":[""], + "cmp_cmd-level":["", 443200] + }, + { + "app_name": "launcher", + "entry": "", + "all_actions": [[2, "shot_cmd"], [2, "cmp_cmd-level"]] + }, + { + "app_name": "settings", + "entry": "aa start -a com.ohos.settings.MainAbility -b com.ohos.settings", + "all_actions": [ + [3, "shot_cmd", "settings"], [3, "cmp_cmd-level"], [3, 400, 120], [3, 400, 120], [20, 400, 80], [3, 400, 80], + [3, "shot_cmd", "keyboard"], [3, "recent-x-y"], [3, "recent_del-x-y"], [3, "recent-x-y"], [3, "recent_del-x-y"], [3, "cmp_cmd-level", 200000] + ] + }, + { + "app_name": "photos", + "entry": "aa start -a com.ohos.photos.MainAbility -b com.ohos.photos", + "all_actions": [[2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "recent-x-y"], [2, "recent_del-x-y"]] + }, + { + "app_name": "photos", + "entry": "aa start -a com.ohos.photos.MainAbility -b com.ohos.photos", + "all_actions": [[2, "shot_cmd"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "cmp_cmd-level"], [2, "recent-x-y"], [2, "recent_del-x-y"]] + }, + { + "app_name": "distributedcalc", + "entry": "aa start -a com.example.distributedcalc.default -b com.example.distributedcalc", + "all_actions": [[2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], [2, "shot_cmd"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "cmp_cmd-level", 3686400], [2, "recent-x-y"], [2, "recent_del-x-y"]] + }, + { + "app_name": "camera", + "entry": "aa start -a com.ohos.camera.MainAbility -b com.ohos.camera", + "all_actions": [ + [2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], + [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "recent-x-y"], [2, "recent_del-x-y"] + ] + }, + { + "app_name": "camera", + "entry": "aa start -a com.ohos.camera.MainAbility -b com.ohos.camera", + "all_actions": [[2, "shot_cmd"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "cmp_cmd-level", 3686400]] + }, + { + "app_name": "contacts", + "entry": "aa start -a com.ohos.contacts.MainAbility -b com.ohos.contacts", + "all_actions": [ + [2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], + [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "recent-x-y"], [2, "recent_del-x-y"] + ] + }, + { + "app_name": "contacts", + "entry": "aa start -a com.ohos.contacts.MainAbility -b com.ohos.contacts", + "all_actions": [[2, "shot_cmd"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "cmp_cmd-level", 3686400], [2, "recent-x-y"], [2, "recent_del-x-y"]] + }, + { + "app_name": "music", + "entry": "aa start -a com.ohos.distributedmusicplayer.MainAbility -b com.ohos.distributedmusicplayer", + "all_actions": [[2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "recent-x-y"], [2, "recent_del-x-y"]] + }, + { + "app_name": "music", + "entry": "aa start -a com.ohos.distributedmusicplayer.MainAbility -b com.ohos.distributedmusicplayer", + "all_actions": [[2, "permisson_ok-x-y"], [2, "shot_cmd"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "cmp_cmd-level", 3686400]] + }, + { + "app_name": "mms", + "entry": "aa start -a com.ohos.mms.MainAbility -b com.ohos.mms", + "all_actions": [ + [2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], + [2, "shot_cmd"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "cmp_cmd-level", 3686400] + ] + }, + { + "app_name": "note", + "entry": "aa start -a com.ohos.note.MainAbility -b com.ohos.note", + "all_actions": [[2, "shot_cmd"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "cmp_cmd-level", 3686400]] + } + +] \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/camera.png b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/camera.png new file mode 100644 index 0000000..571599c Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/camera.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/camera.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/camera.pngraw new file mode 100644 index 0000000..13299f9 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/camera.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/capturescreentest.py b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/capturescreentest.py new file mode 100644 index 0000000..45b83f9 --- /dev/null +++ b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/capturescreentest.py @@ -0,0 +1,136 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from ast import parse +import json +import sys +import os +import time +import argparse +import re + +def EnterCmd(mycmd, waittime = 0, printresult = 1): + if mycmd == "": + return + with os.popen(mycmd) as p: + result = p.readlines() + if printresult == 1: + print(result) + sys.stdout.flush() + if waittime != 0: + time.sleep(waittime) + return result + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='manual to this script') + parser.add_argument('--config', type=str, default = './app_capture_screen_test_config.json') + parser.add_argument('--anwser_path', type=str, default = 'screenshot\\RK\\') + parser.add_argument('--save_path', type=str, default = './report/screenshot_1/') + args = parser.parse_args() + + with open(args.config) as f: + all_app = json.load(f) + + cmp_status = 0 + global_pos = all_app[0] + return_cmd = "hdc_std shell input -M -m {} {} -c 0".format(global_pos['return-x-y'][0], global_pos['return-x-y'][1]) + recent_cmd = "hdc_std shell input -M -m {} {} -c 0".format(global_pos['recent-x-y'][0], global_pos['recent-x-y'][1]) + home_cmd = "hdc_std shell input -M -m {} {} -c 0".format(global_pos['home-x-y'][0], global_pos['home-x-y'][1]) + recent_del_cmd = "hdc_std shell input -M -m {} {} -c 0".format(global_pos['recent_del-x-y'][0], global_pos['recent_del-x-y'][1]) + os.system("hdc_std kill") + os.system("hdc_std start") + EnterCmd("hdc_std list targets", 1) + EnterCmd("hdc_std list targets", 1) + EnterCmd("hdc_std list targets", 1) + EnterCmd("hdc_std shell rm -rf /data/screen_test/train_set") + EnterCmd("hdc_std shell mkdir -p /data/screen_test/train_set") + EnterCmd("hdc_std file send {} {}".format(os.path.join(os.path.dirname(args.config), "printscreen"), "/data/screen_test/")) + EnterCmd("hdc_std shell chmod 777 /data/screen_test/printscreen") + for single_app in all_app[1:]: + print(single_app['entry']) + print(single_app['all_actions']) + sys.stdout.flush() + call_app_cmd = "hdc_std shell " + single_app['entry'] + send_file_cmd = "hdc_std file send {} {}" + capture_screen_cmd = "hdc_std shell /data/screen_test/printscreen -f /data/screen_test/{}" + recv_file_cmd = "hdc_std file recv /data/screen_test/{} {}" + cmp_cmd = "hdc_std shell \"cmp -l /data/screen_test/{} /data/screen_test/train_set/{} | wc -l\"" + if single_app['entry'] != "": + EnterCmd(call_app_cmd, 3) + for single_action in single_app['all_actions']: + #shot_cmd is stable, different to other cmd,so handle it specialy + if type(single_action[1]) == str and single_action[1] == 'shot_cmd': + if len(single_action) == 3: + pic_name = single_action[2] + ".png" + raw_pic_name = single_action[2] + ".pngraw" + else: + pic_name = single_app['app_name'] + ".png" + raw_pic_name = single_app['app_name'] + ".pngraw" + EnterCmd(capture_screen_cmd.format(pic_name), 1) + EnterCmd(recv_file_cmd.format(pic_name, args.save_path), 1) + EnterCmd(recv_file_cmd.format(raw_pic_name, args.save_path), 1) + next_cmd = "" + #cmp_cmd-level is stable, different to other cmd,so handle it specialy + elif type(single_action[1]) == str and single_action[1] == 'cmp_cmd-level': + next_cmd = "" + print(send_file_cmd.format(os.path.join(args.anwser_path, raw_pic_name), "/data/screen_test/train_set")) + sys.stdout.flush() + EnterCmd(send_file_cmd.format(os.path.join(args.anwser_path, raw_pic_name), "/data/screen_test/train_set")) + new_cmp_cmd = cmp_cmd.format(raw_pic_name, raw_pic_name) + if len(single_action) == 3: + tolerance = single_action[2] + else: + tolerance = global_pos['cmp_cmd-level'][1] + p = EnterCmd(new_cmp_cmd, single_action[0]) + num = re.findall(r'[-+]?\d+', p[0]) + if type(num) == list and len(num) > 0 and int(num[0]) < tolerance: + print("{} screenshot check is ok!\n\n".format(raw_pic_name)) + else: + print("ERROR:{} screenshot check is abnarmal!\n\n".format(raw_pic_name)) + cmp_status = cmp_status + 1 + sys.stdout.flush() + #other cmd handle + elif type(single_action[1]) == str: + if single_action[1] not in single_app.keys(): + target_ = global_pos[single_action[1]] + else: + target_ = single_app[single_action[1]] + #this cmd is real cmd,and have a except answer + if type(target_[0]) == str: + next_cmd = "" + p = EnterCmd(target_[0], single_action[0]) + result = "".join(p) + if len(target_) > 1: + findsome = result.find(target_[1], 0, len(result)) + if findsome != -1: + print("\"{}\" execut result success!\n\n".format(target_[0])) + else: + print("ERROR:\"{}\" execut result failed!\n\n".format(target_[0])) + cmp_status = cmp_status + 1 + sys.stdout.flush() + #this cmd only is a name of x,y postion, to get x,y an click it + else: + next_cmd = "hdc_std shell input -M -m {} {} -c 0".format(target_[0], target_[1]) + #input x,y postion, to click it + else: + next_cmd = "hdc_std shell input -M -m {} {} -c 0".format(single_action[1], single_action[2]) + EnterCmd(next_cmd, single_action[0]) + + if cmp_status != 0: + print("ERROR:screenshot check is abnarmal {}".format(cmp_status)) + print("End of check, test failed!") + else: + print("screenshot check is ok {}".format(cmp_status)) + print("End of check, test succeeded!") + sys.stdout.flush() + sys.exit(cmp_status) \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/clock.png b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/clock.png new file mode 100644 index 0000000..9807474 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/clock.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/clock.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/clock.pngraw new file mode 100644 index 0000000..6bb420f Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/clock.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/contacts.png b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/contacts.png new file mode 100644 index 0000000..bc958f7 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/contacts.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/contacts.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/contacts.pngraw new file mode 100644 index 0000000..e8e5d0b Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/contacts.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/distributedcalc.png b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/distributedcalc.png new file mode 100644 index 0000000..bd1cf11 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/distributedcalc.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/distributedcalc.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/distributedcalc.pngraw new file mode 100644 index 0000000..4272d42 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/distributedcalc.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/ecg.png b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/ecg.png new file mode 100644 index 0000000..fb99831 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/ecg.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/ecg.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/ecg.pngraw new file mode 100644 index 0000000..9c263a3 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/ecg.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/flashlight.png b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/flashlight.png new file mode 100644 index 0000000..a0ec45d Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/flashlight.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/flashlight.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/flashlight.pngraw new file mode 100644 index 0000000..ac16582 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/flashlight.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/keyboard.png b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/keyboard.png new file mode 100644 index 0000000..9715d81 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/keyboard.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/keyboard.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/keyboard.pngraw new file mode 100644 index 0000000..48399b6 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/keyboard.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/launcher.png b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/launcher.png new file mode 100644 index 0000000..98ea725 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/launcher.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/launcher.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/launcher.pngraw new file mode 100644 index 0000000..a8328e5 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/launcher.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/mms.png b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/mms.png new file mode 100644 index 0000000..7de247b Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/mms.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/mms.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/mms.pngraw new file mode 100644 index 0000000..cde026f Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/mms.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/music.png b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/music.png new file mode 100644 index 0000000..26b02e8 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/music.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/music.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/music.pngraw new file mode 100644 index 0000000..a79a770 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/music.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/note.png b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/note.png new file mode 100644 index 0000000..5d9d938 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/note.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/note.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/note.pngraw new file mode 100644 index 0000000..ab9491c Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/note.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/photos.png b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/photos.png new file mode 100644 index 0000000..0554a54 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/photos.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/photos.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/photos.pngraw new file mode 100644 index 0000000..4680685 --- /dev/null +++ b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/photos.pngraw @@ -0,0 +1,136 @@ +$1$1$1/:F/:F/:F/:F/:F/:F/:F/:F/:F$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1`ir$1$1$1$1$1$1$1$17AM$1$1$1$1$1$1$1$1rz$1$1$1$1$1$1$1$19DO$1$1$1GQ[$1$1[dn$1$1$1$1$1$1$1$1$1$19DO$1$1$1dlu$1$1$1iqz$1$1$1$1$1$1$1$1$1$19DO$1$1$1HQ\$1$1$1ajsbktow\eo$1$1$1$1$1$1-8D/:F/:F/:F/:F/:F/:F/:F/:F$1$1$1%0$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1HQ\$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1(5 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9$1$1$1$1$1$1$1$1$1$1$1$1HQ\$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1v~`ir`ir`ir`ir`ir`ir`ir`ir`ir`ir`ir`ir$1$1$1$1$1$1yCMX$1$1$1$1$1$1$1$1$1S\f ,9LV`|0;G$1*7$1$1$1$1$17AM$1$1$1px$1$1$1$1$1$1$1$1=HS/:F$1$17AMkt|$1$1$1$1$1$1$1$1$1enw$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1w$1$1$1%0<$1$1|QZd$1$1pxGQ[$1$1$1LV`$1$1$1bkt$1$1$1$1$1$1GQ[Ybk$1$1DNY$1$1#/;$1$1$1`irdlu$1$1$1$1$1$16@L$1$1$1$1$1$1,7CpxT^h$12?}@sHn4<];=>?{O}q<455DT;<>?SR4556DH:;<>Tr5568=:;;=Wh5789:;;gW789:;vG89:ڃ;:َ{ۣ]ezSZnOUi9;O;=R<>S<>SNThJPd9;P78L79M;=R;=Q<>Rjv14E68K;=Q;=R;=R9;P8:O;=Q,.>,.>-/?35H79N78L8;O;=R[dxǷ,.>,.>,.>,.>,.>13E67J57H78Kƽο;@P,.>,.>,.>,.>,.>,.>,.>-.>02D68KqºGP`,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>>CT*,=,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>-/?iklmnppqrttvwBL^+-=#%7+-=,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>-/?klmnppqrttvwxyz{}~.3E"$6%(8*-=%'7&(9,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>=CSºlmnppqstuvwxy{{}~+2F%'8+-='):"$6!#5#%6#%6()9*,=+-=,.>,.>,.>,.>,.>,.>,.>mnppqstuvwxy{|}~ÿBOb"$6#$5 #4"$5$&8*-=&(9"%6"$5#%6"$6"$5$&7&(9&(9(*:)+;feoοnpprstuvxxz{|}~2"$6)+<,.>&(9"$5!#5 "4"$6!3&)9)+;+-=+-=),<)*;"$6hZ_Ѽ̾òϾwwnpprstuvxxzz|}~*0C "4!"5 2"%6&'8'):(*:!$6 1 1 12"4!#5 "4!#5JCLлѼлϺvvvwvwyypqrstuvxyz{|}~1!#5$&7(*;')9 !3 1!2!4"4 #4#%6$&8&'8'(9%(820>ϻѼмлκ͹˸uttuuuvvwwwxzy}qrstuvxyz{|}~12"3&(9*-=%'8%'7%'8"$6!3 2 1!$4"$6%'875CκѼѼмлκ̸ʷɶtrsssttttuuuuvvwxyxrstuvxyz{|}~11 3 !2!2!#5$'7'(9#%7!2%'7+-='*:*+<43B̸ѼѼѼлкι˸ɶƳñoooqqrsssssttuttuvvvwwxxstvvxyz{|}~$):11 2#&7 1 $5#%6 "3 "3!3$&6'):01@ųѼѼѼмлϺ͹˸ȵIJvmmnnoopqrrssssstttuuuuvvuvvwxxtuvxyz{|}ƻl111 3"%6!"4"4#%6$&7%(8(*;')9ЬҽѼѼѼллκ̸ʶdzñlllmllmnooopqqrrrsssstttuuuuuvvvwxuwxyz{|}"&711 11"3 #5 1 1 2"$6"%6$&7ijѼѼѼллκ˸ȵŲ°õklllllllmmnnoppppqrrsssssssttuuuvvvw|uwxyz{|}n1111 3!3 1 #6#%7!#4$&7(+;IEOҽѼѼлϻ͹˸ȵŲrjjkklllllllmmnooooopqrrrrrrssssstuuuuvvwxyz||~-3G 2 111 3 1 22"3"4 "4 "4κѼѼлϺι̸ɵƳñVvJlJkJlIkoojjjjjlllllllllmmnooooopqqqqqrrrrssssttuvvuxyz||~!#4 1111111(*9--=++;eY_ҽѼѼмлι̸ʶȴŲðJlIkIjIkIkjjjjjjjjkllllllllllmnnnnoooppqqrrrqrssssttuttvyz{|~Nby 211111y}ҽҽҽҽѼѼлϺ͹˸ʶȵdzƲdzKlHjHjGiGixjjjjjjjjjjkklllllllllmmmmnooopppqqqqqrrrsssssstux{{}~ij&+=2 2111ҽҽҽҽѼѼѼлκ͹̸ʸʶɶʷTqGhGiGhFhmkjjjjjjjjjjjkkkllllllllmmmmnnnnoooppppqqrrssssssstt|{}~ 21111̺ҽҽҽҽҽҽҽѼѼллκι͹͹͹ϻvFhEgEgEgkkkkkjjjjjjjjjkkkkllllllllllllmmmmnonoppppppqqrsrrsssss}~{ 1111cV]ҽҽҽҽҽҽҽѼѼѼмллϺϻлмEfDfDeEgwkjjjkjjjjjjjjjjjjkkkllllkllllllllmmmmnnnooopppqpqqrrrrssss~~Wm1111npлҽҽҽҽҽҽѼѼѼѼллммѼCeCdCdurkjjjjjjjjjjjjjjjjjjkkklkkkkkklllllllllmmmnnnooopppppqqrrrrsst~GXn11112/>๪ҽҽҽҽҽҽѼѼѼѼѼѼѼѼZsAcBcBcmkkkkjjjjjjjjjjjjjjjjkkkkkkkkkkkllllllllllmmmmnnnoooppppqqrrrrss{APe11111ҮҽҽҽҽҽҽѼѼѼѼѼѽq@b@b@a@b{kkkkkkkjjjjjjjjjjjjjjjjjkkkkkkkkkklllllllllllllmmmnnnoooooppqrqqrrsPd{ 1111乩ϻҽҽҽҽҽҽҽҽҽмMh>_?_?`?aAcqkkkkkkkkkjjjjjjjjjjjjjjjjkkkkkkkkkkkkkllllllllllllllmmnnnooooppqqqqrrr!$51TJSιικҽҽҽҽҽҽҽ@`<]<]<^=_>_Nk~okkkkkkkkkkkkjjjjjjjjjjjjjkkkkkkkkkkkkkkkkkkkklllllllllllmmnnnoopppqqqrrrű̷͸͸͸̸лҽҽҽͺdv9Z:[9[:[;\<]<]}wmkkkkkkkkkkkkkkjjjjjjjjjjjjkkkkkkkkkkkkkkkkkkkkkkklllllllllllmmnnnoppppqqqrκ͸͸̸̷˷ʵʶͺ~8Z8Y8Y8Y8Z9Z9[;[;\}tkkkkkkkkkkkkkkkkkkjjjjjjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllllllmmmnnopppqqqr̸̷̷˷ʶɵDzİ7X6X6X6W6W7X7Y8Y9Z:[okkkkkkkkkkkkkkkkkkkkkjjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllllllmmnoopppqqr̷˶ʶɵȴƲı¯6W5V5V5V5V6W6W7X7YIgokkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkklllllllllmnnnooppquã˷ʶɵȴƲð5V4U4U4U4U4U5V6W7Xmwkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkklllllllmnnnoppp~¡е©lb˶ɵȴƳı°3U3T3T3T3T4U4U5V6W~kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllmmnnoopp¡á؅MoMoMoMoɵȴƲı°7W3T3T3T3T3T3U4U5Vkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllmmnnoop¡áġTvMoMoMoMoMo`z±ðOf4U3U2T3T3T3T4UHekkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllmnnoo¡áššWyKmKmMoMoMoMoMoMoMoNoRtp}vr{h2S2S2S3T銙kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllmnnp¡ġššǡcEgIkHiLnKmMoMoMoMoOql{}}}}vAa2S3T3TkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkklllllmnnqáġšơǡΫ2S=_IkMoGhLnMoMoMoMo\{mn|}}}Ll2S2S3Ukkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkklllllmnt¡áġšơǡȡӳ3T2S2S=^LnMoMoMoMoMoMoMoOpcYynoAa2S2Suzrqpoonmllllkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkklllllm¡áġšơǡȡɡTv1R4U6W4U?aMoMoMoMoMoMoNoNoMoMoMoHj2S2S~uqonllkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllm¡áġšơǡȡɡʡ6V1R1R1R1R1R2SEgMoMoMoMoMoMoMoMoMoMoMo;]{tomllkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllm¡áġšơǡȡɡʡˡ5V2S:[CdLnEg9Z2S1R7WMoMoMoMoMoMoMoMoMoMoMoNpRs]|}uolkkkkkkkkkkkkkkkkkkkkkkkkkllll¡áġšơǡȡɡʡˢ̢NpMoMoLnMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqQrRsUvYysqnlkkkkkkkkkkkkkkkkklllm¦¡áġšơǡȡɡʡˢ̢ШMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqPrRsTuWw\{dvmlkkkkkkkkkllnʮ¡áġšơǡȡɡʡˢ̢͢ٹMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNpOpOqQsSuWw[z`xzvlkkkkllsдġšơǡȡɡʡˢ̢͢΢NpMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqQrSsVvYy]|n||yxmklӷơǡȡɡʡˢ̢͢΢ϢStMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqOqQsSuWw[z^}r|xwzyոȡɡʡˢ̢͢΢ТТnMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqQrRsUuWw[z`s|zxwغˡ̢̢͢΢ТТѢNpMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNoOpOqQrSsUvXx[{_~o{|{z۽̢͢΢ТТѢҢMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqOrQrStVvWx[{^}er{{wzƼȽȾz_ݿ΢ТТѢҢ۵YzMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqOrQrStUvWw[{^}`fr{xr鞷¶¶ƺȼrz_z_z_gz_z_ݽѢѢҢӢQsMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqOrQsSsUuWwZz\|_cozzt~´ƹǼɾpz_z_z_z_z_z_z_z_|aøz_z_z_۷ҢӢԢMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNoNpOqOqQrRsTuWwXx[{^}ahyzwzµĸźǼȽqz_z_z_z_z_z_z_z_z_z_z_z_z_fyz_z_z_z_ٮԢգNqMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOpOqPrQsStUvWwZz\|_~dn{{v׼ɾµĸƺǼɾ¶oz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_ר֣TuMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnMoMoMoMoMoMoMoMoMoNoNoNpOqOqQrStTuWwYy\{^}afv{s䣻iabciҿоɹŸƹǼɾɾez_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_٨\|MoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnLnMoMoMoMoMoMoMoMoMoNoNpOpOqOqQrRsSuVvWwZz]|_djrsabcdefhj͹ķmnĵµöz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_{qMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnLnKmKmMoMoMoMoMoMoMoMoMoMoNoNpOqOqPqQsStTuVwYy[{_~bgnmwbddeghkϺιnppqձռ}az_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_rMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnLnKmJlIkKmMoMoMoMoMoMoMoMoMoMoNoNpNpOqOqQrRsTuUvWw[z^}`dhkqddfghnнлϻκ{pp|}~|NQ֍wz`z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_kNpMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnLnKmJlIkHjGhKmMoMoMoMoMoMoMoMoMoMoNoNpNpNpOqQrQsStTuWwZz\{_cgksf~{zѼѼϻϻqöȷdzIJ¯为|}RKKKKJJIPbՃfz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_iZ{MoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlIkHjFhEfCeLnMoMoMoMoMoMoMoMoMoMoMoNoNpOpOqOqQrRsSuVvXx[{_~bfks隲vuvuvwyϻѼлϻκ̸˷ɶdzŲñ°°°~eMLLKKKKJJIIIIHGMqݗpz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_f숢MoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnLnKmJkHjFhEfBd@a?aLoMoMoMoMoMoMoMoMoMoMoMoNoNpNpOpOqQrRsStUvWw[{^}bhmvҺonnnospssuѼѼлϻι̸˷ɶȴƳŲŲʴONMMLLKKKKJJJIIIHHGGGFFTǫvz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_~dMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlIkGiEgBd@a=^;\=^MoMoMoMoMoMoMoMoMoMoMoMoMoNoNpNpOqPrQsSsUuWwZz]|aekv߱nljiihgghnkopr}ѼѼѼлϺι̸˷ʷɶɵ鿾fONNMMMLLLKKJJJIIIHHHGGGJfz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_|bVwMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnLnKmIkHiFhCe@b=^;\8Y3U;\MoMoMoMoMoMoMoMoMoMoMoMoMoMoNpNpOqPqQrRsSuWwZz\{_~ukq榾߭vojhggfdcba~a~_}_}dggkmrѼѼѼѼлϻκ͹͹̸QOOONNNMMMLLLKJJJIIIIHHGSkz_z_z_z_z_uz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_{a柶MoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlIkHiEgBc>`<\8Y6W2S1R@bMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNoNpOqPrRsSuVwYy[{_~jpvꞶվq`~]}_~_~`aaa`~_}]{[zZxYwXvVuVtZxa~`}bflϻҽѼѼѼлϻzPPOOOONNMMMMLLLKKKJIIIIHi|}bz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_}cOrMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlHjGhDf@b=_:\7X4U1S1R1RDeMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpNpOqPrRsStUvWx[{^}qo{떯昱}ja_~XxXwXxYyZyZz[{[{[z[zZyXwVuTtRrPpOoNmMlMmVuYwYv]{fϻҽ˼z|aQQPPOOONNNMMMMLLLKKKJIIJvo{`z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_qMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlHjFhCe@a<]8Z5W3T1R1R1R1REgMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqPrQrSsUuWwYy^}rq|ݰplc`]|ZzXxVwUvUvUvUvUvVvVvVvUuTtSsQrPpMmKkIiGgFfEeEeFfQoTrSpd|uwxyzVRQQQPPOOOONNMMMLLLKKKJJO|~kz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_MoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlHjEhCe?a<]8Y5W3T1R1R1R1R1RFhMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqOqQrRsSuVvWxZzas|ӿ}}}jca`^}\{YyWxUvTuStRsRsRsRsRrRrQrPpNoMnKkIiGgDeBc@a>^=^<]BbFeKkofZTRQQQPPPOONNNMMMLLLKKKX|{gz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_XyMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlHjEhCe?a<]8Y5W3T1R1R1R1R1R1RGiMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNpOpOqPrRsStUuVw[{w|}|lu{w}ya^}\|[{YyXxVwUuStQsQrPqOqOpOpNoMoMnKmJkHiFgCdBb?_=^:[9Z8Y7X8Y<\͹hVSPOOONNNMMLLLKbx~cz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_d߽MoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlHjFhCe@a<^9Z5X3T1R1R1R1R1R1R1RHjMoMoMoMoMoMoMoMoLnLnLnLnLnMnMoMoMoNpOqOqPrQsStUuUuXx_}lm`iaj^}YyYyXxWwUvUuStRsQrOqNpMoMnLnKmKlIkIjGhEfBcAc?_=];[9Z7W4U5U3THhjONNMMLLk~dz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_tPrMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlIjGhDfAb=`:\8X3T2S1R1R1R1R1R1R1REfMoMoMoMoLnLnLnLnLnLnLnLnLnLnLnMoMoNoNpOqOqQrQsRsStTuWwhdVwfWwVvUvUuTuTtSsQsQrPqOpMoMnKmKlJkHjGiFhDfCdAb?`=^:\7X5W5V4U2S3T xbz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_蓫MoMoMoMoMoMoMoMoMoMoMoMoLnLnKmKlIkHiEgBd@`<]9Z4U3T1R1R1R1R1R1R1R1RBdMoMoLnLnLnLnLmKmKmKmKmKmKmKmLnLnMoMoNoNpOpOqPqQrQrQsRsRsRsStSsRsRsRsQrQrPqOqNpMoLnLmKlIkHjGhFgDfBdAb>`=^9\5V4U5W3T2S2SHglz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_OqMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJkHjFhDe@b=`;\6W3T1R1R1R1R1R1R1R1R1R>`LnLnLnLmKmKmKlJlJlJlJlJlKmKmKmLnMnMoMoMoNpOpOqPqPqPqPrQrQrPrPrPrPqOqOqNpNoMnLmKmJlHjGiFhDfCdAb?a=_;\5V2S1R3T3S1R2S̓p~ez_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_sMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlIkHiEgBd@a<]6X5W1R1R1R1R1R1R1R1R1R1RދMoKmKmJlJlIkIkIjIjIjIkIkJkJlKmKmLnLnMoMoMoNoNpNpOpOpOpNpOpNpNpNpMoMoLnKmKmJkIkGiEgDfCeAc?a>`<]9Z3T2S3S2S1R1R8Yte{`z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_}aMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlIkGiDfBd?a8Z9Z1R1R1R1R1R1R1R1R1R1RԾLmJlIkHjHiGiGhFhGhGiGiHjIkIkJlKmKmKmLnLnMnMoMoMoMoMoMoMoMnMnLnKmKmJlIkIjGiFgEfCeAc@a>_<]:[9Z7X5U2S1R1R1Rnxz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_qRtMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmKlIkHiFhDfAc;]:[2S1R1R1R1R1R1R1R1R1R^~HiFhEgDfDeDeDfDfEgFgGiHjHjIkIkJlKmKmKmLnLnLnLnLnLnLnKmKmJlJlIkHjGiEgEeCeAc?a>_=]:[9Z7X1S2S1R1R1Rc}}az_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_tMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlHjGiFhCe>_:[4U1R1R1R1R1R1R1R1R1RوDfCdAcAbAbAbAcBdCeEfFgGhGiHiHjIkIkJkJlJlKmKmKmJlJlJlIkHjHiGhFgDfCdBc@a>`<]8Z8X6W5U3S2S1R1R}fz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_ܻ嘰MoMoMoMoMoMoMoMoMoMoMoMoMoLnLnLnJlIkHjGhEg@a;]7X1R1R1R1R1R1R1R1R1RƼDe?a>_>_>`?`@bAcBdCeEfFgFhGhGiHjHjIkIkIkIkJkIkIjHjGiFhEgDfBdAc@a>_;\8X4V7X6W5V3T1S6Vȅwez_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_MoMoMoMoMoMoMoMoMoMoMoMoMoMoLnKmKlJlIkGiEh>_=_:[1R1R1R1R1R1R1R1R1R[z;\:\;\;]=^?_@aAbBcCeDeDfEgEgFhGiGiHiHiHiGiGhFhDfDeBdAc?a=^8Z8X6X7Y5V3U3T3S>^åk}az_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_KmKmKmMoMoMoMoMoMoMoMoMoMoMoMoKmKmJlHjHhEh?`>_<\2S1R1R1R1R1R1R1R2Rũ9Y7X8Z:[;]=_>_?a@a@bAcBcBdCeDeEfEgEgEfEfDfCdBc@b?`<]4U1R2T3T4V3S3T2SCbϪw|`z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_lNpKmGiMoLnHiMoJlJlMoMoMoMoMoLnKmKlIkHjFhEgAb=^<\5U1R1R1R1R1R1R1RIh]|6W7Y9[;\;]<^=^=_>_?`?a?aAbAcBcBcBcBc@b@a>`9Z3U1R3U5W5V2S1S1Rkz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_~KlKmLnEgKmMoMoLmEgCe=^CeIkLnKmHjJlHjHiEhEf@c<]<\8Y1R1R1R1R1R1R1Ri<]7Y9Z9[:[:[:[:\;\;]<^=_>`>`>`>`>_;\6W3S2S3T2S1R1R1RBb̨ez_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_ˡFf9[;]?`FhJlGh@cDfIjJlGjCdCeKmJlIkHjFhEgCd@b<]:\8Y1S1R1R1R1R1R1RәǛ=]8Y8Y8Y8Y8Y8Y9Z:[:\;\;]:\8Y6V4V6W3U2R1S1R4Tzt}az_z_z_z_z_z_z_z_z_z_z_Aa2S5V4U5V7X8Y9[:[:\;]=^DeCeEgGiGhFgFgDeBd@`:\9Z7X3T1R1R1R1R1R1RȐ;[4U5V5V5V6W7X7X5V5V7W7Y7Y4T3T2S2SVuԠziz_z_z_z_z_z_z_<\4U6W5X7W6X5V7X<]<^<^;];\<^?`@a>_=_>_?aAb?`;\9Z7X4V1R1R1R1R1R1R=]3T3T3U5U5V5W5V4U4T2T2SBbƏj~bz_z_Ӹ5V4U5V3T3T<]DfBdCd@a>_Bc=_@c?aFhEgCdBc>`@a>`;\9[6X4U2S1R1R1R1R1Rӡʁ2S3T3U4T2S2S[zSq3T3T4U7W7X6X6W7X8Y<]CdCe>`DfBcBcCdBdAc@b@a=`;\8Y5W4U2T1R1R1R1R1Rh5V3T3T3T5V5V6W6W6W5V5V5V5V4U5V5V5V4U4VAb@b@`=_;\8Y6X4U3T1R1R1R1R1R7X3T3T3T3T6W5W4U4U4U3U4U5V5V4U4U3T4U4U8Y@b@a>`=_;]8Y7X4U4T2S1R1R1R1R1R;\2T4U:[5V6W6W5W5W5V5V4U4U4U4U5V8X<]=_>_?a?`?`>_<]8Z7X5V3T3T1R1R1R1R1RӇ2S2S6W:[:[@cCeCdCdBdBcAb@a?`@a>`?`?`?a?a?b?a?`=_<^:\8Y5X4U4T2S1R1R1R1RJi\z2S2S8Y8Z<]<]AbAcAbAb@b@a?`>`>`=_=_>_?`?a@b@b@a>`=_;\9Z7X5V4U3T1R1R1R1R1R5V2S2S7Y8Z:[;\=_?`?`?`>`=`=^=^=^=^=_>`?`?a@bAb@b?a>`<]9Z8Y5W5V4U3T1R1R1R1R2S2S4U7Y8Z9Z=^:[=^=_=_=^<^<]<^<^=^=_>`?a@bAbAbAb@b?a<^:\9Z7X6W4U3T1S1R1R1RӂYw2S2S5V8Y8Z9Z;\;]:[<^<]<]<]<]<]<^=^>_?`@aAbAcBcAdAb@a>_;\9[8Y6X5V3T3T1R1R1R@_5V2S2S6W8Y8Y:[9[;];\:[;]<]<]<]<^=_>_?`?bAbBcCeCdCeBd@b?`<]:\9Z7Y5V4T3T2S1R1R6Vз3T2S2S5W8Z9Z9[9Z9[;\;\:\;\<]=^=_>_?`?aAcBdCeDeDfDeBdBc@a>_;\9Z8Y5W4U2T2S2S1R1R[z3T2S2T5V8Y8Z9Z9Z9Z9[:\;\;\<]=^>_?_?aAbBcCeDfDfDfDeCdBd@a=_<]9Z8X6W4V3T2S2S1R1R8X2T2T2T3U8Y8Y8Y8Z8Z9Z9[:\;\;\<^>_?`@bAcBdDeDfEfEgDfDeCdAc?`<^:\8Y5W4U4U3T2S2S1Rўа2T3T2S2S2S7W7X7X7X7Y8Y8Z9Z:[;\;\<^>_@aAcBdDeDfEgFgEgDfCeBd@a=^;\8Y6X5V4U3T2S2S1Rb~^|2S2S2S2S2S4U5V5V5W6W6W7X7X8Y9Z;\;]<^>`@aBcCdDfEgEgEfDfCeAb?`=_;\9Z6X5V4U3T3T2T2S1R8X2S2S2S2S2S1R4U4U4U4U5V5V6W6W7Y9Z:[;\=^>`@bBdCeDeDfDfDfCd@b?`<^;\8Y6X4U4T3T2S2S2S1Rϸ2S2S2S1R1R1R1R1R2S3T3T3T4U4U4V5W7W7Y9Z;\<^>`@aAcBdCeCeCeBd@b?`<^:\8Y6X4U3T2S2S2S2S2S\{3T2S1R1R1R1R1R1R1R1R2S2S2S3T3T4U4V6W7X9Z:[<]>_@aAbAcBcBcAc@a?`<]:\8Y6W4U3T2S1R1R1R1RЧ7X5V4U2S1R1R1R1R1R1R1R1R1R2S2S2S3T3T4U5W7X8Z:[<]=_?`@b@a@b@a?a>_<]9[8Y5V4U2T2S1R1R1R1RsӁ4U4U4U3T2S1R1R1R1R1R1R1R1R1R1R2S2S2S3T4U5V7W8Y9Z;\<]=_>`>`>`=_<];\9Z8Y5V4U2T1S1R1R1R1R7W;[4U4V4U3T2S2S1R1R2S1R1R1R1R1R1R1R1R1R2S3T4U5V6W7X8Y9Z:[;]<]<]<];\:[8Y7X5V4U2T2S1R1R1R1R1R4U4U4V4V4U3T2S2S2S2S2S1R1R1R1R1R1R1R1R1R2S3T4U5V5V6W7X7Y9Z9[9Z9[9[9Z8Y7X5V4U3T2S1R1R1R1R1Rλ,E5V5W5V4V4U3T3T2S2S2S2S2S2S1R1R1R1R2S2S2S2S3T4U4V5V6W6W7X7X7Y8Y7Y7X6X5V4U3T2S2S1R1R1R1Rэ,,s(?5U6W5V4U4U3T3T2S2S2S2S2S2S1R1R2S2S2S2S2S2T3T4U5V5V5W6W6W6W7X6W6W5V4U3T2S2S1R1R1R1Rjds++*)$,.I4U6W5V4V4U3U3T3T3T2S2S2S2S2S2S2S2S2S2S3T3T4U4U4U4U5V6W6W6W5W4U3T2T2S1R1R1R1RNl,2B+**)('&'["65U6W5V5V4V4U4U3T3T3T2S2S1R1R1R2S2S3T3T3T3T3T3U5V5W6W6W5V4U3T2T2S2S2S1R6V /**)(('%$$#%,"4B%9,F4S5V5V4U4U3T2S1R1R1R2S2S2S2S2S2S2S3S4U5V6W6W6W5V4U3T2T2S2S1R1R+*))('&%$#"& 1!1!2!2!"2#"41#6K';d)@+F/K1P2S2S2S2S2S1R1R1R2S3U5V6W7X6X6W5V4U4U4U3U1R1R+*)(('%$#"!( 1 1!2!2!2 "3 "3 "3!#4!#4!#4"$4#$4$$5&$6'$6+%6:&9I';X(>e*Ap+C{-F/H0I0K0K1L0L1K1K0I/IYs+*)('&%#"" ( 1 1!1!2!2 "2 "3 "3!#4!#4!#4"$4"$5"$5"$5"$5"$5#%5#%5#%5#%6#&7%'7%'7%'7%'9&'9')9');'*;(*<)+=+->boiy*))('%$#"! % 1 1!1!2!2"2 "3 "3!#4!#4"$4"$4"$5"$5"$5#%5#%5#%6#%6#%6$'7%'7%'7%'8%'9')9'):');(*;)+<*,>+->,.?IQcDN_*)((&%$#"  ! 1 1!1!2!2"2 "3 "3!#4!#4"$4"$5"$5#%5#%5#%6#%6#&6$&6$&7%'8%'8&(8&(9')9');(*;)+=*+=*,>,.?-/@./A12D,1A*)((&%#"  !1!1!2!2!2 "3 "3!#3!#4"$4"$5"$5#%6#%6$&6$&6$&7$&7%'7&(8&(8&(9&(:(*:(*;)+<*,=*,>+.?,.?-/A./B/1B/1C(.>*)((&$#!  1!2!2!2"2 "3!#3!#4"$4"$5#%5#%6$&6$&7%'7%'7%'7&'8&(9')9'):'*;(+;)+;*+=+->+-?,.?-/A./B/1C/1C/2E02E(-=*)((%#"! -!2!2!2"2 "3!#4!#4"$5#%5#%6$&6%'7%'7%'8&(8&(9&(:'*:(*:(*;)+<*,=*,=+->,.?-/A./B/1C/2D02E13E13F23F).>*)('%#"! $!2!2"2 "3!#3!#4"$4"$5#%6$&7%'7&'8&(8')9')9'):(*;)+;)+;*,=+-=+->,.?,.?./A/0C/1C03E13E13F24G35H35H39I*('&%$"! !2"2 "3 "3!#4"$4"$5#%6$&6%'7&'8&(8')9'):(*:)+;*+<*,<+->+->,.?-/?-/@./B/1C/2D13E13F24G35H35I35I46Ip~Taq)('&%$"! ) "3 "3!#3!#4"$4#%5#%6$&7%'7&(8')9'):(*:)+;)+;*,=+-=+->,/?-/@./A.0B/1C/2D13E23F24G35I36I46J46J46JXat)('&%$"!  "3 "3!#4!#4"$5#%5#%6$&7%'7&(8')9'*:(*;)+;*+=+-=+->,.?-/?-/@.0A/1C/2D13F24G35G35I46I46J57K57K57KNUh)(('%$#! " "3!#4"$4"$5#%5#%6$&7%'7&(8')9'*:)+;)+;*,<+->,.>,.?-/?./A/1C02C13E23F24G35H36I46J57K57K57K57KBG[,(('&%"  ,!#4!#4!#4"$4"$5#%6$&7%'8&(8'*:(*;)+;*,=+->,.>,.?-/A/1B/2C02D13F24G35G36I46J57K57K57K57L57L8:O"2)('%$"!   0!#3!#4"$4"$5#%6$&6%'7%'7&)9(*:)+;*,<+->,.?-/?-/@/1B02C13E13F24G35I46J46J57K57K57L57L67L68L*)('%$#!    1"$4"$4#%5#%6$&6%'7%'7&(8'*:)+;*+<+-=+.?-/?./A/1C02D13E24G35G36I46J57K57K57K57L57L68L68L*)('&$"!     *"$5#%5#%6$&6$&7%'7&(8'):)+;)+;+-=+.>-/?./A/1C02D13F24G35H36I46J57K57K57L57L57L68L68L8?O))('%$"!      + "$5#%5$&6$&7%'7&(8')9'*;)+;*,=+->-/?./A/1C02D13F24G35H46J46J57K57K57L57L67L67L68L"2))(&%$"!     +  +  + -#%6$&7%'7%'8&(9'):)+;*+<+-=-/?-/A/1B02E13F24G35I46J57K57K57K57L57L67L57L67L**)(&&$#!       +  + +!#4#%6$&7%'7&(8')9(+;)+;+-=+.?./A/1B02E13F24G35I46J57K57K57K57L57L68L68L68L}+*)('&$"!      + + +   "2#%5#%6%'7&(8')9'*;)+;*,=+->-/A/1B/2C13F35G35I46J57K57K57K57L57L68L68L68Liw6=L+*)('%$#!      +  +   0#%5#%6$&7&'8&(9'):)+;*+<+->-/@.0B/2C02F24G35I46J57K57K57K57L57L57L57L68LU_s!1+*)('%%"!      + + +  ."$5#%5$&7%'8&(8')9(+;)+<+->,.?.0B/2C02E23G35I46J57K57K57K57K57L57L57L67LFL`+++)('&$#"     +  + +  +"$5#%5#%6%'7&(8&(9(*;)+;+->,.?.0B/2C02E23G35I46J46J57K57K57K57L57L57L57LDI]j|,+*)('&$#!     +  +  +  ("$5"$5#%6%'7%'8&(9'*:)+;*+<,.?-/A/1C02E23G35H46I46J57K57K57K57L57L57L57L?DX.3D,+*)('%$#!     +  +   !"$4"$5#%6$&7%'7&(8'):(*:*+<+.?-/A/1C02D13F24G35I46J57K57K57K57K57L57L57L=AV!1,+*)('&%#!     +  + +  !#4"$5#%6$&6%'7%'8'):(*:)+<+->-/@.0B/1C13F24G35I46I46J57K57K57K57L57L57L:=R,,+*)('%%#"     +  + +   !#4"$5#%6$&6$&7%'7'(9'):)+;+,=,.?.0B/1C13F24G35H36I46J57K57K57K57K57L57L7:OTbs,,+*)('&$#!     +  +   +"$4"$5#%5#%6$&6%'7&(9')9(+;*+<+.?-/A/1C02E13G35H35I46J46J57K57K57K57L57L57L*/?,,+*)('&$#!      +  + +   "$4"$4"$5#%5#&6%'7&(8&(9'*:*+<+->-/A.0B02E13F24H35I36I46J46K57K57K57K57L57L /,,+*)((&$#!      + +    HS]#&7"$4"$5#%5#%6$'7%'8&(8'):)+;+->,.@.0B/1C13F24G35I36I46J46J46K57K57K57K57L-,,+*)((&$#!    +  +  +   %(9!#4"$4"$5#%6$&7%'7%'8')9'*;*+=,.?-/A/1C02E23G24H35I46I46J46J57K57K57K57L-/@.0B02D13F24G35H36I46J46J46K57K57K57K"&7.,,+*)((&$"!     +  + +   9BJ(++.?.0B/1C02E13G24H35I46J46J46J57K57K57K/-,,+**((&$"!     +  +   39J"$5"$5#%5#%5#%6#%6$&6%'8&(9(*;*+=+.?-/A/1C02E13F23G35H35I46J46J46K57K57K.-,,+**((&$"!    +  +  +  ?J["$5"$5"$5#%5#%5#%6#&6%'7%'9'):)+=*,>+.@./C/1D13F23G35H35I46J46J46J46K57K/5F.-,,,*)((&$"     +  + + +  HT]MYj"$5"$5"$5"$5#%5#%6#%6$&7%'9'):(*;*,=+-@-/B/1C02F13G24G35I35J46J46J46K57K"2--,,+**('&$"     +  + +  [i{"$5"$5"$5"$5#%5#%5#%6$&7%'7&(:(*;)+=+-?-/A.0C02E13F23G35H35I46J46J46K57K.--,,,*)('&$"     + + +  i{"$5"$5"$5"$5"$5#%5#%5#%7%'7&(9(*;)+<+-?,.A.0B/2D02E23G35H35I35J46J46J46Kj|.---,,+)('%$"     + + +  Zit}"$5"$5"$5"$5"$5#%5#%5#%6%'7&(9');)+;*+>,.?./B/1C02E13G24G35I35I46J46J46K%(8.---,++)('%#"      + + +  "$5"$5"$5"$5"$5#%5#%5#%6%'7&'8'):(*;*+>+.?-/B/1C/1E13F23G35H35I36J46J46K/.---,++)('%#!      + + + "$5"$5"$5"$5"$5"$5#%5#%6$&7%'8'):'*;)+=+-?-/A./C/1D02F23G24G35I35J46J46J.----,++)('%#!    +  + + + m"$5"$4"$4"$4"$5"$5"$5#%5$&7$&8&(9');)*=*,>+.@./B/1C02E13F24G35I35I46J46JVcv.----,++)('%#     +  +  #&6"$4"$4"$4"$4"$5"$5"$5#&6$&7%'9'):(*<*+>+.?-/B.0C/2E13F23G24I35I36J46J|#&7.----,+*)(&%#     + + + + +"%(8"$4"$4"$4"$4"$4"$5"$5#%6$&7%'9&(:(*;*+>+-?-/B.0C/1D02F13G24H35I36I46Jx/.----,+*)(&$"      +  + + +'+;!#4!#4!#4!#4"$4"$4"$5#%6#%7%'7&':');)+=*,?,.A./B/1D02F13G24H35I35I46Ju{/.----,+*)(&$"      + + + +)->!#4!#4!#4!#4!#4!#4"$4#%5#%7$&7&'9');(*=*,>+.A-/B/1C02E13G24H35I35I46Jr?I[/.---,,+*('%$!     + + + + %*-1C!#4!#4!#4!#4!#4!#4!#4#%5#%6$&7%'9'):(*<*,>+-@-/A.0C/1E13G24G35H35I46Jr"3/.---,,+*('%#      +  + +=FW!#4!#3!#3!#4!#4!#4!#4"#5"$6$&7%'9&(:(*;)+>+-?,.A.0C/1D13F23G35H35I46Jo/..---,,*)('%#       + +P\n!#3!#3!#3!#3!#3!#3!#4"#5"$5#%7%'7&(:'*;)+=+-?,.A./C/1D02F23G35H35I46Jkz\l}...---,,*)(&$"       + +8ALdu!#3!#3 "3 "3 "3!#3!#3"#5"$5#%6%'7&':');)+=*,?,.@./B.0D02F13G24H35I46Jkz,2C...---,+*((%$"      +  + +v!#3 "3 "3 "3 "3 "3!#3"#4"$5#%6#&7&'9');)+=*,?+-@-/B.0C02F13G24H35I46Jkz 1....-,,+*('%#      +  "3 "3 "3 "3 "3 "3 "3"#4"$5#%6#&7&'9');(*=*,>+-@-/B.0C02E13G24G35I36Jr/....-,,**('$#      + Udp "3 "3 "3 "3 "3 "3 "3"#3"$5#%6#&7&'9'):(*=*,>+-@-/B.0C02E13F24G35I36Jq+-@-/B.0C/2E13F24G35H35Jq"3//...-,,*)(%$!     #* "3 "3 "3 "3 "3 "3 "3"#4"$5#%6#&7%'9'):(*=*+>+-@-/B./C/2E13F23G24I35Iq//...-,,,*((%#!     + q "3 "3 "3 "3 "3 "3 "3"#4"$4#%6#&7%'9'):(*=*+>+-?-/A./C/1E13F23G24H35Iw//...-,,**('%"      + $&8 "3 "3 "3 "3 "3 "3"#4"$4#%6#%7%'9'):(*=)+>+-?,.B./C/1E02F23G24H35Iy,2C//...-,,**(&$"     +1;'+< "3 "3 "3 "3 "3 "3!#4"$4#%6#&7%'9'):(*<*+>+-?,.B./C/1E02F23G24H35I} 1//...-,,*)(%$!     + */@ "3 "3 "3 "3 "3 "3!#4"$4#%6#&7%'9'(:(*<)+>+-?,.A./C/1E02F13G24H35I//...--,+*)'%#!     + 28I "3 "3 "3 "3 "3 "3!#4"$4#%6#&7%'9'(:(*<)+>+-?,.A./C/1E02F13G24H35I]m//...--,+))'$"     9DOIUg "3 "3 "3 "3 "3 "3!#4"$4#%6#&7%'9'):(*;)+>+-?,.A./C/1E02F13G24H35I!%7//...--,+)(&$!     ev "3 "3 "3 "3 "3 "3!#4"$4#%6#&7%'9'):(*;)+>+-?,.A./C/1E02F23G24H35I0//..---++)(&#!    } "3 "3 "3 "3 "3 "3!#4"$4#%6#%7%'8'):(*;)+>+-?,.A./C/1E02F13G24H35Iz///...--+*((%#    Q`l "3 "3 "3 "3 "3 "3!#4"#4#%6#&7%'9&(:(*;)+>+-?,.A./C/1E02F13G24H35I?I[///..---+*('%"     "3 "3 "3 "3 "3 "3 "3"#4#%5#&7%'9'):(*;)+>+-?,.A./C/1E02F13G24H35I"3///..--,+*(&$"   !* "3 "3 "3 "3 "3 "3!#4!#4#%5#&7%'9&(:(*;)+>+-?,.A./C/1E02F23G24H35I////.---,*)(&$!   i~ "3 "3 "3 "3 "3 "3!#3!#4#%5#%7%'9&(:(*<)+>+-?,.A./C/1E02F23G24H35IP^o////.---,*)(%#"   "3 "2 "3 "3 "3 "3!#4!#4#%5#&7%'9&(:(*;)+>+-?,.A./C/1E02F23G24H35I(->////.--,,*((%#! -5?$'8 "2 "2 "3 "3 "3!#4!#4#%5#&7%'9&(:(*;*+>+-?,.A./C/1E02F23G24H35I 1////.--,+*('$#!  )-? "2 "3 "3 "3 "3!#4!#4#%5#&7%'9&(:(*;)+>+-?,.B./C/1E02F23G24I35J/////.-,,+)(&$#  .4E "2 "3 "3 "3 "3!#4!#4#%5#&7%'9'):(*<)+>+-?-/A./C/2E13F23G24I35I).@/////.-,+*)(%$"! =HS=GX "2 "3 "3 "3 "3!#4!#4#%5#&7%'9'):(*<)+>+-?-/A./C/2E13F23G35H35I0////..-,+*((%$" `q "2 "3 "3 "3 "3!#4!#4#%5#&7%'8'(:(*;)+>+-?-/A./C/2E13F23G35H35I/////..-,+)('%#"   "2 "2 "3 "3 "3!#4!#4#%5#&7%'9'(:(*<*+>+-?-/A./C/2E13F23G35H35IUct////...-,*)(&%#"  JWd "2 "2 "3 "3 "3!#4"#4#%6#%7%'9'):(*<*+>+-?,.A./C/1E13F24G35H35I!%6////...-,*((&$#"! "2 "3 "3 "3 "3!#4"#4#%6#&7%'9'):(*<*+>+-?,.B.0C/1E13F24G35H46J0///...-,+)('%$#!  !$5 "3 "3 "3 "3!#4"$4#%6#%7%'8'):'*<*+>+-?-/B.0C/2E13G24G35H58Ln////...-,+*(&%$#"  ES_#%6 "3 "3 "3 "3"#4"$4#%6#&7%'8'):(*<*,>+-?,.B.0C/1E13G24G35H8;O"%6///...-,++)(&$#""! &*< "3 "3 "3 "3"#4"$5#%6#%7%'8');'*<*+>+-?,.B/1C/2E13G24H24I:>R////...-,+*)(%$#""!  +4;M "3 "3 "3!#3!#5"$5#%6#%7%'8');(+<*+>+-?-/B.0C/2E13G24G35I<@THSe////...-,+*('&$#"!!  ]n}BM` "3 "3!#3!#3!#4"$5#%6#&7%'8');(*<*+>+-?-/B.0C02E13F24G35I>CW 1////...-+*)('%$""!!   Vdu!#3!#3!#3!#3!#5"$5#%6$&7%'9&(:(*;*+>+-@-/B.0C02F13G24H35I@F[z/////..-,+*)(&%$#"!!  ;GVw!#3!#3!#4!#4!#5"$5#&6$&7%'9'):(*=*,?+.@-/B/1C02E23G35G35ICJ]06G////...-,+*)'&%$#"!!  !#4!#4!#4!#4!#5#%5#%6$&7%'9'):)+<*,?+.@-/B/1C02E23G35G35IMTi0////...-,+)('%$##"!  "'3!#4!#4!#4!#4"$5#%5#&7$&7&'9');)+<+,?,.@-/B/1C02F23G35H35IYeyWgy/////..-,+*)(&%$#"""! s"$4"$4"$4"$4"$5#%6#%7%'7&(:'*;)+=+,?,.@./B/1D13F23G35H35Ihw"%7/////..-,+*)(&%$#""!!"ew"$5"$5"$5"$5"$5#%6#&7%'8&(9'*;)+=+-?,.A.0C/1E13F23G35H36Iv/////...-,+*('&$$"""! cwVew#%5"$5"$5#%5#%5$&6$&7%'8')9'*;)+>+-?-/A.0C/1D13F24G35H36I;DV/////...-,+*('%$#""!  P]o#%5#%5#%5#%5#%6#&7%'7&'8&(:(*;*+=+-?-/A.0B02E13F24G35I36I0/////...-,*)('%$#"!! 17FJVh#%6#%6#%6#%6#%6$'7%'7&(9'):)+<*,>+.?-/A/1C02D13F34G35I36I//////..--+*)'&%#""   DOa$&6$&6$&6$&7$&7$&7%'8&(9');)+;+,>+.?-/A/1C/2E13F34G35I36I3:L//////..-,+*)'&$#"!  "&2?I[$&7$&7$&7$&7$&7%'7&(8&(:(*;)+;+-?,.?./A/1C02E13G35G35I46J 1//////..-,+*('%$"!  ;DT$&7%'7$&7%'7%'7%'7&(9'):'*:*+<*,>,.?./A/1C02E23G35H35I46Jw///////..-,+*('%$"! %7>O%'7%'7%'7%'7%'8%'9'(9'):(+;)+<+->,/@./A/1C02E23G35G35I46J,1C///////..-,+)(&%#" ]o~17H%'8%'8%'8%'8%'8&(8')9'):(*;*+=+->-/@-/B/1C02E23G35G36I46J0//////...-,+)(&%#! ,1A%'8%'8%'8%'8&(8&(8'):(*:(*;*,=+.?-/?./B/1C13E13F24G36I46Jas///////...-,+)(&%#! ER`),=%'8%'8&'8&(8&(8&(8'):(*:(*<*,=+.?,.@.0A/1C13E13F24G36I;>R'+<///////..--,+)'&%#! *,<&(8&(8&(8&(8&(8&(9'*:(*:)+<*,=+-?,.@./A/1C02E13F24G35IAG[////////..-,+*)'&$#! $)5(+;&(8&(8&(8&(8&(8&(9'):(*;)+;*,=+->-/@./A/1C02E13F34G35IHOcM[l////////..-,+*)'%$#! (+;&(8&(8&(8&(8&(9')9'):)+;)+;+-=+-?-/@./A/1C02D13E24G35IMXk#'8///////...-,+*('%$#"!(*;&(8&(8&(8&(8&(9')9');)+;)+;+-=+.?-/@.0B/1C02D13F24G35HS^s////////..-,++)('%$#"r'):&(8&(8&(8&(9&(9')9');)+;*+<+-=,.?-/@.0B/1C02D13F24G35H^lCMa///////...-,+*)(&%$#$')9&(8&(8&(8&(9')9')9'*;)+;*,<+->,.?-/@.0B/1C/2C13F24G35Hm"3///////..--++*)'&%$#AM['(9&(8&(8&(8&(9')9'):(*;)+;*,<+->,.?./@.0B/1C02C13F24G35H}///////...-,+*)('%$$#%'8&(8&(8&(8&(9')9'):(*;)+;*,<+->,.?./@.0B/1C02D13F24G35HFRc///////...-++*)'&%$$29H%'8%'8&(8&(8&(9')9'):(*;*+<*,<+->,.?./A.0B/1C/2D13F24G35G!3//////...-,+*)('&%$$%'8%'8&(8&(8&(9')9'*:(*;*,<*,<+->,.?./A.0B/1C02E13F24G35G///////..--,+*)''%%$"'4%'7%'8&'8&(8&(9')9'*:(*;*,<+-=+->,.@./A.0B/1C02E13F24G35GTdv///////..--++)('&%$$o%'7%'7&'8&(8&(9')9(*:(*;*,<+-=+->-/@./A.0B/1C02E13F24G35G"3//////...-,+*)''&%$$|%'7%'7%'8&'8&(9')9(*:)+;*+<+-=+->-/?./A.0A/1C02E13F24G35H///////..--,+*('&%%$Tetp$&7%'7%'7&'8&(9')9(*:)+;*+<+-=+->-/?./A.0B/2C13E13F24G35HRas//////...-,+*)('&%$$ev$&7%'7%'7&'8&(9')9'*:)+;*+<+-=+->-/?./A.0A/2C13E13F24G<@S!%6//////...-,+*)'&&%$+3AXgx$&6$&7%'7%'8&(9')9'*:)+;*+<+-=+-?-/?./A.0A/2C02E13F24GHPb///////..--++*)'&%%$KWi$&6$&7%'7%'7&(8')9'*:)+;*+<+-=+->-/?-/@.0A/2C02D13F24GT_raco///////..-,++)('&%$(AK\#%6$&7%'7%'7&(8')9'*:(*;)+<+-=+->-/?-/@.0A/1C02D13E24Gap')9///////..-,+*)('%%$4;L#%6$&6%'7%'7&(8')9'*:)+;)+;+-=+->-/?-/@.0A/1C02D13E23Go0//////...-,+*)'&%%(39J#%6$&6$&7%'7&(8')9'*:(*;)+;+-=+->-/?-/@./A/1C02C13E23Fpq{///////...-,+*)'&%%Raq16F#%6$&6%'7%'7&(8')9'*:(*;)+;+-=+-=,.?-/?-/A/1B/2C02E13F%'8///////...-,+*)'&%$/4F#%6$&6%'7%'7&(8')9'*:(*;)+;+,=+-=,.?-/?-/@/1B/2C02D13E////////...-,+*)'&%KLV.3D$&6$&7%'7%'7&(8')9'):(*;)+;+,=+-=+.?-/?-/@/1B/1C02D13E////////...-,+*)'&%,2B$&6$&7%'7%'8&(8')9'*:(*;)+;*+=+-=+.?-/?-/@.0B/1C02C13E+-<////////...-,+*)(&()6.1@$&7%'7%'7%'8&(8')9'*:(*;)+;*+=+-=+.>-/?-/?.0A/1B/2C02D0////////...-,+*)('-0@$&7%'7%'8&'8&(9')9'*:(*;)+;*+<+-=+.>,.?-/?./A/1B/2C02D/////////...-,++)()-/>%'7%'7%'8&(8&(9')9'*:(*;)+;)+<+-=+.>,.?-/?./A/1B/1C57IIJX//////////..--,+*)*,<%'7%'8&'8&(8&(9')9'*:(*;)+;)+<+-=+.>,.?-/?-/A/1B/1COP` "2//////////...-,,+)),;%'7%'8&(8&(8&(9')9'*:(*;)+;)+<+-=+.>,.?-/?-/A/1B/1Cklz///////////...--,+DFR(*:%'8%'8&(8&(8&(9')9'*:(*;)+;)+<+-=+.>,.?-/?-/A/1B/1Cno{////////////...-,,%'8%'8%'8&(8&(8&(9')9(*:(*;)+;)+<+-=+.>,.?-/?-/A/1B/1C')9////////////....-13B%'8%'8&(8&(8&(9')9')9'*:(*;)+;)+<+-=+.>,.?-/?-/A/1B/1C0/////////////....%'8&(8&(8&(8&(9')9')9'*:(*;)+;)+=+-=+.>,.?-/?-/@/1B/1C///////////////..%'7&(8&(8&(8&(8&(9')9')9'*:(*;)+;)+=+-=+.>,.?-/?-/A/1B/1CADQ///////////////..&(8&(8&(8&(8&(9')9')9'*:(*;)+;*+=+-=+.>,.?-/?-/A/1B/1C!2////////////////0&(8&(8&(8&(8&(9')9')9(*:(*;)+;*+=+-=+.>-/?-/?-/A/1B/1C/////////////////lmy&(8&(8&(8&(8&(9')9')9(*:(*;)+;*+=+-=+-?,.?-/?-/A/1B/1C\_k/////////////////&(8&(8&(8&(8&(9')9')9(*:(*;)+;)+=+-=+.?-/?-/?-/A/1B14E*,;////////////////;,.?-/?-/A/1B////////////////git&(8&(8&(8&(8&(9')9')9(*:(*;)+;*+<+-=+.?,.?-/?-/A/1B////////////////&(8&(8&(8&(8&(9')9')9(*:(*;)+;)+<+-=+.>,.?-/?-/@.0BPR_///////////////EGU&(8&(8&(8&(8&(9')9')9'*:(*;)+;)+=+-=+->,.?-/?-/@24F////////////////&(8&(8&(8&(8&(9')9')9(*:(*;)+;)+=+-=+->,.?,.?-/@79I////////////////2A&(8&(8&(8&(8&(9')9')9'*:(*;)+;)+<+-=+->,.?,.?-/?;=M///////////////&(8&(8&(8&(8&(9')9')9(*:(*;)+;)+;+-=+->,.>,.?-/?XYggiu//////////////0&(8&(8&(8&(8&(9')9')9(*:(*;)+;)+;*,=+->,.>,.>,.?"$5//////////////&(8&(8&(8&(8&(9')9')9(*:(*;)+;)+;*,<+->,.>,.>,.?///////////////&(8&(8&(8&(8&(9')9')9(*:(*;)+;)+;*,<+->,.>,.>,.?//////////////MN[&(8&(8&(8&(8&(9')9'):(*:(*;)+;)+;*,<*,=+->,.>,.?//////////////&(8&(8&(8&(8&(9')9'):(*:(*;)+;*+;*,<+-=+-=+.>,.>KMZ/////////////&(8&(8&(8&(8&(9&(9')9'):(*:)+;)+;*+<*,<+-=+-=+->/1B!#4/////////////&(8&(8&(8&(9&(9')9'):(*:)+;)+;*+<*,<+-=+-=+-==?P/////////////&(8&(8&(8&(8&(9&(9')9'):(*:)+;)+;*,<*,<+-=+-=+-=JL[/////////////&(8&(8&(8&(9')9')9'*:(*:)+;)+;*,<*,<+-=+-=+-=^an?@O//////////0&(8&(8&(8&(9')9')9(*:(*;)+;)+;*,<*,=+-=+-=+-=ϻ|no96C//////bcp&(8&(8&(9')9')9'):(*:)+;)+;*+<*,<*,=+-=+-=+-=кккк˹@;G!1//&(8&(9&(9')9')9(*:(*:)+;)+;*,<*,<+-=+-=+-=+->кккккккȵȯ&(9&(9')9')9'):(*:)+;)+;*+<*,<*,=+-=+-=+-=+->ккккккккк')9')9')9():(*:(*;)+;)+;*,<*,<+-=+-=+-=+-=+.>ѻккккккккк'):'):(*:(*:(*;)+;)+;*+<*,<*,=+-=+-=+-=+->46Fккккккккк(*:(*:(*:(*;)+;)+;*+<*,<*,<+-=+-=+-=+-=,.>OP^jsкккккккк(*;)+;)+;)+;)+;*+<*,<*,<+-=+-=+-=+-=+->,.>giuŧj֡wעyĩкккккк)+;)+;)+;)+<*,<*,<*,<+-=+-=+-=+-=+->,.>,.>\j֡x֡x֡xopкк͵ͺe`z|02F.0B,.?+->+-=+-=+->+-=+-=+-=+-=+.>,.>,.>x-y1֡x֡x֜ojjjjjójj\^q;=T;=T;=T;=T;=T;=T;=T;=T:=S9;Q79O68M57K35I13FjՐZ֡x֡xՂAjjjjjƹjjij|;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=Tj֡x֡x֡xnjjjjjɽjjsu;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=Tkr&֡x֡x֡xkjjjjjj֗f;=T;=TWRcy}ymuiamYSdIH\;=T;=T;=T;=T=@Wt'Ւ]֡x֡x֟tjjjjjjײسкккккккккккj֡w֡x֡x֑]jjjjjjjיiкккккккккккތLw/֡x֡x֡xmjjjjjjשкккккккккккԷҴj֜o֡x֡x֠vjjjjjjjȼjڰкккккккккϹ- + +jk֡x֡x֡xՈLjjjjjjj²֎WккккккккϹ + + + +ޓXj֙k֡x֡x֞sjjjjjjjj֟sՈL黗ɯh̵ккккккœcd%  +jn֡x֡x֡xr$jjjjjjjjo֠vw,֝rjjjjp q"ojjĵjjY +_Pz/j֙i֡x֡xՐYjjjjjjjjjjj֚kv,jo氅֡wjjjjjjjjjjjj +,ѻju+֡x֡x֡xkjjjjjjjjjjׯՅFq$֪jjjr$֡xljjjjjjjjǹjjj + +q"jנv֡x֡xՄEjjjjjjjjjjjjɾՋRjjjjjä֡xnjjjjjjjjjjj-  +`RjՁ>֡x֡x֡wjjjjjjjjjjjjjj֒\ՃCjjjߔX֡xnjjjjjjjjؽjjjO +" q#j֠v֡x֡x}8jjjjjjjjjjjjjjjj֎U°֍T֡xkjjjjjjjj;֕bjji + +ȢՑ\֡x֡x֟tjjjjjjjjjjjjjjjjjjjlןsפ|֙ijjjjjjjjjjjjj@ + +ש֡x~:jjjjjjjjjjjjjjjjjjjv,֡xjjjjjjjjjjjՂB֕bjji$Q@ʣv,jjjjjjjjjjjjjjjjjj֚kຝ֙jjjjjjjjjjjjjp!j֞rjjjjjjjjjjjjjj׫֡xw.jjjjjjjjjjjjjj8mZ + +`Q֡xjjjjjjjjjjjjjjv-ǹjjjۣພՎVjjjjjjjjjjjjjjj~:Ƹjj쾚{4 +VFإ~s'jjjjjjjjjjjjjjjj|6ljjjϿټ*ؼ֡xjjjjjjjjjjjjjjjjjjlx/jj筀lC! +þ׼סvjjjjjjjjjjjjjjjjjjjj°֨jjjjj!  +! ̷Փ`jjjjjjjjjjjjjjjjjjjjj<ՇJjjjjjg&3 ^jjjk݊IjjjjjjjjjjjՀ?Հ=jjjjjjjjjjjjjjjjjjjjjjjjjjjjm֛mؾؼ֞sՆGx/jjjjjjjՄD׻֖dx0r&p"omlkjjjklkjjjjjjjjjjjjjjjjjjjx1רՌRjt(ػ֑Zljjjjjjjjjjjjjjjj֞s±ױ֗fՀ>p!jp"ՄE֡xؾ!,9Ybl$1W`imu}.9E$1$1}qydluV_hGQ[2=I$1$1$1$1$1(50;F'2?sz$1'2?S\f$1$14?JgoxV_h0;F0;F0;F0;F0;F0;F0;F$1w,7Cks{[dm[dm[dm[dm0;F0;F0;F0;F0;F0;F0;F0;F@JU5@K}:EPz0;F0;F0;F0;F0;F0;F0;F$1%1=0;F0;F0;F0;F0;F0;F0;FW`i^fpgoxowx+7V_h0;FFPZ!,9$1$1$1$1$1$1)4@OXb$1$1$1$1$1$1$1$1$1!,9iqz#/;X`j:DO$1IS]MVa$1u|#/;)4@|:EPlt|.9Ebkt)4@gpx@JU5@K}:EPIR](5$1'2?(5$10;F$1$1$1$1$1$1$1$1$1$1$11.QQ.Ht{t/e{0NtLt>??///......///]]^>??>??>??>??>??>??>??>??>??>??>??>??>??>??>??>??>??>??>??NNONNO|}}|}}|}}|}}|}}|}}|}}|}}|}}|}}|}}|}}|}}...|}}|}}lmm}}~>>>|}}///|}}|}}lmm|}}>>>|}}mnn>>>|}}>>>|}}|}}>>>|}}>??|}}|}}>>>|}}}}~>>>|}}...///>>>|}}|}}>>>|}}NNO]]^|}}>>>|}}...|}}......>>>|}}|}}///...>>>|}}MMNNNO|}}>>>|}}|}}>>>|}}|}}///|}}......>>>|}}>>>mnn|}}>>>|}}|}}|}}>>>|}}lmm>??|}}>>>|}}...}}~|}}lmm|}}>>>|}}|}}|}}|}}>>>|}}MMN|}}}}~}}~}}~}}~}}~}}~}}~}}~}}~}}~}}~}}~}}~}}~>>>...//////...]]^>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>MMN \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/printscreen b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/printscreen new file mode 100644 index 0000000..a787321 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/printscreen differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/process.txt b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/process.txt new file mode 100644 index 0000000..0ec2ac6 --- /dev/null +++ b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/process.txt @@ -0,0 +1,70 @@ +hdf_devmgr +param_watcher +storage_manager +appspawn +hilogd +samgr +storage_daemon +udevd +uinput_inject +multimodalinput +token_sync_serv +huks_service +memmgrservice +bluetooth_servi +pulseaudio +accessibility +resource_schedu +faceauth +work_scheduler_ +bgtaskmgr_servi +audio_policy +deviceauth_service +softbus_server +wifi_hal_service +deviceinfoservi +faultloggerd +accountmgr +time_service +distributeddata +medialibrary_se +useriam +updater_sa +inputmethod_ser +ui_service +fms_service +distributedfile +distributedfile +netmanager +battery_stats +dslm_service +sensors +media_service +wifi_manager_se +distributedsche +installs +hiview +telephony +usb_service +camera_service +render_service +thermal +foundation +accesstoken_ser +hdcd +disp_gralloc_host +light_dal_host +vibrator_dal_host +sensor_dal_host +input_user_host +camera_host +audio_hdi_server_host +wifi_host +usbfnMaster_host +usb_host +blue_host +wifi_hal_service +com.ohos.systemui +device_usage_st +com.ohos.launcher +power_host \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/settings.png b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/settings.png new file mode 100644 index 0000000..fcfc72d Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/settings.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/settings.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/settings.pngraw new file mode 100644 index 0000000..0d71742 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_OpenHarmony-3.1-Release/settings.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_master/app_capture_screen_test_config.json b/src/applications/sample/wifi-iot/screenshot/rk_master/app_capture_screen_test_config.json new file mode 100644 index 0000000..b34fd64 --- /dev/null +++ b/src/applications/sample/wifi-iot/screenshot/rk_master/app_capture_screen_test_config.json @@ -0,0 +1,74 @@ +[ + { + "return-x-y":[199, 1262], + "recent-x-y":[500, 1262], + "home-x-y":[350, 1262], + "recent_del-x-y":[350, 1140], + "permisson_ok-x-y":[495, 690], + "permisson_no-x-y":[241, 690], + "shot_cmd":[""], + "remount":["hdc_std shell mount -o rw,remount /"], + "cmp_cmd-level":["", 443200] + }, + { + "app_name": "audio_render", + "entry": "", + "remount":["hdc_std shell mount -o rw,remount /"], + "sendfile1":["hdc_std file send D:\\DeviceTestTools\\screenshot\\audiotest\\hdf_audio_hdi_server_function_test /data/"], + "sendfile2":["hdc_std file send D:\\DeviceTestTools\\screenshot\\audiotest\\audiorendertest.wav /bin/"], + "chmodfile1":["hdc_std shell chmod 777 /data/hdf_audio_hdi_server_function_test"], + "executefile1":["hdc_std shell ./data/hdf_audio_hdi_server_function_test"], + "audio_render_test":["hdc_std shell \"cd /data && ./hdf_audio_hdi_server_function_test --gtest_filter=AudioServerFunctionTest.SUB_Audio_Function_Render_Test_* && rm *.xml\"", "[ PASSED ] 12 tests."], + "audio_capture_test":["hdc_std shell \"cd /data && ./hdf_audio_hdi_server_function_test --gtest_filter=AudioServerFunctionTest.SUB_Audio_Function_Capture_Test_* && rm *.xml\"", "[ PASSED ] 10 test."], + "all_actions": [ + [2, "remount"], [2, "sendfile1"], [2, "sendfile2"], [2, "chmodfile1"], + [5, "audio_render_test"] + ] + }, + { + "app_name": "launcher", + "entry": "", + "all_actions": [[2, "shot_cmd"], [2, "cmp_cmd-level"]] + }, + { + "app_name": "settings", + "entry": "aa start -a com.ohos.settings.MainAbility -b com.ohos.settings", + "all_actions": [ + [3, "shot_cmd", "settings"], [3, "cmp_cmd-level"], [3, 400, 120], [3, 400, 120], [20, 400, 80], [3, 400, 80], + [3, "shot_cmd", "keyboard"], [3, "recent-x-y"], [3, "recent_del-x-y"], [3, "recent-x-y"], [3, "recent_del-x-y"], [3, "cmp_cmd-level", 200000] + ] + }, + { + "app_name": "photos", + "entry": "aa start -a com.ohos.photos.MainAbility -b com.ohos.photos", + "all_actions": [[2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "recent-x-y"], [2, "recent_del-x-y"]] + }, + { + "app_name": "photos", + "entry": "aa start -a com.ohos.photos.MainAbility -b com.ohos.photos", + "all_actions": [[2, "shot_cmd"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "cmp_cmd-level"], [2, "recent-x-y"], [2, "recent_del-x-y"]] + }, + { + "app_name": "distributedcalc", + "entry": "aa start -a com.example.distributedcalc.default -b com.example.distributedcalc", + "all_actions": [[2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], [2, "shot_cmd"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "cmp_cmd-level", 3686400], [2, "recent-x-y"], [2, "recent_del-x-y"]] + }, + { + "app_name": "camera", + "entry": "aa start -a com.ohos.camera.MainAbility -b com.ohos.camera", + "all_actions": [ + [2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], + [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "recent-x-y"], [2, "recent_del-x-y"] + ] + }, + { + "app_name": "camera", + "entry": "aa start -a com.ohos.camera.MainAbility -b com.ohos.camera", + "all_actions": [[2, "shot_cmd"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "cmp_cmd-level", 3686400]] + }, + { + "app_name": "note", + "entry": "aa start -a com.ohos.note.MainAbility -b com.ohos.note", + "all_actions": [[2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], [2, "shot_cmd"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "cmp_cmd-level"]] + } +] \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/screenshot/rk_master/camera.png b/src/applications/sample/wifi-iot/screenshot/rk_master/camera.png new file mode 100644 index 0000000..afe1fe3 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_master/camera.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_master/camera.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_master/camera.pngraw new file mode 100644 index 0000000..6dd0204 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_master/camera.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_master/capturescreentest.py b/src/applications/sample/wifi-iot/screenshot/rk_master/capturescreentest.py new file mode 100644 index 0000000..45b83f9 --- /dev/null +++ b/src/applications/sample/wifi-iot/screenshot/rk_master/capturescreentest.py @@ -0,0 +1,136 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from ast import parse +import json +import sys +import os +import time +import argparse +import re + +def EnterCmd(mycmd, waittime = 0, printresult = 1): + if mycmd == "": + return + with os.popen(mycmd) as p: + result = p.readlines() + if printresult == 1: + print(result) + sys.stdout.flush() + if waittime != 0: + time.sleep(waittime) + return result + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='manual to this script') + parser.add_argument('--config', type=str, default = './app_capture_screen_test_config.json') + parser.add_argument('--anwser_path', type=str, default = 'screenshot\\RK\\') + parser.add_argument('--save_path', type=str, default = './report/screenshot_1/') + args = parser.parse_args() + + with open(args.config) as f: + all_app = json.load(f) + + cmp_status = 0 + global_pos = all_app[0] + return_cmd = "hdc_std shell input -M -m {} {} -c 0".format(global_pos['return-x-y'][0], global_pos['return-x-y'][1]) + recent_cmd = "hdc_std shell input -M -m {} {} -c 0".format(global_pos['recent-x-y'][0], global_pos['recent-x-y'][1]) + home_cmd = "hdc_std shell input -M -m {} {} -c 0".format(global_pos['home-x-y'][0], global_pos['home-x-y'][1]) + recent_del_cmd = "hdc_std shell input -M -m {} {} -c 0".format(global_pos['recent_del-x-y'][0], global_pos['recent_del-x-y'][1]) + os.system("hdc_std kill") + os.system("hdc_std start") + EnterCmd("hdc_std list targets", 1) + EnterCmd("hdc_std list targets", 1) + EnterCmd("hdc_std list targets", 1) + EnterCmd("hdc_std shell rm -rf /data/screen_test/train_set") + EnterCmd("hdc_std shell mkdir -p /data/screen_test/train_set") + EnterCmd("hdc_std file send {} {}".format(os.path.join(os.path.dirname(args.config), "printscreen"), "/data/screen_test/")) + EnterCmd("hdc_std shell chmod 777 /data/screen_test/printscreen") + for single_app in all_app[1:]: + print(single_app['entry']) + print(single_app['all_actions']) + sys.stdout.flush() + call_app_cmd = "hdc_std shell " + single_app['entry'] + send_file_cmd = "hdc_std file send {} {}" + capture_screen_cmd = "hdc_std shell /data/screen_test/printscreen -f /data/screen_test/{}" + recv_file_cmd = "hdc_std file recv /data/screen_test/{} {}" + cmp_cmd = "hdc_std shell \"cmp -l /data/screen_test/{} /data/screen_test/train_set/{} | wc -l\"" + if single_app['entry'] != "": + EnterCmd(call_app_cmd, 3) + for single_action in single_app['all_actions']: + #shot_cmd is stable, different to other cmd,so handle it specialy + if type(single_action[1]) == str and single_action[1] == 'shot_cmd': + if len(single_action) == 3: + pic_name = single_action[2] + ".png" + raw_pic_name = single_action[2] + ".pngraw" + else: + pic_name = single_app['app_name'] + ".png" + raw_pic_name = single_app['app_name'] + ".pngraw" + EnterCmd(capture_screen_cmd.format(pic_name), 1) + EnterCmd(recv_file_cmd.format(pic_name, args.save_path), 1) + EnterCmd(recv_file_cmd.format(raw_pic_name, args.save_path), 1) + next_cmd = "" + #cmp_cmd-level is stable, different to other cmd,so handle it specialy + elif type(single_action[1]) == str and single_action[1] == 'cmp_cmd-level': + next_cmd = "" + print(send_file_cmd.format(os.path.join(args.anwser_path, raw_pic_name), "/data/screen_test/train_set")) + sys.stdout.flush() + EnterCmd(send_file_cmd.format(os.path.join(args.anwser_path, raw_pic_name), "/data/screen_test/train_set")) + new_cmp_cmd = cmp_cmd.format(raw_pic_name, raw_pic_name) + if len(single_action) == 3: + tolerance = single_action[2] + else: + tolerance = global_pos['cmp_cmd-level'][1] + p = EnterCmd(new_cmp_cmd, single_action[0]) + num = re.findall(r'[-+]?\d+', p[0]) + if type(num) == list and len(num) > 0 and int(num[0]) < tolerance: + print("{} screenshot check is ok!\n\n".format(raw_pic_name)) + else: + print("ERROR:{} screenshot check is abnarmal!\n\n".format(raw_pic_name)) + cmp_status = cmp_status + 1 + sys.stdout.flush() + #other cmd handle + elif type(single_action[1]) == str: + if single_action[1] not in single_app.keys(): + target_ = global_pos[single_action[1]] + else: + target_ = single_app[single_action[1]] + #this cmd is real cmd,and have a except answer + if type(target_[0]) == str: + next_cmd = "" + p = EnterCmd(target_[0], single_action[0]) + result = "".join(p) + if len(target_) > 1: + findsome = result.find(target_[1], 0, len(result)) + if findsome != -1: + print("\"{}\" execut result success!\n\n".format(target_[0])) + else: + print("ERROR:\"{}\" execut result failed!\n\n".format(target_[0])) + cmp_status = cmp_status + 1 + sys.stdout.flush() + #this cmd only is a name of x,y postion, to get x,y an click it + else: + next_cmd = "hdc_std shell input -M -m {} {} -c 0".format(target_[0], target_[1]) + #input x,y postion, to click it + else: + next_cmd = "hdc_std shell input -M -m {} {} -c 0".format(single_action[1], single_action[2]) + EnterCmd(next_cmd, single_action[0]) + + if cmp_status != 0: + print("ERROR:screenshot check is abnarmal {}".format(cmp_status)) + print("End of check, test failed!") + else: + print("screenshot check is ok {}".format(cmp_status)) + print("End of check, test succeeded!") + sys.stdout.flush() + sys.exit(cmp_status) \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/screenshot/rk_master/distributedcalc.png b/src/applications/sample/wifi-iot/screenshot/rk_master/distributedcalc.png new file mode 100644 index 0000000..54fa9c4 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_master/distributedcalc.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_master/distributedcalc.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_master/distributedcalc.pngraw new file mode 100644 index 0000000..9c7c13d Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_master/distributedcalc.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_master/keyboard.png b/src/applications/sample/wifi-iot/screenshot/rk_master/keyboard.png new file mode 100644 index 0000000..a6bc072 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_master/keyboard.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_master/keyboard.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_master/keyboard.pngraw new file mode 100644 index 0000000..931c0d7 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_master/keyboard.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_master/launcher.png b/src/applications/sample/wifi-iot/screenshot/rk_master/launcher.png new file mode 100644 index 0000000..b67c5dd Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_master/launcher.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_master/launcher.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_master/launcher.pngraw new file mode 100644 index 0000000..c044990 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_master/launcher.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_master/note.png b/src/applications/sample/wifi-iot/screenshot/rk_master/note.png new file mode 100644 index 0000000..5ed4296 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_master/note.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_master/note.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_master/note.pngraw new file mode 100644 index 0000000..56ce26d Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_master/note.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_master/photos.png b/src/applications/sample/wifi-iot/screenshot/rk_master/photos.png new file mode 100644 index 0000000..cab7f71 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_master/photos.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_master/photos.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_master/photos.pngraw new file mode 100644 index 0000000..c04377b --- /dev/null +++ b/src/applications/sample/wifi-iot/screenshot/rk_master/photos.pngraw @@ -0,0 +1,136 @@ +$1$1$1/:F/:F/:F/:F/:F/:F/:F/:F/:F$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1`ir$1$1$1$1$1$1$1$17AM$1$1$1$1$1$1$1$1rz$1$1$1$1$1$1$1$19DO$1$1$1GQ[$1$1[dn$1$1$1$1$1$1$1$1$1$19DO$1$1$1dlu$1$1$1iqz$1$1$1$1$1$1$1$1$1$19DO$1$1$1HQ\$1$1$1ajsbktow\eo$1$1$1$1$1$1-8D/:F/:F/:F/:F/:F/:F/:F/:F$1$1$1%0$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1HQ\$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1(5 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9$1$1$1$1$1$1$1$1$1$1$1$1HQ\$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1v~`ir`ir`ir`ir`ir`ir`ir`ir`ir`ir`ir`ir$1$1$1$1$1$1yCMX$1$1$1$1$1$1$1$1$1S\f ,9LV`|0;G$1*7$1$1$1$1$17AM$1$1$1px$1$1$1$1$1$1$1$1=HS/:F$1$17AMkt|$1$1$1$1$1$1$1$1$1enw$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1w$1$1$1%0<$1$1|QZd$1$1pxGQ[$1$1$1LV`$1$1$1bkt$1$1$1$1$1$1GQ[Ybk$1$1DNY$1$1#/;$1$1$1`irdlu$1$1$1$1$1$16@L$1$1$1$1$1$1,7CpxT^h$12?}@sHn4<];=>?{O}q<455DT;<>?SR4556DH:;<>Tr5568=:;;=Wh5789:;;gW789:;vG89:ڃ;:َ{ۣ]ezSZnOUi9;O;=R<>S<>SNThJPd9;P78L79M;=R;=Q<>Rjv14E68K;=Q;=R;=R9;P8:O;=Q,.>,.>-/?35H79N78L8;O;=R[dxǷ,.>,.>,.>,.>,.>13E67J57H78Kƽο;@P,.>,.>,.>,.>,.>,.>,.>-.>02D68KqºGP`,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>>CT*,=,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>-/?iklmnppqrttvwBL^+-=#%7+-=,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>-/?klmnppqrttvwxyz{}~.3E"$6%(8*-=%'7&(9,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>=CSºlmnppqstuvwxy{{}~+2F%'8+-='):"$6!#5#%6#%6()9*,=+-=,.>,.>,.>,.>,.>,.>,.>mnppqstuvwxy{|}~ÿBOb"$6#$5 #4"$5$&8*-=&(9"%6"$5#%6"$6"$5$&7&(9&(9(*:)+;feoοnpprstuvxxz{|}~2"$6)+<,.>&(9"$5!#5 "4"$6!3&)9)+;+-=+-=),<)*;"$6hZ_Ѽ̾òϾwwnpprstuvxxzz|}~*0C "4!"5 2"%6&'8'):(*:!$6 1 1 12"4!#5 "4!#5JCLлѼлϺvvvwvwyypqrstuvxyz{|}~1!#5$&7(*;')9 !3 1!2!4"4 #4#%6$&8&'8'(9%(820>ϻѼмлκ͹˸uttuuuvvwwwxzy}qrstuvxyz{|}~12"3&(9*-=%'8%'7%'8"$6!3 2 1!$4"$6%'875CκѼѼмлκ̸ʷɶtrsssttttuuuuvvwxyxrstuvxyz{|}~11 3 !2!2!#5$'7'(9#%7!2%'7+-='*:*+<43B̸ѼѼѼлкι˸ɶƳñoooqqrsssssttuttuvvvwwxxstvvxyz{|}~$):11 2#&7 1 $5#%6 "3 "3!3$&6'):01@ųѼѼѼмлϺ͹˸ȵIJvmmnnoopqrrssssstttuuuuvvuvvwxxtuvxyz{|}ƻl111 3"%6!"4"4#%6$&7%(8(*;')9ЬҽѼѼѼллκ̸ʶdzñlllmllmnooopqqrrrsssstttuuuuuvvvwxuwxyz{|}"&711 11"3 #5 1 1 2"$6"%6$&7ijѼѼѼллκ˸ȵŲ°õklllllllmmnnoppppqrrsssssssttuuuvvvw|uwxyz{|}n1111 3!3 1 #6#%7!#4$&7(+;IEOҽѼѼлϻ͹˸ȵŲrjjkklllllllmmnooooopqrrrrrrssssstuuuuvvwxyz||~-3G 2 111 3 1 22"3"4 "4 "4κѼѼлϺι̸ɵƳñVvJlJkJlIkoojjjjjlllllllllmmnooooopqqqqqrrrrssssttuvvuxyz||~!#4 1111111(*9--=++;eY_ҽѼѼмлι̸ʶȴŲðJlIkIjIkIkjjjjjjjjkllllllllllmnnnnoooppqqrrrqrssssttuttvyz{|~Nby 211111y}ҽҽҽҽѼѼлϺ͹˸ʶȵdzƲdzKlHjHjGiGixjjjjjjjjjjkklllllllllmmmmnooopppqqqqqrrrsssssstux{{}~ij&+=2 2111ҽҽҽҽѼѼѼлκ͹̸ʸʶɶʷTqGhGiGhFhmkjjjjjjjjjjjkkkllllllllmmmmnnnnoooppppqqrrssssssstt|{}~ 21111̺ҽҽҽҽҽҽҽѼѼллκι͹͹͹ϻvFhEgEgEgkkkkkjjjjjjjjjkkkkllllllllllllmmmmnonoppppppqqrsrrsssss}~{ 1111cV]ҽҽҽҽҽҽҽѼѼѼмллϺϻлмEfDfDeEgwkjjjkjjjjjjjjjjjjkkkllllkllllllllmmmmnnnooopppqpqqrrrrssss~~Wm1111npлҽҽҽҽҽҽѼѼѼѼллммѼCeCdCdurkjjjjjjjjjjjjjjjjjjkkklkkkkkklllllllllmmmnnnooopppppqqrrrrsst~GXn11112/>๪ҽҽҽҽҽҽѼѼѼѼѼѼѼѼZsAcBcBcmkkkkjjjjjjjjjjjjjjjjkkkkkkkkkkkllllllllllmmmmnnnoooppppqqrrrrss{APe11111ҮҽҽҽҽҽҽѼѼѼѼѼѽq@b@b@a@b{kkkkkkkjjjjjjjjjjjjjjjjjkkkkkkkkkklllllllllllllmmmnnnoooooppqrqqrrsPd{ 1111乩ϻҽҽҽҽҽҽҽҽҽмMh>_?_?`?aAcqkkkkkkkkkjjjjjjjjjjjjjjjjkkkkkkkkkkkkkllllllllllllllmmnnnooooppqqqqrrr!$51TJSιικҽҽҽҽҽҽҽ@`<]<]<^=_>_Nk~okkkkkkkkkkkkjjjjjjjjjjjjjkkkkkkkkkkkkkkkkkkkklllllllllllmmnnnoopppqqqrrrű̷͸͸͸̸лҽҽҽͺdv9Z:[9[:[;\<]<]}wmkkkkkkkkkkkkkkjjjjjjjjjjjjkkkkkkkkkkkkkkkkkkkkkkklllllllllllmmnnnoppppqqqrκ͸͸̸̷˷ʵʶͺ~8Z8Y8Y8Y8Z9Z9[;[;\}tkkkkkkkkkkkkkkkkkkjjjjjjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllllllmmmnnopppqqqr̸̷̷˷ʶɵDzİ7X6X6X6W6W7X7Y8Y9Z:[okkkkkkkkkkkkkkkkkkkkkjjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllllllmmnoopppqqr̷˶ʶɵȴƲı¯6W5V5V5V5V6W6W7X7YIgokkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkklllllllllmnnnooppquã˷ʶɵȴƲð5V4U4U4U4U4U5V6W7Xmwkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkklllllllmnnnoppp~¡е©lb˶ɵȴƳı°3U3T3T3T3T4U4U5V6W~kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllmmnnoopp¡á؅MoMoMoMoɵȴƲı°7W3T3T3T3T3T3U4U5Vkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllmmnnoop¡áġTvMoMoMoMoMo`z±ðOf4U3U2T3T3T3T4UHekkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllmnnoo¡áššWyKmKmMoMoMoMoMoMoMoNoRtp}vr{h2S2S2S3T銙kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllmnnp¡ġššǡcEgIkHiLnKmMoMoMoMoOql{}}}}vAa2S3T3TkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkklllllmnnqáġšơǡΫ2S=_IkMoGhLnMoMoMoMo\{mn|}}}Ll2S2S3Ukkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkklllllmnt¡áġšơǡȡӳ3T2S2S=^LnMoMoMoMoMoMoMoOpcYynoAa2S2Suzrqpoonmllllkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkklllllm¡áġšơǡȡɡTv1R4U6W4U?aMoMoMoMoMoMoNoNoMoMoMoHj2S2S~uqonllkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllm¡áġšơǡȡɡʡ6V1R1R1R1R1R2SEgMoMoMoMoMoMoMoMoMoMoMo;]{tomllkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllm¡áġšơǡȡɡʡˡ5V2S:[CdLnEg9Z2S1R7WMoMoMoMoMoMoMoMoMoMoMoNpRs]|}uolkkkkkkkkkkkkkkkkkkkkkkkkkllll¡áġšơǡȡɡʡˢ̢NpMoMoLnMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqQrRsUvYysqnlkkkkkkkkkkkkkkkkklllm¦¡áġšơǡȡɡʡˢ̢ШMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqPrRsTuWw\{dvmlkkkkkkkkkllnʮ¡áġšơǡȡɡʡˢ̢͢ٹMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNpOpOqQsSuWw[z`xzvlkkkkllsдġšơǡȡɡʡˢ̢͢΢NpMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqQrSsVvYy]|n||yxmklӷơǡȡɡʡˢ̢͢΢ϢStMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqOqQsSuWw[z^}r|xwzyոȡɡʡˢ̢͢΢ТТnMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqQrRsUuWw[z`s|zxwغˡ̢̢͢΢ТТѢNpMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNoOpOqQrSsUvXx[{_~o{|{z۽̢͢΢ТТѢҢMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqOrQrStVvWx[{^}er{{wzƼȽȾz_ݿ΢ТТѢҢ۵YzMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqOrQrStUvWw[{^}`fr{xr鞷¶¶ƺȼrz_z_z_gz_z_ݽѢѢҢӢQsMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqOrQsSsUuWwZz\|_cozzt~´ƹǼɾpz_z_z_z_z_z_z_z_|aøz_z_z_۷ҢӢԢMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNoNpOqOqQrRsTuWwXx[{^}ahyzwzµĸźǼȽqz_z_z_z_z_z_z_z_z_z_z_z_z_fyz_z_z_z_ٮԢգNqMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOpOqPrQsStUvWwZz\|_~dn{{v׼ɾµĸƺǼɾ¶oz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_ר֣TuMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnMoMoMoMoMoMoMoMoMoNoNoNpOqOqQrStTuWwYy\{^}afv{s䣻iabciҿоɹŸƹǼɾɾez_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_٨\|MoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnLnMoMoMoMoMoMoMoMoMoNoNpOpOqOqQrRsSuVvWwZz]|_djrsabcdefhj͹ķmnĵµöz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_{qMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnLnKmKmMoMoMoMoMoMoMoMoMoMoNoNpOqOqPqQsStTuVwYy[{_~bgnmwbddeghkϺιnppqձռ}az_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_rMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnLnKmJlIkKmMoMoMoMoMoMoMoMoMoMoNoNpNpOqOqQrRsTuUvWw[z^}`dhkqddfghnнлϻκ{pp|}~|NQ֍wz`z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_kNpMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnLnKmJlIkHjGhKmMoMoMoMoMoMoMoMoMoMoNoNpNpNpOqQrQsStTuWwZz\{_cgksf~{zѼѼϻϻqöȷdzIJ¯为|}RKKKKJJIPbՃfz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_iZ{MoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlIkHjFhEfCeLnMoMoMoMoMoMoMoMoMoMoMoNoNpOpOqOqQrRsSuVvXx[{_~bfks隲vuvuvwyϻѼлϻκ̸˷ɶdzŲñ°°°~eMLLKKKKJJIIIIHGMqݗpz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_f숢MoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnLnKmJkHjFhEfBd@a?aLoMoMoMoMoMoMoMoMoMoMoMoNoNpNpOpOqQrRsStUvWw[{^}bhmvҺonnnospssuѼѼлϻι̸˷ɶȴƳŲŲʴONMMLLKKKKJJJIIIHHGGGFFTǫvz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_~dMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlIkGiEgBd@a=^;\=^MoMoMoMoMoMoMoMoMoMoMoMoMoNoNpNpOqPrQsSsUuWwZz]|aekv߱nljiihgghnkopr}ѼѼѼлϺι̸˷ʷɶɵ鿾fONNMMMLLLKKJJJIIIHHHGGGJfz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_|bVwMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnLnKmIkHiFhCe@b=^;\8Y3U;\MoMoMoMoMoMoMoMoMoMoMoMoMoMoNpNpOqPqQrRsSuWwZz\{_~ukq榾߭vojhggfdcba~a~_}_}dggkmrѼѼѼѼлϻκ͹͹̸QOOONNNMMMLLLKJJJIIIIHHGSkz_z_z_z_z_uz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_{a柶MoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlIkHiEgBc>`<\8Y6W2S1R@bMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNoNpOqPrRsSuVwYy[{_~jpvꞶվq`~]}_~_~`aaa`~_}]{[zZxYwXvVuVtZxa~`}bflϻҽѼѼѼлϻzPPOOOONNMMMMLLLKKKJIIIIHi|}bz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_}cOrMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlHjGhDf@b=_:\7X4U1S1R1RDeMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpNpOqPrRsStUvWx[{^}qo{떯昱}ja_~XxXwXxYyZyZz[{[{[z[zZyXwVuTtRrPpOoNmMlMmVuYwYv]{fϻҽ˼z|aQQPPOOONNNMMMMLLLKKKJIIJvo{`z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_qMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlHjFhCe@a<]8Z5W3T1R1R1R1REgMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqPrQrSsUuWwYy^}rq|ݰplc`]|ZzXxVwUvUvUvUvUvVvVvVvUuTtSsQrPpMmKkIiGgFfEeEeFfQoTrSpd|uwxyzVRQQQPPOOOONNMMMLLLKKKJJO|~kz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_MoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlHjEhCe?a<]8Y5W3T1R1R1R1R1RFhMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqOqQrRsSuVvWxZzas|ӿ}}}jca`^}\{YyWxUvTuStRsRsRsRsRrRrQrPpNoMnKkIiGgDeBc@a>^=^<]BbFeKkofZTRQQQPPPOONNNMMMLLLKKKX|{gz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_XyMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlHjEhCe?a<]8Y5W3T1R1R1R1R1R1RGiMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNpOpOqPrRsStUuVw[{w|}|lu{w}ya^}\|[{YyXxVwUuStQsQrPqOqOpOpNoMoMnKmJkHiFgCdBb?_=^:[9Z8Y7X8Y<\͹hVSPOOONNNMMLLLKbx~cz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_d߽MoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlHjFhCe@a<^9Z5X3T1R1R1R1R1R1R1RHjMoMoMoMoMoMoMoMoLnLnLnLnLnMnMoMoMoNpOqOqPrQsStUuUuXx_}lm`iaj^}YyYyXxWwUvUuStRsQrOqNpMoMnLnKmKlIkIjGhEfBcAc?_=];[9Z7W4U5U3THhjONNMMLLk~dz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_tPrMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlIjGhDfAb=`:\8X3T2S1R1R1R1R1R1R1REfMoMoMoMoLnLnLnLnLnLnLnLnLnLnLnMoMoNoNpOqOqQrQsRsStTuWwhdVwfWwVvUvUuTuTtSsQsQrPqOpMoMnKmKlJkHjGiFhDfCdAb?`=^:\7X5W5V4U2S3T xbz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_蓫MoMoMoMoMoMoMoMoMoMoMoMoLnLnKmKlIkHiEgBd@`<]9Z4U3T1R1R1R1R1R1R1R1RBdMoMoLnLnLnLnLmKmKmKmKmKmKmKmLnLnMoMoNoNpOpOqPqQrQrQsRsRsRsStSsRsRsRsQrQrPqOqNpMoLnLmKlIkHjGhFgDfBdAb>`=^9\5V4U5W3T2S2SHglz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_OqMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJkHjFhDe@b=`;\6W3T1R1R1R1R1R1R1R1R1R>`LnLnLnLmKmKmKlJlJlJlJlJlKmKmKmLnMnMoMoMoNpOpOqPqPqPqPrQrQrPrPrPrPqOqOqNpNoMnLmKmJlHjGiFhDfCdAb?a=_;\5V2S1R3T3S1R2S̓p~ez_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_sMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlIkHiEgBd@a<]6X5W1R1R1R1R1R1R1R1R1R1RދMoKmKmJlJlIkIkIjIjIjIkIkJkJlKmKmLnLnMoMoMoNoNpNpOpOpOpNpOpNpNpNpMoMoLnKmKmJkIkGiEgDfCeAc?a>`<]9Z3T2S3S2S1R1R8Yte{`z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_}aMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlIkGiDfBd?a8Z9Z1R1R1R1R1R1R1R1R1R1RԾLmJlIkHjHiGiGhFhGhGiGiHjIkIkJlKmKmKmLnLnMnMoMoMoMoMoMoMoMnMnLnKmKmJlIkIjGiFgEfCeAc@a>_<]:[9Z7X5U2S1R1R1Rnxz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_qRtMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmKlIkHiFhDfAc;]:[2S1R1R1R1R1R1R1R1R1R^~HiFhEgDfDeDeDfDfEgFgGiHjHjIkIkJlKmKmKmLnLnLnLnLnLnLnKmKmJlJlIkHjGiEgEeCeAc?a>_=]:[9Z7X1S2S1R1R1Rc}}az_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_tMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlHjGiFhCe>_:[4U1R1R1R1R1R1R1R1R1RوDfCdAcAbAbAbAcBdCeEfFgGhGiHiHjIkIkJkJlJlKmKmKmJlJlJlIkHjHiGhFgDfCdBc@a>`<]8Z8X6W5U3S2S1R1R}fz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_ܻ嘰MoMoMoMoMoMoMoMoMoMoMoMoMoLnLnLnJlIkHjGhEg@a;]7X1R1R1R1R1R1R1R1R1RƼDe?a>_>_>`?`@bAcBdCeEfFgFhGhGiHjHjIkIkIkIkJkIkIjHjGiFhEgDfBdAc@a>_;\8X4V7X6W5V3T1S6Vȅwez_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_MoMoMoMoMoMoMoMoMoMoMoMoMoMoLnKmKlJlIkGiEh>_=_:[1R1R1R1R1R1R1R1R1R[z;\:\;\;]=^?_@aAbBcCeDeDfEgEgFhGiGiHiHiHiGiGhFhDfDeBdAc?a=^8Z8X6X7Y5V3U3T3S>^åk}az_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_KmKmKmMoMoMoMoMoMoMoMoMoMoMoMoKmKmJlHjHhEh?`>_<\2S1R1R1R1R1R1R1R2Rũ9Y7X8Z:[;]=_>_?a@a@bAcBcBdCeDeEfEgEgEfEfDfCdBc@b?`<]4U1R2T3T4V3S3T2SCbϪw|`z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_lNpKmGiMoLnHiMoJlJlMoMoMoMoMoLnKmKlIkHjFhEgAb=^<\5U1R1R1R1R1R1R1RIh]|6W7Y9[;\;]<^=^=_>_?`?a?aAbAcBcBcBcBc@b@a>`9Z3U1R3U5W5V2S1S1Rkz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_~KlKmLnEgKmMoMoLmEgCe=^CeIkLnKmHjJlHjHiEhEf@c<]<\8Y1R1R1R1R1R1R1Ri<]7Y9Z9[:[:[:[:\;\;]<^=_>`>`>`>`>_;\6W3S2S3T2S1R1R1RBb̨ez_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_ˡFf9[;]?`FhJlGh@cDfIjJlGjCdCeKmJlIkHjFhEgCd@b<]:\8Y1S1R1R1R1R1R1RәǛ=]8Y8Y8Y8Y8Y8Y9Z:[:\;\;]:\8Y6V4V6W3U2R1S1R4Tzt}az_z_z_z_z_z_z_z_z_z_z_Aa2S5V4U5V7X8Y9[:[:\;]=^DeCeEgGiGhFgFgDeBd@`:\9Z7X3T1R1R1R1R1R1RȐ;[4U5V5V5V6W7X7X5V5V7W7Y7Y4T3T2S2SVuԠziz_z_z_z_z_z_z_<\4U6W5X7W6X5V7X<]<^<^;];\<^?`@a>_=_>_?aAb?`;\9Z7X4V1R1R1R1R1R1R=]3T3T3U5U5V5W5V4U4T2T2SBbƏj~bz_z_Ӹ5V4U5V3T3T<]DfBdCd@a>_Bc=_@c?aFhEgCdBc>`@a>`;\9[6X4U2S1R1R1R1R1Rӡʁ2S3T3U4T2S2S[zSq3T3T4U7W7X6X6W7X8Y<]CdCe>`DfBcBcCdBdAc@b@a=`;\8Y5W4U2T1R1R1R1R1Rh5V3T3T3T5V5V6W6W6W5V5V5V5V4U5V5V5V4U4VAb@b@`=_;\8Y6X4U3T1R1R1R1R1R7X3T3T3T3T6W5W4U4U4U3U4U5V5V4U4U3T4U4U8Y@b@a>`=_;]8Y7X4U4T2S1R1R1R1R1R;\2T4U:[5V6W6W5W5W5V5V4U4U4U4U5V8X<]=_>_?a?`?`>_<]8Z7X5V3T3T1R1R1R1R1RӇ2S2S6W:[:[@cCeCdCdBdBcAb@a?`@a>`?`?`?a?a?b?a?`=_<^:\8Y5X4U4T2S1R1R1R1RJi\z2S2S8Y8Z<]<]AbAcAbAb@b@a?`>`>`=_=_>_?`?a@b@b@a>`=_;\9Z7X5V4U3T1R1R1R1R1R5V2S2S7Y8Z:[;\=_?`?`?`>`=`=^=^=^=^=_>`?`?a@bAb@b?a>`<]9Z8Y5W5V4U3T1R1R1R1R2S2S4U7Y8Z9Z=^:[=^=_=_=^<^<]<^<^=^=_>`?a@bAbAbAb@b?a<^:\9Z7X6W4U3T1S1R1R1RӂYw2S2S5V8Y8Z9Z;\;]:[<^<]<]<]<]<]<^=^>_?`@aAbAcBcAdAb@a>_;\9[8Y6X5V3T3T1R1R1R@_5V2S2S6W8Y8Y:[9[;];\:[;]<]<]<]<^=_>_?`?bAbBcCeCdCeBd@b?`<]:\9Z7Y5V4T3T2S1R1R6Vз3T2S2S5W8Z9Z9[9Z9[;\;\:\;\<]=^=_>_?`?aAcBdCeDeDfDeBdBc@a>_;\9Z8Y5W4U2T2S2S1R1R[z3T2S2T5V8Y8Z9Z9Z9Z9[:\;\;\<]=^>_?_?aAbBcCeDfDfDfDeCdBd@a=_<]9Z8X6W4V3T2S2S1R1R8X2T2T2T3U8Y8Y8Y8Z8Z9Z9[:\;\;\<^>_?`@bAcBdDeDfEfEgDfDeCdAc?`<^:\8Y5W4U4U3T2S2S1Rўа2T3T2S2S2S7W7X7X7X7Y8Y8Z9Z:[;\;\<^>_@aAcBdDeDfEgFgEgDfCeBd@a=^;\8Y6X5V4U3T2S2S1Rb~^|2S2S2S2S2S4U5V5V5W6W6W7X7X8Y9Z;\;]<^>`@aBcCdDfEgEgEfDfCeAb?`=_;\9Z6X5V4U3T3T2T2S1R8X2S2S2S2S2S1R4U4U4U4U5V5V6W6W7Y9Z:[;\=^>`@bBdCeDeDfDfDfCd@b?`<^;\8Y6X4U4T3T2S2S2S1Rϸ2S2S2S1R1R1R1R1R2S3T3T3T4U4U4V5W7W7Y9Z;\<^>`@aAcBdCeCeCeBd@b?`<^:\8Y6X4U3T2S2S2S2S2S\{3T2S1R1R1R1R1R1R1R1R2S2S2S3T3T4U4V6W7X9Z:[<]>_@aAbAcBcBcAc@a?`<]:\8Y6W4U3T2S1R1R1R1RЧ7X5V4U2S1R1R1R1R1R1R1R1R1R2S2S2S3T3T4U5W7X8Z:[<]=_?`@b@a@b@a?a>_<]9[8Y5V4U2T2S1R1R1R1RsӁ4U4U4U3T2S1R1R1R1R1R1R1R1R1R1R2S2S2S3T4U5V7W8Y9Z;\<]=_>`>`>`=_<];\9Z8Y5V4U2T1S1R1R1R1R7W;[4U4V4U3T2S2S1R1R2S1R1R1R1R1R1R1R1R1R2S3T4U5V6W7X8Y9Z:[;]<]<]<];\:[8Y7X5V4U2T2S1R1R1R1R1R4U4U4V4V4U3T2S2S2S2S2S1R1R1R1R1R1R1R1R1R2S3T4U5V5V6W7X7Y9Z9[9Z9[9[9Z8Y7X5V4U3T2S1R1R1R1R1Rλ,E5V5W5V4V4U3T3T2S2S2S2S2S2S1R1R1R1R2S2S2S2S3T4U4V5V6W6W7X7X7Y8Y7Y7X6X5V4U3T2S2S1R1R1R1Rэ,,s(?5U6W5V4U4U3T3T2S2S2S2S2S2S1R1R2S2S2S2S2S2T3T4U5V5V5W6W6W6W7X6W6W5V4U3T2S2S1R1R1R1Rjds++*)$,.I4U6W5V4V4U3U3T3T3T2S2S2S2S2S2S2S2S2S2S3T3T4U4U4U4U5V6W6W6W5W4U3T2T2S1R1R1R1RNl,2B+**)('&'["65U6W5V5V4V4U4U3T3T3T2S2S1R1R1R2S2S3T3T3T3T3T3U5V5W6W6W5V4U3T2T2S2S2S1R6V /**)(('%$$#%,"4B%9,F4S5V5V4U4U3T2S1R1R1R2S2S2S2S2S2S2S3S4U5V6W6W6W5V4U3T2T2S2S1R1R+*))('&%$#"& 1!1!2!2!"2#"41#6K';d)@+F/K1P2S2S2S2S2S1R1R1R2S3U5V6W7X6X6W5V4U4U4U3U1R1R+*)(('%$#"!( 1 1!2!2!2 "3 "3 "3!#4!#4!#4"$4#$4$$5&$6'$6+%6:&9I';X(>e*Ap+C{-F/H0I0K0K1L0L1K1K0I/IYs+*)('&%#"" ( 1 1!1!2!2 "2 "3 "3!#4!#4!#4"$4"$5"$5"$5"$5"$5#%5#%5#%5#%6#&7%'7%'7%'7%'9&'9')9');'*;(*<)+=+->boiy*))('%$#"! % 1 1!1!2!2"2 "3 "3!#4!#4"$4"$4"$5"$5"$5#%5#%5#%6#%6#%6$'7%'7%'7%'8%'9')9'):');(*;)+<*,>+->,.?IQcDN_*)((&%$#"  ! 1 1!1!2!2"2 "3 "3!#4!#4"$4"$5"$5#%5#%5#%6#%6#&6$&6$&7%'8%'8&(8&(9')9');(*;)+=*+=*,>,.?-/@./A12D,1A*)((&%#"  !1!1!2!2!2 "3 "3!#3!#4"$4"$5"$5#%6#%6$&6$&6$&7$&7%'7&(8&(8&(9&(:(*:(*;)+<*,=*,>+.?,.?-/A./B/1B/1C(.>*)((&$#!  1!2!2!2"2 "3!#3!#4"$4"$5#%5#%6$&6$&7%'7%'7%'7&'8&(9')9'):'*;(+;)+;*+=+->+-?,.?-/A./B/1C/1C/2E02E(-=*)((%#"! -!2!2!2"2 "3!#4!#4"$5#%5#%6$&6%'7%'7%'8&(8&(9&(:'*:(*:(*;)+<*,=*,=+->,.?-/A./B/1C/2D02E13E13F23F).>*)('%#"! $!2!2"2 "3!#3!#4"$4"$5#%6$&7%'7&'8&(8')9')9'):(*;)+;)+;*,=+-=+->,.?,.?./A/0C/1C03E13E13F24G35H35H39I*('&%$"! !2"2 "3 "3!#4"$4"$5#%6$&6%'7&'8&(8')9'):(*:)+;*+<*,<+->+->,.?-/?-/@./B/1C/2D13E13F24G35H35I35I46Ip~Taq)('&%$"! ) "3 "3!#3!#4"$4#%5#%6$&7%'7&(8')9'):(*:)+;)+;*,=+-=+->,/?-/@./A.0B/1C/2D13E23F24G35I36I46J46J46JXat)('&%$"!  "3 "3!#4!#4"$5#%5#%6$&7%'7&(8')9'*:(*;)+;*+=+-=+->,.?-/?-/@.0A/1C/2D13F24G35G35I46I46J57K57K57KNUh)(('%$#! " "3!#4"$4"$5#%5#%6$&7%'7&(8')9'*:)+;)+;*,<+->,.>,.?-/?./A/1C02C13E23F24G35H36I46J57K57K57K57KBG[,(('&%"  ,!#4!#4!#4"$4"$5#%6$&7%'8&(8'*:(*;)+;*,=+->,.>,.?-/A/1B/2C02D13F24G35G36I46J57K57K57K57L57L8:O"2)('%$"!   0!#3!#4"$4"$5#%6$&6%'7%'7&)9(*:)+;*,<+->,.?-/?-/@/1B02C13E13F24G35I46J46J57K57K57L57L67L68L*)('%$#!    1"$4"$4#%5#%6$&6%'7%'7&(8'*:)+;*+<+-=+.?-/?./A/1C02D13E24G35G36I46J57K57K57K57L57L68L68L*)('&$"!     *"$5#%5#%6$&6$&7%'7&(8'):)+;)+;+-=+.>-/?./A/1C02D13F24G35H36I46J57K57K57L57L57L68L68L8?O))('%$"!      + "$5#%5$&6$&7%'7&(8')9'*;)+;*,=+->-/?./A/1C02D13F24G35H46J46J57K57K57L57L67L67L68L"2))(&%$"!     +  +  + -#%6$&7%'7%'8&(9'):)+;*+<+-=-/?-/A/1B02E13F24G35I46J57K57K57K57L57L67L57L67L**)(&&$#!       +  + +!#4#%6$&7%'7&(8')9(+;)+;+-=+.?./A/1B02E13F24G35I46J57K57K57K57L57L68L68L68L}+*)('&$"!      + + +   "2#%5#%6%'7&(8')9'*;)+;*,=+->-/A/1B/2C13F35G35I46J57K57K57K57L57L68L68L68Liw6=L+*)('%$#!      +  +   0#%5#%6$&7&'8&(9'):)+;*+<+->-/@.0B/2C02F24G35I46J57K57K57K57L57L57L57L68LU_s!1+*)('%%"!      + + +  ."$5#%5$&7%'8&(8')9(+;)+<+->,.?.0B/2C02E23G35I46J57K57K57K57K57L57L57L67LFL`+++)('&$#"     +  + +  +"$5#%5#%6%'7&(8&(9(*;)+;+->,.?.0B/2C02E23G35I46J46J57K57K57K57L57L57L57LDI]j|,+*)('&$#!     +  +  +  ("$5"$5#%6%'7%'8&(9'*:)+;*+<,.?-/A/1C02E23G35H46I46J57K57K57K57L57L57L57L?DX.3D,+*)('%$#!     +  +   !"$4"$5#%6$&7%'7&(8'):(*:*+<+.?-/A/1C02D13F24G35I46J57K57K57K57K57L57L57L=AV!1,+*)('&%#!     +  + +  !#4"$5#%6$&6%'7%'8'):(*:)+<+->-/@.0B/1C13F24G35I46I46J57K57K57K57L57L57L:=R,,+*)('%%#"     +  + +   !#4"$5#%6$&6$&7%'7'(9'):)+;+,=,.?.0B/1C13F24G35H36I46J57K57K57K57K57L57L7:OTbs,,+*)('&$#!     +  +   +"$4"$5#%5#%6$&6%'7&(9')9(+;*+<+.?-/A/1C02E13G35H35I46J46J57K57K57K57L57L57L*/?,,+*)('&$#!      +  + +   "$4"$4"$5#%5#&6%'7&(8&(9'*:*+<+->-/A.0B02E13F24H35I36I46J46K57K57K57K57L57L /,,+*)((&$#!      + +    HS]#&7"$4"$5#%5#%6$'7%'8&(8'):)+;+->,.@.0B/1C13F24G35I36I46J46J46K57K57K57K57L-,,+*)((&$#!    +  +  +   %(9!#4"$4"$5#%6$&7%'7%'8')9'*;*+=,.?-/A/1C02E23G24H35I46I46J46J57K57K57K57L-/@.0B02D13F24G35H36I46J46J46K57K57K57K"&7.,,+*)((&$"!     +  + +   9BJ(++.?.0B/1C02E13G24H35I46J46J46J57K57K57K/-,,+**((&$"!     +  +   39J"$5"$5#%5#%5#%6#%6$&6%'8&(9(*;*+=+.?-/A/1C02E13F23G35H35I46J46J46K57K57K.-,,+**((&$"!    +  +  +  ?J["$5"$5"$5#%5#%5#%6#&6%'7%'9'):)+=*,>+.@./C/1D13F23G35H35I46J46J46J46K57K/5F.-,,,*)((&$"     +  + + +  HT]MYj"$5"$5"$5"$5#%5#%6#%6$&7%'9'):(*;*,=+-@-/B/1C02F13G24G35I35J46J46J46K57K"2--,,+**('&$"     +  + +  [i{"$5"$5"$5"$5#%5#%5#%6$&7%'7&(:(*;)+=+-?-/A.0C02E13F23G35H35I46J46J46K57K.--,,,*)('&$"     + + +  i{"$5"$5"$5"$5"$5#%5#%5#%7%'7&(9(*;)+<+-?,.A.0B/2D02E23G35H35I35J46J46J46Kj|.---,,+)('%$"     + + +  Zit}"$5"$5"$5"$5"$5#%5#%5#%6%'7&(9');)+;*+>,.?./B/1C02E13G24G35I35I46J46J46K%(8.---,++)('%#"      + + +  "$5"$5"$5"$5"$5#%5#%5#%6%'7&'8'):(*;*+>+.?-/B/1C/1E13F23G35H35I36J46J46K/.---,++)('%#!      + + + "$5"$5"$5"$5"$5"$5#%5#%6$&7%'8'):'*;)+=+-?-/A./C/1D02F23G24G35I35J46J46J.----,++)('%#!    +  + + + m"$5"$4"$4"$4"$5"$5"$5#%5$&7$&8&(9');)*=*,>+.@./B/1C02E13F24G35I35I46J46JVcv.----,++)('%#     +  +  #&6"$4"$4"$4"$4"$5"$5"$5#&6$&7%'9'):(*<*+>+.?-/B.0C/2E13F23G24I35I36J46J|#&7.----,+*)(&%#     + + + + +"%(8"$4"$4"$4"$4"$4"$5"$5#%6$&7%'9&(:(*;*+>+-?-/B.0C/1D02F13G24H35I36I46Jx/.----,+*)(&$"      +  + + +'+;!#4!#4!#4!#4"$4"$4"$5#%6#%7%'7&':');)+=*,?,.A./B/1D02F13G24H35I35I46Ju{/.----,+*)(&$"      + + + +)->!#4!#4!#4!#4!#4!#4"$4#%5#%7$&7&'9');(*=*,>+.A-/B/1C02E13G24H35I35I46Jr?I[/.---,,+*('%$!     + + + + %*-1C!#4!#4!#4!#4!#4!#4!#4#%5#%6$&7%'9'):(*<*,>+-@-/A.0C/1E13G24G35H35I46Jr"3/.---,,+*('%#      +  + +=FW!#4!#3!#3!#4!#4!#4!#4"#5"$6$&7%'9&(:(*;)+>+-?,.A.0C/1D13F23G35H35I46Jo/..---,,*)('%#       + +P\n!#3!#3!#3!#3!#3!#3!#4"#5"$5#%7%'7&(:'*;)+=+-?,.A./C/1D02F23G35H35I46Jkz\l}...---,,*)(&$"       + +8ALdu!#3!#3 "3 "3 "3!#3!#3"#5"$5#%6%'7&':');)+=*,?,.@./B.0D02F13G24H35I46Jkz,2C...---,+*((%$"      +  + +v!#3 "3 "3 "3 "3 "3!#3"#4"$5#%6#&7&'9');)+=*,?+-@-/B.0C02F13G24H35I46Jkz 1....-,,+*('%#      +  "3 "3 "3 "3 "3 "3 "3"#4"$5#%6#&7&'9');(*=*,>+-@-/B.0C02E13G24G35I36Jr/....-,,**('$#      + Udp "3 "3 "3 "3 "3 "3 "3"#3"$5#%6#&7&'9'):(*=*,>+-@-/B.0C02E13F24G35I36Jq+-@-/B.0C/2E13F24G35H35Jq"3//...-,,*)(%$!     #* "3 "3 "3 "3 "3 "3 "3"#4"$5#%6#&7%'9'):(*=*+>+-@-/B./C/2E13F23G24I35Iq//...-,,,*((%#!     + q "3 "3 "3 "3 "3 "3 "3"#4"$4#%6#&7%'9'):(*=*+>+-?-/A./C/1E13F23G24H35Iw//...-,,**('%"      + $&8 "3 "3 "3 "3 "3 "3"#4"$4#%6#%7%'9'):(*=)+>+-?,.B./C/1E02F23G24H35Iy,2C//...-,,**(&$"     +1;'+< "3 "3 "3 "3 "3 "3!#4"$4#%6#&7%'9'):(*<*+>+-?,.B./C/1E02F23G24H35I} 1//...-,,*)(%$!     + */@ "3 "3 "3 "3 "3 "3!#4"$4#%6#&7%'9'(:(*<)+>+-?,.A./C/1E02F13G24H35I//...--,+*)'%#!     + 28I "3 "3 "3 "3 "3 "3!#4"$4#%6#&7%'9'(:(*<)+>+-?,.A./C/1E02F13G24H35I]m//...--,+))'$"     9DOIUg "3 "3 "3 "3 "3 "3!#4"$4#%6#&7%'9'):(*;)+>+-?,.A./C/1E02F13G24H35I!%7//...--,+)(&$!     ev "3 "3 "3 "3 "3 "3!#4"$4#%6#&7%'9'):(*;)+>+-?,.A./C/1E02F23G24H35I0//..---++)(&#!    } "3 "3 "3 "3 "3 "3!#4"$4#%6#%7%'8'):(*;)+>+-?,.A./C/1E02F13G24H35Iz///...--+*((%#    Q`l "3 "3 "3 "3 "3 "3!#4"#4#%6#&7%'9&(:(*;)+>+-?,.A./C/1E02F13G24H35I?I[///..---+*('%"     "3 "3 "3 "3 "3 "3 "3"#4#%5#&7%'9'):(*;)+>+-?,.A./C/1E02F13G24H35I"3///..--,+*(&$"   !* "3 "3 "3 "3 "3 "3!#4!#4#%5#&7%'9&(:(*;)+>+-?,.A./C/1E02F23G24H35I////.---,*)(&$!   i~ "3 "3 "3 "3 "3 "3!#3!#4#%5#%7%'9&(:(*<)+>+-?,.A./C/1E02F23G24H35IP^o////.---,*)(%#"   "3 "2 "3 "3 "3 "3!#4!#4#%5#&7%'9&(:(*;)+>+-?,.A./C/1E02F23G24H35I(->////.--,,*((%#! -5?$'8 "2 "2 "3 "3 "3!#4!#4#%5#&7%'9&(:(*;*+>+-?,.A./C/1E02F23G24H35I 1////.--,+*('$#!  )-? "2 "3 "3 "3 "3!#4!#4#%5#&7%'9&(:(*;)+>+-?,.B./C/1E02F23G24I35J/////.-,,+)(&$#  .4E "2 "3 "3 "3 "3!#4!#4#%5#&7%'9'):(*<)+>+-?-/A./C/2E13F23G24I35I).@/////.-,+*)(%$"! =HS=GX "2 "3 "3 "3 "3!#4!#4#%5#&7%'9'):(*<)+>+-?-/A./C/2E13F23G35H35I0////..-,+*((%$" `q "2 "3 "3 "3 "3!#4!#4#%5#&7%'8'(:(*;)+>+-?-/A./C/2E13F23G35H35I/////..-,+)('%#"   "2 "2 "3 "3 "3!#4!#4#%5#&7%'9'(:(*<*+>+-?-/A./C/2E13F23G35H35IUct////...-,*)(&%#"  JWd "2 "2 "3 "3 "3!#4"#4#%6#%7%'9'):(*<*+>+-?,.A./C/1E13F24G35H35I!%6////...-,*((&$#"! "2 "3 "3 "3 "3!#4"#4#%6#&7%'9'):(*<*+>+-?,.B.0C/1E13F24G35H46J0///...-,+)('%$#!  !$5 "3 "3 "3 "3!#4"$4#%6#%7%'8'):'*<*+>+-?-/B.0C/2E13G24G35H58Ln////...-,+*(&%$#"  ES_#%6 "3 "3 "3 "3"#4"$4#%6#&7%'8'):(*<*,>+-?,.B.0C/1E13G24G35H8;O"%6///...-,++)(&$#""! &*< "3 "3 "3 "3"#4"$5#%6#%7%'8');'*<*+>+-?,.B/1C/2E13G24H24I:>R////...-,+*)(%$#""!  +4;M "3 "3 "3!#3!#5"$5#%6#%7%'8');(+<*+>+-?-/B.0C/2E13G24G35I<@THSe////...-,+*('&$#"!!  ]n}BM` "3 "3!#3!#3!#4"$5#%6#&7%'8');(*<*+>+-?-/B.0C02E13F24G35I>CW 1////...-+*)('%$""!!   Vdu!#3!#3!#3!#3!#5"$5#%6$&7%'9&(:(*;*+>+-@-/B.0C02F13G24H35I@F[z/////..-,+*)(&%$#"!!  ;GVw!#3!#3!#4!#4!#5"$5#&6$&7%'9'):(*=*,?+.@-/B/1C02E23G35G35ICJ]06G////...-,+*)'&%$#"!!  !#4!#4!#4!#4!#5#%5#%6$&7%'9'):)+<*,?+.@-/B/1C02E23G35G35IMTi0////...-,+)('%$##"!  "'3!#4!#4!#4!#4"$5#%5#&7$&7&'9');)+<+,?,.@-/B/1C02F23G35H35IYeyWgy/////..-,+*)(&%$#"""! s"$4"$4"$4"$4"$5#%6#%7%'7&(:'*;)+=+,?,.@./B/1D13F23G35H35Ihw"%7/////..-,+*)(&%$#""!!"ew"$5"$5"$5"$5"$5#%6#&7%'8&(9'*;)+=+-?,.A.0C/1E13F23G35H36Iv/////...-,+*('&$$"""! cwVew#%5"$5"$5#%5#%5$&6$&7%'8')9'*;)+>+-?-/A.0C/1D13F24G35H36I;DV/////...-,+*('%$#""!  P]o#%5#%5#%5#%5#%6#&7%'7&'8&(:(*;*+=+-?-/A.0B02E13F24G35I36I0/////...-,*)('%$#"!! 17FJVh#%6#%6#%6#%6#%6$'7%'7&(9'):)+<*,>+.?-/A/1C02D13F34G35I36I//////..--+*)'&%#""   DOa$&6$&6$&6$&7$&7$&7%'8&(9');)+;+,>+.?-/A/1C/2E13F34G35I36I3:L//////..-,+*)'&$#"!  "&2?I[$&7$&7$&7$&7$&7%'7&(8&(:(*;)+;+-?,.?./A/1C02E13G35G35I46J 1//////..-,+*('%$"!  ;DT$&7%'7$&7%'7%'7%'7&(9'):'*:*+<*,>,.?./A/1C02E23G35H35I46Jw///////..-,+*('%$"! %7>O%'7%'7%'7%'7%'8%'9'(9'):(+;)+<+->,/@./A/1C02E23G35G35I46J,1C///////..-,+)(&%#" ]o~17H%'8%'8%'8%'8%'8&(8')9'):(*;*+=+->-/@-/B/1C02E23G35G36I46J0//////...-,+)(&%#! ,1A%'8%'8%'8%'8&(8&(8'):(*:(*;*,=+.?-/?./B/1C13E13F24G36I46Jas///////...-,+)(&%#! ER`),=%'8%'8&'8&(8&(8&(8'):(*:(*<*,=+.?,.@.0A/1C13E13F24G36I;>R'+<///////..--,+)'&%#! *,<&(8&(8&(8&(8&(8&(9'*:(*:)+<*,=+-?,.@./A/1C02E13F24G35IAG[////////..-,+*)'&$#! $)5(+;&(8&(8&(8&(8&(8&(9'):(*;)+;*,=+->-/@./A/1C02E13F34G35IHOcM[l////////..-,+*)'%$#! (+;&(8&(8&(8&(8&(9')9'):)+;)+;+-=+-?-/@./A/1C02D13E24G35IMXk#'8///////...-,+*('%$#"!(*;&(8&(8&(8&(8&(9')9');)+;)+;+-=+.?-/@.0B/1C02D13F24G35HS^s////////..-,++)('%$#"r'):&(8&(8&(8&(9&(9')9');)+;*+<+-=,.?-/@.0B/1C02D13F24G35H^lCMa///////...-,+*)(&%$#$')9&(8&(8&(8&(9')9')9'*;)+;*,<+->,.?-/@.0B/1C/2C13F24G35Hm"3///////..--++*)'&%$#AM['(9&(8&(8&(8&(9')9'):(*;)+;*,<+->,.?./@.0B/1C02C13F24G35H}///////...-,+*)('%$$#%'8&(8&(8&(8&(9')9'):(*;)+;*,<+->,.?./@.0B/1C02D13F24G35HFRc///////...-++*)'&%$$29H%'8%'8&(8&(8&(9')9'):(*;*+<*,<+->,.?./A.0B/1C/2D13F24G35G!3//////...-,+*)('&%$$%'8%'8&(8&(8&(9')9'*:(*;*,<*,<+->,.?./A.0B/1C02E13F24G35G///////..--,+*)''%%$"'4%'7%'8&'8&(8&(9')9'*:(*;*,<+-=+->,.@./A.0B/1C02E13F24G35GTdv///////..--++)('&%$$o%'7%'7&'8&(8&(9')9(*:(*;*,<+-=+->-/@./A.0B/1C02E13F24G35G"3//////...-,+*)''&%$$|%'7%'7%'8&'8&(9')9(*:)+;*+<+-=+->-/?./A.0A/1C02E13F24G35H///////..--,+*('&%%$Tetp$&7%'7%'7&'8&(9')9(*:)+;*+<+-=+->-/?./A.0B/2C13E13F24G35HRas//////...-,+*)('&%$$ev$&7%'7%'7&'8&(9')9'*:)+;*+<+-=+->-/?./A.0A/2C13E13F24G<@S!%6//////...-,+*)'&&%$+3AXgx$&6$&7%'7%'8&(9')9'*:)+;*+<+-=+-?-/?./A.0A/2C02E13F24GHPb///////..--++*)'&%%$KWi$&6$&7%'7%'7&(8')9'*:)+;*+<+-=+->-/?-/@.0A/2C02D13F24GT_raco///////..-,++)('&%$(AK\#%6$&7%'7%'7&(8')9'*:(*;)+<+-=+->-/?-/@.0A/1C02D13E24Gap')9///////..-,+*)('%%$4;L#%6$&6%'7%'7&(8')9'*:)+;)+;+-=+->-/?-/@.0A/1C02D13E23Go0//////...-,+*)'&%%(39J#%6$&6$&7%'7&(8')9'*:(*;)+;+-=+->-/?-/@./A/1C02C13E23Fpq{///////...-,+*)'&%%Raq16F#%6$&6%'7%'7&(8')9'*:(*;)+;+-=+-=,.?-/?-/A/1B/2C02E13F%'8///////...-,+*)'&%$/4F#%6$&6%'7%'7&(8')9'*:(*;)+;+,=+-=,.?-/?-/@/1B/2C02D13E////////...-,+*)'&%KLV.3D$&6$&7%'7%'7&(8')9'):(*;)+;+,=+-=+.?-/?-/@/1B/1C02D13E////////...-,+*)'&%,2B$&6$&7%'7%'8&(8')9'*:(*;)+;*+=+-=+.?-/?-/@.0B/1C02C13E+-<////////...-,+*)(&()6.1@$&7%'7%'7%'8&(8')9'*:(*;)+;*+=+-=+.>-/?-/?.0A/1B/2C02D0////////...-,+*)('-0@$&7%'7%'8&'8&(9')9'*:(*;)+;*+<+-=+.>,.?-/?./A/1B/2C02D/////////...-,++)()-/>%'7%'7%'8&(8&(9')9'*:(*;)+;)+<+-=+.>,.?-/?./A/1B/1C57IIJX//////////..--,+*)*,<%'7%'8&'8&(8&(9')9'*:(*;)+;)+<+-=+.>,.?-/?-/A/1B/1COP` "2//////////...-,,+)),;%'7%'8&(8&(8&(9')9'*:(*;)+;)+<+-=+.>,.?-/?-/A/1B/1Cklz///////////...--,+DFR(*:%'8%'8&(8&(8&(9')9'*:(*;)+;)+<+-=+.>,.?-/?-/A/1B/1Cno{////////////...-,,%'8%'8%'8&(8&(8&(9')9(*:(*;)+;)+<+-=+.>,.?-/?-/A/1B/1C')9////////////....-13B%'8%'8&(8&(8&(9')9')9'*:(*;)+;)+<+-=+.>,.?-/?-/A/1B/1C0/////////////....%'8&(8&(8&(8&(9')9')9'*:(*;)+;)+=+-=+.>,.?-/?-/@/1B/1C///////////////..%'7&(8&(8&(8&(8&(9')9')9'*:(*;)+;)+=+-=+.>,.?-/?-/A/1B/1CADQ///////////////..&(8&(8&(8&(8&(9')9')9'*:(*;)+;*+=+-=+.>,.?-/?-/A/1B/1C!2////////////////0&(8&(8&(8&(8&(9')9')9(*:(*;)+;*+=+-=+.>-/?-/?-/A/1B/1C/////////////////lmy&(8&(8&(8&(8&(9')9')9(*:(*;)+;*+=+-=+-?,.?-/?-/A/1B/1C\_k/////////////////&(8&(8&(8&(8&(9')9')9(*:(*;)+;)+=+-=+.?-/?-/?-/A/1B14E*,;////////////////;,.?-/?-/A/1B////////////////git&(8&(8&(8&(8&(9')9')9(*:(*;)+;*+<+-=+.?,.?-/?-/A/1B////////////////&(8&(8&(8&(8&(9')9')9(*:(*;)+;)+<+-=+.>,.?-/?-/@.0BPR_///////////////EGU&(8&(8&(8&(8&(9')9')9'*:(*;)+;)+=+-=+->,.?-/?-/@24F////////////////&(8&(8&(8&(8&(9')9')9(*:(*;)+;)+=+-=+->,.?,.?-/@79I////////////////2A&(8&(8&(8&(8&(9')9')9'*:(*;)+;)+<+-=+->,.?,.?-/?;=M///////////////&(8&(8&(8&(8&(9')9')9(*:(*;)+;)+;+-=+->,.>,.?-/?XYggiu//////////////0&(8&(8&(8&(8&(9')9')9(*:(*;)+;)+;*,=+->,.>,.>,.?"$5//////////////&(8&(8&(8&(8&(9')9')9(*:(*;)+;)+;*,<+->,.>,.>,.?///////////////&(8&(8&(8&(8&(9')9')9(*:(*;)+;)+;*,<+->,.>,.>,.?//////////////MN[&(8&(8&(8&(8&(9')9'):(*:(*;)+;)+;*,<*,=+->,.>,.?//////////////&(8&(8&(8&(8&(9')9'):(*:(*;)+;*+;*,<+-=+-=+.>,.>KMZ/////////////&(8&(8&(8&(8&(9&(9')9'):(*:)+;)+;*+<*,<+-=+-=+->/1B!#4/////////////&(8&(8&(8&(9&(9')9'):(*:)+;)+;*+<*,<+-=+-=+-==?P/////////////&(8&(8&(8&(8&(9&(9')9'):(*:)+;)+;*,<*,<+-=+-=+-=JL[/////////////&(8&(8&(8&(9')9')9'*:(*:)+;)+;*,<*,<+-=+-=+-=^an?@O//////////0&(8&(8&(8&(9')9')9(*:(*;)+;)+;*,<*,=+-=+-=+-=ϻ|no96C//////bcp&(8&(8&(9')9')9'):(*:)+;)+;*+<*,<*,=+-=+-=+-=кккк˹@;G!1//&(8&(9&(9')9')9(*:(*:)+;)+;*,<*,<+-=+-=+-=+->кккккккȵȯ&(9&(9')9')9'):(*:)+;)+;*+<*,<*,=+-=+-=+-=+->ккккккккк')9')9')9():(*:(*;)+;)+;*,<*,<+-=+-=+-=+-=+.>ѻккккккккк'):'):(*:(*:(*;)+;)+;*+<*,<*,=+-=+-=+-=+->46Fккккккккк(*:(*:(*:(*;)+;)+;*+<*,<*,<+-=+-=+-=+-=,.>OP^jsкккккккк(*;)+;)+;)+;)+;*+<*,<*,<+-=+-=+-=+-=+->,.>giuŧj֡wעyĩкккккк)+;)+;)+;)+<*,<*,<*,<+-=+-=+-=+-=+->,.>,.>\j֡x֡x֡xopкк͵ͺe`z|02F.0B,.?+->+-=+-=+->+-=+-=+-=+-=+.>,.>,.>x-y1֡x֡x֜ojjjjjójj\^q;=T;=T;=T;=T;=T;=T;=T;=T:=S9;Q79O68M57K35I13FjՐZ֡x֡xՂAjjjjjƹjjij|;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=Tj֡x֡x֡xnjjjjjɽjjsu;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=Tkr&֡x֡x֡xkjjjjjj֗f;=T;=TWRcy}ymuiamYSdIH\;=T;=T;=T;=T=@Wt'Ւ]֡x֡x֟tjjjjjjײسкккккккккккj֡w֡x֡x֑]jjjjjjjיiкккккккккккތLw/֡x֡x֡xmjjjjjjשкккккккккккԷҴj֜o֡x֡x֠vjjjjjjjȼjڰкккккккккϹ- + +jk֡x֡x֡xՈLjjjjjjj²֎WккккккккϹ + + + +ޓXj֙k֡x֡x֞sjjjjjjjj֟sՈL黗ɯh̵ккккккœcd%  +jn֡x֡x֡xr$jjjjjjjjo֠vw,֝rjjjjp q"ojjĵjjY +_Pz/j֙i֡x֡xՐYjjjjjjjjjjj֚kv,jo氅֡wjjjjjjjjjjjj +,ѻju+֡x֡x֡xkjjjjjjjjjjׯՅFq$֪jjjr$֡xljjjjjjjjǹjjj + +q"jנv֡x֡xՄEjjjjjjjjjjjjɾՋRjjjjjä֡xnjjjjjjjjjjj-  +`RjՁ>֡x֡x֡wjjjjjjjjjjjjjj֒\ՃCjjjߔX֡xnjjjjjjjjؽjjjO +" q#j֠v֡x֡x}8jjjjjjjjjjjjjjjj֎U°֍T֡xkjjjjjjjj;֕bjji + +ȢՑ\֡x֡x֟tjjjjjjjjjjjjjjjjjjjlןsפ|֙ijjjjjjjjjjjjj@ + +ש֡x~:jjjjjjjjjjjjjjjjjjjv,֡xjjjjjjjjjjjՂB֕bjji$Q@ʣv,jjjjjjjjjjjjjjjjjj֚kຝ֙jjjjjjjjjjjjjp!j֞rjjjjjjjjjjjjjj׫֡xw.jjjjjjjjjjjjjj8mZ + +`Q֡xjjjjjjjjjjjjjjv-ǹjjjۣພՎVjjjjjjjjjjjjjjj~:Ƹjj쾚{4 +VFإ~s'jjjjjjjjjjjjjjjj|6ljjjϿټ*ؼ֡xjjjjjjjjjjjjjjjjjjlx/jj筀lC! +þ׼סvjjjjjjjjjjjjjjjjjjjj°֨jjjjj!  +! ̷Փ`jjjjjjjjjjjjjjjjjjjjj<ՇJjjjjjg&3 ^jjjk݊IjjjjjjjjjjjՀ?Հ=jjjjjjjjjjjjjjjjjjjjjjjjjjjjm֛mؾؼ֞sՆGx/jjjjjjjՄD׻֖dx0r&p"omlkjjjklkjjjjjjjjjjjjjjjjjjjx1רՌRjt(ػ֑Zljjjjjjjjjjjjjjjj֞s±ױ֗fՀ>p!jp"ՄE֡xؾ!,9Ybl$1W`imu}.9E$1$1}qydluV_hGQ[2=I$1$1$1$1$1(50;F'2?sz$1'2?S\f$1$14?JgoxV_h0;F0;F0;F0;F0;F0;F0;F$1w,7Cks{[dm[dm[dm[dm0;F0;F0;F0;F0;F0;F0;F0;F@JU5@K}:EPz0;F0;F0;F0;F0;F0;F0;F$1%1=0;F0;F0;F0;F0;F0;F0;FW`i^fpgoxowx+7V_h0;FFPZ!,9$1$1$1$1$1$1)4@OXb$1$1$1$1$1$1$1$1$1!,9iqz#/;X`j:DO$1IS]MVa$1u|#/;)4@|:EPlt|.9Ebkt)4@gpx@JU5@K}:EPIR](5$1'2?(5$10;F$1$1$1$1$1$1$1$1$1$1$11.QQ.Ht{t/e{0NtLt>??///......///]]^>??>??>??>??>??>??>??>??>??>??>??>??>??>??>??>??>??>??>??NNONNO|}}|}}|}}|}}|}}|}}|}}|}}|}}|}}|}}|}}|}}...|}}|}}lmm}}~>>>|}}///|}}|}}lmm|}}>>>|}}mnn>>>|}}>>>|}}|}}>>>|}}>??|}}|}}>>>|}}}}~>>>|}}...///>>>|}}|}}>>>|}}NNO]]^|}}>>>|}}...|}}......>>>|}}|}}///...>>>|}}MMNNNO|}}>>>|}}|}}>>>|}}|}}///|}}......>>>|}}>>>mnn|}}>>>|}}|}}|}}>>>|}}lmm>??|}}>>>|}}...}}~|}}lmm|}}>>>|}}|}}|}}|}}>>>|}}MMN|}}}}~}}~}}~}}~}}~}}~}}~}}~}}~}}~}}~}}~}}~}}~>>>...//////...]]^>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>MMN \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/screenshot/rk_master/printscreen b/src/applications/sample/wifi-iot/screenshot/rk_master/printscreen new file mode 100644 index 0000000..a787321 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_master/printscreen differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_master/process.txt b/src/applications/sample/wifi-iot/screenshot/rk_master/process.txt new file mode 100644 index 0000000..0ec2ac6 --- /dev/null +++ b/src/applications/sample/wifi-iot/screenshot/rk_master/process.txt @@ -0,0 +1,70 @@ +hdf_devmgr +param_watcher +storage_manager +appspawn +hilogd +samgr +storage_daemon +udevd +uinput_inject +multimodalinput +token_sync_serv +huks_service +memmgrservice +bluetooth_servi +pulseaudio +accessibility +resource_schedu +faceauth +work_scheduler_ +bgtaskmgr_servi +audio_policy +deviceauth_service +softbus_server +wifi_hal_service +deviceinfoservi +faultloggerd +accountmgr +time_service +distributeddata +medialibrary_se +useriam +updater_sa +inputmethod_ser +ui_service +fms_service +distributedfile +distributedfile +netmanager +battery_stats +dslm_service +sensors +media_service +wifi_manager_se +distributedsche +installs +hiview +telephony +usb_service +camera_service +render_service +thermal +foundation +accesstoken_ser +hdcd +disp_gralloc_host +light_dal_host +vibrator_dal_host +sensor_dal_host +input_user_host +camera_host +audio_hdi_server_host +wifi_host +usbfnMaster_host +usb_host +blue_host +wifi_hal_service +com.ohos.systemui +device_usage_st +com.ohos.launcher +power_host \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/screenshot/rk_master/settings.png b/src/applications/sample/wifi-iot/screenshot/rk_master/settings.png new file mode 100644 index 0000000..ce67da1 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_master/settings.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_master/settings.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_master/settings.pngraw new file mode 100644 index 0000000..987afd3 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_master/settings.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/airquality.png b/src/applications/sample/wifi-iot/screenshot/rk_weekly/airquality.png new file mode 100644 index 0000000..901d198 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_weekly/airquality.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/airquality.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_weekly/airquality.pngraw new file mode 100644 index 0000000..203d3d6 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_weekly/airquality.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/app_capture_screen_test_config.json b/src/applications/sample/wifi-iot/screenshot/rk_weekly/app_capture_screen_test_config.json new file mode 100644 index 0000000..6ce2540 --- /dev/null +++ b/src/applications/sample/wifi-iot/screenshot/rk_weekly/app_capture_screen_test_config.json @@ -0,0 +1,90 @@ +[ + { + "return-x-y":[199, 1262], + "recent-x-y":[500, 1262], + "home-x-y":[350, 1262], + "recent_del-x-y":[350, 1140], + "permisson_ok-x-y":[495, 690], + "permisson_no-x-y":[241, 690], + "shot_cmd":[""], + "cmp_cmd-level":["", 443200] + }, + { + "app_name": "launcher", + "entry": "", + "all_actions": [[2, "shot_cmd"], [2, "cmp_cmd-level"]] + }, + { + "app_name": "settings", + "entry": "aa start -a com.ohos.settings.MainAbility -b com.ohos.settings", + "all_actions": [ + [3, "shot_cmd", "settings"], [3, "cmp_cmd-level"], [3, 400, 120], [3, 400, 120], [20, 400, 80], [3, 400, 80], + [3, "shot_cmd", "keyboard"], [3, "recent-x-y"], [3, "recent_del-x-y"], [3, "recent-x-y"], [3, "recent_del-x-y"], [3, "cmp_cmd-level", 200000] + ] + }, + { + "app_name": "photos", + "entry": "aa start -a com.ohos.photos.MainAbility -b com.ohos.photos", + "all_actions": [[2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "recent-x-y"], [2, "recent_del-x-y"]] + }, + { + "app_name": "photos", + "entry": "aa start -a com.ohos.photos.MainAbility -b com.ohos.photos", + "all_actions": [[2, "shot_cmd"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "cmp_cmd-level"], [2, "recent-x-y"], [2, "recent_del-x-y"]] + }, + { + "app_name": "distributedcalc", + "entry": "aa start -a com.example.distributedcalc.default -b com.example.distributedcalc", + "all_actions": [[2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], [2, "shot_cmd"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "cmp_cmd-level", 3686400], [2, "recent-x-y"], [2, "recent_del-x-y"]] + }, + { + "app_name": "camera", + "entry": "aa start -a com.ohos.camera.MainAbility -b com.ohos.camera", + "all_actions": [ + [2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], + [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "recent-x-y"], [2, "recent_del-x-y"] + ] + }, + { + "app_name": "camera", + "entry": "aa start -a com.ohos.camera.MainAbility -b com.ohos.camera", + "all_actions": [[2, "shot_cmd"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "cmp_cmd-level", 3686400]] + }, + { + "app_name": "contacts", + "entry": "aa start -a com.ohos.contacts.MainAbility -b com.ohos.contacts", + "all_actions": [ + [2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], + [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "recent-x-y"], [2, "recent_del-x-y"] + ] + }, + { + "app_name": "contacts", + "entry": "aa start -a com.ohos.contacts.MainAbility -b com.ohos.contacts", + "all_actions": [[2, "shot_cmd"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "cmp_cmd-level", 3686400], [2, "recent-x-y"], [2, "recent_del-x-y"]] + }, + { + "app_name": "music", + "entry": "aa start -a com.ohos.distributedmusicplayer.MainAbility -b com.ohos.distributedmusicplayer", + "all_actions": [[2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "recent-x-y"], [2, "recent_del-x-y"]] + }, + { + "app_name": "music", + "entry": "aa start -a com.ohos.distributedmusicplayer.MainAbility -b com.ohos.distributedmusicplayer", + "all_actions": [[2, "permisson_ok-x-y"], [2, "shot_cmd"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "cmp_cmd-level", 3686400]] + }, + { + "app_name": "mms", + "entry": "aa start -a com.ohos.mms.MainAbility -b com.ohos.mms", + "all_actions": [ + [2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], [2, "permisson_ok-x-y"], + [2, "shot_cmd"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "cmp_cmd-level", 3686400] + ] + }, + { + "app_name": "note", + "entry": "aa start -a com.ohos.note.MainAbility -b com.ohos.note", + "all_actions": [[2, "shot_cmd"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "recent-x-y"], [2, "recent_del-x-y"], [2, "cmp_cmd-level", 3686400]] + } + +] \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/camera.png b/src/applications/sample/wifi-iot/screenshot/rk_weekly/camera.png new file mode 100644 index 0000000..afe1fe3 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_weekly/camera.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/camera.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_weekly/camera.pngraw new file mode 100644 index 0000000..6dd0204 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_weekly/camera.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/capturescreentest.py b/src/applications/sample/wifi-iot/screenshot/rk_weekly/capturescreentest.py new file mode 100644 index 0000000..45b83f9 --- /dev/null +++ b/src/applications/sample/wifi-iot/screenshot/rk_weekly/capturescreentest.py @@ -0,0 +1,136 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from ast import parse +import json +import sys +import os +import time +import argparse +import re + +def EnterCmd(mycmd, waittime = 0, printresult = 1): + if mycmd == "": + return + with os.popen(mycmd) as p: + result = p.readlines() + if printresult == 1: + print(result) + sys.stdout.flush() + if waittime != 0: + time.sleep(waittime) + return result + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='manual to this script') + parser.add_argument('--config', type=str, default = './app_capture_screen_test_config.json') + parser.add_argument('--anwser_path', type=str, default = 'screenshot\\RK\\') + parser.add_argument('--save_path', type=str, default = './report/screenshot_1/') + args = parser.parse_args() + + with open(args.config) as f: + all_app = json.load(f) + + cmp_status = 0 + global_pos = all_app[0] + return_cmd = "hdc_std shell input -M -m {} {} -c 0".format(global_pos['return-x-y'][0], global_pos['return-x-y'][1]) + recent_cmd = "hdc_std shell input -M -m {} {} -c 0".format(global_pos['recent-x-y'][0], global_pos['recent-x-y'][1]) + home_cmd = "hdc_std shell input -M -m {} {} -c 0".format(global_pos['home-x-y'][0], global_pos['home-x-y'][1]) + recent_del_cmd = "hdc_std shell input -M -m {} {} -c 0".format(global_pos['recent_del-x-y'][0], global_pos['recent_del-x-y'][1]) + os.system("hdc_std kill") + os.system("hdc_std start") + EnterCmd("hdc_std list targets", 1) + EnterCmd("hdc_std list targets", 1) + EnterCmd("hdc_std list targets", 1) + EnterCmd("hdc_std shell rm -rf /data/screen_test/train_set") + EnterCmd("hdc_std shell mkdir -p /data/screen_test/train_set") + EnterCmd("hdc_std file send {} {}".format(os.path.join(os.path.dirname(args.config), "printscreen"), "/data/screen_test/")) + EnterCmd("hdc_std shell chmod 777 /data/screen_test/printscreen") + for single_app in all_app[1:]: + print(single_app['entry']) + print(single_app['all_actions']) + sys.stdout.flush() + call_app_cmd = "hdc_std shell " + single_app['entry'] + send_file_cmd = "hdc_std file send {} {}" + capture_screen_cmd = "hdc_std shell /data/screen_test/printscreen -f /data/screen_test/{}" + recv_file_cmd = "hdc_std file recv /data/screen_test/{} {}" + cmp_cmd = "hdc_std shell \"cmp -l /data/screen_test/{} /data/screen_test/train_set/{} | wc -l\"" + if single_app['entry'] != "": + EnterCmd(call_app_cmd, 3) + for single_action in single_app['all_actions']: + #shot_cmd is stable, different to other cmd,so handle it specialy + if type(single_action[1]) == str and single_action[1] == 'shot_cmd': + if len(single_action) == 3: + pic_name = single_action[2] + ".png" + raw_pic_name = single_action[2] + ".pngraw" + else: + pic_name = single_app['app_name'] + ".png" + raw_pic_name = single_app['app_name'] + ".pngraw" + EnterCmd(capture_screen_cmd.format(pic_name), 1) + EnterCmd(recv_file_cmd.format(pic_name, args.save_path), 1) + EnterCmd(recv_file_cmd.format(raw_pic_name, args.save_path), 1) + next_cmd = "" + #cmp_cmd-level is stable, different to other cmd,so handle it specialy + elif type(single_action[1]) == str and single_action[1] == 'cmp_cmd-level': + next_cmd = "" + print(send_file_cmd.format(os.path.join(args.anwser_path, raw_pic_name), "/data/screen_test/train_set")) + sys.stdout.flush() + EnterCmd(send_file_cmd.format(os.path.join(args.anwser_path, raw_pic_name), "/data/screen_test/train_set")) + new_cmp_cmd = cmp_cmd.format(raw_pic_name, raw_pic_name) + if len(single_action) == 3: + tolerance = single_action[2] + else: + tolerance = global_pos['cmp_cmd-level'][1] + p = EnterCmd(new_cmp_cmd, single_action[0]) + num = re.findall(r'[-+]?\d+', p[0]) + if type(num) == list and len(num) > 0 and int(num[0]) < tolerance: + print("{} screenshot check is ok!\n\n".format(raw_pic_name)) + else: + print("ERROR:{} screenshot check is abnarmal!\n\n".format(raw_pic_name)) + cmp_status = cmp_status + 1 + sys.stdout.flush() + #other cmd handle + elif type(single_action[1]) == str: + if single_action[1] not in single_app.keys(): + target_ = global_pos[single_action[1]] + else: + target_ = single_app[single_action[1]] + #this cmd is real cmd,and have a except answer + if type(target_[0]) == str: + next_cmd = "" + p = EnterCmd(target_[0], single_action[0]) + result = "".join(p) + if len(target_) > 1: + findsome = result.find(target_[1], 0, len(result)) + if findsome != -1: + print("\"{}\" execut result success!\n\n".format(target_[0])) + else: + print("ERROR:\"{}\" execut result failed!\n\n".format(target_[0])) + cmp_status = cmp_status + 1 + sys.stdout.flush() + #this cmd only is a name of x,y postion, to get x,y an click it + else: + next_cmd = "hdc_std shell input -M -m {} {} -c 0".format(target_[0], target_[1]) + #input x,y postion, to click it + else: + next_cmd = "hdc_std shell input -M -m {} {} -c 0".format(single_action[1], single_action[2]) + EnterCmd(next_cmd, single_action[0]) + + if cmp_status != 0: + print("ERROR:screenshot check is abnarmal {}".format(cmp_status)) + print("End of check, test failed!") + else: + print("screenshot check is ok {}".format(cmp_status)) + print("End of check, test succeeded!") + sys.stdout.flush() + sys.exit(cmp_status) \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/clock.png b/src/applications/sample/wifi-iot/screenshot/rk_weekly/clock.png new file mode 100644 index 0000000..221c4c9 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_weekly/clock.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/clock.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_weekly/clock.pngraw new file mode 100644 index 0000000..da269b9 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_weekly/clock.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/contacts.png b/src/applications/sample/wifi-iot/screenshot/rk_weekly/contacts.png new file mode 100644 index 0000000..7a749a1 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_weekly/contacts.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/contacts.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_weekly/contacts.pngraw new file mode 100644 index 0000000..58e9597 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_weekly/contacts.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/distributedcalc.png b/src/applications/sample/wifi-iot/screenshot/rk_weekly/distributedcalc.png new file mode 100644 index 0000000..54fa9c4 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_weekly/distributedcalc.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/distributedcalc.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_weekly/distributedcalc.pngraw new file mode 100644 index 0000000..9c7c13d Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_weekly/distributedcalc.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/ecg.png b/src/applications/sample/wifi-iot/screenshot/rk_weekly/ecg.png new file mode 100644 index 0000000..7be1247 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_weekly/ecg.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/ecg.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_weekly/ecg.pngraw new file mode 100644 index 0000000..d5bd08d Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_weekly/ecg.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/flashlight.png b/src/applications/sample/wifi-iot/screenshot/rk_weekly/flashlight.png new file mode 100644 index 0000000..fd8c0c6 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_weekly/flashlight.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/flashlight.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_weekly/flashlight.pngraw new file mode 100644 index 0000000..e412671 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_weekly/flashlight.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/keyboard.png b/src/applications/sample/wifi-iot/screenshot/rk_weekly/keyboard.png new file mode 100644 index 0000000..7b74c0d Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_weekly/keyboard.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/keyboard.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_weekly/keyboard.pngraw new file mode 100644 index 0000000..cc498d7 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_weekly/keyboard.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/launcher.png b/src/applications/sample/wifi-iot/screenshot/rk_weekly/launcher.png new file mode 100644 index 0000000..c832b69 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_weekly/launcher.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/launcher.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_weekly/launcher.pngraw new file mode 100644 index 0000000..17f3bf9 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_weekly/launcher.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/mms.png b/src/applications/sample/wifi-iot/screenshot/rk_weekly/mms.png new file mode 100644 index 0000000..3096a70 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_weekly/mms.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/mms.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_weekly/mms.pngraw new file mode 100644 index 0000000..ad75d74 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_weekly/mms.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/music.png b/src/applications/sample/wifi-iot/screenshot/rk_weekly/music.png new file mode 100644 index 0000000..016dd21 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_weekly/music.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/music.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_weekly/music.pngraw new file mode 100644 index 0000000..e00bb62 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_weekly/music.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/note.png b/src/applications/sample/wifi-iot/screenshot/rk_weekly/note.png new file mode 100644 index 0000000..58e5183 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_weekly/note.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/note.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_weekly/note.pngraw new file mode 100644 index 0000000..41bd453 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_weekly/note.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/photos.png b/src/applications/sample/wifi-iot/screenshot/rk_weekly/photos.png new file mode 100644 index 0000000..cab7f71 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_weekly/photos.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/photos.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_weekly/photos.pngraw new file mode 100644 index 0000000..c04377b --- /dev/null +++ b/src/applications/sample/wifi-iot/screenshot/rk_weekly/photos.pngraw @@ -0,0 +1,136 @@ +$1$1$1/:F/:F/:F/:F/:F/:F/:F/:F/:F$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1`ir$1$1$1$1$1$1$1$17AM$1$1$1$1$1$1$1$1rz$1$1$1$1$1$1$1$19DO$1$1$1GQ[$1$1[dn$1$1$1$1$1$1$1$1$1$19DO$1$1$1dlu$1$1$1iqz$1$1$1$1$1$1$1$1$1$19DO$1$1$1HQ\$1$1$1ajsbktow\eo$1$1$1$1$1$1-8D/:F/:F/:F/:F/:F/:F/:F/:F$1$1$1%0$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1HQ\$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1(5 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9$1$1$1$1$1$1$1$1$1$1$1$1HQ\$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1v~`ir`ir`ir`ir`ir`ir`ir`ir`ir`ir`ir`ir$1$1$1$1$1$1yCMX$1$1$1$1$1$1$1$1$1S\f ,9LV`|0;G$1*7$1$1$1$1$17AM$1$1$1px$1$1$1$1$1$1$1$1=HS/:F$1$17AMkt|$1$1$1$1$1$1$1$1$1enw$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1w$1$1$1%0<$1$1|QZd$1$1pxGQ[$1$1$1LV`$1$1$1bkt$1$1$1$1$1$1GQ[Ybk$1$1DNY$1$1#/;$1$1$1`irdlu$1$1$1$1$1$16@L$1$1$1$1$1$1,7CpxT^h$12?}@sHn4<];=>?{O}q<455DT;<>?SR4556DH:;<>Tr5568=:;;=Wh5789:;;gW789:;vG89:ڃ;:َ{ۣ]ezSZnOUi9;O;=R<>S<>SNThJPd9;P78L79M;=R;=Q<>Rjv14E68K;=Q;=R;=R9;P8:O;=Q,.>,.>-/?35H79N78L8;O;=R[dxǷ,.>,.>,.>,.>,.>13E67J57H78Kƽο;@P,.>,.>,.>,.>,.>,.>,.>-.>02D68KqºGP`,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>>CT*,=,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>-/?iklmnppqrttvwBL^+-=#%7+-=,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>-/?klmnppqrttvwxyz{}~.3E"$6%(8*-=%'7&(9,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>,.>=CSºlmnppqstuvwxy{{}~+2F%'8+-='):"$6!#5#%6#%6()9*,=+-=,.>,.>,.>,.>,.>,.>,.>mnppqstuvwxy{|}~ÿBOb"$6#$5 #4"$5$&8*-=&(9"%6"$5#%6"$6"$5$&7&(9&(9(*:)+;feoοnpprstuvxxz{|}~2"$6)+<,.>&(9"$5!#5 "4"$6!3&)9)+;+-=+-=),<)*;"$6hZ_Ѽ̾òϾwwnpprstuvxxzz|}~*0C "4!"5 2"%6&'8'):(*:!$6 1 1 12"4!#5 "4!#5JCLлѼлϺvvvwvwyypqrstuvxyz{|}~1!#5$&7(*;')9 !3 1!2!4"4 #4#%6$&8&'8'(9%(820>ϻѼмлκ͹˸uttuuuvvwwwxzy}qrstuvxyz{|}~12"3&(9*-=%'8%'7%'8"$6!3 2 1!$4"$6%'875CκѼѼмлκ̸ʷɶtrsssttttuuuuvvwxyxrstuvxyz{|}~11 3 !2!2!#5$'7'(9#%7!2%'7+-='*:*+<43B̸ѼѼѼлкι˸ɶƳñoooqqrsssssttuttuvvvwwxxstvvxyz{|}~$):11 2#&7 1 $5#%6 "3 "3!3$&6'):01@ųѼѼѼмлϺ͹˸ȵIJvmmnnoopqrrssssstttuuuuvvuvvwxxtuvxyz{|}ƻl111 3"%6!"4"4#%6$&7%(8(*;')9ЬҽѼѼѼллκ̸ʶdzñlllmllmnooopqqrrrsssstttuuuuuvvvwxuwxyz{|}"&711 11"3 #5 1 1 2"$6"%6$&7ijѼѼѼллκ˸ȵŲ°õklllllllmmnnoppppqrrsssssssttuuuvvvw|uwxyz{|}n1111 3!3 1 #6#%7!#4$&7(+;IEOҽѼѼлϻ͹˸ȵŲrjjkklllllllmmnooooopqrrrrrrssssstuuuuvvwxyz||~-3G 2 111 3 1 22"3"4 "4 "4κѼѼлϺι̸ɵƳñVvJlJkJlIkoojjjjjlllllllllmmnooooopqqqqqrrrrssssttuvvuxyz||~!#4 1111111(*9--=++;eY_ҽѼѼмлι̸ʶȴŲðJlIkIjIkIkjjjjjjjjkllllllllllmnnnnoooppqqrrrqrssssttuttvyz{|~Nby 211111y}ҽҽҽҽѼѼлϺ͹˸ʶȵdzƲdzKlHjHjGiGixjjjjjjjjjjkklllllllllmmmmnooopppqqqqqrrrsssssstux{{}~ij&+=2 2111ҽҽҽҽѼѼѼлκ͹̸ʸʶɶʷTqGhGiGhFhmkjjjjjjjjjjjkkkllllllllmmmmnnnnoooppppqqrrssssssstt|{}~ 21111̺ҽҽҽҽҽҽҽѼѼллκι͹͹͹ϻvFhEgEgEgkkkkkjjjjjjjjjkkkkllllllllllllmmmmnonoppppppqqrsrrsssss}~{ 1111cV]ҽҽҽҽҽҽҽѼѼѼмллϺϻлмEfDfDeEgwkjjjkjjjjjjjjjjjjkkkllllkllllllllmmmmnnnooopppqpqqrrrrssss~~Wm1111npлҽҽҽҽҽҽѼѼѼѼллммѼCeCdCdurkjjjjjjjjjjjjjjjjjjkkklkkkkkklllllllllmmmnnnooopppppqqrrrrsst~GXn11112/>๪ҽҽҽҽҽҽѼѼѼѼѼѼѼѼZsAcBcBcmkkkkjjjjjjjjjjjjjjjjkkkkkkkkkkkllllllllllmmmmnnnoooppppqqrrrrss{APe11111ҮҽҽҽҽҽҽѼѼѼѼѼѽq@b@b@a@b{kkkkkkkjjjjjjjjjjjjjjjjjkkkkkkkkkklllllllllllllmmmnnnoooooppqrqqrrsPd{ 1111乩ϻҽҽҽҽҽҽҽҽҽмMh>_?_?`?aAcqkkkkkkkkkjjjjjjjjjjjjjjjjkkkkkkkkkkkkkllllllllllllllmmnnnooooppqqqqrrr!$51TJSιικҽҽҽҽҽҽҽ@`<]<]<^=_>_Nk~okkkkkkkkkkkkjjjjjjjjjjjjjkkkkkkkkkkkkkkkkkkkklllllllllllmmnnnoopppqqqrrrű̷͸͸͸̸лҽҽҽͺdv9Z:[9[:[;\<]<]}wmkkkkkkkkkkkkkkjjjjjjjjjjjjkkkkkkkkkkkkkkkkkkkkkkklllllllllllmmnnnoppppqqqrκ͸͸̸̷˷ʵʶͺ~8Z8Y8Y8Y8Z9Z9[;[;\}tkkkkkkkkkkkkkkkkkkjjjjjjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllllllmmmnnopppqqqr̸̷̷˷ʶɵDzİ7X6X6X6W6W7X7Y8Y9Z:[okkkkkkkkkkkkkkkkkkkkkjjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllllllmmnoopppqqr̷˶ʶɵȴƲı¯6W5V5V5V5V6W6W7X7YIgokkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkklllllllllmnnnooppquã˷ʶɵȴƲð5V4U4U4U4U4U5V6W7Xmwkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkklllllllmnnnoppp~¡е©lb˶ɵȴƳı°3U3T3T3T3T4U4U5V6W~kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllmmnnoopp¡á؅MoMoMoMoɵȴƲı°7W3T3T3T3T3T3U4U5Vkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllmmnnoop¡áġTvMoMoMoMoMo`z±ðOf4U3U2T3T3T3T4UHekkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllmnnoo¡áššWyKmKmMoMoMoMoMoMoMoNoRtp}vr{h2S2S2S3T銙kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllmnnp¡ġššǡcEgIkHiLnKmMoMoMoMoOql{}}}}vAa2S3T3TkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkklllllmnnqáġšơǡΫ2S=_IkMoGhLnMoMoMoMo\{mn|}}}Ll2S2S3Ukkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkklllllmnt¡áġšơǡȡӳ3T2S2S=^LnMoMoMoMoMoMoMoOpcYynoAa2S2Suzrqpoonmllllkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkklllllm¡áġšơǡȡɡTv1R4U6W4U?aMoMoMoMoMoMoNoNoMoMoMoHj2S2S~uqonllkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllm¡áġšơǡȡɡʡ6V1R1R1R1R1R2SEgMoMoMoMoMoMoMoMoMoMoMo;]{tomllkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllm¡áġšơǡȡɡʡˡ5V2S:[CdLnEg9Z2S1R7WMoMoMoMoMoMoMoMoMoMoMoNpRs]|}uolkkkkkkkkkkkkkkkkkkkkkkkkkllll¡áġšơǡȡɡʡˢ̢NpMoMoLnMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqQrRsUvYysqnlkkkkkkkkkkkkkkkkklllm¦¡áġšơǡȡɡʡˢ̢ШMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqPrRsTuWw\{dvmlkkkkkkkkkllnʮ¡áġšơǡȡɡʡˢ̢͢ٹMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNpOpOqQsSuWw[z`xzvlkkkkllsдġšơǡȡɡʡˢ̢͢΢NpMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqQrSsVvYy]|n||yxmklӷơǡȡɡʡˢ̢͢΢ϢStMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqOqQsSuWw[z^}r|xwzyոȡɡʡˢ̢͢΢ТТnMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqQrRsUuWw[z`s|zxwغˡ̢̢͢΢ТТѢNpMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNoOpOqQrSsUvXx[{_~o{|{z۽̢͢΢ТТѢҢMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqOrQrStVvWx[{^}er{{wzƼȽȾz_ݿ΢ТТѢҢ۵YzMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqOrQrStUvWw[{^}`fr{xr鞷¶¶ƺȼrz_z_z_gz_z_ݽѢѢҢӢQsMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqOrQsSsUuWwZz\|_cozzt~´ƹǼɾpz_z_z_z_z_z_z_z_|aøz_z_z_۷ҢӢԢMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNoNpOqOqQrRsTuWwXx[{^}ahyzwzµĸźǼȽqz_z_z_z_z_z_z_z_z_z_z_z_z_fyz_z_z_z_ٮԢգNqMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOpOqPrQsStUvWwZz\|_~dn{{v׼ɾµĸƺǼɾ¶oz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_ר֣TuMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnMoMoMoMoMoMoMoMoMoNoNoNpOqOqQrStTuWwYy\{^}afv{s䣻iabciҿоɹŸƹǼɾɾez_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_٨\|MoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnLnMoMoMoMoMoMoMoMoMoNoNpOpOqOqQrRsSuVvWwZz]|_djrsabcdefhj͹ķmnĵµöz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_{qMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnLnKmKmMoMoMoMoMoMoMoMoMoMoNoNpOqOqPqQsStTuVwYy[{_~bgnmwbddeghkϺιnppqձռ}az_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_rMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnLnKmJlIkKmMoMoMoMoMoMoMoMoMoMoNoNpNpOqOqQrRsTuUvWw[z^}`dhkqddfghnнлϻκ{pp|}~|NQ֍wz`z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_kNpMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnLnKmJlIkHjGhKmMoMoMoMoMoMoMoMoMoMoNoNpNpNpOqQrQsStTuWwZz\{_cgksf~{zѼѼϻϻqöȷdzIJ¯为|}RKKKKJJIPbՃfz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_iZ{MoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlIkHjFhEfCeLnMoMoMoMoMoMoMoMoMoMoMoNoNpOpOqOqQrRsSuVvXx[{_~bfks隲vuvuvwyϻѼлϻκ̸˷ɶdzŲñ°°°~eMLLKKKKJJIIIIHGMqݗpz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_f숢MoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnLnKmJkHjFhEfBd@a?aLoMoMoMoMoMoMoMoMoMoMoMoNoNpNpOpOqQrRsStUvWw[{^}bhmvҺonnnospssuѼѼлϻι̸˷ɶȴƳŲŲʴONMMLLKKKKJJJIIIHHGGGFFTǫvz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_~dMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlIkGiEgBd@a=^;\=^MoMoMoMoMoMoMoMoMoMoMoMoMoNoNpNpOqPrQsSsUuWwZz]|aekv߱nljiihgghnkopr}ѼѼѼлϺι̸˷ʷɶɵ鿾fONNMMMLLLKKJJJIIIHHHGGGJfz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_|bVwMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnLnKmIkHiFhCe@b=^;\8Y3U;\MoMoMoMoMoMoMoMoMoMoMoMoMoMoNpNpOqPqQrRsSuWwZz\{_~ukq榾߭vojhggfdcba~a~_}_}dggkmrѼѼѼѼлϻκ͹͹̸QOOONNNMMMLLLKJJJIIIIHHGSkz_z_z_z_z_uz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_{a柶MoMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlIkHiEgBc>`<\8Y6W2S1R@bMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNoNpOqPrRsSuVwYy[{_~jpvꞶվq`~]}_~_~`aaa`~_}]{[zZxYwXvVuVtZxa~`}bflϻҽѼѼѼлϻzPPOOOONNMMMMLLLKKKJIIIIHi|}bz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_}cOrMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlHjGhDf@b=_:\7X4U1S1R1RDeMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpNpOqPrRsStUvWx[{^}qo{떯昱}ja_~XxXwXxYyZyZz[{[{[z[zZyXwVuTtRrPpOoNmMlMmVuYwYv]{fϻҽ˼z|aQQPPOOONNNMMMMLLLKKKJIIJvo{`z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_qMoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlHjFhCe@a<]8Z5W3T1R1R1R1REgMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqPrQrSsUuWwYy^}rq|ݰplc`]|ZzXxVwUvUvUvUvUvVvVvVvUuTtSsQrPpMmKkIiGgFfEeEeFfQoTrSpd|uwxyzVRQQQPPOOOONNMMMLLLKKKJJO|~kz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_MoMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlHjEhCe?a<]8Y5W3T1R1R1R1R1RFhMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNoNpOqOqQrRsSuVvWxZzas|ӿ}}}jca`^}\{YyWxUvTuStRsRsRsRsRrRrQrPpNoMnKkIiGgDeBc@a>^=^<]BbFeKkofZTRQQQPPPOONNNMMMLLLKKKX|{gz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_XyMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlHjEhCe?a<]8Y5W3T1R1R1R1R1R1RGiMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoMoNpOpOqPrRsStUuVw[{w|}|lu{w}ya^}\|[{YyXxVwUuStQsQrPqOqOpOpNoMoMnKmJkHiFgCdBb?_=^:[9Z8Y7X8Y<\͹hVSPOOONNNMMLLLKbx~cz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_d߽MoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlHjFhCe@a<^9Z5X3T1R1R1R1R1R1R1RHjMoMoMoMoMoMoMoMoLnLnLnLnLnMnMoMoMoNpOqOqPrQsStUuUuXx_}lm`iaj^}YyYyXxWwUvUuStRsQrOqNpMoMnLnKmKlIkIjGhEfBcAc?_=];[9Z7W4U5U3THhjONNMMLLk~dz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_tPrMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlIjGhDfAb=`:\8X3T2S1R1R1R1R1R1R1REfMoMoMoMoLnLnLnLnLnLnLnLnLnLnLnMoMoNoNpOqOqQrQsRsStTuWwhdVwfWwVvUvUuTuTtSsQsQrPqOpMoMnKmKlJkHjGiFhDfCdAb?`=^:\7X5W5V4U2S3T xbz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_蓫MoMoMoMoMoMoMoMoMoMoMoMoLnLnKmKlIkHiEgBd@`<]9Z4U3T1R1R1R1R1R1R1R1RBdMoMoLnLnLnLnLmKmKmKmKmKmKmKmLnLnMoMoNoNpOpOqPqQrQrQsRsRsRsStSsRsRsRsQrQrPqOqNpMoLnLmKlIkHjGhFgDfBdAb>`=^9\5V4U5W3T2S2SHglz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_OqMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJkHjFhDe@b=`;\6W3T1R1R1R1R1R1R1R1R1R>`LnLnLnLmKmKmKlJlJlJlJlJlKmKmKmLnMnMoMoMoNpOpOqPqPqPqPrQrQrPrPrPrPqOqOqNpNoMnLmKmJlHjGiFhDfCdAb?a=_;\5V2S1R3T3S1R2S̓p~ez_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_sMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlIkHiEgBd@a<]6X5W1R1R1R1R1R1R1R1R1R1RދMoKmKmJlJlIkIkIjIjIjIkIkJkJlKmKmLnLnMoMoMoNoNpNpOpOpOpNpOpNpNpNpMoMoLnKmKmJkIkGiEgDfCeAc?a>`<]9Z3T2S3S2S1R1R8Yte{`z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_}aMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlIkGiDfBd?a8Z9Z1R1R1R1R1R1R1R1R1R1RԾLmJlIkHjHiGiGhFhGhGiGiHjIkIkJlKmKmKmLnLnMnMoMoMoMoMoMoMoMnMnLnKmKmJlIkIjGiFgEfCeAc@a>_<]:[9Z7X5U2S1R1R1Rnxz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_qRtMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmKlIkHiFhDfAc;]:[2S1R1R1R1R1R1R1R1R1R^~HiFhEgDfDeDeDfDfEgFgGiHjHjIkIkJlKmKmKmLnLnLnLnLnLnLnKmKmJlJlIkHjGiEgEeCeAc?a>_=]:[9Z7X1S2S1R1R1Rc}}az_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_tMoMoMoMoMoMoMoMoMoMoMoMoMoLnLnKmJlHjGiFhCe>_:[4U1R1R1R1R1R1R1R1R1RوDfCdAcAbAbAbAcBdCeEfFgGhGiHiHjIkIkJkJlJlKmKmKmJlJlJlIkHjHiGhFgDfCdBc@a>`<]8Z8X6W5U3S2S1R1R}fz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_ܻ嘰MoMoMoMoMoMoMoMoMoMoMoMoMoLnLnLnJlIkHjGhEg@a;]7X1R1R1R1R1R1R1R1R1RƼDe?a>_>_>`?`@bAcBdCeEfFgFhGhGiHjHjIkIkIkIkJkIkIjHjGiFhEgDfBdAc@a>_;\8X4V7X6W5V3T1S6Vȅwez_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_MoMoMoMoMoMoMoMoMoMoMoMoMoMoLnKmKlJlIkGiEh>_=_:[1R1R1R1R1R1R1R1R1R[z;\:\;\;]=^?_@aAbBcCeDeDfEgEgFhGiGiHiHiHiGiGhFhDfDeBdAc?a=^8Z8X6X7Y5V3U3T3S>^åk}az_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_KmKmKmMoMoMoMoMoMoMoMoMoMoMoMoKmKmJlHjHhEh?`>_<\2S1R1R1R1R1R1R1R2Rũ9Y7X8Z:[;]=_>_?a@a@bAcBcBdCeDeEfEgEgEfEfDfCdBc@b?`<]4U1R2T3T4V3S3T2SCbϪw|`z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_lNpKmGiMoLnHiMoJlJlMoMoMoMoMoLnKmKlIkHjFhEgAb=^<\5U1R1R1R1R1R1R1RIh]|6W7Y9[;\;]<^=^=_>_?`?a?aAbAcBcBcBcBc@b@a>`9Z3U1R3U5W5V2S1S1Rkz_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_~KlKmLnEgKmMoMoLmEgCe=^CeIkLnKmHjJlHjHiEhEf@c<]<\8Y1R1R1R1R1R1R1Ri<]7Y9Z9[:[:[:[:\;\;]<^=_>`>`>`>`>_;\6W3S2S3T2S1R1R1RBb̨ez_z_z_z_z_z_z_z_z_z_z_z_z_z_z_z_ˡFf9[;]?`FhJlGh@cDfIjJlGjCdCeKmJlIkHjFhEgCd@b<]:\8Y1S1R1R1R1R1R1RәǛ=]8Y8Y8Y8Y8Y8Y9Z:[:\;\;]:\8Y6V4V6W3U2R1S1R4Tzt}az_z_z_z_z_z_z_z_z_z_z_Aa2S5V4U5V7X8Y9[:[:\;]=^DeCeEgGiGhFgFgDeBd@`:\9Z7X3T1R1R1R1R1R1RȐ;[4U5V5V5V6W7X7X5V5V7W7Y7Y4T3T2S2SVuԠziz_z_z_z_z_z_z_<\4U6W5X7W6X5V7X<]<^<^;];\<^?`@a>_=_>_?aAb?`;\9Z7X4V1R1R1R1R1R1R=]3T3T3U5U5V5W5V4U4T2T2SBbƏj~bz_z_Ӹ5V4U5V3T3T<]DfBdCd@a>_Bc=_@c?aFhEgCdBc>`@a>`;\9[6X4U2S1R1R1R1R1Rӡʁ2S3T3U4T2S2S[zSq3T3T4U7W7X6X6W7X8Y<]CdCe>`DfBcBcCdBdAc@b@a=`;\8Y5W4U2T1R1R1R1R1Rh5V3T3T3T5V5V6W6W6W5V5V5V5V4U5V5V5V4U4VAb@b@`=_;\8Y6X4U3T1R1R1R1R1R7X3T3T3T3T6W5W4U4U4U3U4U5V5V4U4U3T4U4U8Y@b@a>`=_;]8Y7X4U4T2S1R1R1R1R1R;\2T4U:[5V6W6W5W5W5V5V4U4U4U4U5V8X<]=_>_?a?`?`>_<]8Z7X5V3T3T1R1R1R1R1RӇ2S2S6W:[:[@cCeCdCdBdBcAb@a?`@a>`?`?`?a?a?b?a?`=_<^:\8Y5X4U4T2S1R1R1R1RJi\z2S2S8Y8Z<]<]AbAcAbAb@b@a?`>`>`=_=_>_?`?a@b@b@a>`=_;\9Z7X5V4U3T1R1R1R1R1R5V2S2S7Y8Z:[;\=_?`?`?`>`=`=^=^=^=^=_>`?`?a@bAb@b?a>`<]9Z8Y5W5V4U3T1R1R1R1R2S2S4U7Y8Z9Z=^:[=^=_=_=^<^<]<^<^=^=_>`?a@bAbAbAb@b?a<^:\9Z7X6W4U3T1S1R1R1RӂYw2S2S5V8Y8Z9Z;\;]:[<^<]<]<]<]<]<^=^>_?`@aAbAcBcAdAb@a>_;\9[8Y6X5V3T3T1R1R1R@_5V2S2S6W8Y8Y:[9[;];\:[;]<]<]<]<^=_>_?`?bAbBcCeCdCeBd@b?`<]:\9Z7Y5V4T3T2S1R1R6Vз3T2S2S5W8Z9Z9[9Z9[;\;\:\;\<]=^=_>_?`?aAcBdCeDeDfDeBdBc@a>_;\9Z8Y5W4U2T2S2S1R1R[z3T2S2T5V8Y8Z9Z9Z9Z9[:\;\;\<]=^>_?_?aAbBcCeDfDfDfDeCdBd@a=_<]9Z8X6W4V3T2S2S1R1R8X2T2T2T3U8Y8Y8Y8Z8Z9Z9[:\;\;\<^>_?`@bAcBdDeDfEfEgDfDeCdAc?`<^:\8Y5W4U4U3T2S2S1Rўа2T3T2S2S2S7W7X7X7X7Y8Y8Z9Z:[;\;\<^>_@aAcBdDeDfEgFgEgDfCeBd@a=^;\8Y6X5V4U3T2S2S1Rb~^|2S2S2S2S2S4U5V5V5W6W6W7X7X8Y9Z;\;]<^>`@aBcCdDfEgEgEfDfCeAb?`=_;\9Z6X5V4U3T3T2T2S1R8X2S2S2S2S2S1R4U4U4U4U5V5V6W6W7Y9Z:[;\=^>`@bBdCeDeDfDfDfCd@b?`<^;\8Y6X4U4T3T2S2S2S1Rϸ2S2S2S1R1R1R1R1R2S3T3T3T4U4U4V5W7W7Y9Z;\<^>`@aAcBdCeCeCeBd@b?`<^:\8Y6X4U3T2S2S2S2S2S\{3T2S1R1R1R1R1R1R1R1R2S2S2S3T3T4U4V6W7X9Z:[<]>_@aAbAcBcBcAc@a?`<]:\8Y6W4U3T2S1R1R1R1RЧ7X5V4U2S1R1R1R1R1R1R1R1R1R2S2S2S3T3T4U5W7X8Z:[<]=_?`@b@a@b@a?a>_<]9[8Y5V4U2T2S1R1R1R1RsӁ4U4U4U3T2S1R1R1R1R1R1R1R1R1R1R2S2S2S3T4U5V7W8Y9Z;\<]=_>`>`>`=_<];\9Z8Y5V4U2T1S1R1R1R1R7W;[4U4V4U3T2S2S1R1R2S1R1R1R1R1R1R1R1R1R2S3T4U5V6W7X8Y9Z:[;]<]<]<];\:[8Y7X5V4U2T2S1R1R1R1R1R4U4U4V4V4U3T2S2S2S2S2S1R1R1R1R1R1R1R1R1R2S3T4U5V5V6W7X7Y9Z9[9Z9[9[9Z8Y7X5V4U3T2S1R1R1R1R1Rλ,E5V5W5V4V4U3T3T2S2S2S2S2S2S1R1R1R1R2S2S2S2S3T4U4V5V6W6W7X7X7Y8Y7Y7X6X5V4U3T2S2S1R1R1R1Rэ,,s(?5U6W5V4U4U3T3T2S2S2S2S2S2S1R1R2S2S2S2S2S2T3T4U5V5V5W6W6W6W7X6W6W5V4U3T2S2S1R1R1R1Rjds++*)$,.I4U6W5V4V4U3U3T3T3T2S2S2S2S2S2S2S2S2S2S3T3T4U4U4U4U5V6W6W6W5W4U3T2T2S1R1R1R1RNl,2B+**)('&'["65U6W5V5V4V4U4U3T3T3T2S2S1R1R1R2S2S3T3T3T3T3T3U5V5W6W6W5V4U3T2T2S2S2S1R6V /**)(('%$$#%,"4B%9,F4S5V5V4U4U3T2S1R1R1R2S2S2S2S2S2S2S3S4U5V6W6W6W5V4U3T2T2S2S1R1R+*))('&%$#"& 1!1!2!2!"2#"41#6K';d)@+F/K1P2S2S2S2S2S1R1R1R2S3U5V6W7X6X6W5V4U4U4U3U1R1R+*)(('%$#"!( 1 1!2!2!2 "3 "3 "3!#4!#4!#4"$4#$4$$5&$6'$6+%6:&9I';X(>e*Ap+C{-F/H0I0K0K1L0L1K1K0I/IYs+*)('&%#"" ( 1 1!1!2!2 "2 "3 "3!#4!#4!#4"$4"$5"$5"$5"$5"$5#%5#%5#%5#%6#&7%'7%'7%'7%'9&'9')9');'*;(*<)+=+->boiy*))('%$#"! % 1 1!1!2!2"2 "3 "3!#4!#4"$4"$4"$5"$5"$5#%5#%5#%6#%6#%6$'7%'7%'7%'8%'9')9'):');(*;)+<*,>+->,.?IQcDN_*)((&%$#"  ! 1 1!1!2!2"2 "3 "3!#4!#4"$4"$5"$5#%5#%5#%6#%6#&6$&6$&7%'8%'8&(8&(9')9');(*;)+=*+=*,>,.?-/@./A12D,1A*)((&%#"  !1!1!2!2!2 "3 "3!#3!#4"$4"$5"$5#%6#%6$&6$&6$&7$&7%'7&(8&(8&(9&(:(*:(*;)+<*,=*,>+.?,.?-/A./B/1B/1C(.>*)((&$#!  1!2!2!2"2 "3!#3!#4"$4"$5#%5#%6$&6$&7%'7%'7%'7&'8&(9')9'):'*;(+;)+;*+=+->+-?,.?-/A./B/1C/1C/2E02E(-=*)((%#"! -!2!2!2"2 "3!#4!#4"$5#%5#%6$&6%'7%'7%'8&(8&(9&(:'*:(*:(*;)+<*,=*,=+->,.?-/A./B/1C/2D02E13E13F23F).>*)('%#"! $!2!2"2 "3!#3!#4"$4"$5#%6$&7%'7&'8&(8')9')9'):(*;)+;)+;*,=+-=+->,.?,.?./A/0C/1C03E13E13F24G35H35H39I*('&%$"! !2"2 "3 "3!#4"$4"$5#%6$&6%'7&'8&(8')9'):(*:)+;*+<*,<+->+->,.?-/?-/@./B/1C/2D13E13F24G35H35I35I46Ip~Taq)('&%$"! ) "3 "3!#3!#4"$4#%5#%6$&7%'7&(8')9'):(*:)+;)+;*,=+-=+->,/?-/@./A.0B/1C/2D13E23F24G35I36I46J46J46JXat)('&%$"!  "3 "3!#4!#4"$5#%5#%6$&7%'7&(8')9'*:(*;)+;*+=+-=+->,.?-/?-/@.0A/1C/2D13F24G35G35I46I46J57K57K57KNUh)(('%$#! " "3!#4"$4"$5#%5#%6$&7%'7&(8')9'*:)+;)+;*,<+->,.>,.?-/?./A/1C02C13E23F24G35H36I46J57K57K57K57KBG[,(('&%"  ,!#4!#4!#4"$4"$5#%6$&7%'8&(8'*:(*;)+;*,=+->,.>,.?-/A/1B/2C02D13F24G35G36I46J57K57K57K57L57L8:O"2)('%$"!   0!#3!#4"$4"$5#%6$&6%'7%'7&)9(*:)+;*,<+->,.?-/?-/@/1B02C13E13F24G35I46J46J57K57K57L57L67L68L*)('%$#!    1"$4"$4#%5#%6$&6%'7%'7&(8'*:)+;*+<+-=+.?-/?./A/1C02D13E24G35G36I46J57K57K57K57L57L68L68L*)('&$"!     *"$5#%5#%6$&6$&7%'7&(8'):)+;)+;+-=+.>-/?./A/1C02D13F24G35H36I46J57K57K57L57L57L68L68L8?O))('%$"!      + "$5#%5$&6$&7%'7&(8')9'*;)+;*,=+->-/?./A/1C02D13F24G35H46J46J57K57K57L57L67L67L68L"2))(&%$"!     +  +  + -#%6$&7%'7%'8&(9'):)+;*+<+-=-/?-/A/1B02E13F24G35I46J57K57K57K57L57L67L57L67L**)(&&$#!       +  + +!#4#%6$&7%'7&(8')9(+;)+;+-=+.?./A/1B02E13F24G35I46J57K57K57K57L57L68L68L68L}+*)('&$"!      + + +   "2#%5#%6%'7&(8')9'*;)+;*,=+->-/A/1B/2C13F35G35I46J57K57K57K57L57L68L68L68Liw6=L+*)('%$#!      +  +   0#%5#%6$&7&'8&(9'):)+;*+<+->-/@.0B/2C02F24G35I46J57K57K57K57L57L57L57L68LU_s!1+*)('%%"!      + + +  ."$5#%5$&7%'8&(8')9(+;)+<+->,.?.0B/2C02E23G35I46J57K57K57K57K57L57L57L67LFL`+++)('&$#"     +  + +  +"$5#%5#%6%'7&(8&(9(*;)+;+->,.?.0B/2C02E23G35I46J46J57K57K57K57L57L57L57LDI]j|,+*)('&$#!     +  +  +  ("$5"$5#%6%'7%'8&(9'*:)+;*+<,.?-/A/1C02E23G35H46I46J57K57K57K57L57L57L57L?DX.3D,+*)('%$#!     +  +   !"$4"$5#%6$&7%'7&(8'):(*:*+<+.?-/A/1C02D13F24G35I46J57K57K57K57K57L57L57L=AV!1,+*)('&%#!     +  + +  !#4"$5#%6$&6%'7%'8'):(*:)+<+->-/@.0B/1C13F24G35I46I46J57K57K57K57L57L57L:=R,,+*)('%%#"     +  + +   !#4"$5#%6$&6$&7%'7'(9'):)+;+,=,.?.0B/1C13F24G35H36I46J57K57K57K57K57L57L7:OTbs,,+*)('&$#!     +  +   +"$4"$5#%5#%6$&6%'7&(9')9(+;*+<+.?-/A/1C02E13G35H35I46J46J57K57K57K57L57L57L*/?,,+*)('&$#!      +  + +   "$4"$4"$5#%5#&6%'7&(8&(9'*:*+<+->-/A.0B02E13F24H35I36I46J46K57K57K57K57L57L /,,+*)((&$#!      + +    HS]#&7"$4"$5#%5#%6$'7%'8&(8'):)+;+->,.@.0B/1C13F24G35I36I46J46J46K57K57K57K57L-,,+*)((&$#!    +  +  +   %(9!#4"$4"$5#%6$&7%'7%'8')9'*;*+=,.?-/A/1C02E23G24H35I46I46J46J57K57K57K57L-/@.0B02D13F24G35H36I46J46J46K57K57K57K"&7.,,+*)((&$"!     +  + +   9BJ(++.?.0B/1C02E13G24H35I46J46J46J57K57K57K/-,,+**((&$"!     +  +   39J"$5"$5#%5#%5#%6#%6$&6%'8&(9(*;*+=+.?-/A/1C02E13F23G35H35I46J46J46K57K57K.-,,+**((&$"!    +  +  +  ?J["$5"$5"$5#%5#%5#%6#&6%'7%'9'):)+=*,>+.@./C/1D13F23G35H35I46J46J46J46K57K/5F.-,,,*)((&$"     +  + + +  HT]MYj"$5"$5"$5"$5#%5#%6#%6$&7%'9'):(*;*,=+-@-/B/1C02F13G24G35I35J46J46J46K57K"2--,,+**('&$"     +  + +  [i{"$5"$5"$5"$5#%5#%5#%6$&7%'7&(:(*;)+=+-?-/A.0C02E13F23G35H35I46J46J46K57K.--,,,*)('&$"     + + +  i{"$5"$5"$5"$5"$5#%5#%5#%7%'7&(9(*;)+<+-?,.A.0B/2D02E23G35H35I35J46J46J46Kj|.---,,+)('%$"     + + +  Zit}"$5"$5"$5"$5"$5#%5#%5#%6%'7&(9');)+;*+>,.?./B/1C02E13G24G35I35I46J46J46K%(8.---,++)('%#"      + + +  "$5"$5"$5"$5"$5#%5#%5#%6%'7&'8'):(*;*+>+.?-/B/1C/1E13F23G35H35I36J46J46K/.---,++)('%#!      + + + "$5"$5"$5"$5"$5"$5#%5#%6$&7%'8'):'*;)+=+-?-/A./C/1D02F23G24G35I35J46J46J.----,++)('%#!    +  + + + m"$5"$4"$4"$4"$5"$5"$5#%5$&7$&8&(9');)*=*,>+.@./B/1C02E13F24G35I35I46J46JVcv.----,++)('%#     +  +  #&6"$4"$4"$4"$4"$5"$5"$5#&6$&7%'9'):(*<*+>+.?-/B.0C/2E13F23G24I35I36J46J|#&7.----,+*)(&%#     + + + + +"%(8"$4"$4"$4"$4"$4"$5"$5#%6$&7%'9&(:(*;*+>+-?-/B.0C/1D02F13G24H35I36I46Jx/.----,+*)(&$"      +  + + +'+;!#4!#4!#4!#4"$4"$4"$5#%6#%7%'7&':');)+=*,?,.A./B/1D02F13G24H35I35I46Ju{/.----,+*)(&$"      + + + +)->!#4!#4!#4!#4!#4!#4"$4#%5#%7$&7&'9');(*=*,>+.A-/B/1C02E13G24H35I35I46Jr?I[/.---,,+*('%$!     + + + + %*-1C!#4!#4!#4!#4!#4!#4!#4#%5#%6$&7%'9'):(*<*,>+-@-/A.0C/1E13G24G35H35I46Jr"3/.---,,+*('%#      +  + +=FW!#4!#3!#3!#4!#4!#4!#4"#5"$6$&7%'9&(:(*;)+>+-?,.A.0C/1D13F23G35H35I46Jo/..---,,*)('%#       + +P\n!#3!#3!#3!#3!#3!#3!#4"#5"$5#%7%'7&(:'*;)+=+-?,.A./C/1D02F23G35H35I46Jkz\l}...---,,*)(&$"       + +8ALdu!#3!#3 "3 "3 "3!#3!#3"#5"$5#%6%'7&':');)+=*,?,.@./B.0D02F13G24H35I46Jkz,2C...---,+*((%$"      +  + +v!#3 "3 "3 "3 "3 "3!#3"#4"$5#%6#&7&'9');)+=*,?+-@-/B.0C02F13G24H35I46Jkz 1....-,,+*('%#      +  "3 "3 "3 "3 "3 "3 "3"#4"$5#%6#&7&'9');(*=*,>+-@-/B.0C02E13G24G35I36Jr/....-,,**('$#      + Udp "3 "3 "3 "3 "3 "3 "3"#3"$5#%6#&7&'9'):(*=*,>+-@-/B.0C02E13F24G35I36Jq+-@-/B.0C/2E13F24G35H35Jq"3//...-,,*)(%$!     #* "3 "3 "3 "3 "3 "3 "3"#4"$5#%6#&7%'9'):(*=*+>+-@-/B./C/2E13F23G24I35Iq//...-,,,*((%#!     + q "3 "3 "3 "3 "3 "3 "3"#4"$4#%6#&7%'9'):(*=*+>+-?-/A./C/1E13F23G24H35Iw//...-,,**('%"      + $&8 "3 "3 "3 "3 "3 "3"#4"$4#%6#%7%'9'):(*=)+>+-?,.B./C/1E02F23G24H35Iy,2C//...-,,**(&$"     +1;'+< "3 "3 "3 "3 "3 "3!#4"$4#%6#&7%'9'):(*<*+>+-?,.B./C/1E02F23G24H35I} 1//...-,,*)(%$!     + */@ "3 "3 "3 "3 "3 "3!#4"$4#%6#&7%'9'(:(*<)+>+-?,.A./C/1E02F13G24H35I//...--,+*)'%#!     + 28I "3 "3 "3 "3 "3 "3!#4"$4#%6#&7%'9'(:(*<)+>+-?,.A./C/1E02F13G24H35I]m//...--,+))'$"     9DOIUg "3 "3 "3 "3 "3 "3!#4"$4#%6#&7%'9'):(*;)+>+-?,.A./C/1E02F13G24H35I!%7//...--,+)(&$!     ev "3 "3 "3 "3 "3 "3!#4"$4#%6#&7%'9'):(*;)+>+-?,.A./C/1E02F23G24H35I0//..---++)(&#!    } "3 "3 "3 "3 "3 "3!#4"$4#%6#%7%'8'):(*;)+>+-?,.A./C/1E02F13G24H35Iz///...--+*((%#    Q`l "3 "3 "3 "3 "3 "3!#4"#4#%6#&7%'9&(:(*;)+>+-?,.A./C/1E02F13G24H35I?I[///..---+*('%"     "3 "3 "3 "3 "3 "3 "3"#4#%5#&7%'9'):(*;)+>+-?,.A./C/1E02F13G24H35I"3///..--,+*(&$"   !* "3 "3 "3 "3 "3 "3!#4!#4#%5#&7%'9&(:(*;)+>+-?,.A./C/1E02F23G24H35I////.---,*)(&$!   i~ "3 "3 "3 "3 "3 "3!#3!#4#%5#%7%'9&(:(*<)+>+-?,.A./C/1E02F23G24H35IP^o////.---,*)(%#"   "3 "2 "3 "3 "3 "3!#4!#4#%5#&7%'9&(:(*;)+>+-?,.A./C/1E02F23G24H35I(->////.--,,*((%#! -5?$'8 "2 "2 "3 "3 "3!#4!#4#%5#&7%'9&(:(*;*+>+-?,.A./C/1E02F23G24H35I 1////.--,+*('$#!  )-? "2 "3 "3 "3 "3!#4!#4#%5#&7%'9&(:(*;)+>+-?,.B./C/1E02F23G24I35J/////.-,,+)(&$#  .4E "2 "3 "3 "3 "3!#4!#4#%5#&7%'9'):(*<)+>+-?-/A./C/2E13F23G24I35I).@/////.-,+*)(%$"! =HS=GX "2 "3 "3 "3 "3!#4!#4#%5#&7%'9'):(*<)+>+-?-/A./C/2E13F23G35H35I0////..-,+*((%$" `q "2 "3 "3 "3 "3!#4!#4#%5#&7%'8'(:(*;)+>+-?-/A./C/2E13F23G35H35I/////..-,+)('%#"   "2 "2 "3 "3 "3!#4!#4#%5#&7%'9'(:(*<*+>+-?-/A./C/2E13F23G35H35IUct////...-,*)(&%#"  JWd "2 "2 "3 "3 "3!#4"#4#%6#%7%'9'):(*<*+>+-?,.A./C/1E13F24G35H35I!%6////...-,*((&$#"! "2 "3 "3 "3 "3!#4"#4#%6#&7%'9'):(*<*+>+-?,.B.0C/1E13F24G35H46J0///...-,+)('%$#!  !$5 "3 "3 "3 "3!#4"$4#%6#%7%'8'):'*<*+>+-?-/B.0C/2E13G24G35H58Ln////...-,+*(&%$#"  ES_#%6 "3 "3 "3 "3"#4"$4#%6#&7%'8'):(*<*,>+-?,.B.0C/1E13G24G35H8;O"%6///...-,++)(&$#""! &*< "3 "3 "3 "3"#4"$5#%6#%7%'8');'*<*+>+-?,.B/1C/2E13G24H24I:>R////...-,+*)(%$#""!  +4;M "3 "3 "3!#3!#5"$5#%6#%7%'8');(+<*+>+-?-/B.0C/2E13G24G35I<@THSe////...-,+*('&$#"!!  ]n}BM` "3 "3!#3!#3!#4"$5#%6#&7%'8');(*<*+>+-?-/B.0C02E13F24G35I>CW 1////...-+*)('%$""!!   Vdu!#3!#3!#3!#3!#5"$5#%6$&7%'9&(:(*;*+>+-@-/B.0C02F13G24H35I@F[z/////..-,+*)(&%$#"!!  ;GVw!#3!#3!#4!#4!#5"$5#&6$&7%'9'):(*=*,?+.@-/B/1C02E23G35G35ICJ]06G////...-,+*)'&%$#"!!  !#4!#4!#4!#4!#5#%5#%6$&7%'9'):)+<*,?+.@-/B/1C02E23G35G35IMTi0////...-,+)('%$##"!  "'3!#4!#4!#4!#4"$5#%5#&7$&7&'9');)+<+,?,.@-/B/1C02F23G35H35IYeyWgy/////..-,+*)(&%$#"""! s"$4"$4"$4"$4"$5#%6#%7%'7&(:'*;)+=+,?,.@./B/1D13F23G35H35Ihw"%7/////..-,+*)(&%$#""!!"ew"$5"$5"$5"$5"$5#%6#&7%'8&(9'*;)+=+-?,.A.0C/1E13F23G35H36Iv/////...-,+*('&$$"""! cwVew#%5"$5"$5#%5#%5$&6$&7%'8')9'*;)+>+-?-/A.0C/1D13F24G35H36I;DV/////...-,+*('%$#""!  P]o#%5#%5#%5#%5#%6#&7%'7&'8&(:(*;*+=+-?-/A.0B02E13F24G35I36I0/////...-,*)('%$#"!! 17FJVh#%6#%6#%6#%6#%6$'7%'7&(9'):)+<*,>+.?-/A/1C02D13F34G35I36I//////..--+*)'&%#""   DOa$&6$&6$&6$&7$&7$&7%'8&(9');)+;+,>+.?-/A/1C/2E13F34G35I36I3:L//////..-,+*)'&$#"!  "&2?I[$&7$&7$&7$&7$&7%'7&(8&(:(*;)+;+-?,.?./A/1C02E13G35G35I46J 1//////..-,+*('%$"!  ;DT$&7%'7$&7%'7%'7%'7&(9'):'*:*+<*,>,.?./A/1C02E23G35H35I46Jw///////..-,+*('%$"! %7>O%'7%'7%'7%'7%'8%'9'(9'):(+;)+<+->,/@./A/1C02E23G35G35I46J,1C///////..-,+)(&%#" ]o~17H%'8%'8%'8%'8%'8&(8')9'):(*;*+=+->-/@-/B/1C02E23G35G36I46J0//////...-,+)(&%#! ,1A%'8%'8%'8%'8&(8&(8'):(*:(*;*,=+.?-/?./B/1C13E13F24G36I46Jas///////...-,+)(&%#! ER`),=%'8%'8&'8&(8&(8&(8'):(*:(*<*,=+.?,.@.0A/1C13E13F24G36I;>R'+<///////..--,+)'&%#! *,<&(8&(8&(8&(8&(8&(9'*:(*:)+<*,=+-?,.@./A/1C02E13F24G35IAG[////////..-,+*)'&$#! $)5(+;&(8&(8&(8&(8&(8&(9'):(*;)+;*,=+->-/@./A/1C02E13F34G35IHOcM[l////////..-,+*)'%$#! (+;&(8&(8&(8&(8&(9')9'):)+;)+;+-=+-?-/@./A/1C02D13E24G35IMXk#'8///////...-,+*('%$#"!(*;&(8&(8&(8&(8&(9')9');)+;)+;+-=+.?-/@.0B/1C02D13F24G35HS^s////////..-,++)('%$#"r'):&(8&(8&(8&(9&(9')9');)+;*+<+-=,.?-/@.0B/1C02D13F24G35H^lCMa///////...-,+*)(&%$#$')9&(8&(8&(8&(9')9')9'*;)+;*,<+->,.?-/@.0B/1C/2C13F24G35Hm"3///////..--++*)'&%$#AM['(9&(8&(8&(8&(9')9'):(*;)+;*,<+->,.?./@.0B/1C02C13F24G35H}///////...-,+*)('%$$#%'8&(8&(8&(8&(9')9'):(*;)+;*,<+->,.?./@.0B/1C02D13F24G35HFRc///////...-++*)'&%$$29H%'8%'8&(8&(8&(9')9'):(*;*+<*,<+->,.?./A.0B/1C/2D13F24G35G!3//////...-,+*)('&%$$%'8%'8&(8&(8&(9')9'*:(*;*,<*,<+->,.?./A.0B/1C02E13F24G35G///////..--,+*)''%%$"'4%'7%'8&'8&(8&(9')9'*:(*;*,<+-=+->,.@./A.0B/1C02E13F24G35GTdv///////..--++)('&%$$o%'7%'7&'8&(8&(9')9(*:(*;*,<+-=+->-/@./A.0B/1C02E13F24G35G"3//////...-,+*)''&%$$|%'7%'7%'8&'8&(9')9(*:)+;*+<+-=+->-/?./A.0A/1C02E13F24G35H///////..--,+*('&%%$Tetp$&7%'7%'7&'8&(9')9(*:)+;*+<+-=+->-/?./A.0B/2C13E13F24G35HRas//////...-,+*)('&%$$ev$&7%'7%'7&'8&(9')9'*:)+;*+<+-=+->-/?./A.0A/2C13E13F24G<@S!%6//////...-,+*)'&&%$+3AXgx$&6$&7%'7%'8&(9')9'*:)+;*+<+-=+-?-/?./A.0A/2C02E13F24GHPb///////..--++*)'&%%$KWi$&6$&7%'7%'7&(8')9'*:)+;*+<+-=+->-/?-/@.0A/2C02D13F24GT_raco///////..-,++)('&%$(AK\#%6$&7%'7%'7&(8')9'*:(*;)+<+-=+->-/?-/@.0A/1C02D13E24Gap')9///////..-,+*)('%%$4;L#%6$&6%'7%'7&(8')9'*:)+;)+;+-=+->-/?-/@.0A/1C02D13E23Go0//////...-,+*)'&%%(39J#%6$&6$&7%'7&(8')9'*:(*;)+;+-=+->-/?-/@./A/1C02C13E23Fpq{///////...-,+*)'&%%Raq16F#%6$&6%'7%'7&(8')9'*:(*;)+;+-=+-=,.?-/?-/A/1B/2C02E13F%'8///////...-,+*)'&%$/4F#%6$&6%'7%'7&(8')9'*:(*;)+;+,=+-=,.?-/?-/@/1B/2C02D13E////////...-,+*)'&%KLV.3D$&6$&7%'7%'7&(8')9'):(*;)+;+,=+-=+.?-/?-/@/1B/1C02D13E////////...-,+*)'&%,2B$&6$&7%'7%'8&(8')9'*:(*;)+;*+=+-=+.?-/?-/@.0B/1C02C13E+-<////////...-,+*)(&()6.1@$&7%'7%'7%'8&(8')9'*:(*;)+;*+=+-=+.>-/?-/?.0A/1B/2C02D0////////...-,+*)('-0@$&7%'7%'8&'8&(9')9'*:(*;)+;*+<+-=+.>,.?-/?./A/1B/2C02D/////////...-,++)()-/>%'7%'7%'8&(8&(9')9'*:(*;)+;)+<+-=+.>,.?-/?./A/1B/1C57IIJX//////////..--,+*)*,<%'7%'8&'8&(8&(9')9'*:(*;)+;)+<+-=+.>,.?-/?-/A/1B/1COP` "2//////////...-,,+)),;%'7%'8&(8&(8&(9')9'*:(*;)+;)+<+-=+.>,.?-/?-/A/1B/1Cklz///////////...--,+DFR(*:%'8%'8&(8&(8&(9')9'*:(*;)+;)+<+-=+.>,.?-/?-/A/1B/1Cno{////////////...-,,%'8%'8%'8&(8&(8&(9')9(*:(*;)+;)+<+-=+.>,.?-/?-/A/1B/1C')9////////////....-13B%'8%'8&(8&(8&(9')9')9'*:(*;)+;)+<+-=+.>,.?-/?-/A/1B/1C0/////////////....%'8&(8&(8&(8&(9')9')9'*:(*;)+;)+=+-=+.>,.?-/?-/@/1B/1C///////////////..%'7&(8&(8&(8&(8&(9')9')9'*:(*;)+;)+=+-=+.>,.?-/?-/A/1B/1CADQ///////////////..&(8&(8&(8&(8&(9')9')9'*:(*;)+;*+=+-=+.>,.?-/?-/A/1B/1C!2////////////////0&(8&(8&(8&(8&(9')9')9(*:(*;)+;*+=+-=+.>-/?-/?-/A/1B/1C/////////////////lmy&(8&(8&(8&(8&(9')9')9(*:(*;)+;*+=+-=+-?,.?-/?-/A/1B/1C\_k/////////////////&(8&(8&(8&(8&(9')9')9(*:(*;)+;)+=+-=+.?-/?-/?-/A/1B14E*,;////////////////;,.?-/?-/A/1B////////////////git&(8&(8&(8&(8&(9')9')9(*:(*;)+;*+<+-=+.?,.?-/?-/A/1B////////////////&(8&(8&(8&(8&(9')9')9(*:(*;)+;)+<+-=+.>,.?-/?-/@.0BPR_///////////////EGU&(8&(8&(8&(8&(9')9')9'*:(*;)+;)+=+-=+->,.?-/?-/@24F////////////////&(8&(8&(8&(8&(9')9')9(*:(*;)+;)+=+-=+->,.?,.?-/@79I////////////////2A&(8&(8&(8&(8&(9')9')9'*:(*;)+;)+<+-=+->,.?,.?-/?;=M///////////////&(8&(8&(8&(8&(9')9')9(*:(*;)+;)+;+-=+->,.>,.?-/?XYggiu//////////////0&(8&(8&(8&(8&(9')9')9(*:(*;)+;)+;*,=+->,.>,.>,.?"$5//////////////&(8&(8&(8&(8&(9')9')9(*:(*;)+;)+;*,<+->,.>,.>,.?///////////////&(8&(8&(8&(8&(9')9')9(*:(*;)+;)+;*,<+->,.>,.>,.?//////////////MN[&(8&(8&(8&(8&(9')9'):(*:(*;)+;)+;*,<*,=+->,.>,.?//////////////&(8&(8&(8&(8&(9')9'):(*:(*;)+;*+;*,<+-=+-=+.>,.>KMZ/////////////&(8&(8&(8&(8&(9&(9')9'):(*:)+;)+;*+<*,<+-=+-=+->/1B!#4/////////////&(8&(8&(8&(9&(9')9'):(*:)+;)+;*+<*,<+-=+-=+-==?P/////////////&(8&(8&(8&(8&(9&(9')9'):(*:)+;)+;*,<*,<+-=+-=+-=JL[/////////////&(8&(8&(8&(9')9')9'*:(*:)+;)+;*,<*,<+-=+-=+-=^an?@O//////////0&(8&(8&(8&(9')9')9(*:(*;)+;)+;*,<*,=+-=+-=+-=ϻ|no96C//////bcp&(8&(8&(9')9')9'):(*:)+;)+;*+<*,<*,=+-=+-=+-=кккк˹@;G!1//&(8&(9&(9')9')9(*:(*:)+;)+;*,<*,<+-=+-=+-=+->кккккккȵȯ&(9&(9')9')9'):(*:)+;)+;*+<*,<*,=+-=+-=+-=+->ккккккккк')9')9')9():(*:(*;)+;)+;*,<*,<+-=+-=+-=+-=+.>ѻккккккккк'):'):(*:(*:(*;)+;)+;*+<*,<*,=+-=+-=+-=+->46Fккккккккк(*:(*:(*:(*;)+;)+;*+<*,<*,<+-=+-=+-=+-=,.>OP^jsкккккккк(*;)+;)+;)+;)+;*+<*,<*,<+-=+-=+-=+-=+->,.>giuŧj֡wעyĩкккккк)+;)+;)+;)+<*,<*,<*,<+-=+-=+-=+-=+->,.>,.>\j֡x֡x֡xopкк͵ͺe`z|02F.0B,.?+->+-=+-=+->+-=+-=+-=+-=+.>,.>,.>x-y1֡x֡x֜ojjjjjójj\^q;=T;=T;=T;=T;=T;=T;=T;=T:=S9;Q79O68M57K35I13FjՐZ֡x֡xՂAjjjjjƹjjij|;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=Tj֡x֡x֡xnjjjjjɽjjsu;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=T;=Tkr&֡x֡x֡xkjjjjjj֗f;=T;=TWRcy}ymuiamYSdIH\;=T;=T;=T;=T=@Wt'Ւ]֡x֡x֟tjjjjjjײسкккккккккккj֡w֡x֡x֑]jjjjjjjיiкккккккккккތLw/֡x֡x֡xmjjjjjjשкккккккккккԷҴj֜o֡x֡x֠vjjjjjjjȼjڰкккккккккϹ- + +jk֡x֡x֡xՈLjjjjjjj²֎WккккккккϹ + + + +ޓXj֙k֡x֡x֞sjjjjjjjj֟sՈL黗ɯh̵ккккккœcd%  +jn֡x֡x֡xr$jjjjjjjjo֠vw,֝rjjjjp q"ojjĵjjY +_Pz/j֙i֡x֡xՐYjjjjjjjjjjj֚kv,jo氅֡wjjjjjjjjjjjj +,ѻju+֡x֡x֡xkjjjjjjjjjjׯՅFq$֪jjjr$֡xljjjjjjjjǹjjj + +q"jנv֡x֡xՄEjjjjjjjjjjjjɾՋRjjjjjä֡xnjjjjjjjjjjj-  +`RjՁ>֡x֡x֡wjjjjjjjjjjjjjj֒\ՃCjjjߔX֡xnjjjjjjjjؽjjjO +" q#j֠v֡x֡x}8jjjjjjjjjjjjjjjj֎U°֍T֡xkjjjjjjjj;֕bjji + +ȢՑ\֡x֡x֟tjjjjjjjjjjjjjjjjjjjlןsפ|֙ijjjjjjjjjjjjj@ + +ש֡x~:jjjjjjjjjjjjjjjjjjjv,֡xjjjjjjjjjjjՂB֕bjji$Q@ʣv,jjjjjjjjjjjjjjjjjj֚kຝ֙jjjjjjjjjjjjjp!j֞rjjjjjjjjjjjjjj׫֡xw.jjjjjjjjjjjjjj8mZ + +`Q֡xjjjjjjjjjjjjjjv-ǹjjjۣພՎVjjjjjjjjjjjjjjj~:Ƹjj쾚{4 +VFإ~s'jjjjjjjjjjjjjjjj|6ljjjϿټ*ؼ֡xjjjjjjjjjjjjjjjjjjlx/jj筀lC! +þ׼סvjjjjjjjjjjjjjjjjjjjj°֨jjjjj!  +! ̷Փ`jjjjjjjjjjjjjjjjjjjjj<ՇJjjjjjg&3 ^jjjk݊IjjjjjjjjjjjՀ?Հ=jjjjjjjjjjjjjjjjjjjjjjjjjjjjm֛mؾؼ֞sՆGx/jjjjjjjՄD׻֖dx0r&p"omlkjjjklkjjjjjjjjjjjjjjjjjjjx1רՌRjt(ػ֑Zljjjjjjjjjjjjjjjj֞s±ױ֗fՀ>p!jp"ՄE֡xؾ!,9Ybl$1W`imu}.9E$1$1}qydluV_hGQ[2=I$1$1$1$1$1(50;F'2?sz$1'2?S\f$1$14?JgoxV_h0;F0;F0;F0;F0;F0;F0;F$1w,7Cks{[dm[dm[dm[dm0;F0;F0;F0;F0;F0;F0;F0;F@JU5@K}:EPz0;F0;F0;F0;F0;F0;F0;F$1%1=0;F0;F0;F0;F0;F0;F0;FW`i^fpgoxowx+7V_h0;FFPZ!,9$1$1$1$1$1$1)4@OXb$1$1$1$1$1$1$1$1$1!,9iqz#/;X`j:DO$1IS]MVa$1u|#/;)4@|:EPlt|.9Ebkt)4@gpx@JU5@K}:EPIR](5$1'2?(5$10;F$1$1$1$1$1$1$1$1$1$1$11.QQ.Ht{t/e{0NtLt>??///......///]]^>??>??>??>??>??>??>??>??>??>??>??>??>??>??>??>??>??>??>??NNONNO|}}|}}|}}|}}|}}|}}|}}|}}|}}|}}|}}|}}|}}...|}}|}}lmm}}~>>>|}}///|}}|}}lmm|}}>>>|}}mnn>>>|}}>>>|}}|}}>>>|}}>??|}}|}}>>>|}}}}~>>>|}}...///>>>|}}|}}>>>|}}NNO]]^|}}>>>|}}...|}}......>>>|}}|}}///...>>>|}}MMNNNO|}}>>>|}}|}}>>>|}}|}}///|}}......>>>|}}>>>mnn|}}>>>|}}|}}|}}>>>|}}lmm>??|}}>>>|}}...}}~|}}lmm|}}>>>|}}|}}|}}|}}>>>|}}MMN|}}}}~}}~}}~}}~}}~}}~}}~}}~}}~}}~}}~}}~}}~}}~>>>...//////...]]^>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>MMN \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/printscreen b/src/applications/sample/wifi-iot/screenshot/rk_weekly/printscreen new file mode 100644 index 0000000..a787321 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_weekly/printscreen differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/process.txt b/src/applications/sample/wifi-iot/screenshot/rk_weekly/process.txt new file mode 100644 index 0000000..0ec2ac6 --- /dev/null +++ b/src/applications/sample/wifi-iot/screenshot/rk_weekly/process.txt @@ -0,0 +1,70 @@ +hdf_devmgr +param_watcher +storage_manager +appspawn +hilogd +samgr +storage_daemon +udevd +uinput_inject +multimodalinput +token_sync_serv +huks_service +memmgrservice +bluetooth_servi +pulseaudio +accessibility +resource_schedu +faceauth +work_scheduler_ +bgtaskmgr_servi +audio_policy +deviceauth_service +softbus_server +wifi_hal_service +deviceinfoservi +faultloggerd +accountmgr +time_service +distributeddata +medialibrary_se +useriam +updater_sa +inputmethod_ser +ui_service +fms_service +distributedfile +distributedfile +netmanager +battery_stats +dslm_service +sensors +media_service +wifi_manager_se +distributedsche +installs +hiview +telephony +usb_service +camera_service +render_service +thermal +foundation +accesstoken_ser +hdcd +disp_gralloc_host +light_dal_host +vibrator_dal_host +sensor_dal_host +input_user_host +camera_host +audio_hdi_server_host +wifi_host +usbfnMaster_host +usb_host +blue_host +wifi_hal_service +com.ohos.systemui +device_usage_st +com.ohos.launcher +power_host \ No newline at end of file diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/settings.png b/src/applications/sample/wifi-iot/screenshot/rk_weekly/settings.png new file mode 100644 index 0000000..ce67da1 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_weekly/settings.png differ diff --git a/src/applications/sample/wifi-iot/screenshot/rk_weekly/settings.pngraw b/src/applications/sample/wifi-iot/screenshot/rk_weekly/settings.pngraw new file mode 100644 index 0000000..987afd3 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/rk_weekly/settings.pngraw differ diff --git a/src/applications/sample/wifi-iot/screenshot/vediotest/ActsVideoPlayerJsTest.hap b/src/applications/sample/wifi-iot/screenshot/vediotest/ActsVideoPlayerJsTest.hap new file mode 100644 index 0000000..aa4914c Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/vediotest/ActsVideoPlayerJsTest.hap differ diff --git a/src/applications/sample/wifi-iot/screenshot/vediotest/H264_AAC.mp4 b/src/applications/sample/wifi-iot/screenshot/vediotest/H264_AAC.mp4 new file mode 100644 index 0000000..301c808 Binary files /dev/null and b/src/applications/sample/wifi-iot/screenshot/vediotest/H264_AAC.mp4 differ diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/BUILD.gn b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/BUILD.gn new file mode 100644 index 0000000..2e9a621 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/BUILD.gn @@ -0,0 +1,205 @@ +# Copyright (C) 2021 Hisilicon (Shanghai) Technologies Co., Ltd. All rights reserved. + +if (defined(ohos_lite)) { + import("//build/lite/config/component/lite_component.gni") +} else { + import("//build/config/clang/clang.gni") + import("//build/ohos.gni") +} +import("//build/ohos/kernel/kernel.gni") + +SDK_LINUX_PATH = "//device/soc/hisilicon/hi3516dv300/sdk_linux" +SDK_LINUX_LIB_LITE_PATH = "$SDK_LINUX_PATH/out/lib" + +group("hispark_taurus_sdk") { + if (defined(ohos_lite)) { + deps = [ + ":sdk_linux_lite_libs", + ":sdk_make", + "//kernel/linux/build:linux_kernel", + #"sample/taurus/ai_sample:hi3516dv300_ai_sample", + "sample/taurus/smart_vendor_ai:smart_vendor_ai", + #"sample/platform/svp/nnie:hi3516dv300_nnie_sample", + ] + } else { + deps = [ + ":sdk_linux_modules", + ":sdk_make", + "out/lib:sdk_linux_mpp_group", + "//kernel/linux/build:linux_kernel", + ] + } +} + +##################################################################### +sdk_modules_name_list = [ + "hi3516cv500_base.ko", + "hi3516cv500_hdmi.ko", + "hi3516cv500_ir.ko", + "hi3516cv500_sys.ko", + "hi3516cv500_tde.ko", + "hi3516cv500_vo_dev.ko", + "hi3516cv500_wdt.ko", + "hi_cipher.ko", + "hifb.ko", + "hi_irq.ko", + "hi_mipi_rx.ko", + "hi_mipi_tx.ko", + "hi_osal.ko", + "hi_proc.ko", + "sys_config.ko", + "load3516dv300_user", +] + +if (defined(ohos_lite)) { + build_ext_component("sdk_make") { + exec_path = rebase_path(".", root_build_dir) + outdir = rebase_path("$root_out_dir") + clang_dir = "" + if (ohos_build_compiler_dir != "") { + clang_dir = rebase_path("$ohos_build_compiler_dir") + } + command = "./build.sh ${ohos_root_path} ${outdir} y ${clang_dir} ${linux_kernel_version}" + deps = [ "//kernel/linux/build:linux_kernel" ] + } + not_needed(sdk_modules_name_list) +} else { + sdk_tmp_root_path = root_out_dir + sdk_tmp_dir = "$sdk_tmp_root_path/sdk_linux/src_tmp" + sdk_tmp_mods_dir = "$sdk_tmp_dir/out/ko" + + action("sdk_make") { + script = "build.sh" + outputs = [] + foreach(module, sdk_modules_name_list) { + outputs += [ "$sdk_tmp_mods_dir/$module" ] + } + args = [ + rebase_path("//"), + rebase_path("$sdk_tmp_root_path"), + "n", + rebase_path("$clang_base_path"), + linux_kernel_version, + ] + deps = [ "//kernel/linux/build:linux_kernel" ] + } + + sdk_modules_file_list = get_target_outputs(":sdk_make") + kernel_modules_targets = [] + + foreach(km, sdk_modules_file_list) { + _name = get_path_info(km, "file") + ohos_prebuilt_shared_library(_name) { + deps = [ ":sdk_make" ] + source = km + module_install_dir = "modules" + install_images = [ + vendor_base_dir, + "updater", + ] + part_name = "hisilicon_products" + } + kernel_modules_targets += [ ":$_name" ] + } + + group("sdk_linux_modules") { + deps = kernel_modules_targets + } +} + +##################################################################### +sdk_libs_name_set = [ + "libVoiceEngine.so", + "lib_hiacs.so", + "lib_hiae.so", + "lib_hiawb.so", + "lib_hiawb_natura.so", + "lib_hicalcflicker.so", + "lib_hidehaze.so", + "lib_hidrc.so", + "lib_hiir_auto.so", + "lib_hildci.so", + "libaaccomm.so", + "libaacdec.so", + "libaacenc.so", + "libaacsbrdec.so", + "libaacsbrenc.so", + "libdnvqe.so", + "libhdmi.so", + "libhi3516cv500_acodec.so", + "libhi3516cv500_adec.so", + "libhi3516cv500_aenc.so", + "libhi3516cv500_ai.so", + "libhi3516cv500_aio.so", + "libhi3516cv500_ao.so", + "libhi3516cv500_base.so", + "libhi3516cv500_chnl.so", + "libhi3516cv500_dis.so", + "libhi3516cv500_gdc.so", + "libhi3516cv500_h264e.so", + "libhi3516cv500_h265e.so", + "libhi3516cv500_isp.so", + "libhi3516cv500_ive.so", + "libhi3516cv500_jpegd.so", + "libhi3516cv500_jpege.so", + "libhi3516cv500_nnie.so", + "libhi3516cv500_rc.so", + "libhi3516cv500_rgn.so", + "libhi3516cv500_sys.so", + "libhi3516cv500_vdec.so", + "libhi3516cv500_vedu.so", + "libhi3516cv500_venc.so", + "libhi3516cv500_vfmw.so", + "libhi3516cv500_vgs.so", + "libhi3516cv500_vi.so", + "libhi3516cv500_vo.so", + "libhi3516cv500_vpss.so", + "libhi_irq.so", + "libhi_osal.so", + "libhi_sensor_i2c.so", + "libhifisheyecalibrate.so", + "libhive_AEC.so", + "libhive_AGC.so", + "libhive_ANR.so", + "libhive_EQ.so", + "libhive_HPF.so", + "libhive_RES.so", + "libhive_RES_ext.so", + "libhive_common.so", + "libhive_record.so", + "libhive_talkv2.so", + "libhive_wnr.so", + "libisp.so", + "libive.so", + "libmd.so", + "libmpi.so", + "libnnie.so", + "libsdk.so", + "libsecurec.so", + "libsns_imx335.so", + "libtde.so", + "libupvqe.so", +] + +if (defined(ohos_lite)) { + lib_lite_abspath = rebase_path("$SDK_LINUX_LIB_LITE_PATH", ".") + sdk_linux_libs_targets = [] + + foreach(lib, sdk_libs_name_set) { + copy("$lib") { + sources = [ "$lib_lite_abspath/$lib" ] + outputs = [ "$root_out_dir/$lib" ] + } + sdk_linux_libs_targets += [ ":$lib" ] + } + + group("sdk_linux_lite_libs") { + deps = sdk_linux_libs_targets + } +} else { + not_needed([ + SDK_LINUX_LIB_LITE_PATH, + SDK_LINUX_PATH, + ]) + not_needed(sdk_libs_name_set) +} diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/BUILD.gn b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/BUILD.gn new file mode 100644 index 0000000..5bf090f --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/BUILD.gn @@ -0,0 +1,170 @@ +# Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. +# Copyright (c) 2022 Sidi Liang. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +#     http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/lite/config/component/lite_component.gni") +lite_component("smart_vendor_ai") { + features = [ ":smart_vendor_main" ] +} + +need_link_mpp_lib = true +if (need_link_mpp_lib) { + mpp_lib_path = "//device/soc/hisilicon/hi3516dv300/sdk_linux/out" +} + + +executable("smart_vendor_main") { + output_name = "smart_vendor_main" + sources = [ + "//device/soc/hisilicon/hi3516dv300/sdk_linux/sample/platform/audio/adp/audio_aac_adp.c", + "//device/soc/hisilicon/hi3516dv300/sdk_linux/sample/platform/audio/adp/audio_dl_adp.c", + "//device/soc/hisilicon/hi3516dv300/sdk_linux/sample/platform/common/sample_comm_audio.c", + "//device/soc/hisilicon/hi3516dv300/sdk_linux/sample/platform/common/sample_comm_isp.c", + "//device/soc/hisilicon/hi3516dv300/sdk_linux/sample/platform/common/sample_comm_sys.c", + "//device/soc/hisilicon/hi3516dv300/sdk_linux/sample/platform/common/sample_comm_vi.c", + "//device/soc/hisilicon/hi3516dv300/sdk_linux/sample/platform/common/sample_comm_vo.c", + "//device/soc/hisilicon/hi3516dv300/sdk_linux/sample/platform/common/sample_comm_vpss.c", + "//device/soc/hisilicon/hi3516dv300/sdk_linux/sample/platform/svp/common/sample_comm_nnie.c", + "//device/soc/hisilicon/hi3516dv300/sdk_linux/sample/platform/svp/common/sample_comm_svp.c", + "//device/soc/hisilicon/hi3516dv300/sdk_linux/sample/platform/svp/nnie/sample_nnie_software/sample_svp_nnie_software.c", + "ai_infer_process/ai_infer_process.c", + "dependency/audio_test.c", + "ext_util/base_interface.c", + "ext_util/misc_util.c", + "ext_util/posix_help.c", + "interconnection_server/hisignalling.c", + "mpp_help/src/ive_img.c", + "mpp_help/src/osd_img.c", + "mpp_help/src/vgs_img.c", + "scenario/hand_classify/hand_classify.c", + "scenario/hand_classify/yolov2_hand_detect.c", + "smp/vendor_main.cpp", + "smp/sample_media_ai.c", + "smp/smart_vendor_classification.c", + "cjson/cJSON.c", + "messaging/messaging.c", + "messaging/json_helper.c", + "messaging/data_store.c", + "third_party/src/iniparser/src/dictionary.c", + "third_party/src/iniparser/src/iniparser.c", + ] + + include_dirs = [ + "//device/soc/hisilicon/hi3516dv300/sdk_linux/include", + "//device/soc/hisilicon/hi3516dv300/sdk_linux/drv/mpp/cbb/include", + "//device/soc/hisilicon/hi3516dv300/sdk_linux/drv/mpp/cbb/init", + "//device/soc/hisilicon/hi3516dv300/sdk_linux/mpp/include", + "ai_infer_process", + "smp", + "cjson", + "messaging", + "//device/soc/hisilicon/hi3516dv300/sdk_linux/sample/platform/common", + "//device/soc/hisilicon/hi3516dv300/sdk_linux/sample/platform/svp/common", + "//device/soc/hisilicon/hi3516dv300/sdk_linux/sample/platform/svp/nnie/sample_nnie_software", + "//device/soc/hisilicon/hi3516dv300/sdk_linux/sample/platform/audio/adp/", + "scenario/hand_classify", + "mpp_help/include", + "ext_util", + "dependency", + "third_party/src/iniparser/src", + "//third_party/bounds_checking_function/include", + "interconnection_server", + ] + + defines = [ + "SENSOR0_TYPE=SONY_IMX335_MIPI_4M_30FPS_12BIT", + "SENSOR1_TYPE=SONY_IMX335_MIPI_4M_30FPS_12BIT", + ] + + if (need_link_mpp_lib) { + outdir = rebase_path("$mpp_lib_path/lib") + ldflags = [ "-L$outdir" ] + ldflags += [ "-laaccomm" ] + ldflags += [ "-laacdec" ] + ldflags += [ "-laacenc" ] + ldflags += [ "-laacsbrdec" ] + ldflags += [ "-laacsbrenc" ] + ldflags += [ "-ldnvqe" ] + ldflags += [ "-lhdmi" ] + ldflags += [ "-lhi3516cv500_acodec" ] + ldflags += [ "-lhi3516cv500_adec" ] + ldflags += [ "-lhi3516cv500_aenc" ] + ldflags += [ "-lhi3516cv500_aio" ] + ldflags += [ "-lhi3516cv500_ai" ] + ldflags += [ "-lhi3516cv500_ao" ] + ldflags += [ "-lhi3516cv500_base" ] + ldflags += [ "-lhi3516cv500_chnl" ] + ldflags += [ "-lhi3516cv500_dis" ] + ldflags += [ "-lhi3516cv500_gdc" ] + ldflags += [ "-lhi3516cv500_h264e" ] + ldflags += [ "-lhi3516cv500_h265e" ] + ldflags += [ "-lhi3516cv500_isp" ] + ldflags += [ "-lhi3516cv500_ive" ] + ldflags += [ "-lhi3516cv500_jpegd" ] + ldflags += [ "-lhi3516cv500_jpege" ] + ldflags += [ "-lhi3516cv500_nnie" ] + ldflags += [ "-lhi3516cv500_rc" ] + ldflags += [ "-lhi3516cv500_rgn" ] + ldflags += [ "-lhi3516cv500_sys" ] + ldflags += [ "-lhi3516cv500_vdec" ] + ldflags += [ "-lhi3516cv500_vedu" ] + ldflags += [ "-lhi3516cv500_venc" ] + ldflags += [ "-lhi3516cv500_vfmw" ] + ldflags += [ "-lhi3516cv500_vgs" ] + ldflags += [ "-lhi3516cv500_vi" ] + ldflags += [ "-lhi3516cv500_vo" ] + ldflags += [ "-lhi3516cv500_vpss" ] + ldflags += [ "-l_hiacs" ] + ldflags += [ "-l_hiae" ] + ldflags += [ "-l_hiawb_natura" ] + ldflags += [ "-l_hiawb" ] + ldflags += [ "-l_hicalcflicker" ] + ldflags += [ "-l_hidehaze" ] + ldflags += [ "-l_hidrc" ] + ldflags += [ "-lhifisheyecalibrate" ] + ldflags += [ "-l_hiir_auto" ] + ldflags += [ "-lhi_irq" ] + ldflags += [ "-l_hildci" ] + ldflags += [ "-lhi_osal" ] + ldflags += [ "-lhi_sensor_i2c" ] + ldflags += [ "-lhive_AEC" ] + ldflags += [ "-lhive_AGC" ] + ldflags += [ "-lhive_ANR" ] + ldflags += [ "-lhive_common" ] + ldflags += [ "-lhive_EQ" ] + ldflags += [ "-lhive_HPF" ] + ldflags += [ "-lhive_record" ] + ldflags += [ "-lhive_RES_ext" ] + ldflags += [ "-lhive_RES" ] + ldflags += [ "-lhive_talkv2" ] + ldflags += [ "-lhive_wnr" ] + ldflags += [ "-lisp" ] + ldflags += [ "-live" ] + ldflags += [ "-lmd" ] + ldflags += [ "-lmpi" ] + ldflags += [ "-lmpp_vbs" ] + ldflags += [ "-lnnie" ] + ldflags += [ "-lsdk" ] + ldflags += [ "-lsecurec" ] + ldflags += [ "-lsns_imx335" ] + ldflags += [ "-ltde" ] + ldflags += [ "-lupvqe" ] + ldflags += [ "-lvb_server" ] + ldflags += [ "-lVoiceEngine" ] + + ldflags += [ "-Wl,-rpath=//userdata/lib" ] + + deps = [] + } +} diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/ai_infer_process/ai_infer_process.c b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/ai_infer_process/ai_infer_process.c new file mode 100644 index 0000000..7dbb157 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/ai_infer_process/ai_infer_process.c @@ -0,0 +1,830 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hi_common.h" +#include "hi_comm_sys.h" +#include "hi_comm_svp.h" +#include "sample_comm_svp.h" +#include "hi_comm_ive.h" +#include "sample_svp_nnie_software.h" +#include "sample_media_ai.h" +#include "ai_infer_process.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* End of #ifdef __cplusplus */ + +#define USLEEP_TIME 100 // 100: usleep time, in microseconds + +#define ARRAY_SUBSCRIPT_0 0 +#define ARRAY_SUBSCRIPT_1 1 +#define ARRAY_SUBSCRIPT_2 2 +#define ARRAY_SUBSCRIPT_3 3 +#define ARRAY_SUBSCRIPT_4 4 +#define ARRAY_SUBSCRIPT_5 5 +#define ARRAY_SUBSCRIPT_6 6 +#define ARRAY_SUBSCRIPT_7 7 +#define ARRAY_SUBSCRIPT_8 8 +#define ARRAY_SUBSCRIPT_9 9 + +#define ARRAY_SUBSCRIPT_OFFSET_1 1 +#define ARRAY_SUBSCRIPT_OFFSET_2 2 +#define ARRAY_SUBSCRIPT_OFFSET_3 3 + +#define THRESH_MIN 0.25 + +/* cnn parameter */ +static SAMPLE_SVP_NNIE_MODEL_S g_stCnnModel = {0}; +static SAMPLE_SVP_NNIE_PARAM_S g_stCnnNnieParam = {0}; +static SAMPLE_SVP_NNIE_CNN_SOFTWARE_PARAM_S g_stCnnSoftwareParam = {0}; + +/* yolov2 parameter */ +static SAMPLE_SVP_NNIE_MODEL_S g_stYolov2Model = {0}; +static SAMPLE_SVP_NNIE_PARAM_S g_stYolov2NnieParam = {0}; +static SAMPLE_SVP_NNIE_YOLOV2_SOFTWARE_PARAM_S g_stYolov2SoftwareParam = {0}; + +/* function : Cnn software parameter init */ +static HI_S32 SampleSvpNnieCnnSoftwareParaInit(SAMPLE_SVP_NNIE_CFG_S* pstNnieCfg, + SAMPLE_SVP_NNIE_PARAM_S *pstCnnPara, SAMPLE_SVP_NNIE_CNN_SOFTWARE_PARAM_S* pstCnnSoftWarePara) +{ + HI_U32 u32GetTopNMemSize; + HI_U32 u32GetTopBufSize; + HI_U32 u32GetTopFrameSize; + HI_U32 u32TotalSize; + HI_U32 u32ClassNum = pstCnnPara->pstModel->astSeg[0].astDstNode[0].unShape.stWhc.u32Width; + HI_U64 u64PhyAddr = 0; + HI_U8* pu8VirAddr = NULL; + HI_S32 s32Ret; + + /* get mem size */ + u32GetTopFrameSize = pstCnnSoftWarePara->u32TopN*sizeof(SAMPLE_SVP_NNIE_CNN_GETTOPN_UNIT_S); + u32GetTopNMemSize = SAMPLE_SVP_NNIE_ALIGN16(u32GetTopFrameSize)*pstNnieCfg->u32MaxInputNum; + u32GetTopBufSize = u32ClassNum*sizeof(SAMPLE_SVP_NNIE_CNN_GETTOPN_UNIT_S); + u32TotalSize = u32GetTopNMemSize + u32GetTopBufSize; + + /* malloc mem */ + s32Ret = SAMPLE_COMM_SVP_MallocMem("SAMPLE_CNN_INIT", NULL, (HI_U64*)&u64PhyAddr, + (void**)&pu8VirAddr, u32TotalSize); + SAMPLE_SVP_CHECK_EXPR_RET(HI_SUCCESS != s32Ret, s32Ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error,Malloc memory failed!\n"); + memset_s(pu8VirAddr, u32TotalSize, 0, u32TotalSize); + + /* init GetTopn */ + pstCnnSoftWarePara->stGetTopN.u32Num = pstNnieCfg->u32MaxInputNum; + pstCnnSoftWarePara->stGetTopN.unShape.stWhc.u32Chn = 1; + pstCnnSoftWarePara->stGetTopN.unShape.stWhc.u32Height = 1; + pstCnnSoftWarePara->stGetTopN.unShape.stWhc.u32Width = u32GetTopFrameSize / sizeof(HI_U32); + pstCnnSoftWarePara->stGetTopN.u32Stride = SAMPLE_SVP_NNIE_ALIGN16(u32GetTopFrameSize); + pstCnnSoftWarePara->stGetTopN.u64PhyAddr = u64PhyAddr; + pstCnnSoftWarePara->stGetTopN.u64VirAddr = (HI_U64)(HI_UL)pu8VirAddr; + + /* init AssistBuf */ + pstCnnSoftWarePara->stAssistBuf.u32Size = u32GetTopBufSize; + pstCnnSoftWarePara->stAssistBuf.u64PhyAddr = u64PhyAddr + u32GetTopNMemSize; + pstCnnSoftWarePara->stAssistBuf.u64VirAddr = (HI_U64)(HI_UL)pu8VirAddr + u32GetTopNMemSize; + + return s32Ret; +} + +/* function : Cnn software deinit */ +static HI_S32 SampleSvpNnieCnnSoftwareDeinit(SAMPLE_SVP_NNIE_CNN_SOFTWARE_PARAM_S* pstCnnSoftWarePara) +{ + HI_S32 s32Ret = HI_SUCCESS; + SAMPLE_SVP_CHECK_EXPR_RET(pstCnnSoftWarePara == NULL, HI_INVALID_VALUE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error, pstCnnSoftWarePara can't be NULL!\n"); + if (pstCnnSoftWarePara->stGetTopN.u64PhyAddr != 0 && pstCnnSoftWarePara->stGetTopN.u64VirAddr != 0) { + SAMPLE_SVP_MMZ_FREE(pstCnnSoftWarePara->stGetTopN.u64PhyAddr, + pstCnnSoftWarePara->stGetTopN.u64VirAddr); + pstCnnSoftWarePara->stGetTopN.u64PhyAddr = 0; + pstCnnSoftWarePara->stGetTopN.u64VirAddr = 0; + } + return s32Ret; +} + +/* function : Cnn Deinit */ +static HI_S32 SampleSvpNnieCnnDeinit(SAMPLE_SVP_NNIE_PARAM_S *pstNnieParam, + SAMPLE_SVP_NNIE_CNN_SOFTWARE_PARAM_S* pstSoftWareParam, SAMPLE_SVP_NNIE_MODEL_S* pstNnieModel) +{ + HI_S32 s32Ret = HI_SUCCESS; + /* hardware para deinit */ + if (pstNnieParam != NULL) { + s32Ret = SAMPLE_COMM_SVP_NNIE_ParamDeinit(pstNnieParam); + SAMPLE_SVP_CHECK_EXPR_TRACE(HI_SUCCESS != s32Ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error,SAMPLE_COMM_SVP_NNIE_ParamDeinit failed!\n"); + } + /* software para deinit */ + if (pstSoftWareParam != NULL) { + s32Ret = SampleSvpNnieCnnSoftwareDeinit(pstSoftWareParam); + SAMPLE_SVP_CHECK_EXPR_TRACE(HI_SUCCESS != s32Ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error,SampleSvpNnieCnnSoftwareDeinit failed!\n"); + } + /* model deinit */ + if (pstNnieModel != NULL) { + s32Ret = SAMPLE_COMM_SVP_NNIE_UnloadModel(pstNnieModel); + SAMPLE_SVP_CHECK_EXPR_TRACE(HI_SUCCESS != s32Ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error,SAMPLE_COMM_SVP_NNIE_UnloadModel failed!\n"); + } + return s32Ret; +} + +/* function : Cnn init */ +static HI_S32 SampleSvpNnieCnnParamInit(SAMPLE_SVP_NNIE_CFG_S* pstNnieCfg, + SAMPLE_SVP_NNIE_PARAM_S *pstCnnPara, SAMPLE_SVP_NNIE_CNN_SOFTWARE_PARAM_S* pstCnnSoftWarePara) +{ + HI_S32 s32Ret; + /* init hardware para */ + s32Ret = SAMPLE_COMM_SVP_NNIE_ParamInit(pstNnieCfg, pstCnnPara); + SAMPLE_SVP_CHECK_EXPR_GOTO(HI_SUCCESS != s32Ret, INIT_FAIL_0, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),SAMPLE_COMM_SVP_NNIE_ParamInit failed!\n", s32Ret); + + /* init software para */ + if (pstCnnSoftWarePara != NULL) { + s32Ret = SampleSvpNnieCnnSoftwareParaInit(pstNnieCfg, pstCnnPara, pstCnnSoftWarePara); + SAMPLE_SVP_CHECK_EXPR_GOTO(HI_SUCCESS != s32Ret, INIT_FAIL_0, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),SampleSvpNnieCnnSoftwareParaInit failed!\n", s32Ret); + } + + return s32Ret; +INIT_FAIL_0: + s32Ret = SampleSvpNnieCnnDeinit(pstCnnPara, pstCnnSoftWarePara, NULL); + SAMPLE_SVP_CHECK_EXPR_RET(HI_SUCCESS != s32Ret, s32Ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),SampleSvpNnieCnnDeinit failed!\n", s32Ret); + return HI_FAILURE; +} + +/* create CNN model based mode file */ +int CnnCreate(SAMPLE_SVP_NNIE_CFG_S **model, const char* modelFile) +{ + SAMPLE_SVP_NNIE_CFG_S *self; + HI_U32 u32PicNum = 1; + HI_S32 s32Ret; + + self = (SAMPLE_SVP_NNIE_CFG_S*)malloc(sizeof(*self)); + HI_ASSERT(self); + if (memset_s(self, sizeof(*self), 0x00, sizeof(*self)) != EOK) { + HI_ASSERT(0); + } + + // Set configuration parameter + self->pszPic = NULL; + self->u32MaxInputNum = u32PicNum; // max input image num in each batch + self->u32MaxRoiNum = 0; + self->aenNnieCoreId[0] = SVP_NNIE_ID_0; // set NNIE core + g_stCnnSoftwareParam.u32TopN = 5; // 5: value of the u32TopN + + // Sys init + // CNN Load model + SAMPLE_SVP_TRACE_INFO("Cnn Load model!\n"); + s32Ret = SAMPLE_COMM_SVP_NNIE_LoadModel((char*)modelFile, &g_stCnnModel); + SAMPLE_SVP_CHECK_EXPR_GOTO(HI_SUCCESS != s32Ret, CNN_FAIL_0, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error,SAMPLE_COMM_SVP_NNIE_LoadModel failed!\n"); + + // CNN parameter initialization + // Cnn software parameters are set in SampleSvpNnieCnnSoftwareParaInit, + // if user has changed net struct, please make sure the parameter settings in + // SampleSvpNnieCnnSoftwareParaInit function are correct + SAMPLE_SVP_TRACE_INFO("Cnn parameter initialization!\n"); + g_stCnnNnieParam.pstModel = &g_stCnnModel.stModel; + s32Ret = SampleSvpNnieCnnParamInit(self, &g_stCnnNnieParam, &g_stCnnSoftwareParam); + SAMPLE_SVP_CHECK_EXPR_GOTO(HI_SUCCESS != s32Ret, CNN_FAIL_0, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error,SampleSvpNnieCnnParamInit failed!\n"); + + // Model key information + SAMPLE_PRT("model={ type=%x, frmNum=%u, chnNum=%u, w=%u, h=%u, stride=%u }\n", + g_stCnnNnieParam.astSegData[0].astSrc[0].enType, + g_stCnnNnieParam.astSegData[0].astSrc[0].u32Num, + g_stCnnNnieParam.astSegData[0].astSrc[0].unShape.stWhc.u32Chn, + g_stCnnNnieParam.astSegData[0].astSrc[0].unShape.stWhc.u32Width, + g_stCnnNnieParam.astSegData[0].astSrc[0].unShape.stWhc.u32Height, + g_stCnnNnieParam.astSegData[0].astSrc[0].u32Stride); + + // record tskBuf + s32Ret = HI_MPI_SVP_NNIE_AddTskBuf(&(g_stCnnNnieParam.astForwardCtrl[0].stTskBuf)); + SAMPLE_SVP_CHECK_EXPR_GOTO(HI_SUCCESS != s32Ret, CNN_FAIL_0, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error,HI_MPI_SVP_NNIE_AddTskBuf failed!\n"); + *model = self; + return 0; + + CNN_FAIL_0: + SampleSvpNnieCnnDeinit(&g_stCnnNnieParam, &g_stCnnSoftwareParam, &g_stCnnModel); + *model = NULL; + return -1; +} + +/* destroy CNN model */ +void CnnDestroy(SAMPLE_SVP_NNIE_CFG_S *self) +{ + HI_S32 s32Ret; + + /* Remove TskBuf */ + s32Ret = HI_MPI_SVP_NNIE_RemoveTskBuf(&(g_stCnnNnieParam.astForwardCtrl[0].stTskBuf)); + SAMPLE_SVP_CHECK_EXPR_GOTO(HI_SUCCESS != s32Ret, CNN_FAIL_0, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error,HI_MPI_SVP_NNIE_RemoveTskBuf failed!\n"); + + CNN_FAIL_0: + SampleSvpNnieCnnDeinit(&g_stCnnNnieParam, &g_stCnnSoftwareParam, &g_stCnnModel); + free(self); +} + +static HI_S32 FillNnieByImg(SAMPLE_SVP_NNIE_CFG_S* pstNnieCfg, + SAMPLE_SVP_NNIE_PARAM_S *pstNnieParam, int segId, int nodeId, const IVE_IMAGE_S *img) +{ + HI_U32 i; + HI_U32 j; + HI_U32 n; + HI_U32 u32Height = 0; + HI_U32 u32Width = 0; + HI_U32 u32Chn = 0; + HI_U32 u32Stride = 0; + HI_U32 u32VarSize; + HI_U8 *pu8PicAddr = NULL; + + /* get data size */ + if (SVP_BLOB_TYPE_U8 <= pstNnieParam->astSegData[segId].astSrc[nodeId].enType && + SVP_BLOB_TYPE_YVU422SP >= pstNnieParam->astSegData[segId].astSrc[nodeId].enType) { + u32VarSize = sizeof(HI_U8); + } else { + u32VarSize = sizeof(HI_U32); + } + + /* fill src data */ + if (SVP_BLOB_TYPE_SEQ_S32 == pstNnieParam->astSegData[segId].astSrc[nodeId].enType) { + HI_ASSERT(0); + } else { + u32Height = pstNnieParam->astSegData[segId].astSrc[nodeId].unShape.stWhc.u32Height; + u32Width = pstNnieParam->astSegData[segId].astSrc[nodeId].unShape.stWhc.u32Width; + u32Chn = pstNnieParam->astSegData[segId].astSrc[nodeId].unShape.stWhc.u32Chn; + u32Stride = pstNnieParam->astSegData[segId].astSrc[nodeId].u32Stride; + pu8PicAddr = SAMPLE_SVP_NNIE_CONVERT_64BIT_ADDR(HI_U8, + pstNnieParam->astSegData[segId].astSrc[nodeId].u64VirAddr); + + if (SVP_BLOB_TYPE_YVU420SP == pstNnieParam->astSegData[segId].astSrc[nodeId].enType) { + HI_ASSERT(pstNnieParam->astSegData[segId].astSrc[nodeId].u32Num == 1); + for (n = 0; n < pstNnieParam->astSegData[segId].astSrc[nodeId].u32Num; n++) { + // Y + const uint8_t *srcData = (const uint8_t*)(uintptr_t)img->au64VirAddr[0]; + HI_ASSERT(srcData); + for (j = 0; j < u32Height; j++) { + if (memcpy_s(pu8PicAddr, u32Width * u32VarSize, srcData, u32Width * u32VarSize) != EOK) { + HI_ASSERT(0); + } + pu8PicAddr += u32Stride; + srcData += img->au32Stride[0]; + } + // UV + srcData = (const uint8_t*)(uintptr_t)img->au64VirAddr[1]; + HI_ASSERT(srcData); + for (j = 0; j < u32Height / 2; j++) { // 2: 1/2Height + if (memcpy_s(pu8PicAddr, u32Width * u32VarSize, srcData, u32Width * u32VarSize) != EOK) { + HI_ASSERT(0); + } + pu8PicAddr += u32Stride; + srcData += img->au32Stride[1]; + } + } + } else if (SVP_BLOB_TYPE_YVU422SP == pstNnieParam->astSegData[segId].astSrc[nodeId].enType) { + HI_ASSERT(0); + } else { + for (n = 0; n < pstNnieParam->astSegData[segId].astSrc[nodeId].u32Num; n++) { + for (i = 0; i < u32Chn; i++) { + const uint8_t *srcData = (const uint8_t*)(uintptr_t)img->au64VirAddr[i]; + HI_ASSERT(srcData); + for (j = 0; j < u32Height; j++) { + if (memcpy_s(pu8PicAddr, u32Width * u32VarSize, srcData, u32Width * u32VarSize) != EOK) { + HI_ASSERT(0); + } + pu8PicAddr += u32Stride; + srcData += img->au32Stride[i]; + } + } + } + } + + SAMPLE_COMM_SVP_FlushCache(pstNnieParam->astSegData[segId].astSrc[nodeId].u64PhyAddr, + SAMPLE_SVP_NNIE_CONVERT_64BIT_ADDR(HI_VOID, pstNnieParam->astSegData[segId].astSrc[nodeId].u64VirAddr), + pstNnieParam->astSegData[segId].astSrc[nodeId].u32Num*u32Chn*u32Height*u32Stride); + } + + return HI_SUCCESS; +} + +void CnnFetchRes(SVP_BLOB_S *pstGetTopN, HI_U32 u32TopN, RecogNumInfo resBuf[], int resSize, int* resLen) +{ + HI_ASSERT(pstGetTopN); + HI_U32 i; + HI_U32 j = 0; + HI_U32 *pu32Tmp = NULL; + HI_U32 u32Stride = pstGetTopN->u32Stride; + if (memset_s(resBuf, resSize * sizeof(resBuf[0]), 0x00, resSize * sizeof(resBuf[0])) != EOK) { + HI_ASSERT(0); + } + + int resId = 0; + pu32Tmp = (HI_U32*)((HI_UL)pstGetTopN->u64VirAddr + j * u32Stride); + for (i = 0; i < u32TopN * 2 && resId < resSize; i += 2, resId++) { // 2: u32TopN*2 + resBuf[resId].num = pu32Tmp[i]; + resBuf[resId].score = pu32Tmp[i + 1]; + } + *resLen = resId; +} + +/* function : NNIE Forward */ +static HI_S32 SAMPLE_SVP_NNIE_Forward(SAMPLE_SVP_NNIE_PARAM_S *pstNnieParam, + SAMPLE_SVP_NNIE_INPUT_DATA_INDEX_S* pstInputDataIdx, + SAMPLE_SVP_NNIE_PROCESS_SEG_INDEX_S* pstProcSegIdx, HI_BOOL bInstant) +{ + HI_S32 s32Ret = HI_SUCCESS; + HI_U32 i; + HI_U32 j; + HI_BOOL bFinish = HI_FALSE; + SVP_NNIE_HANDLE hSvpNnieHandle = 0; + HI_U32 u32TotalStepNum = 0; + + SAMPLE_COMM_SVP_FlushCache(pstNnieParam->astForwardCtrl[pstProcSegIdx->u32SegIdx].stTskBuf.u64PhyAddr, + SAMPLE_SVP_NNIE_CONVERT_64BIT_ADDR(HI_VOID, + pstNnieParam->astForwardCtrl[pstProcSegIdx->u32SegIdx].stTskBuf.u64VirAddr), + pstNnieParam->astForwardCtrl[pstProcSegIdx->u32SegIdx].stTskBuf.u32Size); + + for (i = 0; i < pstNnieParam->astForwardCtrl[pstProcSegIdx->u32SegIdx].u32DstNum; i++) { + if (pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astDst[i].enType == SVP_BLOB_TYPE_SEQ_S32) { + for (j = 0; j < pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astDst[i].u32Num; j++) { + u32TotalStepNum += *(SAMPLE_SVP_NNIE_CONVERT_64BIT_ADDR(HI_U32, + pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astDst[i].unShape.stSeq.u64VirAddrStep) + j); + } + SAMPLE_COMM_SVP_FlushCache(pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astDst[i].u64PhyAddr, + SAMPLE_SVP_NNIE_CONVERT_64BIT_ADDR(HI_VOID, + pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astDst[i].u64VirAddr), + u32TotalStepNum*pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astDst[i].u32Stride); + } else { + SAMPLE_COMM_SVP_FlushCache(pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astDst[i].u64PhyAddr, + SAMPLE_SVP_NNIE_CONVERT_64BIT_ADDR(HI_VOID, + pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astDst[i].u64VirAddr), + pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astDst[i].u32Num* + pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astDst[i].unShape.stWhc.u32Chn* + pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astDst[i].unShape.stWhc.u32Height* + pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astDst[i].u32Stride); + } + } + + /* set input blob according to node name */ + if (pstInputDataIdx->u32SegIdx != pstProcSegIdx->u32SegIdx) { + for (i = 0; i < pstNnieParam->pstModel->astSeg[pstProcSegIdx->u32SegIdx].u16SrcNum; i++) { + for (j = 0; j < pstNnieParam->pstModel->astSeg[pstInputDataIdx->u32SegIdx].u16DstNum; j++) { + if (strncmp(pstNnieParam->pstModel->astSeg[pstInputDataIdx->u32SegIdx].astDstNode[j].szName, + pstNnieParam->pstModel->astSeg[pstProcSegIdx->u32SegIdx].astSrcNode[i].szName, + SVP_NNIE_NODE_NAME_LEN) == 0) { + pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astSrc[i] = + pstNnieParam->astSegData[pstInputDataIdx->u32SegIdx].astDst[j]; + break; + } + } + SAMPLE_SVP_CHECK_EXPR_RET((j == pstNnieParam->pstModel->astSeg[pstInputDataIdx->u32SegIdx].u16DstNum), + HI_FAILURE, SAMPLE_SVP_ERR_LEVEL_ERROR, "Error,can't find %d-th seg's %d-th src blob!\n", + pstProcSegIdx->u32SegIdx, i); + } + } + + /* NNIE_Forward */ + s32Ret = HI_MPI_SVP_NNIE_Forward(&hSvpNnieHandle, + pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astSrc, + pstNnieParam->pstModel, pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astDst, + &pstNnieParam->astForwardCtrl[pstProcSegIdx->u32SegIdx], bInstant); + SAMPLE_SVP_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error,HI_MPI_SVP_NNIE_Forward failed!\n"); + + if (bInstant) { + /* Wait NNIE finish */ + while (HI_ERR_SVP_NNIE_QUERY_TIMEOUT == (s32Ret = + HI_MPI_SVP_NNIE_Query(pstNnieParam->astForwardCtrl[pstProcSegIdx->u32SegIdx].enNnieId, + hSvpNnieHandle, &bFinish, HI_TRUE))) { + usleep(USLEEP_TIME); + SAMPLE_SVP_TRACE(SAMPLE_SVP_ERR_LEVEL_INFO, + "HI_MPI_SVP_NNIE_Query Query timeout!\n"); + } + } + u32TotalStepNum = 0; + + for (i = 0; i < pstNnieParam->astForwardCtrl[pstProcSegIdx->u32SegIdx].u32DstNum; i++) { + if (SVP_BLOB_TYPE_SEQ_S32 == pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astDst[i].enType) { + for (j = 0; j < pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astDst[i].u32Num; j++) { + u32TotalStepNum += *(SAMPLE_SVP_NNIE_CONVERT_64BIT_ADDR(HI_U32, + pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astDst[i].unShape.stSeq.u64VirAddrStep) + j); + } + SAMPLE_COMM_SVP_FlushCache(pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astDst[i].u64PhyAddr, + SAMPLE_SVP_NNIE_CONVERT_64BIT_ADDR(HI_VOID, + pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astDst[i].u64VirAddr), + u32TotalStepNum*pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astDst[i].u32Stride); + } else { + SAMPLE_COMM_SVP_FlushCache(pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astDst[i].u64PhyAddr, + SAMPLE_SVP_NNIE_CONVERT_64BIT_ADDR(HI_VOID, + pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astDst[i].u64VirAddr), + pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astDst[i].u32Num* + pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astDst[i].unShape.stWhc.u32Chn* + pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astDst[i].unShape.stWhc.u32Height* + pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astDst[i].u32Stride); + } + } + + return s32Ret; +} + +/* Calculate a U8C1 image */ +int CnnCalU8c1Img(SAMPLE_SVP_NNIE_CFG_S* self, + const IVE_IMAGE_S *img, RecogNumInfo resBuf[], int resSize, int* resLen) +{ + HI_S32 s32Ret; + SAMPLE_SVP_NNIE_INPUT_DATA_INDEX_S stInputDataIdx = {0}; + SAMPLE_SVP_NNIE_PROCESS_SEG_INDEX_S stProcSegIdx = {0}; + + /* Fill src data */ + self->pszPic = NULL; + stInputDataIdx.u32SegIdx = 0; + stInputDataIdx.u32NodeIdx = 0; + s32Ret = FillNnieByImg(self, &g_stCnnNnieParam, 0, 0, img); + SAMPLE_SVP_CHECK_EXPR_GOTO(HI_SUCCESS != s32Ret, CNN_FAIL_1, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error,SAMPLE_SVP_NNIE_FillSrcData failed!\n"); + + /* NNIE process(process the 0-th segment) */ + stProcSegIdx.u32SegIdx = 0; + s32Ret = SAMPLE_SVP_NNIE_Forward(&g_stCnnNnieParam, &stInputDataIdx, &stProcSegIdx, HI_TRUE); + SAMPLE_SVP_CHECK_EXPR_GOTO(HI_SUCCESS != s32Ret, CNN_FAIL_1, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error,SAMPLE_SVP_NNIE_Forward failed!\n"); + + /* Software process */ + /* if user has changed net struct, please make sure SAMPLE_SVP_NNIE_Cnn_GetTopN + function's input datas are correct */ + s32Ret = SAMPLE_SVP_NNIE_Cnn_GetTopN(&g_stCnnNnieParam, &g_stCnnSoftwareParam); + SAMPLE_SVP_CHECK_EXPR_GOTO(HI_SUCCESS != s32Ret, CNN_FAIL_1, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error,SAMPLE_SVP_NNIE_CnnGetTopN failed!\n"); + + /* Print result */ + CnnFetchRes(&g_stCnnSoftwareParam.stGetTopN, g_stCnnSoftwareParam.u32TopN, resBuf, resSize, resLen); + return 0; + + CNN_FAIL_1: + return -1; +} + +/* function : Yolov2 software para init */ +static HI_S32 SampleSvpNnieYolov2SoftwareInit(SAMPLE_SVP_NNIE_CFG_S* pstCfg, + SAMPLE_SVP_NNIE_PARAM_S *pstNnieParam, SAMPLE_SVP_NNIE_YOLOV2_SOFTWARE_PARAM_S* pstSoftWareParam) +{ + HI_S32 s32Ret; + HI_U32 u32ClassNum = 0; + HI_U32 u32BboxNum; + HI_U32 u32TotalSize = 0; + HI_U32 u32DstRoiSize; + HI_U32 u32DstScoreSize; + HI_U32 u32ClassRoiNumSize; + HI_U32 u32TmpBufTotalSize; + HI_U64 u64PhyAddr = 0; + HI_U8* pu8VirAddr = NULL; + + pstSoftWareParam->u32OriImHeight = pstNnieParam->astSegData[0].astSrc[0].unShape.stWhc.u32Height; + pstSoftWareParam->u32OriImWidth = pstNnieParam->astSegData[0].astSrc[0].unShape.stWhc.u32Width; + pstSoftWareParam->u32BboxNumEachGrid = 5; // 5: 2BboxNumEachGrid + pstSoftWareParam->u32ClassNum = 1; // 5: class number + pstSoftWareParam->u32GridNumHeight = 12; // 12: GridNumHeight + pstSoftWareParam->u32GridNumWidth = 20; // 20: GridNumWidth + pstSoftWareParam->u32NmsThresh = (HI_U32)(0.3f*SAMPLE_SVP_NNIE_QUANT_BASE); + pstSoftWareParam->u32ConfThresh = (HI_U32)(0.25f*SAMPLE_SVP_NNIE_QUANT_BASE); + pstSoftWareParam->u32MaxRoiNum = 10; // 10: MaxRoiNum + pstSoftWareParam->af32Bias[0] = 0.52; // 0.52: af32Bias[0] value + pstSoftWareParam->af32Bias[1] = 0.61; // 0.61: af32Bias[1] value + pstSoftWareParam->af32Bias[ARRAY_SUBSCRIPT_2] = 1.05; // 1.05: af32Bias[ARRAY_SUBSCRIPT_2] value + pstSoftWareParam->af32Bias[ARRAY_SUBSCRIPT_3] = 1.12; // 1.12: af32Bias[ARRAY_SUBSCRIPT_3] value + pstSoftWareParam->af32Bias[ARRAY_SUBSCRIPT_4] = 1.85; // 1.85: af32Bias[ARRAY_SUBSCRIPT_4] value + pstSoftWareParam->af32Bias[ARRAY_SUBSCRIPT_5] = 2.05; // 2.05: af32Bias[ARRAY_SUBSCRIPT_5] value + pstSoftWareParam->af32Bias[ARRAY_SUBSCRIPT_6] = 4.63; // 4.63: af32Bias[ARRAY_SUBSCRIPT_6] value + pstSoftWareParam->af32Bias[ARRAY_SUBSCRIPT_7] = 4.49; // 4.49: af32Bias[ARRAY_SUBSCRIPT_7] value + pstSoftWareParam->af32Bias[ARRAY_SUBSCRIPT_8] = 7.15; // 7.15: af32Bias[ARRAY_SUBSCRIPT_8] value + pstSoftWareParam->af32Bias[ARRAY_SUBSCRIPT_9] = 7.56; // 7.56: af32Bias[ARRAY_SUBSCRIPT_9] value + + /* Malloc assist buffer memory */ + u32ClassNum = pstSoftWareParam->u32ClassNum + 1; + u32BboxNum = pstSoftWareParam->u32BboxNumEachGrid*pstSoftWareParam->u32GridNumHeight* + pstSoftWareParam->u32GridNumWidth; + u32TmpBufTotalSize = SAMPLE_SVP_NNIE_Yolov2_GetResultTmpBuf(pstSoftWareParam); + u32DstRoiSize = SAMPLE_SVP_NNIE_ALIGN16(u32ClassNum * u32BboxNum * sizeof(HI_U32) * SAMPLE_SVP_NNIE_COORDI_NUM); + u32DstScoreSize = SAMPLE_SVP_NNIE_ALIGN16(u32ClassNum * u32BboxNum * sizeof(HI_U32)); + u32ClassRoiNumSize = SAMPLE_SVP_NNIE_ALIGN16(u32ClassNum * sizeof(HI_U32)); + u32TotalSize = u32TotalSize + u32DstRoiSize + u32DstScoreSize + u32ClassRoiNumSize + u32TmpBufTotalSize; + s32Ret = SAMPLE_COMM_SVP_MallocCached("SAMPLE_YOLOV2_INIT", NULL, (HI_U64*)&u64PhyAddr, + (void**)&pu8VirAddr, u32TotalSize); + SAMPLE_SVP_CHECK_EXPR_RET(HI_SUCCESS != s32Ret, s32Ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error,Malloc memory failed!\n"); + memset_s(pu8VirAddr, u32TotalSize, 0, u32TotalSize); + SAMPLE_COMM_SVP_FlushCache(u64PhyAddr, (void*)pu8VirAddr, u32TotalSize); + + /* set each tmp buffer addr */ + pstSoftWareParam->stGetResultTmpBuf.u64PhyAddr = u64PhyAddr; + pstSoftWareParam->stGetResultTmpBuf.u64VirAddr = (HI_U64)((HI_UL)pu8VirAddr); + + /* set result blob */ + pstSoftWareParam->stDstRoi.enType = SVP_BLOB_TYPE_S32; + pstSoftWareParam->stDstRoi.u64PhyAddr = u64PhyAddr + u32TmpBufTotalSize; + pstSoftWareParam->stDstRoi.u64VirAddr = (HI_U64)((HI_UL)pu8VirAddr + u32TmpBufTotalSize); + pstSoftWareParam->stDstRoi.u32Stride = SAMPLE_SVP_NNIE_ALIGN16(u32ClassNum * + u32BboxNum * sizeof(HI_U32) * SAMPLE_SVP_NNIE_COORDI_NUM); + pstSoftWareParam->stDstRoi.u32Num = 1; + pstSoftWareParam->stDstRoi.unShape.stWhc.u32Chn = 1; + pstSoftWareParam->stDstRoi.unShape.stWhc.u32Height = 1; + pstSoftWareParam->stDstRoi.unShape.stWhc.u32Width = u32ClassNum * + u32BboxNum*SAMPLE_SVP_NNIE_COORDI_NUM; + + pstSoftWareParam->stDstScore.enType = SVP_BLOB_TYPE_S32; + pstSoftWareParam->stDstScore.u64PhyAddr = u64PhyAddr + u32TmpBufTotalSize + u32DstRoiSize; + pstSoftWareParam->stDstScore.u64VirAddr = (HI_U64)((HI_UL)pu8VirAddr + u32TmpBufTotalSize + u32DstRoiSize); + pstSoftWareParam->stDstScore.u32Stride = SAMPLE_SVP_NNIE_ALIGN16(u32ClassNum * u32BboxNum * sizeof(HI_U32)); + pstSoftWareParam->stDstScore.u32Num = 1; + pstSoftWareParam->stDstScore.unShape.stWhc.u32Chn = 1; + pstSoftWareParam->stDstScore.unShape.stWhc.u32Height = 1; + pstSoftWareParam->stDstScore.unShape.stWhc.u32Width = u32ClassNum*u32BboxNum; + + pstSoftWareParam->stClassRoiNum.enType = SVP_BLOB_TYPE_S32; + pstSoftWareParam->stClassRoiNum.u64PhyAddr = u64PhyAddr + u32TmpBufTotalSize + + u32DstRoiSize + u32DstScoreSize; + pstSoftWareParam->stClassRoiNum.u64VirAddr = (HI_U64)((HI_UL)pu8VirAddr + u32TmpBufTotalSize + + u32DstRoiSize + u32DstScoreSize); + pstSoftWareParam->stClassRoiNum.u32Stride = SAMPLE_SVP_NNIE_ALIGN16(u32ClassNum*sizeof(HI_U32)); + pstSoftWareParam->stClassRoiNum.u32Num = 1; + pstSoftWareParam->stClassRoiNum.unShape.stWhc.u32Chn = 1; + pstSoftWareParam->stClassRoiNum.unShape.stWhc.u32Height = 1; + pstSoftWareParam->stClassRoiNum.unShape.stWhc.u32Width = u32ClassNum; + + return s32Ret; +} + +/* function : Yolov2 software deinit */ +static HI_S32 SampleSvpNnieYolov2SoftwareDeinit(SAMPLE_SVP_NNIE_YOLOV2_SOFTWARE_PARAM_S* pstSoftWareParam) +{ + HI_S32 s32Ret = HI_SUCCESS; + SAMPLE_SVP_CHECK_EXPR_RET(pstSoftWareParam == NULL, HI_INVALID_VALUE, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error, pstSoftWareParam can't be NULL!\n"); + if (pstSoftWareParam->stGetResultTmpBuf.u64PhyAddr != 0 && pstSoftWareParam->stGetResultTmpBuf.u64VirAddr != 0) { + SAMPLE_SVP_MMZ_FREE(pstSoftWareParam->stGetResultTmpBuf.u64PhyAddr, + pstSoftWareParam->stGetResultTmpBuf.u64VirAddr); + pstSoftWareParam->stGetResultTmpBuf.u64PhyAddr = 0; + pstSoftWareParam->stGetResultTmpBuf.u64VirAddr = 0; + pstSoftWareParam->stDstRoi.u64PhyAddr = 0; + pstSoftWareParam->stDstRoi.u64VirAddr = 0; + pstSoftWareParam->stDstScore.u64PhyAddr = 0; + pstSoftWareParam->stDstScore.u64VirAddr = 0; + pstSoftWareParam->stClassRoiNum.u64PhyAddr = 0; + pstSoftWareParam->stClassRoiNum.u64VirAddr = 0; + } + return s32Ret; +} + +/* function : Yolov2 Deinit */ +static HI_S32 SampleSvpNnieYolov2Deinit(SAMPLE_SVP_NNIE_PARAM_S *pstNnieParam, + SAMPLE_SVP_NNIE_YOLOV2_SOFTWARE_PARAM_S* pstSoftWareParam, SAMPLE_SVP_NNIE_MODEL_S *pstNnieModel) +{ + HI_S32 s32Ret = HI_SUCCESS; + /* hardware deinit */ + if (pstNnieParam != NULL) { + s32Ret = SAMPLE_COMM_SVP_NNIE_ParamDeinit(pstNnieParam); + SAMPLE_SVP_CHECK_EXPR_TRACE(HI_SUCCESS != s32Ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error,SAMPLE_COMM_SVP_NNIE_ParamDeinit failed!\n"); + } + /* software deinit */ + if (pstSoftWareParam != NULL) { + s32Ret = SampleSvpNnieYolov2SoftwareDeinit(pstSoftWareParam); + SAMPLE_SVP_CHECK_EXPR_TRACE(HI_SUCCESS != s32Ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error,SampleSvpNnieYolov2SoftwareDeinit failed!\n"); + } + /* model deinit */ + if (pstNnieModel != NULL) { + s32Ret = SAMPLE_COMM_SVP_NNIE_UnloadModel(pstNnieModel); + SAMPLE_SVP_CHECK_EXPR_TRACE(HI_SUCCESS != s32Ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error,SAMPLE_COMM_SVP_NNIE_UnloadModel failed!\n"); + } + return s32Ret; +} + +/* function : Yolov2 init */ +static HI_S32 SampleSvpNnieYolov2ParamInit(SAMPLE_SVP_NNIE_CFG_S* pstCfg, + SAMPLE_SVP_NNIE_PARAM_S *pstNnieParam, SAMPLE_SVP_NNIE_YOLOV2_SOFTWARE_PARAM_S* pstSoftWareParam) +{ + HI_S32 s32Ret; + /* init hardware para */ + s32Ret = SAMPLE_COMM_SVP_NNIE_ParamInit(pstCfg, pstNnieParam); + SAMPLE_SVP_CHECK_EXPR_GOTO(HI_SUCCESS != s32Ret, INIT_FAIL_0, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),SAMPLE_COMM_SVP_NNIE_ParamInit failed!\n", s32Ret); + + /* init software para */ + s32Ret = SampleSvpNnieYolov2SoftwareInit(pstCfg, pstNnieParam, + pstSoftWareParam); + SAMPLE_SVP_CHECK_EXPR_GOTO(HI_SUCCESS != s32Ret, INIT_FAIL_0, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),SAMPLE_SVP_NNIE_Yolov1_SoftwareInit failed!\n", s32Ret); + return s32Ret; +INIT_FAIL_0: + s32Ret = SampleSvpNnieYolov2Deinit(pstNnieParam, pstSoftWareParam, NULL); + SAMPLE_SVP_CHECK_EXPR_RET(HI_SUCCESS != s32Ret, s32Ret, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error(%#x),SAMPLE_SVP_NNIE_Yolov1_Deinit failed!\n", s32Ret); + return HI_FAILURE; +} + +/* function : creat yolo2 model basad mode file */ +int Yolo2Create(SAMPLE_SVP_NNIE_CFG_S **model, const char* modelFile) +{ + SAMPLE_SVP_NNIE_CFG_S *self; + HI_U32 u32PicNum = 1; + HI_S32 s32Ret; + + self = (SAMPLE_SVP_NNIE_CFG_S*)malloc(sizeof(*self)); + HI_ASSERT(self); + memset_s(self, sizeof(*self), 0x00, sizeof(*self)); + + // Set configuration parameter + self->pszPic = NULL; + self->u32MaxInputNum = u32PicNum; // max input image num in each batch + self->u32MaxRoiNum = 0; + self->aenNnieCoreId[0] = SVP_NNIE_ID_0; // set NNIE core + + // Yolov2 Load model + SAMPLE_SVP_TRACE_INFO("Yolov2 Load model!\n"); + s32Ret = SAMPLE_COMM_SVP_NNIE_LoadModel((char*)modelFile, &g_stYolov2Model); + SAMPLE_SVP_CHECK_EXPR_GOTO(HI_SUCCESS != s32Ret, YOLOV2_FAIL_0, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error, SAMPLE_COMM_SVP_NNIE_LoadModel failed!\n"); + + /* Yolov2 parameter initialization */ + /* Yolov2 software parameters are set in SampleSvpNnieYolov2SoftwareInit, + if user has changed net struct, please make sure the parameter settings in + SampleSvpNnieYolov2SoftwareInit function are correct */ + SAMPLE_SVP_TRACE_INFO("Yolov2 parameter initialization!\n"); + g_stYolov2NnieParam.pstModel = &g_stYolov2Model.stModel; + s32Ret = SampleSvpNnieYolov2ParamInit(self, &g_stYolov2NnieParam, &g_stYolov2SoftwareParam); + SAMPLE_SVP_CHECK_EXPR_GOTO(HI_SUCCESS != s32Ret, YOLOV2_FAIL_0, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error,SampleSvpNnieYolov2ParamInit failed!\n"); + + // model important info + SAMPLE_PRT("model.base={ type=%x, frmNum=%u, chnNum=%u, w=%u, h=%u, stride=%u }\n", + g_stYolov2NnieParam.astSegData[0].astSrc[0].enType, + g_stYolov2NnieParam.astSegData[0].astSrc[0].u32Num, + g_stYolov2NnieParam.astSegData[0].astSrc[0].unShape.stWhc.u32Chn, + g_stYolov2NnieParam.astSegData[0].astSrc[0].unShape.stWhc.u32Width, + g_stYolov2NnieParam.astSegData[0].astSrc[0].unShape.stWhc.u32Height, + g_stYolov2NnieParam.astSegData[0].astSrc[0].u32Stride); + SAMPLE_PRT("model.soft={ class=%u, ori.w=%u, ori.h=%u, bnum=%u, \ + grid.w=%u, grid.h=%u, nmsThresh=%u, confThresh=%u, u32MaxRoiNum=%u }\n", + g_stYolov2SoftwareParam.u32ClassNum, + g_stYolov2SoftwareParam.u32OriImWidth, + g_stYolov2SoftwareParam.u32OriImHeight, + g_stYolov2SoftwareParam.u32BboxNumEachGrid, + g_stYolov2SoftwareParam.u32GridNumWidth, + g_stYolov2SoftwareParam.u32GridNumHeight, + g_stYolov2SoftwareParam.u32NmsThresh, + g_stYolov2SoftwareParam.u32ConfThresh, + g_stYolov2SoftwareParam.u32MaxRoiNum); + + *model = self; + return 0; + + YOLOV2_FAIL_0: + SAMPLE_PRT("Yolo2Create SampleSvpNnieYolov2Deinit\n"); + SampleSvpNnieYolov2Deinit(&g_stYolov2NnieParam, &g_stYolov2SoftwareParam, &g_stYolov2Model); + *model = NULL; + return -1; +} + +/* function : destory yolo2 model */ +void Yolo2Destory(SAMPLE_SVP_NNIE_CFG_S *self) +{ + SampleSvpNnieYolov2Deinit(&g_stYolov2NnieParam, &g_stYolov2SoftwareParam, &g_stYolov2Model); + SAMPLE_COMM_SVP_CheckSysExit(); + free(self); +} + +/* function : fetch result */ +static void Yolo2FetchRes(SVP_BLOB_S *pstDstScore, SVP_BLOB_S *pstDstRoi, SVP_BLOB_S *pstClassRoiNum, + DetectObjInfo resBuf[], int resSize, int* resLen) +{ + HI_U32 i; + HI_U32 j; + HI_U32 u32RoiNumBias = 0; + HI_U32 u32ScoreBias; + HI_U32 u32BboxBias; + HI_FLOAT f32Score; + HI_S32* ps32Score = SAMPLE_SVP_NNIE_CONVERT_64BIT_ADDR(HI_S32, pstDstScore->u64VirAddr); + HI_S32* ps32Roi = SAMPLE_SVP_NNIE_CONVERT_64BIT_ADDR(HI_S32, pstDstRoi->u64VirAddr); + HI_S32* ps32ClassRoiNum = SAMPLE_SVP_NNIE_CONVERT_64BIT_ADDR(HI_S32, pstClassRoiNum->u64VirAddr); + HI_U32 u32ClassNum = pstClassRoiNum->unShape.stWhc.u32Width; + + HI_ASSERT(u32ClassNum == 2); // 2: the number of class + HI_ASSERT(resSize > 0); + int resId = 0; + *resLen = 0; + memset_s(resBuf, resSize * sizeof(resBuf[0]), 0x00, resSize * sizeof(resBuf[0])); + + u32RoiNumBias += ps32ClassRoiNum[0]; + for (i = 1; i < u32ClassNum; i++) { + u32ScoreBias = u32RoiNumBias; + u32BboxBias = u32RoiNumBias * SAMPLE_SVP_NNIE_COORDI_NUM; + /* if the confidence score greater than result threshold, the result will be printed */ + if ((HI_FLOAT)ps32Score[u32ScoreBias] / SAMPLE_SVP_NNIE_QUANT_BASE >= + THRESH_MIN && ps32ClassRoiNum[i] != 0) { + } + for (j = 0; j < (HI_U32)ps32ClassRoiNum[i]; j++) { + f32Score = (HI_FLOAT)ps32Score[u32ScoreBias + j] / SAMPLE_SVP_NNIE_QUANT_BASE; + if (f32Score < THRESH_MIN) { + SAMPLE_PRT("f32Score:%.2f\n", f32Score); + break; + } + if (resId >= resSize) { + SAMPLE_PRT("yolo2 resBuf full\n"); + break; + } + resBuf[resId].cls = 1; // class 1 + resBuf[resId].score = f32Score; + + RectBox *box = &resBuf[resId].box; + box->xmin = ps32Roi[u32BboxBias + j * SAMPLE_SVP_NNIE_COORDI_NUM]; + box->ymin = ps32Roi[u32BboxBias + j * SAMPLE_SVP_NNIE_COORDI_NUM + ARRAY_SUBSCRIPT_OFFSET_1]; + box->xmax = ps32Roi[u32BboxBias + j * SAMPLE_SVP_NNIE_COORDI_NUM + ARRAY_SUBSCRIPT_OFFSET_2]; + box->ymax = ps32Roi[u32BboxBias + j * SAMPLE_SVP_NNIE_COORDI_NUM + ARRAY_SUBSCRIPT_OFFSET_3]; + if (box->xmin >= box->xmax || box->ymin >= box->ymax) { + SAMPLE_PRT("yolo1_orig: {%d, %d, %d, %d}, %f, discard for coord ERR\n", + box->xmin, box->ymin, box->xmax, box->ymax, f32Score); + } else { + resId++; + } + } + u32RoiNumBias += ps32ClassRoiNum[i]; + } + + *resLen = resId; +} + +/* function : calculation yuv image */ +int Yolo2CalImg(SAMPLE_SVP_NNIE_CFG_S* self, + const IVE_IMAGE_S *img, DetectObjInfo resBuf[], int resSize, int* resLen) +{ + SAMPLE_SVP_NNIE_INPUT_DATA_INDEX_S stInputDataIdx = {0}; + SAMPLE_SVP_NNIE_PROCESS_SEG_INDEX_S stProcSegIdx = {0}; + HI_S32 s32Ret; + + // Fill src data + self->pszPic = NULL; + stInputDataIdx.u32SegIdx = 0; + stInputDataIdx.u32NodeIdx = 0; + + s32Ret = FillNnieByImg(self, &g_stYolov2NnieParam, 0, 0, img); + SAMPLE_SVP_CHECK_EXPR_GOTO(HI_SUCCESS != s32Ret, YOLOV2_FAIL_0, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error,SAMPLE_SVP_NNIE_FillSrcData failed!\n"); + + // NNIE process(process the 0-th segment) + stProcSegIdx.u32SegIdx = 0; + s32Ret = SAMPLE_SVP_NNIE_Forward(&g_stYolov2NnieParam, &stInputDataIdx, &stProcSegIdx, HI_TRUE); + SAMPLE_SVP_CHECK_EXPR_GOTO(HI_SUCCESS != s32Ret, YOLOV2_FAIL_0, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error,SAMPLE_SVP_NNIE_Forward failed!\n"); + + /* Software process */ + /* if user has changed net struct, please make sure SAMPLE_SVP_NNIE_Yolov2_GetResult + function input datas are correct */ + s32Ret = SAMPLE_SVP_NNIE_Yolov2_GetResult(&g_stYolov2NnieParam, &g_stYolov2SoftwareParam); + SAMPLE_SVP_CHECK_EXPR_GOTO(HI_SUCCESS != s32Ret, YOLOV2_FAIL_0, SAMPLE_SVP_ERR_LEVEL_ERROR, + "Error,SAMPLE_SVP_NNIE_Yolov2_GetResult failed!\n"); + + Yolo2FetchRes(&g_stYolov2SoftwareParam.stDstScore, + &g_stYolov2SoftwareParam.stDstRoi, &g_stYolov2SoftwareParam.stClassRoiNum, resBuf, resSize, resLen); + return 0; + + YOLOV2_FAIL_0: + return -1; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* End of #ifdef __cplusplus */ diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/ai_infer_process/ai_infer_process.h b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/ai_infer_process/ai_infer_process.h new file mode 100644 index 0000000..85620fc --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/ai_infer_process/ai_infer_process.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AI_INFER_PROCESS_H +#define AI_INFER_PROCESS_H + +#include +#include "sample_comm_nnie.h" + +#if __cplusplus +extern "C" { +#endif + +#define HI_PER_BASE 100 +#define HI_OVEN_BASE 2 // Even base + +/* rect box */ +typedef struct RectBox { + int xmin; + int xmax; + int ymin; + int ymax; +} RectBox; + +/* recognized number information */ +typedef struct RecogNumInfo { + uint32_t num; // Recognized numeric value, 0~9 + uint32_t score; // The credibility score of a number, the value range of which is defined by a specific model +} RecogNumInfo; + +/* plug related information */ +typedef struct AiPlugLib { + int width; + int height; + uintptr_t model; +} AiPlugLib; + +/* Information of detected objects */ +typedef struct DetectObjInfo { + int cls; // The category of the object, an integer> 0 + RectBox box; // The rectangular area of the object (pixels) + float score; // Object's credibility score +} DetectObjInfo; + +void CnnDestroy(SAMPLE_SVP_NNIE_CFG_S *self); +int CnnCreate(SAMPLE_SVP_NNIE_CFG_S **model, const char* modelFile); + +/* Calculate a U8C1 image */ +int CnnCalU8c1Img(SAMPLE_SVP_NNIE_CFG_S* self, + const IVE_IMAGE_S *img, RecogNumInfo resBuf[], int resSize, int* resLen); + +/* creat yolo2 model basad mode file */ +int Yolo2Create(SAMPLE_SVP_NNIE_CFG_S **model, const char* modelFile); + +/* destory yolo2 model */ +void Yolo2Destory(SAMPLE_SVP_NNIE_CFG_S *self); + +/* cal U8C3 image */ +int Yolo2CalImg(SAMPLE_SVP_NNIE_CFG_S* self, + const IVE_IMAGE_S *img, DetectObjInfo resBuf[], int resSize, int* resLen); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/cjson/cJSON.c b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/cjson/cJSON.c new file mode 100644 index 0000000..3063f74 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/cjson/cJSON.c @@ -0,0 +1,3110 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +/* cJSON */ +/* JSON parser in C. */ + +/* disable warnings about old C89 functions in MSVC */ +#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) +#define _CRT_SECURE_NO_DEPRECATE +#endif + +#ifdef __GNUC__ +#pragma GCC visibility push(default) +#endif +#if defined(_MSC_VER) +#pragma warning (push) +/* disable warning about single line comments in system headers */ +#pragma warning (disable : 4001) +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifdef ENABLE_LOCALES +#include +#endif + +#if defined(_MSC_VER) +#pragma warning (pop) +#endif +#ifdef __GNUC__ +#pragma GCC visibility pop +#endif + +#include "cJSON.h" + +/* define our own boolean type */ +#ifdef true +#undef true +#endif +#define true ((cJSON_bool)1) + +#ifdef false +#undef false +#endif +#define false ((cJSON_bool)0) + +/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */ +#ifndef isinf +#define isinf(d) (isnan((d - d)) && !isnan(d)) +#endif +#ifndef isnan +#define isnan(d) (d != d) +#endif + +#ifndef NAN +#ifdef _WIN32 +#define NAN sqrt(-1.0) +#else +#define NAN 0.0/0.0 +#endif +#endif + +typedef struct { + const unsigned char *json; + size_t position; +} error; +static error global_error = { NULL, 0 }; + +CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) +{ + return (const char*) (global_error.json + global_error.position); +} + +CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item) +{ + if (!cJSON_IsString(item)) + { + return NULL; + } + + return item->valuestring; +} + +CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item) +{ + if (!cJSON_IsNumber(item)) + { + return (double) NAN; + } + + return item->valuedouble; +} + +/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ +#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 15) + #error cJSON.h and cJSON.c have different versions. Make sure that both have the same. +#endif + +CJSON_PUBLIC(const char*) cJSON_Version(void) +{ + static char version[15]; + sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); + + return version; +} + +/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */ +static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) +{ + if ((string1 == NULL) || (string2 == NULL)) + { + return 1; + } + + if (string1 == string2) + { + return 0; + } + + for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++) + { + if (*string1 == '\0') + { + return 0; + } + } + + return tolower(*string1) - tolower(*string2); +} + +typedef struct internal_hooks +{ + void *(CJSON_CDECL *allocate)(size_t size); + void (CJSON_CDECL *deallocate)(void *pointer); + void *(CJSON_CDECL *reallocate)(void *pointer, size_t size); +} internal_hooks; + +#if defined(_MSC_VER) +/* work around MSVC error C2322: '...' address of dllimport '...' is not static */ +static void * CJSON_CDECL internal_malloc(size_t size) +{ + return malloc(size); +} +static void CJSON_CDECL internal_free(void *pointer) +{ + free(pointer); +} +static void * CJSON_CDECL internal_realloc(void *pointer, size_t size) +{ + return realloc(pointer, size); +} +#else +#define internal_malloc malloc +#define internal_free free +#define internal_realloc realloc +#endif + +/* strlen of character literals resolved at compile time */ +#define static_strlen(string_literal) (sizeof(string_literal) - sizeof("")) + +static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc }; + +static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks) +{ + size_t length = 0; + unsigned char *copy = NULL; + + if (string == NULL) + { + return NULL; + } + + length = strlen((const char*)string) + sizeof(""); + copy = (unsigned char*)hooks->allocate(length); + if (copy == NULL) + { + return NULL; + } + memcpy(copy, string, length); + + return copy; +} + +CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks) +{ + if (hooks == NULL) + { + /* Reset hooks */ + global_hooks.allocate = malloc; + global_hooks.deallocate = free; + global_hooks.reallocate = realloc; + return; + } + + global_hooks.allocate = malloc; + if (hooks->malloc_fn != NULL) + { + global_hooks.allocate = hooks->malloc_fn; + } + + global_hooks.deallocate = free; + if (hooks->free_fn != NULL) + { + global_hooks.deallocate = hooks->free_fn; + } + + /* use realloc only if both free and malloc are used */ + global_hooks.reallocate = NULL; + if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) + { + global_hooks.reallocate = realloc; + } +} + +/* Internal constructor. */ +static cJSON *cJSON_New_Item(const internal_hooks * const hooks) +{ + cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON)); + if (node) + { + memset(node, '\0', sizeof(cJSON)); + } + + return node; +} + +/* Delete a cJSON structure. */ +CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) +{ + cJSON *next = NULL; + while (item != NULL) + { + next = item->next; + if (!(item->type & cJSON_IsReference) && (item->child != NULL)) + { + cJSON_Delete(item->child); + } + if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) + { + global_hooks.deallocate(item->valuestring); + } + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) + { + global_hooks.deallocate(item->string); + } + global_hooks.deallocate(item); + item = next; + } +} + +/* get the decimal point character of the current locale */ +static unsigned char get_decimal_point(void) +{ +#ifdef ENABLE_LOCALES + struct lconv *lconv = localeconv(); + return (unsigned char) lconv->decimal_point[0]; +#else + return '.'; +#endif +} + +typedef struct +{ + const unsigned char *content; + size_t length; + size_t offset; + size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */ + internal_hooks hooks; +} parse_buffer; + +/* check if the given size is left to read in a given parse buffer (starting with 1) */ +#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length)) +/* check if the buffer can be accessed at the given index (starting with 0) */ +#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length)) +#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index)) +/* get a pointer to the buffer at the position */ +#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) + +/* Parse the input text to generate a number, and populate the result into item. */ +static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer) +{ + double number = 0; + unsigned char *after_end = NULL; + unsigned char number_c_string[64]; + unsigned char decimal_point = get_decimal_point(); + size_t i = 0; + + if ((input_buffer == NULL) || (input_buffer->content == NULL)) + { + return false; + } + + /* copy the number into a temporary buffer and replace '.' with the decimal point + * of the current locale (for strtod) + * This also takes care of '\0' not necessarily being available for marking the end of the input */ + for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) + { + switch (buffer_at_offset(input_buffer)[i]) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '+': + case '-': + case 'e': + case 'E': + number_c_string[i] = buffer_at_offset(input_buffer)[i]; + break; + + case '.': + number_c_string[i] = decimal_point; + break; + + default: + goto loop_end; + } + } +loop_end: + number_c_string[i] = '\0'; + + number = strtod((const char*)number_c_string, (char**)&after_end); + if (number_c_string == after_end) + { + return false; /* parse_error */ + } + + item->valuedouble = number; + + /* use saturation in case of overflow */ + if (number >= INT_MAX) + { + item->valueint = INT_MAX; + } + else if (number <= (double)INT_MIN) + { + item->valueint = INT_MIN; + } + else + { + item->valueint = (int)number; + } + + item->type = cJSON_Number; + + input_buffer->offset += (size_t)(after_end - number_c_string); + return true; +} + +/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */ +CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) +{ + if (number >= INT_MAX) + { + object->valueint = INT_MAX; + } + else if (number <= (double)INT_MIN) + { + object->valueint = INT_MIN; + } + else + { + object->valueint = (int)number; + } + + return object->valuedouble = number; +} + +CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring) +{ + char *copy = NULL; + /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */ + if (!(object->type & cJSON_String) || (object->type & cJSON_IsReference)) + { + return NULL; + } + if (strlen(valuestring) <= strlen(object->valuestring)) + { + strcpy(object->valuestring, valuestring); + return object->valuestring; + } + copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks); + if (copy == NULL) + { + return NULL; + } + if (object->valuestring != NULL) + { + cJSON_free(object->valuestring); + } + object->valuestring = copy; + + return copy; +} + +typedef struct +{ + unsigned char *buffer; + size_t length; + size_t offset; + size_t depth; /* current nesting depth (for formatted printing) */ + cJSON_bool noalloc; + cJSON_bool format; /* is this print a formatted print */ + internal_hooks hooks; +} printbuffer; + +/* realloc printbuffer if necessary to have at least "needed" bytes more */ +static unsigned char* ensure(printbuffer * const p, size_t needed) +{ + unsigned char *newbuffer = NULL; + size_t newsize = 0; + + if ((p == NULL) || (p->buffer == NULL)) + { + return NULL; + } + + if ((p->length > 0) && (p->offset >= p->length)) + { + /* make sure that offset is valid */ + return NULL; + } + + if (needed > INT_MAX) + { + /* sizes bigger than INT_MAX are currently not supported */ + return NULL; + } + + needed += p->offset + 1; + if (needed <= p->length) + { + return p->buffer + p->offset; + } + + if (p->noalloc) { + return NULL; + } + + /* calculate new buffer size */ + if (needed > (INT_MAX / 2)) + { + /* overflow of int, use INT_MAX if possible */ + if (needed <= INT_MAX) + { + newsize = INT_MAX; + } + else + { + return NULL; + } + } + else + { + newsize = needed * 2; + } + + if (p->hooks.reallocate != NULL) + { + /* reallocate with realloc if available */ + newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize); + if (newbuffer == NULL) + { + p->hooks.deallocate(p->buffer); + p->length = 0; + p->buffer = NULL; + + return NULL; + } + } + else + { + /* otherwise reallocate manually */ + newbuffer = (unsigned char*)p->hooks.allocate(newsize); + if (!newbuffer) + { + p->hooks.deallocate(p->buffer); + p->length = 0; + p->buffer = NULL; + + return NULL; + } + + memcpy(newbuffer, p->buffer, p->offset + 1); + p->hooks.deallocate(p->buffer); + } + p->length = newsize; + p->buffer = newbuffer; + + return newbuffer + p->offset; +} + +/* calculate the new length of the string in a printbuffer and update the offset */ +static void update_offset(printbuffer * const buffer) +{ + const unsigned char *buffer_pointer = NULL; + if ((buffer == NULL) || (buffer->buffer == NULL)) + { + return; + } + buffer_pointer = buffer->buffer + buffer->offset; + + buffer->offset += strlen((const char*)buffer_pointer); +} + +/* securely comparison of floating-point variables */ +static cJSON_bool compare_double(double a, double b) +{ + double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b); + return (fabs(a - b) <= maxVal * DBL_EPSILON); +} + +/* Render the number nicely from the given item into a string. */ +static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output_pointer = NULL; + double d = item->valuedouble; + int length = 0; + size_t i = 0; + unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */ + unsigned char decimal_point = get_decimal_point(); + double test = 0.0; + + if (output_buffer == NULL) + { + return false; + } + + /* This checks for NaN and Infinity */ + if (isnan(d) || isinf(d)) + { + length = sprintf((char*)number_buffer, "null"); + } + else + { + /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ + length = sprintf((char*)number_buffer, "%1.15g", d); + + /* Check whether the original double can be recovered */ + if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d)) + { + /* If not, print with 17 decimal places of precision */ + length = sprintf((char*)number_buffer, "%1.17g", d); + } + } + + /* sprintf failed or buffer overrun occurred */ + if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) + { + return false; + } + + /* reserve appropriate space in the output */ + output_pointer = ensure(output_buffer, (size_t)length + sizeof("")); + if (output_pointer == NULL) + { + return false; + } + + /* copy the printed number to the output and replace locale + * dependent decimal point with '.' */ + for (i = 0; i < ((size_t)length); i++) + { + if (number_buffer[i] == decimal_point) + { + output_pointer[i] = '.'; + continue; + } + + output_pointer[i] = number_buffer[i]; + } + output_pointer[i] = '\0'; + + output_buffer->offset += (size_t)length; + + return true; +} + +/* parse 4 digit hexadecimal number */ +static unsigned parse_hex4(const unsigned char * const input) +{ + unsigned int h = 0; + size_t i = 0; + + for (i = 0; i < 4; i++) + { + /* parse digit */ + if ((input[i] >= '0') && (input[i] <= '9')) + { + h += (unsigned int) input[i] - '0'; + } + else if ((input[i] >= 'A') && (input[i] <= 'F')) + { + h += (unsigned int) 10 + input[i] - 'A'; + } + else if ((input[i] >= 'a') && (input[i] <= 'f')) + { + h += (unsigned int) 10 + input[i] - 'a'; + } + else /* invalid */ + { + return 0; + } + + if (i < 3) + { + /* shift left to make place for the next nibble */ + h = h << 4; + } + } + + return h; +} + +/* converts a UTF-16 literal to UTF-8 + * A literal can be one or two sequences of the form \uXXXX */ +static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer) +{ + long unsigned int codepoint = 0; + unsigned int first_code = 0; + const unsigned char *first_sequence = input_pointer; + unsigned char utf8_length = 0; + unsigned char utf8_position = 0; + unsigned char sequence_length = 0; + unsigned char first_byte_mark = 0; + + if ((input_end - first_sequence) < 6) + { + /* input ends unexpectedly */ + goto fail; + } + + /* get the first utf16 sequence */ + first_code = parse_hex4(first_sequence + 2); + + /* check that the code is valid */ + if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) + { + goto fail; + } + + /* UTF16 surrogate pair */ + if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) + { + const unsigned char *second_sequence = first_sequence + 6; + unsigned int second_code = 0; + sequence_length = 12; /* \uXXXX\uXXXX */ + + if ((input_end - second_sequence) < 6) + { + /* input ends unexpectedly */ + goto fail; + } + + if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) + { + /* missing second half of the surrogate pair */ + goto fail; + } + + /* get the second utf16 sequence */ + second_code = parse_hex4(second_sequence + 2); + /* check that the code is valid */ + if ((second_code < 0xDC00) || (second_code > 0xDFFF)) + { + /* invalid second half of the surrogate pair */ + goto fail; + } + + + /* calculate the unicode codepoint from the surrogate pair */ + codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF)); + } + else + { + sequence_length = 6; /* \uXXXX */ + codepoint = first_code; + } + + /* encode as UTF-8 + * takes at maximum 4 bytes to encode: + * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ + if (codepoint < 0x80) + { + /* normal ascii, encoding 0xxxxxxx */ + utf8_length = 1; + } + else if (codepoint < 0x800) + { + /* two bytes, encoding 110xxxxx 10xxxxxx */ + utf8_length = 2; + first_byte_mark = 0xC0; /* 11000000 */ + } + else if (codepoint < 0x10000) + { + /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */ + utf8_length = 3; + first_byte_mark = 0xE0; /* 11100000 */ + } + else if (codepoint <= 0x10FFFF) + { + /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */ + utf8_length = 4; + first_byte_mark = 0xF0; /* 11110000 */ + } + else + { + /* invalid unicode codepoint */ + goto fail; + } + + /* encode as utf8 */ + for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) + { + /* 10xxxxxx */ + (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF); + codepoint >>= 6; + } + /* encode first byte */ + if (utf8_length > 1) + { + (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF); + } + else + { + (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F); + } + + *output_pointer += utf8_length; + + return sequence_length; + +fail: + return 0; +} + +/* Parse the input text into an unescaped cinput, and populate item. */ +static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer) +{ + const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1; + const unsigned char *input_end = buffer_at_offset(input_buffer) + 1; + unsigned char *output_pointer = NULL; + unsigned char *output = NULL; + + /* not a string */ + if (buffer_at_offset(input_buffer)[0] != '\"') + { + goto fail; + } + + { + /* calculate approximate size of the output (overestimate) */ + size_t allocation_length = 0; + size_t skipped_bytes = 0; + while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) + { + /* is escape sequence */ + if (input_end[0] == '\\') + { + if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) + { + /* prevent buffer overflow when last input character is a backslash */ + goto fail; + } + skipped_bytes++; + input_end++; + } + input_end++; + } + if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) + { + goto fail; /* string ended unexpectedly */ + } + + /* This is at most how much we need for the output */ + allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes; + output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof("")); + if (output == NULL) + { + goto fail; /* allocation failure */ + } + } + + output_pointer = output; + /* loop through the string literal */ + while (input_pointer < input_end) + { + if (*input_pointer != '\\') + { + *output_pointer++ = *input_pointer++; + } + /* escape sequence */ + else + { + unsigned char sequence_length = 2; + if ((input_end - input_pointer) < 1) + { + goto fail; + } + + switch (input_pointer[1]) + { + case 'b': + *output_pointer++ = '\b'; + break; + case 'f': + *output_pointer++ = '\f'; + break; + case 'n': + *output_pointer++ = '\n'; + break; + case 'r': + *output_pointer++ = '\r'; + break; + case 't': + *output_pointer++ = '\t'; + break; + case '\"': + case '\\': + case '/': + *output_pointer++ = input_pointer[1]; + break; + + /* UTF-16 literal */ + case 'u': + sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer); + if (sequence_length == 0) + { + /* failed to convert UTF16-literal to UTF-8 */ + goto fail; + } + break; + + default: + goto fail; + } + input_pointer += sequence_length; + } + } + + /* zero terminate the output */ + *output_pointer = '\0'; + + item->type = cJSON_String; + item->valuestring = (char*)output; + + input_buffer->offset = (size_t) (input_end - input_buffer->content); + input_buffer->offset++; + + return true; + +fail: + if (output != NULL) + { + input_buffer->hooks.deallocate(output); + } + + if (input_pointer != NULL) + { + input_buffer->offset = (size_t)(input_pointer - input_buffer->content); + } + + return false; +} + +/* Render the cstring provided to an escaped version that can be printed. */ +static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer) +{ + const unsigned char *input_pointer = NULL; + unsigned char *output = NULL; + unsigned char *output_pointer = NULL; + size_t output_length = 0; + /* numbers of additional characters needed for escaping */ + size_t escape_characters = 0; + + if (output_buffer == NULL) + { + return false; + } + + /* empty string */ + if (input == NULL) + { + output = ensure(output_buffer, sizeof("\"\"")); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "\"\""); + + return true; + } + + /* set "flag" to 1 if something needs to be escaped */ + for (input_pointer = input; *input_pointer; input_pointer++) + { + switch (*input_pointer) + { + case '\"': + case '\\': + case '\b': + case '\f': + case '\n': + case '\r': + case '\t': + /* one character escape sequence */ + escape_characters++; + break; + default: + if (*input_pointer < 32) + { + /* UTF-16 escape sequence uXXXX */ + escape_characters += 5; + } + break; + } + } + output_length = (size_t)(input_pointer - input) + escape_characters; + + output = ensure(output_buffer, output_length + sizeof("\"\"")); + if (output == NULL) + { + return false; + } + + /* no characters have to be escaped */ + if (escape_characters == 0) + { + output[0] = '\"'; + memcpy(output + 1, input, output_length); + output[output_length + 1] = '\"'; + output[output_length + 2] = '\0'; + + return true; + } + + output[0] = '\"'; + output_pointer = output + 1; + /* copy the string */ + for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) + { + if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) + { + /* normal character, copy */ + *output_pointer = *input_pointer; + } + else + { + /* character needs to be escaped */ + *output_pointer++ = '\\'; + switch (*input_pointer) + { + case '\\': + *output_pointer = '\\'; + break; + case '\"': + *output_pointer = '\"'; + break; + case '\b': + *output_pointer = 'b'; + break; + case '\f': + *output_pointer = 'f'; + break; + case '\n': + *output_pointer = 'n'; + break; + case '\r': + *output_pointer = 'r'; + break; + case '\t': + *output_pointer = 't'; + break; + default: + /* escape and print as unicode codepoint */ + sprintf((char*)output_pointer, "u%04x", *input_pointer); + output_pointer += 4; + break; + } + } + } + output[output_length + 1] = '\"'; + output[output_length + 2] = '\0'; + + return true; +} + +/* Invoke print_string_ptr (which is useful) on an item. */ +static cJSON_bool print_string(const cJSON * const item, printbuffer * const p) +{ + return print_string_ptr((unsigned char*)item->valuestring, p); +} + +/* Predeclare these prototypes. */ +static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer); +static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer); +static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer); +static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer); +static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer); +static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer); + +/* Utility to jump whitespace and cr/lf */ +static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer) +{ + if ((buffer == NULL) || (buffer->content == NULL)) + { + return NULL; + } + + if (cannot_access_at_index(buffer, 0)) + { + return buffer; + } + + while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) + { + buffer->offset++; + } + + if (buffer->offset == buffer->length) + { + buffer->offset--; + } + + return buffer; +} + +/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */ +static parse_buffer *skip_utf8_bom(parse_buffer * const buffer) +{ + if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) + { + return NULL; + } + + if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) + { + buffer->offset += 3; + } + + return buffer; +} + +CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) +{ + size_t buffer_length; + + if (NULL == value) + { + return NULL; + } + + /* Adding null character size due to require_null_terminated. */ + buffer_length = strlen(value) + sizeof(""); + + return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated); +} + +/* Parse an object - create a new root, and populate. */ +CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated) +{ + parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; + cJSON *item = NULL; + + /* reset error position */ + global_error.json = NULL; + global_error.position = 0; + + if (value == NULL || 0 == buffer_length) + { + goto fail; + } + + buffer.content = (const unsigned char*)value; + buffer.length = buffer_length; + buffer.offset = 0; + buffer.hooks = global_hooks; + + item = cJSON_New_Item(&global_hooks); + if (item == NULL) /* memory fail */ + { + goto fail; + } + + if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)))) + { + /* parse failure. ep is set. */ + goto fail; + } + + /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ + if (require_null_terminated) + { + buffer_skip_whitespace(&buffer); + if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') + { + goto fail; + } + } + if (return_parse_end) + { + *return_parse_end = (const char*)buffer_at_offset(&buffer); + } + + return item; + +fail: + if (item != NULL) + { + cJSON_Delete(item); + } + + if (value != NULL) + { + error local_error; + local_error.json = (const unsigned char*)value; + local_error.position = 0; + + if (buffer.offset < buffer.length) + { + local_error.position = buffer.offset; + } + else if (buffer.length > 0) + { + local_error.position = buffer.length - 1; + } + + if (return_parse_end != NULL) + { + *return_parse_end = (const char*)local_error.json + local_error.position; + } + + global_error = local_error; + } + + return NULL; +} + +/* Default options for cJSON_Parse */ +CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value) +{ + return cJSON_ParseWithOpts(value, 0, 0); +} + +CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length) +{ + return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0); +} + +#define cjson_min(a, b) (((a) < (b)) ? (a) : (b)) + +static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks) +{ + static const size_t default_buffer_size = 256; + printbuffer buffer[1]; + unsigned char *printed = NULL; + + memset(buffer, 0, sizeof(buffer)); + + /* create buffer */ + buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size); + buffer->length = default_buffer_size; + buffer->format = format; + buffer->hooks = *hooks; + if (buffer->buffer == NULL) + { + goto fail; + } + + /* print the value */ + if (!print_value(item, buffer)) + { + goto fail; + } + update_offset(buffer); + + /* check if reallocate is available */ + if (hooks->reallocate != NULL) + { + printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1); + if (printed == NULL) { + goto fail; + } + buffer->buffer = NULL; + } + else /* otherwise copy the JSON over to a new buffer */ + { + printed = (unsigned char*) hooks->allocate(buffer->offset + 1); + if (printed == NULL) + { + goto fail; + } + memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1)); + printed[buffer->offset] = '\0'; /* just to be sure */ + + /* free the buffer */ + hooks->deallocate(buffer->buffer); + } + + return printed; + +fail: + if (buffer->buffer != NULL) + { + hooks->deallocate(buffer->buffer); + } + + if (printed != NULL) + { + hooks->deallocate(printed); + } + + return NULL; +} + +/* Render a cJSON item/entity/structure to text. */ +CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item) +{ + return (char*)print(item, true, &global_hooks); +} + +CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item) +{ + return (char*)print(item, false, &global_hooks); +} + +CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) +{ + printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; + + if (prebuffer < 0) + { + return NULL; + } + + p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer); + if (!p.buffer) + { + return NULL; + } + + p.length = (size_t)prebuffer; + p.offset = 0; + p.noalloc = false; + p.format = fmt; + p.hooks = global_hooks; + + if (!print_value(item, &p)) + { + global_hooks.deallocate(p.buffer); + return NULL; + } + + return (char*)p.buffer; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format) +{ + printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; + + if ((length < 0) || (buffer == NULL)) + { + return false; + } + + p.buffer = (unsigned char*)buffer; + p.length = (size_t)length; + p.offset = 0; + p.noalloc = true; + p.format = format; + p.hooks = global_hooks; + + return print_value(item, &p); +} + +/* Parser core - when encountering text, process appropriately. */ +static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer) +{ + if ((input_buffer == NULL) || (input_buffer->content == NULL)) + { + return false; /* no input */ + } + + /* parse the different types of values */ + /* null */ + if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0)) + { + item->type = cJSON_NULL; + input_buffer->offset += 4; + return true; + } + /* false */ + if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0)) + { + item->type = cJSON_False; + input_buffer->offset += 5; + return true; + } + /* true */ + if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0)) + { + item->type = cJSON_True; + item->valueint = 1; + input_buffer->offset += 4; + return true; + } + /* string */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) + { + return parse_string(item, input_buffer); + } + /* number */ + if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) + { + return parse_number(item, input_buffer); + } + /* array */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) + { + return parse_array(item, input_buffer); + } + /* object */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) + { + return parse_object(item, input_buffer); + } + + return false; +} + +/* Render a value to text. */ +static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output = NULL; + + if ((item == NULL) || (output_buffer == NULL)) + { + return false; + } + + switch ((item->type) & 0xFF) + { + case cJSON_NULL: + output = ensure(output_buffer, 5); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "null"); + return true; + + case cJSON_False: + output = ensure(output_buffer, 6); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "false"); + return true; + + case cJSON_True: + output = ensure(output_buffer, 5); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "true"); + return true; + + case cJSON_Number: + return print_number(item, output_buffer); + + case cJSON_Raw: + { + size_t raw_length = 0; + if (item->valuestring == NULL) + { + return false; + } + + raw_length = strlen(item->valuestring) + sizeof(""); + output = ensure(output_buffer, raw_length); + if (output == NULL) + { + return false; + } + memcpy(output, item->valuestring, raw_length); + return true; + } + + case cJSON_String: + return print_string(item, output_buffer); + + case cJSON_Array: + return print_array(item, output_buffer); + + case cJSON_Object: + return print_object(item, output_buffer); + + default: + return false; + } +} + +/* Build an array from input text. */ +static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer) +{ + cJSON *head = NULL; /* head of the linked list */ + cJSON *current_item = NULL; + + if (input_buffer->depth >= CJSON_NESTING_LIMIT) + { + return false; /* to deeply nested */ + } + input_buffer->depth++; + + if (buffer_at_offset(input_buffer)[0] != '[') + { + /* not an array */ + goto fail; + } + + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) + { + /* empty array */ + goto success; + } + + /* check if we skipped to the end of the buffer */ + if (cannot_access_at_index(input_buffer, 0)) + { + input_buffer->offset--; + goto fail; + } + + /* step back to character in front of the first element */ + input_buffer->offset--; + /* loop through the comma separated array elements */ + do + { + /* allocate next item */ + cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); + if (new_item == NULL) + { + goto fail; /* allocation failure */ + } + + /* attach next item to list */ + if (head == NULL) + { + /* start the linked list */ + current_item = head = new_item; + } + else + { + /* add to the end and advance */ + current_item->next = new_item; + new_item->prev = current_item; + current_item = new_item; + } + + /* parse next value */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_value(current_item, input_buffer)) + { + goto fail; /* failed to parse value */ + } + buffer_skip_whitespace(input_buffer); + } + while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + + if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') + { + goto fail; /* expected end of array */ + } + +success: + input_buffer->depth--; + + if (head != NULL) { + head->prev = current_item; + } + + item->type = cJSON_Array; + item->child = head; + + input_buffer->offset++; + + return true; + +fail: + if (head != NULL) + { + cJSON_Delete(head); + } + + return false; +} + +/* Render an array to text */ +static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output_pointer = NULL; + size_t length = 0; + cJSON *current_element = item->child; + + if (output_buffer == NULL) + { + return false; + } + + /* Compose the output array. */ + /* opening square bracket */ + output_pointer = ensure(output_buffer, 1); + if (output_pointer == NULL) + { + return false; + } + + *output_pointer = '['; + output_buffer->offset++; + output_buffer->depth++; + + while (current_element != NULL) + { + if (!print_value(current_element, output_buffer)) + { + return false; + } + update_offset(output_buffer); + if (current_element->next) + { + length = (size_t) (output_buffer->format ? 2 : 1); + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) + { + return false; + } + *output_pointer++ = ','; + if(output_buffer->format) + { + *output_pointer++ = ' '; + } + *output_pointer = '\0'; + output_buffer->offset += length; + } + current_element = current_element->next; + } + + output_pointer = ensure(output_buffer, 2); + if (output_pointer == NULL) + { + return false; + } + *output_pointer++ = ']'; + *output_pointer = '\0'; + output_buffer->depth--; + + return true; +} + +/* Build an object from the text. */ +static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer) +{ + cJSON *head = NULL; /* linked list head */ + cJSON *current_item = NULL; + + if (input_buffer->depth >= CJSON_NESTING_LIMIT) + { + return false; /* to deeply nested */ + } + input_buffer->depth++; + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) + { + goto fail; /* not an object */ + } + + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) + { + goto success; /* empty object */ + } + + /* check if we skipped to the end of the buffer */ + if (cannot_access_at_index(input_buffer, 0)) + { + input_buffer->offset--; + goto fail; + } + + /* step back to character in front of the first element */ + input_buffer->offset--; + /* loop through the comma separated array elements */ + do + { + /* allocate next item */ + cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); + if (new_item == NULL) + { + goto fail; /* allocation failure */ + } + + /* attach next item to list */ + if (head == NULL) + { + /* start the linked list */ + current_item = head = new_item; + } + else + { + /* add to the end and advance */ + current_item->next = new_item; + new_item->prev = current_item; + current_item = new_item; + } + + /* parse the name of the child */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_string(current_item, input_buffer)) + { + goto fail; /* failed to parse name */ + } + buffer_skip_whitespace(input_buffer); + + /* swap valuestring and string, because we parsed the name */ + current_item->string = current_item->valuestring; + current_item->valuestring = NULL; + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) + { + goto fail; /* invalid object */ + } + + /* parse the value */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_value(current_item, input_buffer)) + { + goto fail; /* failed to parse value */ + } + buffer_skip_whitespace(input_buffer); + } + while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) + { + goto fail; /* expected end of object */ + } + +success: + input_buffer->depth--; + + if (head != NULL) { + head->prev = current_item; + } + + item->type = cJSON_Object; + item->child = head; + + input_buffer->offset++; + return true; + +fail: + if (head != NULL) + { + cJSON_Delete(head); + } + + return false; +} + +/* Render an object to text. */ +static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output_pointer = NULL; + size_t length = 0; + cJSON *current_item = item->child; + + if (output_buffer == NULL) + { + return false; + } + + /* Compose the output: */ + length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */ + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) + { + return false; + } + + *output_pointer++ = '{'; + output_buffer->depth++; + if (output_buffer->format) + { + *output_pointer++ = '\n'; + } + output_buffer->offset += length; + + while (current_item) + { + if (output_buffer->format) + { + size_t i; + output_pointer = ensure(output_buffer, output_buffer->depth); + if (output_pointer == NULL) + { + return false; + } + for (i = 0; i < output_buffer->depth; i++) + { + *output_pointer++ = '\t'; + } + output_buffer->offset += output_buffer->depth; + } + + /* print key */ + if (!print_string_ptr((unsigned char*)current_item->string, output_buffer)) + { + return false; + } + update_offset(output_buffer); + + length = (size_t) (output_buffer->format ? 2 : 1); + output_pointer = ensure(output_buffer, length); + if (output_pointer == NULL) + { + return false; + } + *output_pointer++ = ':'; + if (output_buffer->format) + { + *output_pointer++ = '\t'; + } + output_buffer->offset += length; + + /* print value */ + if (!print_value(current_item, output_buffer)) + { + return false; + } + update_offset(output_buffer); + + /* print comma if not last */ + length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0)); + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) + { + return false; + } + if (current_item->next) + { + *output_pointer++ = ','; + } + + if (output_buffer->format) + { + *output_pointer++ = '\n'; + } + *output_pointer = '\0'; + output_buffer->offset += length; + + current_item = current_item->next; + } + + output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2); + if (output_pointer == NULL) + { + return false; + } + if (output_buffer->format) + { + size_t i; + for (i = 0; i < (output_buffer->depth - 1); i++) + { + *output_pointer++ = '\t'; + } + } + *output_pointer++ = '}'; + *output_pointer = '\0'; + output_buffer->depth--; + + return true; +} + +/* Get Array size/item / object item. */ +CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) +{ + cJSON *child = NULL; + size_t size = 0; + + if (array == NULL) + { + return 0; + } + + child = array->child; + + while(child != NULL) + { + size++; + child = child->next; + } + + /* FIXME: Can overflow here. Cannot be fixed without breaking the API */ + + return (int)size; +} + +static cJSON* get_array_item(const cJSON *array, size_t index) +{ + cJSON *current_child = NULL; + + if (array == NULL) + { + return NULL; + } + + current_child = array->child; + while ((current_child != NULL) && (index > 0)) + { + index--; + current_child = current_child->next; + } + + return current_child; +} + +CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index) +{ + if (index < 0) + { + return NULL; + } + + return get_array_item(array, (size_t)index); +} + +static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive) +{ + cJSON *current_element = NULL; + + if ((object == NULL) || (name == NULL)) + { + return NULL; + } + + current_element = object->child; + if (case_sensitive) + { + while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0)) + { + current_element = current_element->next; + } + } + else + { + while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0)) + { + current_element = current_element->next; + } + } + + if ((current_element == NULL) || (current_element->string == NULL)) { + return NULL; + } + + return current_element; +} + +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string) +{ + return get_object_item(object, string, false); +} + +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string) +{ + return get_object_item(object, string, true); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string) +{ + return cJSON_GetObjectItem(object, string) ? 1 : 0; +} + +/* Utility for array list handling. */ +static void suffix_object(cJSON *prev, cJSON *item) +{ + prev->next = item; + item->prev = prev; +} + +/* Utility for handling references. */ +static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks) +{ + cJSON *reference = NULL; + if (item == NULL) + { + return NULL; + } + + reference = cJSON_New_Item(hooks); + if (reference == NULL) + { + return NULL; + } + + memcpy(reference, item, sizeof(cJSON)); + reference->string = NULL; + reference->type |= cJSON_IsReference; + reference->next = reference->prev = NULL; + return reference; +} + +static cJSON_bool add_item_to_array(cJSON *array, cJSON *item) +{ + cJSON *child = NULL; + + if ((item == NULL) || (array == NULL) || (array == item)) + { + return false; + } + + child = array->child; + /* + * To find the last item in array quickly, we use prev in array + */ + if (child == NULL) + { + /* list is empty, start new one */ + array->child = item; + item->prev = item; + item->next = NULL; + } + else + { + /* append to the end */ + if (child->prev) + { + suffix_object(child->prev, item); + array->child->prev = item; + } + } + + return true; +} + +/* Add item to array/object. */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item) +{ + return add_item_to_array(array, item); +} + +#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) + #pragma GCC diagnostic push +#endif +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif +/* helper function to cast away const */ +static void* cast_away_const(const void* string) +{ + return (void*)string; +} +#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) + #pragma GCC diagnostic pop +#endif + + +static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key) +{ + char *new_key = NULL; + int new_type = cJSON_Invalid; + + if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item)) + { + return false; + } + + if (constant_key) + { + new_key = (char*)cast_away_const(string); + new_type = item->type | cJSON_StringIsConst; + } + else + { + new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks); + if (new_key == NULL) + { + return false; + } + + new_type = item->type & ~cJSON_StringIsConst; + } + + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) + { + hooks->deallocate(item->string); + } + + item->string = new_key; + item->type = new_type; + + return add_item_to_array(object, item); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) +{ + return add_item_to_object(object, string, item, &global_hooks, false); +} + +/* Add an item to an object with constant string as key */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) +{ + return add_item_to_object(object, string, item, &global_hooks, true); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) +{ + if (array == NULL) + { + return false; + } + + return add_item_to_array(array, create_reference(item, &global_hooks)); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) +{ + if ((object == NULL) || (string == NULL)) + { + return false; + } + + return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false); +} + +CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name) +{ + cJSON *null = cJSON_CreateNull(); + if (add_item_to_object(object, name, null, &global_hooks, false)) + { + return null; + } + + cJSON_Delete(null); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name) +{ + cJSON *true_item = cJSON_CreateTrue(); + if (add_item_to_object(object, name, true_item, &global_hooks, false)) + { + return true_item; + } + + cJSON_Delete(true_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name) +{ + cJSON *false_item = cJSON_CreateFalse(); + if (add_item_to_object(object, name, false_item, &global_hooks, false)) + { + return false_item; + } + + cJSON_Delete(false_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean) +{ + cJSON *bool_item = cJSON_CreateBool(boolean); + if (add_item_to_object(object, name, bool_item, &global_hooks, false)) + { + return bool_item; + } + + cJSON_Delete(bool_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number) +{ + cJSON *number_item = cJSON_CreateNumber(number); + if (add_item_to_object(object, name, number_item, &global_hooks, false)) + { + return number_item; + } + + cJSON_Delete(number_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string) +{ + cJSON *string_item = cJSON_CreateString(string); + if (add_item_to_object(object, name, string_item, &global_hooks, false)) + { + return string_item; + } + + cJSON_Delete(string_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw) +{ + cJSON *raw_item = cJSON_CreateRaw(raw); + if (add_item_to_object(object, name, raw_item, &global_hooks, false)) + { + return raw_item; + } + + cJSON_Delete(raw_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name) +{ + cJSON *object_item = cJSON_CreateObject(); + if (add_item_to_object(object, name, object_item, &global_hooks, false)) + { + return object_item; + } + + cJSON_Delete(object_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name) +{ + cJSON *array = cJSON_CreateArray(); + if (add_item_to_object(object, name, array, &global_hooks, false)) + { + return array; + } + + cJSON_Delete(array); + return NULL; +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item) +{ + if ((parent == NULL) || (item == NULL)) + { + return NULL; + } + + if (item != parent->child) + { + /* not the first element */ + item->prev->next = item->next; + } + if (item->next != NULL) + { + /* not the last element */ + item->next->prev = item->prev; + } + + if (item == parent->child) + { + /* first element */ + parent->child = item->next; + } + else if (item->next == NULL) + { + /* last element */ + parent->child->prev = item->prev; + } + + /* make sure the detached item doesn't point anywhere anymore */ + item->prev = NULL; + item->next = NULL; + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which) +{ + if (which < 0) + { + return NULL; + } + + return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which)); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which) +{ + cJSON_Delete(cJSON_DetachItemFromArray(array, which)); +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string) +{ + cJSON *to_detach = cJSON_GetObjectItem(object, string); + + return cJSON_DetachItemViaPointer(object, to_detach); +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string) +{ + cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string); + + return cJSON_DetachItemViaPointer(object, to_detach); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string) +{ + cJSON_Delete(cJSON_DetachItemFromObject(object, string)); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string) +{ + cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string)); +} + +/* Replace array/object items with new ones. */ +CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) +{ + cJSON *after_inserted = NULL; + + if (which < 0) + { + return false; + } + + after_inserted = get_array_item(array, (size_t)which); + if (after_inserted == NULL) + { + return add_item_to_array(array, newitem); + } + + newitem->next = after_inserted; + newitem->prev = after_inserted->prev; + after_inserted->prev = newitem; + if (after_inserted == array->child) + { + array->child = newitem; + } + else + { + newitem->prev->next = newitem; + } + return true; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement) +{ + if ((parent == NULL) || (replacement == NULL) || (item == NULL)) + { + return false; + } + + if (replacement == item) + { + return true; + } + + replacement->next = item->next; + replacement->prev = item->prev; + + if (replacement->next != NULL) + { + replacement->next->prev = replacement; + } + if (parent->child == item) + { + if (parent->child->prev == parent->child) + { + replacement->prev = replacement; + } + parent->child = replacement; + } + else + { /* + * To find the last item in array quickly, we use prev in array. + * We can't modify the last item's next pointer where this item was the parent's child + */ + if (replacement->prev != NULL) + { + replacement->prev->next = replacement; + } + if (replacement->next == NULL) + { + parent->child->prev = replacement; + } + } + + item->next = NULL; + item->prev = NULL; + cJSON_Delete(item); + + return true; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) +{ + if (which < 0) + { + return false; + } + + return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem); +} + +static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive) +{ + if ((replacement == NULL) || (string == NULL)) + { + return false; + } + + /* replace the name in the replacement */ + if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) + { + cJSON_free(replacement->string); + } + replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); + replacement->type &= ~cJSON_StringIsConst; + + return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) +{ + return replace_item_in_object(object, string, newitem, false); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem) +{ + return replace_item_in_object(object, string, newitem, true); +} + +/* Create basic types: */ +CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_NULL; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_True; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_False; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = boolean ? cJSON_True : cJSON_False; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_Number; + item->valuedouble = num; + + /* use saturation in case of overflow */ + if (num >= INT_MAX) + { + item->valueint = INT_MAX; + } + else if (num <= (double)INT_MIN) + { + item->valueint = INT_MIN; + } + else + { + item->valueint = (int)num; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_String; + item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); + if(!item->valuestring) + { + cJSON_Delete(item); + return NULL; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) + { + item->type = cJSON_String | cJSON_IsReference; + item->valuestring = (char*)cast_away_const(string); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) { + item->type = cJSON_Object | cJSON_IsReference; + item->child = (cJSON*)cast_away_const(child); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) { + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) { + item->type = cJSON_Array | cJSON_IsReference; + item->child = (cJSON*)cast_away_const(child); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_Raw; + item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks); + if(!item->valuestring) + { + cJSON_Delete(item); + return NULL; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type=cJSON_Array; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) + { + item->type = cJSON_Object; + } + + return item; +} + +/* Create Arrays: */ +CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for(i = 0; a && (i < (size_t)count); i++) + { + n = cJSON_CreateNumber(numbers[i]); + if (!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p, n); + } + p = n; + } + + if (a && a->child) { + a->child->prev = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for(i = 0; a && (i < (size_t)count); i++) + { + n = cJSON_CreateNumber((double)numbers[i]); + if(!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p, n); + } + p = n; + } + + if (a && a->child) { + a->child->prev = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for(i = 0; a && (i < (size_t)count); i++) + { + n = cJSON_CreateNumber(numbers[i]); + if(!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p, n); + } + p = n; + } + + if (a && a->child) { + a->child->prev = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (strings == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for (i = 0; a && (i < (size_t)count); i++) + { + n = cJSON_CreateString(strings[i]); + if(!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p,n); + } + p = n; + } + + if (a && a->child) { + a->child->prev = n; + } + + return a; +} + +/* Duplication */ +CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) +{ + cJSON *newitem = NULL; + cJSON *child = NULL; + cJSON *next = NULL; + cJSON *newchild = NULL; + + /* Bail on bad ptr */ + if (!item) + { + goto fail; + } + /* Create new item */ + newitem = cJSON_New_Item(&global_hooks); + if (!newitem) + { + goto fail; + } + /* Copy over all vars */ + newitem->type = item->type & (~cJSON_IsReference); + newitem->valueint = item->valueint; + newitem->valuedouble = item->valuedouble; + if (item->valuestring) + { + newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks); + if (!newitem->valuestring) + { + goto fail; + } + } + if (item->string) + { + newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks); + if (!newitem->string) + { + goto fail; + } + } + /* If non-recursive, then we're done! */ + if (!recurse) + { + return newitem; + } + /* Walk the ->next chain for the child. */ + child = item->child; + while (child != NULL) + { + newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */ + if (!newchild) + { + goto fail; + } + if (next != NULL) + { + /* If newitem->child already set, then crosswire ->prev and ->next and move on */ + next->next = newchild; + newchild->prev = next; + next = newchild; + } + else + { + /* Set newitem->child and move to it */ + newitem->child = newchild; + next = newchild; + } + child = child->next; + } + if (newitem && newitem->child) + { + newitem->child->prev = newchild; + } + + return newitem; + +fail: + if (newitem != NULL) + { + cJSON_Delete(newitem); + } + + return NULL; +} + +static void skip_oneline_comment(char **input) +{ + *input += static_strlen("//"); + + for (; (*input)[0] != '\0'; ++(*input)) + { + if ((*input)[0] == '\n') { + *input += static_strlen("\n"); + return; + } + } +} + +static void skip_multiline_comment(char **input) +{ + *input += static_strlen("/*"); + + for (; (*input)[0] != '\0'; ++(*input)) + { + if (((*input)[0] == '*') && ((*input)[1] == '/')) + { + *input += static_strlen("*/"); + return; + } + } +} + +static void minify_string(char **input, char **output) { + (*output)[0] = (*input)[0]; + *input += static_strlen("\""); + *output += static_strlen("\""); + + + for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) { + (*output)[0] = (*input)[0]; + + if ((*input)[0] == '\"') { + (*output)[0] = '\"'; + *input += static_strlen("\""); + *output += static_strlen("\""); + return; + } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) { + (*output)[1] = (*input)[1]; + *input += static_strlen("\""); + *output += static_strlen("\""); + } + } +} + +CJSON_PUBLIC(void) cJSON_Minify(char *json) +{ + char *into = json; + + if (json == NULL) + { + return; + } + + while (json[0] != '\0') + { + switch (json[0]) + { + case ' ': + case '\t': + case '\r': + case '\n': + json++; + break; + + case '/': + if (json[1] == '/') + { + skip_oneline_comment(&json); + } + else if (json[1] == '*') + { + skip_multiline_comment(&json); + } else { + json++; + } + break; + + case '\"': + minify_string(&json, (char**)&into); + break; + + default: + into[0] = json[0]; + json++; + into++; + } + } + + /* and null-terminate. */ + *into = '\0'; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Invalid; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_False; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xff) == cJSON_True; +} + + +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & (cJSON_True | cJSON_False)) != 0; +} +CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_NULL; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Number; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_String; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Array; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Object; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Raw; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive) +{ + if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) + { + return false; + } + + /* check if type is valid */ + switch (a->type & 0xFF) + { + case cJSON_False: + case cJSON_True: + case cJSON_NULL: + case cJSON_Number: + case cJSON_String: + case cJSON_Raw: + case cJSON_Array: + case cJSON_Object: + break; + + default: + return false; + } + + /* identical objects are equal */ + if (a == b) + { + return true; + } + + switch (a->type & 0xFF) + { + /* in these cases and equal type is enough */ + case cJSON_False: + case cJSON_True: + case cJSON_NULL: + return true; + + case cJSON_Number: + if (compare_double(a->valuedouble, b->valuedouble)) + { + return true; + } + return false; + + case cJSON_String: + case cJSON_Raw: + if ((a->valuestring == NULL) || (b->valuestring == NULL)) + { + return false; + } + if (strcmp(a->valuestring, b->valuestring) == 0) + { + return true; + } + + return false; + + case cJSON_Array: + { + cJSON *a_element = a->child; + cJSON *b_element = b->child; + + for (; (a_element != NULL) && (b_element != NULL);) + { + if (!cJSON_Compare(a_element, b_element, case_sensitive)) + { + return false; + } + + a_element = a_element->next; + b_element = b_element->next; + } + + /* one of the arrays is longer than the other */ + if (a_element != b_element) { + return false; + } + + return true; + } + + case cJSON_Object: + { + cJSON *a_element = NULL; + cJSON *b_element = NULL; + cJSON_ArrayForEach(a_element, a) + { + /* TODO This has O(n^2) runtime, which is horrible! */ + b_element = get_object_item(b, a_element->string, case_sensitive); + if (b_element == NULL) + { + return false; + } + + if (!cJSON_Compare(a_element, b_element, case_sensitive)) + { + return false; + } + } + + /* doing this twice, once on a and b to prevent true comparison if a subset of b + * TODO: Do this the proper way, this is just a fix for now */ + cJSON_ArrayForEach(b_element, b) + { + a_element = get_object_item(a, b_element->string, case_sensitive); + if (a_element == NULL) + { + return false; + } + + if (!cJSON_Compare(b_element, a_element, case_sensitive)) + { + return false; + } + } + + return true; + } + + default: + return false; + } +} + +CJSON_PUBLIC(void *) cJSON_malloc(size_t size) +{ + return global_hooks.allocate(size); +} + +CJSON_PUBLIC(void) cJSON_free(void *object) +{ + global_hooks.deallocate(object); +} diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/cjson/cJSON.h b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/cjson/cJSON.h new file mode 100644 index 0000000..92907a2 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/cjson/cJSON.h @@ -0,0 +1,293 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#ifndef cJSON__h +#define cJSON__h + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)) +#define __WINDOWS__ +#endif + +#ifdef __WINDOWS__ + +/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options: + +CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols +CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default) +CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol + +For *nix builds that support visibility attribute, you can define similar behavior by + +setting default visibility to hidden by adding +-fvisibility=hidden (for gcc) +or +-xldscope=hidden (for sun cc) +to CFLAGS + +then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does + +*/ + +#define CJSON_CDECL __cdecl +#define CJSON_STDCALL __stdcall + +/* export symbols by default, this is necessary for copy pasting the C and header file */ +#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS) +#define CJSON_EXPORT_SYMBOLS +#endif + +#if defined(CJSON_HIDE_SYMBOLS) +#define CJSON_PUBLIC(type) type CJSON_STDCALL +#elif defined(CJSON_EXPORT_SYMBOLS) +#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL +#elif defined(CJSON_IMPORT_SYMBOLS) +#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL +#endif +#else /* !__WINDOWS__ */ +#define CJSON_CDECL +#define CJSON_STDCALL + +#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY) +#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type +#else +#define CJSON_PUBLIC(type) type +#endif +#endif + +/* project version */ +#define CJSON_VERSION_MAJOR 1 +#define CJSON_VERSION_MINOR 7 +#define CJSON_VERSION_PATCH 15 + +#include + +/* cJSON Types: */ +#define cJSON_Invalid (0) +#define cJSON_False (1 << 0) +#define cJSON_True (1 << 1) +#define cJSON_NULL (1 << 2) +#define cJSON_Number (1 << 3) +#define cJSON_String (1 << 4) +#define cJSON_Array (1 << 5) +#define cJSON_Object (1 << 6) +#define cJSON_Raw (1 << 7) /* raw json */ + +#define cJSON_IsReference 256 +#define cJSON_StringIsConst 512 + +/* The cJSON structure: */ +typedef struct cJSON +{ + /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ + struct cJSON *next; + struct cJSON *prev; + /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ + struct cJSON *child; + + /* The type of the item, as above. */ + int type; + + /* The item's string, if type==cJSON_String and type == cJSON_Raw */ + char *valuestring; + /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */ + int valueint; + /* The item's number, if type==cJSON_Number */ + double valuedouble; + + /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ + char *string; +} cJSON; + +typedef struct cJSON_Hooks +{ + /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */ + void *(CJSON_CDECL *malloc_fn)(size_t sz); + void (CJSON_CDECL *free_fn)(void *ptr); +} cJSON_Hooks; + +typedef int cJSON_bool; + +/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them. + * This is to prevent stack overflows. */ +#ifndef CJSON_NESTING_LIMIT +#define CJSON_NESTING_LIMIT 1000 +#endif + +/* returns the version of cJSON as a string */ +CJSON_PUBLIC(const char*) cJSON_Version(void); + +/* Supply malloc, realloc and free functions to cJSON */ +CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks); + +/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */ +/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */ +CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); +CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length); +/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ +/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */ +CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated); +CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated); + +/* Render a cJSON entity to text for transfer/storage. */ +CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item); +/* Render a cJSON entity to text for transfer/storage without any formatting. */ +CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item); +/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ +CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt); +/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */ +/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */ +CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format); +/* Delete a cJSON entity and all subentities. */ +CJSON_PUBLIC(void) cJSON_Delete(cJSON *item); + +/* Returns the number of items in an array (or object). */ +CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array); +/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */ +CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index); +/* Get item "string" from object. Case insensitive. */ +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string); +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string); +CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string); +/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ +CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void); + +/* Check item type and return its value */ +CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item); +CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item); + +/* These functions check the type of an item */ +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item); + +/* These calls create a cJSON item of the appropriate type. */ +CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean); +CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num); +CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string); +/* raw json */ +CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw); +CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); + +/* Create a string where valuestring references a string so + * it will not be freed by cJSON_Delete */ +CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string); +/* Create an object/array that only references it's elements so + * they will not be freed by cJSON_Delete */ +CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child); +CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child); + +/* These utilities create an Array of count items. + * The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/ +CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count); + +/* Append item to the specified array/object. */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item); +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); +/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object. + * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before + * writing to `item->string` */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item); +/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); + +/* Remove/Detach items from Arrays/Objects. */ +CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which); +CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string); +CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string); +CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string); + +/* Update array items. */ +CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */ +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement); +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem); + +/* Duplicate a cJSON item */ +CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse); +/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will + * need to be released. With recurse!=0, it will duplicate any children connected to the item. + * The item->next and ->prev pointers are always zero on return from Duplicate. */ +/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal. + * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */ +CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive); + +/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings. + * The input pointer json cannot point to a read-only address area, such as a string constant, + * but should point to a readable and writable address area. */ +CJSON_PUBLIC(void) cJSON_Minify(char *json); + +/* Helper functions for creating and adding items to an object at the same time. + * They return the added item or NULL on failure. */ +CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean); +CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number); +CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string); +CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw); +CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name); + +/* When assigning an integer value, it needs to be propagated to valuedouble too. */ +#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number)) +/* helper for the cJSON_SetNumberValue macro */ +CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number); +#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number)) +/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */ +CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring); + +/* Macro for iterating over an array or object */ +#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next) + +/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */ +CJSON_PUBLIC(void *) cJSON_malloc(size_t size); +CJSON_PUBLIC(void) cJSON_free(void *object); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/dependency/audio_test.c b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/dependency/audio_test.c new file mode 100644 index 0000000..630fd5a --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/dependency/audio_test.c @@ -0,0 +1,458 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hi_resampler_api.h" +#include "sample_comm.h" +#include "acodec.h" +#include "audio_aac_adp.h" +#include "audio_dl_adp.h" +#include "audio_mp3_adp.h" +#include "sample_comm_ive.h" +#include "sample_media_ai.h" + +static PAYLOAD_TYPE_E gs_enPayloadType = PT_AAC; +static HI_BOOL gs_bAioReSample = HI_FALSE; +static HI_BOOL gs_bUserGetMode = HI_FALSE; +static HI_BOOL gs_bAoVolumeCtrl = HI_FALSE; +static AUDIO_SAMPLE_RATE_E g_in_sample_rate = AUDIO_SAMPLE_RATE_BUTT; +static AUDIO_SAMPLE_RATE_E g_out_sample_rate = AUDIO_SAMPLE_RATE_BUTT; +/* 0: close, 1: record, 2:reserved, 3:talkv2 */ +static HI_U32 g_ai_vqe_type = 1; +static HI_BOOL g_sample_audio_exit = HI_FALSE; + +static AI_RECORDVQE_CONFIG_S g_ai_record_vqe_attr; +static AI_TALKVQEV2_CONFIG_S g_ai_talkv2_vqe_attr; + +static int audio_wait_quit(int quitFd) +{ + eventfd_t eval; + int ret = eventfd_read(quitFd, &eval); + assert(ret == 0); + + return 0; +} + +/* function : PT Number to String */ +static char *SAMPLE_AUDIO_Pt2Str(PAYLOAD_TYPE_E enType) +{ + if (enType == PT_G711A) { + return "g711a"; + } else if (enType == PT_G711U) { + return "g711u"; + } else if (enType == PT_ADPCMA) { + return "adpcm"; + } else if (enType == PT_G726) { + return "g726"; + } else if (enType == PT_LPCM) { + return "pcm"; + } else if (enType == PT_AAC) { + return "aac"; + } else if (enType == PT_MP3) { + return "mp3"; + } else { + return "data"; + } +} + +/* function : Add dynamic load path */ +#ifndef HI_VQE_USE_STATIC_MODULE_REGISTER +static HI_VOID SAMPLE_AUDIO_AddLibPath(HI_VOID) +{ + HI_S32 s32Ret; + HI_CHAR aszLibPath[FILE_NAME_LEN] = {0}; +#if defined(__HuaweiLite__) && (!defined(__OHOS__)) + s32Ret = snprintf_s(aszLibPath, FILE_NAME_LEN, FILE_NAME_LEN - 1, "/sharefs/"); + if (s32Ret <= EOK) { + SAMPLE_PRT("\n snprintf_s fail! ret = 0x%x", s32Ret); + return; + } +#else +#endif + s32Ret = Audio_Dlpath(aszLibPath); + if (s32Ret != HI_SUCCESS) { + SAMPLE_PRT("%s: add lib path %s failed\n", __FUNCTION__, aszLibPath); + } + return; +} +#endif + +/* function : Open Adec File */ +static FILE* SAMPLE_AUDIO_OpenAdecFile_AAC(int num, ADEC_CHN AdChn, PAYLOAD_TYPE_E enType) +{ + FILE* pfd; + HI_CHAR aszFileName[FILE_NAME_LEN] = {0}; + + /* create file for save stream */ +#ifdef __HuaweiLite__ + if (snprintf_s(aszFileName, FILE_NAME_LEN, FILE_NAME_LEN - 1, "/sharefs/audio_chn%d.%s", + AdChn, SAMPLE_AUDIO_Pt2Str(enType)) < 0) { + HI_ASSERT(0); + } +#else + if (num == -1) { + if (snprintf_s(aszFileName, FILE_NAME_LEN, FILE_NAME_LEN - 1, + "audio_chn%d.%s", AdChn, SAMPLE_AUDIO_Pt2Str(enType)) < 0) { + HI_ASSERT(0); + } + } else { + SAMPLE_PRT("SAMPLE_AUDIO_OpenAdecFile_AAC\n"); + SAMPLE_PRT("filename:%d.%s\n", num, SAMPLE_AUDIO_Pt2Str(enType)); + if (snprintf_s(aszFileName, FILE_NAME_LEN, FILE_NAME_LEN - 1, + "/userdata/aac_file/%d.%s", num, SAMPLE_AUDIO_Pt2Str(enType)) < 0) { + HI_ASSERT(0); + } + } +#endif + + pfd = fopen(aszFileName, "rb"); + if (pfd == NULL) { + SAMPLE_PRT("%s: open file %s failed\n", __FUNCTION__, aszFileName); + return NULL; + } + SAMPLE_PRT("open stream file:\"%s\" for adec ok\n", aszFileName); + return pfd; +} + +static hi_void sample_audio_adec_ao_init_param(AIO_ATTR_S *attr) +{ + attr->enSamplerate = AUDIO_SAMPLE_RATE_48000; + attr->u32FrmNum = FPS_30; + attr->enBitwidth = AUDIO_BIT_WIDTH_16; + attr->enWorkmode = AIO_MODE_I2S_MASTER; + attr->enSoundmode = AUDIO_SOUND_MODE_STEREO; + attr->u32ChnCnt = 2; /* 2: chn num */ + attr->u32ClkSel = 1; + attr->enI2sType = AIO_I2STYPE_INNERCODEC; + attr->u32PtNumPerFrm = AACLC_SAMPLES_PER_FRAME; + attr->u32EXFlag = 0; + + gs_bAioReSample = HI_FALSE; + g_in_sample_rate = AUDIO_SAMPLE_RATE_BUTT; + g_out_sample_rate = AUDIO_SAMPLE_RATE_BUTT; +} + +static HI_VOID SAMPLE_AUDIO_AdecAoInner(HI_S32 num, HI_S32 fd, AUDIO_DEV AoDev, AO_CHN AoChn, ADEC_CHN AdChn) +{ + HI_S32 s32Ret; + FILE *pfd = NULL; + + s32Ret = SAMPLE_COMM_AUDIO_AoBindAdec(AoDev, AoChn, AdChn); + if (s32Ret != HI_SUCCESS) { + SAMPLE_PRT(s32Ret); + return; + } + + pfd = SAMPLE_AUDIO_OpenAdecFile_AAC(num, AdChn, gs_enPayloadType); + if (pfd == NULL) { + SAMPLE_PRT(HI_FAILURE); + SAMPLE_CHECK_EXPR_GOTO(pfd == NULL, ADECAO_ERR0, + "SAMPLE_AUDIO_OpenAdecFile_AAC FAIL, ret=%#x\n", s32Ret); + } + + s32Ret = SAMPLE_COMM_AUDIO_CreateTrdFileAdec(AdChn, pfd); + if (s32Ret != HI_SUCCESS) { + fclose(pfd); + pfd = HI_NULL; + SAMPLE_PRT(s32Ret); + SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, ADECAO_ERR0, + "SAMPLE_COMM_AUDIO_CreateTrdFileAdec FAIL, ret=%#x\n", s32Ret); + } + + printf("bind adec:%d to ao(%d,%d) ok \n", AdChn, AoDev, AoChn); + + if (num == -1) { + audio_wait_quit(fd); + } else { + sleep(3); // 3: sleep time + } + + s32Ret = SAMPLE_COMM_AUDIO_DestroyTrdFileAdec(AdChn); + if (s32Ret != HI_SUCCESS) { + SAMPLE_PRT(s32Ret); + return; + } + +ADECAO_ERR0: + s32Ret = SAMPLE_COMM_AUDIO_AoUnbindAdec(AoDev, AoChn, AdChn); + if (s32Ret != HI_SUCCESS) { + SAMPLE_PRT(s32Ret); + } + + return; +} + +/* function : file -> Adec -> Ao */ +static HI_S32 SAMPLE_AUDIO_AdecAo(HI_S32 num, HI_S32 quitFd) +{ + HI_S32 s32Ret, s32AoChnCnt; + const AO_CHN AoChn = 0; + const ADEC_CHN AdChn = 0; + AIO_ATTR_S stAioAttr; + AUDIO_DEV AoDev = SAMPLE_AUDIO_INNER_AO_DEV; + + sample_audio_adec_ao_init_param(&stAioAttr); + + s32Ret = SAMPLE_COMM_AUDIO_StartAdec(AdChn, gs_enPayloadType); + SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, ADECAO_ERR3, + "SAMPLE_COMM_AUDIO_StartAdec FAIL, ret=%#x\n", s32Ret); + + s32AoChnCnt = stAioAttr.u32ChnCnt; + s32Ret = SAMPLE_COMM_AUDIO_StartAo(AoDev, s32AoChnCnt, &stAioAttr, g_in_sample_rate, gs_bAioReSample); + SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, ADECAO_ERR2, + "SAMPLE_COMM_AUDIO_StartAo FAIL, ret=%#x\n", s32Ret); + + s32Ret = SAMPLE_COMM_AUDIO_CfgAcodec(&stAioAttr); + SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, ADECAO_ERR1, + "SAMPLE_COMM_AUDIO_CfgAcodec FAIL, ret=%#x\n", s32Ret); + + SAMPLE_AUDIO_AdecAoInner(num, quitFd, AoDev, AoChn, AdChn); + +ADECAO_ERR1: + s32Ret = SAMPLE_COMM_AUDIO_StopAo(AoDev, s32AoChnCnt, gs_bAioReSample); + if (s32Ret != HI_SUCCESS) { + SAMPLE_PRT(s32Ret); + } +ADECAO_ERR2: + s32Ret = SAMPLE_COMM_AUDIO_StopAdec(AdChn); + if (s32Ret != HI_SUCCESS) { + SAMPLE_PRT(s32Ret); + } + +ADECAO_ERR3: + return s32Ret; +} + +static HI_VOID SAMPLE_AUDIO_StartAdecAo(HI_BOOL bSendAdec, AUDIO_DEV AoDev, AENC_CHN AeChn, AIO_ATTR_S *pstAioAttr) +{ + HI_S32 s32Ret, s32AoChnCnt; + const AO_CHN AoChn = 0; + const ADEC_CHN AdChn = 0; + FILE *pfd = NULL; + + if (bSendAdec == HI_TRUE) { + s32Ret = SAMPLE_COMM_AUDIO_StartAdec(AdChn, gs_enPayloadType); + if (s32Ret != HI_SUCCESS) { + return; + } + + s32AoChnCnt = pstAioAttr->u32ChnCnt; + s32Ret = SAMPLE_COMM_AUDIO_StartAo(AoDev, s32AoChnCnt, pstAioAttr, g_in_sample_rate, gs_bAioReSample); + SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, STOP_ADEC, + "SAMPLE_COMM_AUDIO_StartAo FAIL. s32Ret: 0x%x\n", s32Ret); + + pfd = SAMPLE_AUDIO_OpenAencFile(AdChn, gs_enPayloadType); + SAMPLE_CHECK_EXPR_GOTO(pfd == NULL, STOP_AO, "SAMPLE_AUDIO_OpenAencFile FAIL. s32Ret: 0x%x\n", s32Ret); + + s32Ret = SAMPLE_COMM_AUDIO_CreateTrdAencAdec(AeChn, AdChn, pfd); + if (s32Ret != HI_SUCCESS) { + fclose(pfd); + pfd = HI_NULL; + SAMPLE_PRT(s32Ret); + SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, STOP_AO, + "SAMPLE_COMM_AUDIO_CreateTrdAencAdec FAIL. s32Ret: 0x%x\n", s32Ret); + } + + s32Ret = SAMPLE_COMM_AUDIO_AoBindAdec(AoDev, AoChn, AdChn); + if (s32Ret != HI_SUCCESS) { + SAMPLE_PRT(s32Ret); + SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, DESTORY_AENC_THREAD, + "SAMPLE_COMM_AUDIO_AoBindAdec FAIL. s32Ret: 0x%x\n", s32Ret); + } + + SAMPLE_PRT("bind adec:%d to ao(%d,%d) ok \n", AdChn, AoDev, AoChn); + } + + if (bSendAdec == HI_TRUE) { + s32Ret = SAMPLE_COMM_AUDIO_AoUnbindAdec(AoDev, AoChn, AdChn); + if (s32Ret != HI_SUCCESS) { + SAMPLE_PRT(s32Ret); + } + + DESTORY_AENC_THREAD: + (HI_VOID)SAMPLE_COMM_AUDIO_DestroyTrdAencAdec(AdChn); + + STOP_AO: + (HI_VOID)SAMPLE_COMM_AUDIO_StopAo(AoDev, s32AoChnCnt, gs_bAioReSample); + + STOP_ADEC: + (HI_VOID)SAMPLE_COMM_AUDIO_StopAdec(AdChn); + } +} + +static hi_void sample_audio_ai_ao_init_param(AIO_ATTR_S *attr) +{ + attr->enSamplerate = AUDIO_SAMPLE_RATE_48000; + attr->enBitwidth = AUDIO_BIT_WIDTH_16; + attr->enWorkmode = AIO_MODE_I2S_MASTER; + attr->enSoundmode = AUDIO_SOUND_MODE_STEREO; + attr->u32EXFlag = 0; + attr->u32FrmNum = FPS_30; + attr->u32PtNumPerFrm = AACLC_SAMPLES_PER_FRAME; + attr->u32ChnCnt = 2; /* 2: chn num */ + attr->u32ClkSel = 1; + attr->enI2sType = AIO_I2STYPE_INNERCODEC; + + gs_bAioReSample = HI_FALSE; + /* config ao resample attr if needed */ + if (gs_bAioReSample == HI_TRUE) { + /* ai 48k -> 32k */ + g_out_sample_rate = AUDIO_SAMPLE_RATE_32000; + + /* ao 32k -> 48k */ + g_in_sample_rate = AUDIO_SAMPLE_RATE_32000; + } else { + g_in_sample_rate = AUDIO_SAMPLE_RATE_BUTT; + g_out_sample_rate = AUDIO_SAMPLE_RATE_BUTT; + } + + gs_bUserGetMode = (gs_bAioReSample == HI_TRUE) ? HI_TRUE : HI_FALSE; +} + +static HI_VOID SAMPLE_AUDIO_AiAoInner(AUDIO_DEV AiDev, AI_CHN AiChn, AUDIO_DEV AoDev, AO_CHN AoChn) +{ + HI_S32 s32Ret; + + /* bind AI to AO channel */ + if (gs_bUserGetMode == HI_TRUE) { + s32Ret = SAMPLE_COMM_AUDIO_CreateTrdAiAo(AiDev, AiChn, AoDev, AoChn); + if (s32Ret != HI_SUCCESS) { + SAMPLE_PRT(s32Ret); + return; + } + } else { + s32Ret = SAMPLE_COMM_AUDIO_AoBindAi(AiDev, AiChn, AoDev, AoChn); + if (s32Ret != HI_SUCCESS) { + SAMPLE_PRT(s32Ret); + return; + } + } + SAMPLE_PRT("ai(%d,%d) bind to ao(%d,%d) ok\n", AiDev, AiChn, AoDev, AoChn); + + if (gs_bAoVolumeCtrl == HI_TRUE) { + s32Ret = SAMPLE_COMM_AUDIO_CreateTrdAoVolCtrl(AoDev); + if (s32Ret != HI_SUCCESS) { + SAMPLE_PRT(s32Ret); + SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, AIAO_ERR0, + "SAMPLE_COMM_AUDIO_CreateTrdAoVolCtrl FAIL. s32Ret: 0x%x\n", s32Ret); + } + } + + if (gs_bAoVolumeCtrl == HI_TRUE) { + s32Ret = SAMPLE_COMM_AUDIO_DestroyTrdAoVolCtrl(AoDev); + if (s32Ret != HI_SUCCESS) { + SAMPLE_PRT(s32Ret); + return; + } + } + +AIAO_ERR0: + if (gs_bUserGetMode == HI_TRUE) { + s32Ret = SAMPLE_COMM_AUDIO_DestroyTrdAi(AiDev, AiChn); + if (s32Ret != HI_SUCCESS) { + SAMPLE_PRT(s32Ret); + } + } else { + s32Ret = SAMPLE_COMM_AUDIO_AoUnbindAi(AiDev, AiChn, AoDev, AoChn); + if (s32Ret != HI_SUCCESS) { + SAMPLE_PRT(s32Ret); + } + } + + return; +} + +/* function : Ai -> Ao(with fade in/out and volume adjust) */ +static HI_S32 SAMPLE_AUDIO_AiAo(HI_VOID) +{ + HI_S32 s32Ret; + HI_S32 s32AiChnCnt; + HI_S32 s32AoChnCnt; + const AI_CHN AiChn = 0; + const AO_CHN AoChn = 0; + AIO_ATTR_S stAioAttr; + AUDIO_DEV AiDev = SAMPLE_AUDIO_INNER_AI_DEV; + AUDIO_DEV AoDev = SAMPLE_AUDIO_INNER_AO_DEV; + + sample_audio_ai_ao_init_param(&stAioAttr); + + /* enable AI channel */ + s32AiChnCnt = stAioAttr.u32ChnCnt; + s32Ret = SAMPLE_COMM_AUDIO_StartAi(AiDev, s32AiChnCnt, &stAioAttr, g_out_sample_rate, gs_bAioReSample, NULL, 0); + if (s32Ret != HI_SUCCESS) { + SAMPLE_PRT(s32Ret); + SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, AIAO_ERR3, + "SAMPLE_COMM_AUDIO_StartAi FAIL. s32Ret: 0x%x\n", s32Ret); + } + + /* enable AO channel */ + s32AoChnCnt = stAioAttr.u32ChnCnt; + s32Ret = SAMPLE_COMM_AUDIO_StartAo(AoDev, s32AoChnCnt, &stAioAttr, g_in_sample_rate, gs_bAioReSample); + if (s32Ret != HI_SUCCESS) { + SAMPLE_PRT(s32Ret); + SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, AIAO_ERR2, + "SAMPLE_COMM_AUDIO_StartAo FAIL. s32Ret: 0x%x\n", s32Ret); + } + + /* config internal audio codec */ + s32Ret = SAMPLE_COMM_AUDIO_CfgAcodec(&stAioAttr); + SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, AIAO_ERR1, + "SAMPLE_COMM_AUDIO_CfgAcodec FAIL. s32Ret: 0x%x\n", s32Ret); + + SAMPLE_AUDIO_AiAoInner(AiDev, AiChn, AoDev, AoChn); + +AIAO_ERR1: + s32Ret = SAMPLE_COMM_AUDIO_StopAo(AoDev, s32AoChnCnt, gs_bAioReSample); + if (s32Ret != HI_SUCCESS) { + SAMPLE_PRT(s32Ret); + } + +AIAO_ERR2: + s32Ret = SAMPLE_COMM_AUDIO_StopAi(AiDev, s32AiChnCnt, gs_bAioReSample, HI_FALSE); + if (s32Ret != HI_SUCCESS) { + SAMPLE_PRT(s32Ret); + } + +AIAO_ERR3: + return s32Ret; +} + +/* function : main */ +HI_S32 AudioTest(HI_U32 num, HI_S32 quitFd) +{ + HI_S32 s32Ret = HI_SUCCESS; + SAMPLE_AUDIO_AddLibPath(); + + HI_MPI_AENC_AacInit(); + HI_MPI_ADEC_AacInit(); + SAMPLE_AUDIO_AdecAo(num, quitFd); + + HI_MPI_AENC_AacDeInit(); + HI_MPI_ADEC_AacDeInit(); + + return s32Ret; +} \ No newline at end of file diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/dependency/audio_test.h b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/dependency/audio_test.h new file mode 100644 index 0000000..0786f66 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/dependency/audio_test.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AUDIO_TEST_H +#define AUDIO_TEST_H + +#include "sample_comm.h" + +#ifdef __cplusplus +extern "C" { +#endif + +HI_S32 SAMPLE_AUDIO_AdecAo(HI_S32 num, HI_S32 quitFd); + +#ifdef __cplusplus +} +#endif + +#endif // AUDIO_TEST_H diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/ext_util/base_interface.c b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/ext_util/base_interface.c new file mode 100644 index 0000000..cd344e0 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/ext_util/base_interface.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iniparser.h" +#include "sample_media_ai.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* End of #ifdef __cplusplus */ + +#define CFG_KEY_MAX 256 // Maximum length of config key buf + +static dictionary *g_appCfg = NULL; // Global configuration +static pthread_t g_mainThrdId = 0; // Main thread ID, the thread that called app_base_init() + +HI_S32 ConfBaseInit(const char* cfgFilePath) +{ + // Do not allow repeated init + HI_ASSERT(!g_mainThrdId); + + g_mainThrdId = pthread_self(); + SAMPLE_PRT("mainThrdId=%ld\n", (long)g_mainThrdId); + + if (cfgFilePath && *cfgFilePath) { + g_appCfg = iniparser_load(cfgFilePath); + if (!g_appCfg) { + SAMPLE_PRT("load '%s' FAIL, all config to default\n", cfgFilePath); + } + } else { + SAMPLE_PRT("no config file provided, all config to default\n"); + g_appCfg = NULL; + } + SAMPLE_PRT("conf file init success\n"); + + return 0; +} + +void ConfBaseExt(void) +{ + g_mainThrdId = 0; + if (g_appCfg) { + iniparser_freedict(g_appCfg); + g_appCfg = NULL; + } + SAMPLE_PRT("conf file exit success\n"); +} + +/* Get the int type configuration item corresponding to the key */ +int GetCfgInt(const char* key, int defVal) +{ + HI_ASSERT(key && *key); + return g_appCfg ? iniparser_getint(g_appCfg, key, defVal) : defVal; +} + +/* Get the double configuration item corresponding to the key */ +double GetCfgDouble(const char* key, double defVal) +{ + HI_ASSERT(key && *key); + return g_appCfg ? iniparser_getdouble(g_appCfg, key, defVal) : defVal; +} + +/* Get the string configuration corresponding to the key */ +const char* GetCfgStr(const char* key, const char* defVal) +{ + HI_ASSERT(key && *key); + return g_appCfg ? iniparser_getstring(g_appCfg, key, defVal) : defVal; +} + +/* Get the bool type configuration item corresponding to the key */ +bool GetCfgBool(const char* key, bool defVal) +{ + static const size_t trueSize = 4; + static const size_t falseSize = 5; + const char *val; + + val = GetCfgStr(key, NULL); + if (val && *val) { + if (val[0] == '1' || val[0] == 'y' || val[0] == 'Y') { + return true; + } else if (val[0] == '0' || val[0] == 'n' || val[0] == 'N') { + return false; + } else if (strncmp(val, "true", trueSize) == 0) { + return true; + } else if (strncmp(val, "false", falseSize) == 0) { + return false; + } else { + return defVal; + } + } else { + return defVal; + } +} + +/* Get the int type configuration item corresponding to section+field */ +int SectGetCfgInt(const char* section, const char* field, int defVal) +{ + HI_ASSERT(field && *field); + char key[CFG_KEY_MAX]; + + if (snprintf_s(key, sizeof(key), sizeof(key) - 1, "%s:%s", (section ? section : ""), field) < 0) { + HI_ASSERT(0); + } + return GetCfgInt(key, defVal); +} + +/* Get the double configuration item corresponding to section+field */ +double SectGetCfgDouble(const char* section, const char* field, double defVal) +{ + HI_ASSERT(field && *field); + char key[CFG_KEY_MAX]; + + if (snprintf_s(key, sizeof(key), sizeof(key) - 1, "%s:%s", (section ? section : ""), field) < 0) { + HI_ASSERT(0); + } + return GetCfgDouble(key, defVal); +} + +/* Get the bool type configuration item corresponding to section+field */ +bool SectGetCfgBool(const char* section, const char* field, bool defVal) +{ + HI_ASSERT(field && *field); + char key[CFG_KEY_MAX]; + + if (snprintf_s(key, sizeof(key), sizeof(key) - 1, "%s:%s", (section ? section : ""), field) < 0) { + HI_ASSERT(0); + } + return GetCfgBool(key, defVal); +} + +/* Get the string configuration item corresponding to section+field */ +const char* SectGetCfgStr(const char* section, const char* field, const char* defVal) +{ + HI_ASSERT(field && *field); + char key[CFG_KEY_MAX]; + + if (snprintf_s(key, sizeof(key), sizeof(key) - 1, "%s:%s", (section ? section : ""), field) < 0) { + HI_ASSERT(0); + } + return GetCfgStr(key, defVal); +} + +/* strxfrm */ +int HiStrxfrm(char *s1, char *s2, int n) +{ + int i; + + for (i = 0; (i < n - 1) && s2[i]; i++) { + s1[i] = s2[i]; + } + s1[i] = 0; + return i; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* End of #ifdef __cplusplus */ diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/ext_util/base_interface.h b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/ext_util/base_interface.h new file mode 100644 index 0000000..affc05b --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/ext_util/base_interface.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BASE_INTERFACE_H +#define BASE_INTERFACE_H + +#include +#include + +#if __cplusplus +extern "C" { +#endif + +HI_S32 ConfBaseInit(const char* cfgFilePath); +bool IsMainThrd(void); +void ConfBaseExt(void); + +int GetCfgInt(const char* key, int defVal); +double GetCfgDouble(const char* key, double defVal); +bool GetCfgBool(const char* key, bool defVal); +const char* GetCfgStr(const char* key, const char* defVal); + +int SectGetCfgInt(const char* section, const char* field, int defVal); +double SectGetCfgDouble(const char* section, const char* field, double defVal); +bool SectGetCfgBool(const char* section, const char* field, bool defVal); +const char* SectGetCfgStr(const char* section, const char* field, const char* defVal); + +int HiStrincmp(const char *s1, const char *s2, size_t n); +int HiStrxfrm(char *s1, char *s2, int n); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/ext_util/misc_util.c b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/ext_util/misc_util.c new file mode 100644 index 0000000..5694ffd --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/ext_util/misc_util.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "sample_media_ai.h" +#include "ai_infer_process.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* End of #ifdef __cplusplus */ + +/* Amplify the integer to the given multiple range */ +int IntZoomTo(int n, double rate, double rateMin, double rateMax) +{ + HI_ASSERT(rateMin < 1 && rateMax > 1); + int ret; + + if (!rateMin) { + HI_ASSERT(rateMin); + return n; + } else { + if (rate > rateMax) { + ret = n * (int)rateMax; + } else if (rate < rateMin) { + ret = n / (int)(1 / rateMin); + } else { + ret = (int)(n * rate); + } + return ret < 1 ? 1 : ret; + } +} + +/* Convert coordinates proportionally */ +void RectBoxTran(RectBox* box, int srcWidth, int srcHeight, int dstWidth, int dstHeight) +{ + if (!srcWidth || !srcHeight) { + HI_ASSERT(srcWidth && srcHeight); + } else { + if (srcWidth != 0 && srcHeight != 0) { + box->xmin = box->xmin * dstWidth / srcWidth * HI_OVEN_BASE / HI_OVEN_BASE; + box->xmax = box->xmax * dstWidth / srcWidth * HI_OVEN_BASE / HI_OVEN_BASE; + box->ymin = box->ymin * dstHeight / srcHeight * HI_OVEN_BASE / HI_OVEN_BASE; + box->ymax = box->ymax * dstHeight / srcHeight * HI_OVEN_BASE / HI_OVEN_BASE; + } + } +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* End of #ifdef __cplusplus */ diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/ext_util/misc_util.h b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/ext_util/misc_util.h new file mode 100644 index 0000000..1d68fa4 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/ext_util/misc_util.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MISC_UTIL_H +#define MISC_UTIL_H + +#include +#include + +#include "ai_infer_process.h" + +#if __cplusplus +extern "C" { +#endif + +/* RGB888 commonly used colors */ +#define RGB888_RED ((uint32_t)0xFF0000) +#define RGB888_GREEN ((uint32_t)0x00FF00) +#define RGB888_BLUE ((uint32_t)0x0000FF) +#define RGB888_YELLOW ((uint32_t)0xFFFF00) +#define RGB888_WHITE ((uint32_t)0xFFFFFF) +#define RGB888_BLACK ((uint32_t)0x000000) + +/* Amplify the integer to the given multiple range */ +int IntZoomTo(int n, double rate, double rateMin, double rateMax); + +/* Convert coordinates proportionally */ +void RectBoxTran(RectBox* box, int srcWidth, int srcHeight, int dstWidth, int dstHeight); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/ext_util/posix_help.c b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/ext_util/posix_help.c new file mode 100644 index 0000000..c1853d9 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/ext_util/posix_help.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sample_media_ai.h" +#include "posix_help.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* End of #ifdef __cplusplus */ + +#define SKPAIR_FDS 2 + +/* SkPair create */ +int SkPairCreate(SkPair* chn) +{ + HI_ASSERT(chn); + int fds[SKPAIR_FDS]; + + if (socketpair(PF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, fds) < 0) { + HI_ASSERT(0); + } + chn->in = fds[0]; + chn->out = fds[1]; + return 0; +} + +/* Read complete message */ +int FdReadMsg(int fd, HI_VOID* msgBuf, int msgSize) +{ + HI_ASSERT(msgBuf && msgSize > 0); + static const int logPerCount = 1000; // Circulate 1000 times and log information once + int loopNum = 0; + int total = 0; + int ret; + while (total < msgSize) { + ret = read(fd, (char*)msgBuf + total, msgSize - total); + if (ret > 0) { + total += ret; + } else if (ret == 0) { // fd closed by peer + SAMPLE_PRT("read FAIL, for fd closed by peer\n"); + return -1; + } else if (errno == EAGAIN || errno == EWOULDBLOCK) { // no data now + if (total == 0) { // When no data has been read before, return + return 0; + } + if (++loopNum % logPerCount == 0) { + SAMPLE_PRT("FdReadMsg wait %ds, ERR, CHECK it\n", loopNum / logPerCount); + } + usleep(HI_USLEEP_MS); // wait 1ms, and try again + } else { + return -1; // read error + } + } + return msgSize; +} + +/* Write complete message */ +int FdWriteMsg(int fd, const HI_VOID* msgData, int msgLen) +{ + HI_ASSERT(msgData && msgLen > 0); + static const int logPerCount = 1000; // Circulate 1000 times and log information once + int loopNum = 0; + int total = 0; + int ret; + + while (total < msgLen) { + ret = write(fd, (const char*)msgData + total, msgLen - total); + if (ret > 0) { + total += ret; + } else if (ret == 0 || (ret < 0 && (errno == EAGAIN || errno == EWOULDBLOCK))) { // no data now + if (++loopNum % logPerCount == 0) { + SAMPLE_PRT("FdWriteMsg wait %ds, ERR, CHECK it\n", loopNum / logPerCount); + } + usleep(HI_USLEEP_MS); // wait 1ms, and try again + } else { // write error + HI_ASSERT(ret < 0); + SAMPLE_PRT("FdWriteMsg FAIL, err='%s'\n", strerror(errno)); + return -1; + } + } + return msgLen; +} + +/* SkPair destroy */ +void SkPairDestroy(SkPair* chn) +{ + HI_ASSERT(chn); + + if (chn->in >= 0) { + if (close(chn->in) < 0) { + HI_ASSERT(0); + } + chn->in = -1; + } + if (chn->out >= 0) { + if (close(chn->out) < 0) { + HI_ASSERT(0); + } + chn->out = -1; + } +} + +/* init recursive pmutex replaced PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */ +void RecurMutexInit(pthread_mutex_t* mutex) +{ + HI_ASSERT(mutex); + pthread_mutexattr_t attr; + int res; + + res = pthread_mutexattr_init(&attr); + HI_ASSERT(!res); + + res = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + HI_ASSERT(!res); + res = pthread_mutex_init(mutex, &attr); + HI_ASSERT(!res); + + pthread_mutexattr_destroy(&attr); +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* End of #ifdef __cplusplus */ diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/ext_util/posix_help.h b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/ext_util/posix_help.h new file mode 100644 index 0000000..012b581 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/ext_util/posix_help.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef POSIX_HELP_H +#define POSIX_HELP_H + +#include +#include +#include +#include +#include + +#if __cplusplus +extern "C" { +#endif + +/* + * usleep time length + * The unit of usleep() is microseconds + */ +#define HI_USLEEP_MS 1000 + +/* Socketpair channel */ +typedef struct SkPair { + int in; // in fd + int out; // out fd +} SkPair; + +/* SkPair create */ +int SkPairCreate(SkPair* chn); + +/* Read complete message */ +int FdReadMsg(int fd, HI_VOID* msgBuf, int msgSize); + +/* Write complete message */ +int FdWriteMsg(int fd, const HI_VOID* msgData, int msgLen); + +/* SkPair destroy */ +void SkPairDestroy(SkPair* chn); + +void RecurMutexInit(pthread_mutex_t* mutex); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/interconnection_server/README.md b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/interconnection_server/README.md new file mode 100644 index 0000000..00772ed --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/interconnection_server/README.md @@ -0,0 +1,43 @@ +# Pegasus与Taurus串口互联通信 +-注意:在使用串口互联前,请确认手势检测+手势识别可以正常运行。 + +## 硬件环境搭建 +- 硬件要求:Taurus开发板;硬件搭建如下图所示。注意这里需要跟Pegasus同时使用,详情可以参考[串口互联client端](http://gitee.com/openharmony/vendor_hisilicon/blob/master/hispark_pegasus/demo/interconnection_client_demo/README.md),由于Pegasus有两种方式,下面介绍两种硬件搭建方式。 + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E4%BA%92%E8%81%94/10.jpg) + +![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E4%BA%92%E8%81%94/11.jpg) + +## 串口通信控制协议HiSignalling介绍 +- 为了便于Taurus与Pegasus开发套件之间进行通信和控制,定义了一套简易的HiSignalling通信控制协议,数据帧格式如下表所示,并提供相关参考代码,大家也可以根据自己的需要使用其他协议。 + +| 帧头(2Byte) | Payload Len (2Byte) | payload | 帧尾(1Byte) | CRC32(4Byte) | +|---|---|---|---|---| +| 0xAA,0x55 | | | 0xFF | CRC32 | + +例如一组数据帧为:AA5500020003FF8ED2BEDF (十六进制不区分大小写) +- 0AA55: 帧头 +- 0002: Payload Len +- 0003: Payload +- FF: 帧尾 +- 8ED2BEDF: CRC32校验码 + +## 软件介绍 +- 这里以手势识别为例:1.hand_classify.c文件中在初始化uart + ``` + uartFd = UartOpenInit(); + if (uartFd < 0) { + printf("uart1 open failed\r\n"); + } else { + printf("uart1 open successed\r\n"); + } + return ret; + ``` +- 2.在HandDetectFlag调用UartSendRead()函数实现数据的发送,Pegasus接收到数据后实现对应外设的响应。 +- 3.当Taurus的摄像头检测到特定的手势之后,Taurus会将对应的检测结果通过串口发送给Pegasus端,此时Pegasus主板上的灯会亮起,具体实验结果及打印信息如下图所示。 + + ![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E4%BA%92%E8%81%94/6.png) + + ![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E4%BA%92%E8%81%94/7.png) + + ![输入图片说明](https://gitee.com/asd1122/tupian/raw/master/%E5%9B%BE%E7%89%87/%E4%BA%92%E8%81%94/8.jpg) \ No newline at end of file diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/interconnection_server/hisignalling.c b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/interconnection_server/hisignalling.c new file mode 100644 index 0000000..a6ddcc7 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/interconnection_server/hisignalling.c @@ -0,0 +1,757 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hisignalling.h" + +#define MSG(args...) printf(args) +pthread_t hisignallingMsgHandleID; +#define HISIGNALLING_HEAD_1 (0xaa) +#define HISIGNALLING_HEAD_2 (0x55) + +/** + @berf GPIO enable of key + @param pin: gpio port +*/ + +static int GpioExport(int pin) +{ + char buffer[64] = {0}; + int len = -1; + int fd = -1; + + fd = open("/sys/class/gpio/export", O_WRONLY); + if (fd < 0) { + MSG("Failed to open export for writing!\n"); + close(fd); + return -1; + } + + len = snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "%d", pin); + if (len < 0) { + MSG("printf msg failed\r\n"); + } + if (write(fd, buffer, len) < 0) { + MSG("Failed to export gpio!"); + close(fd); + return -1; + } + + close(fd); + return 0; +} +/** + @berf GPIO disable of key + @param pin: gpio port +*/ +static int GpioUnexport(int pin) +{ + char buffer[64] = {0}; + int len = -1; + int fd = -1; + + fd = open("/sys/class/gpio/unexport", O_WRONLY); + if (fd < 0) { + MSG("Failed to open unexport for writing!\n"); + close(fd); + return -1; + } + + len = snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "%d", pin); + if (len < 0) { + MSG("printf msg failed\r\n"); + } + if (write(fd, buffer, len) < 0) { + MSG("Failed to unexport gpio!"); + close(fd); + return -1; + } + + close(fd); + return 0; +} + +// dir: 0-->IN, 1-->OUT +static int GpioDirection(int pin, int dir) +{ + static const char dirStr[] = "in\0out"; + char path[64] = {0}; + int fd = -1; + + int len = snprintf_s(path, sizeof(path), sizeof(path) - 1, "/sys/class/gpio/gpio%d/direction", pin); + if (len < 0) { + MSG("printf msg failed\r\n"); + } + fd = open(path, O_WRONLY); + if (fd < 0) { + MSG("Failed to open gpio direction for writing!\n"); + close(fd); + return -1; + } + + if (write(fd, &dirStr[dir == 0 ? 0 : 3], dir == 0 ? 2 : 3) < 0) { /* 3, 2, 3 gpio register */ + MSG("Failed to set direction!\n"); + close(fd); + return -1; + } + + close(fd); + return 0; +} + +// value: 0-->LOW, 1-->HIGH +static int GpioWrite(int pin, int value) +{ + static const char valuesStr[] = "01"; + char path[64] = {0}; + int fd = -1; + + int len = snprintf_s(path, sizeof(path), sizeof(path) - 1, "/sys/class/gpio/gpio%d/value", pin); + if (len < 0) { + MSG("printf Msg failed\r\n"); + } + fd = open(path, O_WRONLY); + if (fd < 0) { + MSG("Failed to open gpio value for writing!\n"); + close(fd); + return -1; + } + + if (write(fd, &valuesStr[value == 0 ? 0 : 1], 1) < 0) { /* 1, 1 gpio register */ + MSG("Failed to write value!\n"); + close(fd); + return -1; + } + + close(fd); + return 0; +} +/** + @berf Read GPIO port level change + @param int pin: gpio port +*/ +static int GpioRead(int pin) +{ + char path[64] = {0}; + char value_str[3] = {0}; + int fd = -1; + + int len = snprintf_s(path, sizeof(path), sizeof(path) - 1, "/sys/class/gpio/gpio%d/value", pin); + if (len < 0) { + MSG("printf msg failed\r\n"); + } + fd = open(path, O_RDONLY); + if (fd < 0) { + MSG("Failed to open gpio value for reading!\n"); + close(fd); + return -1; + } + + if (read(fd, value_str, 3) < 0) { /* 3: gpio register */ + MSG("Failed to read value!\n"); + close(fd); + return -1; + } + + close(fd); + return (atoi(value_str)); +} + +// none表示引脚为输入,不是中断引脚 +// rising表示引脚为中断输入,上升沿触发 +// falling表示引脚为中断输入,下降沿触发 +// both表示引脚为中断输入,边沿触发 +// 0-->none, 1-->rising, 2-->falling, 3-->both +static int GpioEdge(int pin, int edge) +{ + const char dirStr[] = "none\0rising\0falling\0both"; + char ptr = 0; + char path[64] = {0}; + int fd = -1; + + switch (edge) { + case EAGE_0: + ptr = 0; + break; + case EAGE_1: + ptr = 5; /* 5: gpio register */ + break; + case EAGE_2: + ptr = 12; /* 12: gpio register */ + break; + case EAGE_3: + ptr = 20; /* 20: gpio register */ + break; + default: + ptr = 0; + } + int len = snprintf_s(path, sizeof(path), sizeof(path) - 1, "/sys/class/gpio/gpio%d/edge", pin); + if (len < 0) { + MSG("printf Msg failed\r\n"); + } + + fd = open(path, O_WRONLY); + if (fd < 0) { + MSG("Failed to open gpio edge for writing!\n"); + close(fd); + return -1; + } + + if (write(fd, &dirStr[ptr], strlen(&dirStr[ptr])) < 0) { + MSG("Failed to set edge!\n"); + close(fd); + return -1; + } + + close(fd); + return 0; +} + +// 初始化按键1 +void InitGpio1(void) +{ + MSG("\n =============== InitGpio1 start ========== \n"); + GpioUnexport(1); /* 1: gpio pin */ + GpioExport(1); /* 1: gpio pin */ + GpioDirection(1, 0); /* 1, 0: gpio pin */ + GpioEdge(1, 2); /* 1, 2: gpio pin */ + MSG("\n =============== InitGpio1 end ========== \n"); +} + +// 初始化按键2 +void InitGpio2(void) +{ + MSG("\n =============== InitGpio2 start ========== \n"); + GpioUnexport(2); /* 2: gpio pin */ + GpioExport(2); /* 2: gpio pin */ + GpioDirection(2, 0); /* 2, 0: gpio pin */ + GpioEdge(2, 2); /* 2, 2: gpio pin */ + MSG("\n =============== InitGpio2 end ========== \n"); +} + +/* 串口设置 */ +int Uart1Config(int fd) +{ + struct termios newtio = {0}, oldtio = {0}; + /* 获取原有串口配置 */ + if (tcgetattr(fd, &oldtio) != 0) { + perror("SetupSerial 1"); + return -1; + } + (void)memset_s(&newtio, sizeof(newtio), 0, sizeof(newtio)); + /* CREAD 开启串行数据接收,CLOCAL并打开本地连接模式 */ + newtio.c_cflag |= CLOCAL | CREAD; + + /* 设置数据位8 */ + newtio.c_cflag &= ~CSIZE; + newtio.c_cflag |= CS8; + /* 设置奇偶校验位 */ + newtio.c_cflag &= ~PARENB; // 无奇偶校验 + /* 设置波特率 115200 */ + cfsetispeed(&newtio, B115200); + cfsetospeed(&newtio, B115200); + + /* 设置停止位 */ + newtio.c_cflag &= ~CSTOPB; /* 默认为一位停止位 */ + /* 设置最少字符和等待时间,对于接收字符和等待时间没有特别的要求时 */ + newtio.c_cc[VTIME] = 0; /* 非规范模式读取时的超时时间 */ + newtio.c_cc[VMIN] = 0; /* 非规范模式读取时的最小字符数 */ + /* tcflush清空终端未完成的输入/输出请求及数据;TCIFLUSH表示清空正收到的数据,且不读取出来 */ + tcflush(fd, TCIFLUSH); + if ((tcsetattr(fd, TCSANOW, &newtio)) != 0) { + perror("com set error"); + return -1; + } + return 0; +} + +/** + @berf uart send + @param int fd: uart file descriptor + @param void *buf:send data buf + @param int len:data buf len +*/ +int UartSend(int fd, char *buf, int len) +{ + int ret = 0; + int count = 0; + char *sendBuf = buf; + int sendLen = len; + + tcflush(fd, TCIFLUSH); + + while (sendLen > 0) { + ret = write(fd, (char*)sendBuf + count, sendLen); + if (ret < 1) { + printf("write data below 1 byte % d\r\n", ret); + break; + } + count += ret; + sendLen = sendLen - ret; + } + + return count; +} +/** + @berf uart read + @param int uart_fd: uart file descriptor + @param void *buf:read data buf + @param int len:data buf len + @param int timeoutMs: read data time +*/ +int UartRead(int uartFd, char *buf, int len, int timeoutMs) +{ + int ret = 0; + size_t rsum = 0; + ret = 0; + fd_set rset; + struct timeval time; + int timeout = timeoutMs; + char *readBuf = buf; + int readLen = len; + + while (rsum < readLen) { + time.tv_sec = timeout / 1000; /* 1000:转换成秒 */ + time.tv_usec = (timeout - time.tv_sec * 1000) * 1000; /* 1000, 1000:转换为微秒 */ + FD_ZERO(&rset); + FD_SET(uartFd, &rset); + ret = select(uartFd + 1, &rset, NULL, NULL, &time); + if (ret <= 0) { + if (ret == 0) { + //printf("time over!\r\n"); + return -1; + } + if (ret == -1) { + printf("[ERROR][UART] select error!\r\n"); + // 信号中断 + continue; + } + return -1; + } else { + ret = read(uartFd, (char *)readBuf + rsum, readLen - rsum); + if (ret < 0) { + printf("[ERROR][UART] read data failed\r\n"); + return ret; + } else { + rsum += ret; + } + } + } + return rsum; +} + +/* +* crc32 Verification implementation +*/ +static const unsigned int crc32table[] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, + 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, + 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, + 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, + 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, + 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, + 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, + 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, + 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, + 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, + 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, + 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, + 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, + 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, + 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, + 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, + 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, + 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, + 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, + 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, + 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, + 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, + 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, + 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, + 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, + 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, + 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, + 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, + 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, + 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, + 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, + 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, + 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, + 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, + 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, + 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L, + 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, + 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, + 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, + 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, + 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, + 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, + 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, + 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, + 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, + 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, + 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, + 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, + 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, + 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, + 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, + 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL +}; + +/** + @berf CRC check + @param const unsigned char *buf: Data to be verified buff + @param unsigned int size: Data to be verified length +*/ +static unsigned int crc32(const unsigned char *buf, unsigned int size) +{ + unsigned int i, crc = 0xFFFFFFFF; + + for (i = 0; i < size; i++) { + crc = crc32table[(crc ^ buf[i]) & 0xff] ^ (crc >> 8); /* 8: 右移8bit */ + } + return crc ^ 0xFFFFFFFF; +} + +#define RIGHT_MOVE_8_BIT (8) +#define RIGHT_MOVE_16_BIT (16) +#define RIGHT_MOVE_24_BIT (24) +/* hisignal Hi3516 message send */ +static unsigned int HisignallingDataPackage(HisignallingProtocalType *buf, + unsigned int len, unsigned char *hisignallingDataBuf) +{ + unsigned int crcCheckSend = 0; + unsigned int packageLen = 0; + unsigned int DataPackLen = len; + + (void)memcpy_s(hisignallingDataBuf, HISGNALLING_MSG_FRAME_HEADER_LEN, + buf->frameHeader, HISGNALLING_MSG_FRAME_HEADER_LEN); + (void)memcpy_s(&hisignallingDataBuf[HISGNALLING_MSG_FRAME_HEADER_LEN], + DataPackLen, buf->hisignallingMsgBuf, DataPackLen); + (void)memcpy_s(&hisignallingDataBuf[HISGNALLING_MSG_FRAME_HEADER_LEN + DataPackLen], + HISIGNALLING_MSG_HEADER_LEN, &(buf->endOfFrame), HISIGNALLING_MSG_HEADER_LEN); + crcCheckSend = crc32(hisignallingDataBuf, (DataPackLen + HISIGNALLING_MSG_HEADER_TAIL_LEN)); + hisignallingDataBuf[DataPackLen + HISIGNALLING_MSG_HEADER_TAIL_LEN] = + (unsigned char)((crcCheckSend & 0xff000000) >> RIGHT_MOVE_24_BIT); + hisignallingDataBuf[DataPackLen + HISIGNALLING_MSG_HEADER_TAIL_LEN + 1] = /* 1: addr offset */ + (unsigned char)((crcCheckSend & 0x00ff0000) >> RIGHT_MOVE_16_BIT); + hisignallingDataBuf[DataPackLen + HISIGNALLING_MSG_HEADER_TAIL_LEN + 2] = /* 2: addr offset */ + (unsigned char)((crcCheckSend & 0x0000ff00) >> RIGHT_MOVE_8_BIT); + hisignallingDataBuf[DataPackLen + HISIGNALLING_MSG_HEADER_TAIL_LEN + 3] = /* 3: addr offset */ + (unsigned char)crcCheckSend; + packageLen = DataPackLen + HISIGNALLING_MSG_HEADER_TAIL_LEN + 4; /* 4: crc check lenght */ + return packageLen; +} + +/* hisignalling Hi3561 message recevice */ +static HisignallingErrorType HisignallingMsgReceive(int fd, unsigned char *buf, unsigned int len) +{ + unsigned int crcCheckReceived = 0; + int i = 0, readLen = 0; + unsigned int RecvLen = len; + + /* Hi3516dv300 uart read */ + readLen = UartRead(fd, buf, RecvLen, 1000); /* 1000 :time out */ + if (readLen <= 0) { + printf("uart_read data failed\r\n"); + return HISIGNALLING_RET_VAL_ERROR; + } + printf("read_len=%d\r\n", readLen); + /* 校验crc */ + if (RecvLen > 4) { /* 4:crc check lenght */ + crcCheckReceived = crc32(buf, RecvLen - 4); /* 4:crc check lenght */ + if (((unsigned char)((crcCheckReceived & 0xff000000) >> RIGHT_MOVE_24_BIT) != + buf[RecvLen - 4]) && /* 4: addr offset */ + ((unsigned char)((crcCheckReceived & 0x00ff0000) >> RIGHT_MOVE_16_BIT) != + buf[RecvLen - 3]) && /* 3: addr offset */ + ((unsigned char)((crcCheckReceived & 0x0000ff00) >> RIGHT_MOVE_8_BIT) != + buf[RecvLen - 2]) && /* 2: addr offset */ + ((unsigned char)crcCheckReceived != buf[RecvLen - 1])) { /* 1: addr offset */ + printf(": crc32 Verification failed!\r\n"); + printf(": crc_4=0x%x, crc_3=0x%x, crc_2=0x%x, crc_1=0x%x\r\n", + buf[RecvLen - 4], buf[RecvLen - 3], buf[RecvLen - 2], buf[RecvLen - 1]); /* 4, 3, 2, 1: addr offset */ + return HISIGNALLING_RET_VAL_ERROR; + } + } + /* 输出收到的数据 */ + for (i = 0; i < RecvLen; i++) { + printf("0x%x ", buf[i]); + } + printf("\r\n"); + + return HISIGNALLING_RET_VAL_CORRECT; +} + +/** + @berf hisignalling protocol send msg + @param void *buf: send data buff + @param unsigned int data_len: send data length +*/ +unsigned int HisignallingMsgSend(int fd, char *buf, unsigned int dataLen) +{ + unsigned int ret = 0; + HisignallingProtocalType hisignallingMsg = {0}; + unsigned char hisignallingSendBuf[HISIGNALLING_MSG_BUFF_LEN] = {0}; + unsigned int hisignallingPackageLen = 0; + unsigned int writeDataLen = 0; + + hisignallingMsg.frameHeader[0]= 0xAA; /* Protocol head data 1 */ + hisignallingMsg.frameHeader[1]= 0x55; /* Protocol head data 2 */ + (void)memcpy_s(hisignallingMsg.hisignallingMsgBuf, dataLen, buf, dataLen); + hisignallingMsg.endOfFrame = 0xff; /* Protocol tail data */ + + hisignallingPackageLen = HisignallingDataPackage(&hisignallingMsg, dataLen, hisignallingSendBuf); + if (!hisignallingPackageLen) { + printf("hisignalling_data_package failed\r\n"); + return -1; + } + if (*hisignallingSendBuf == 0) { + printf("hisignalling send buf is null!\r\n"); + return -1; + } + + ret = UartSend(fd, hisignallingSendBuf, hisignallingPackageLen); + if (ret < 0) { + printf("write data failed\r\n"); + return -1; + } + + for (int i = 0; i < hisignallingPackageLen; i++) { + printf("send data = 0x%x \r\n", hisignallingSendBuf[i]); + } + + return 0; +} + +/* hisignalling message handle */ +void *HisignallingMsgHandle(char *param) +{ + unsigned int err = 0; + + while (1) { + printf("hisignalling_msg_handle\r\n"); + usleep(HISGNALLING_FREE_TASK_TIME); + } + err = pthread_join(hisignallingMsgHandleID, NULL); + if (err != 0) { + printf("Failed to delete hisignalling msg task\r\n"); + } +} + +#define HISIGNALLING_TASK_STACK_SIZE (2048) +/* hisignalling message task */ +unsigned int HisignallingMsgTask(void) +{ + unsigned int ret = 0; + int err = 0, stacksize = HISIGNALLING_TASK_STACK_SIZE; + + pthread_attr_t hisignallingAttr = {0}; + err = pthread_attr_init(&hisignallingAttr); + err = pthread_attr_setstacksize(&hisignallingAttr, stacksize); + ret = pthread_create(&hisignallingMsgHandleID, &hisignallingAttr, HisignallingMsgHandle, NULL); + if (ret != 0) { + printf("Failed to create hisignalling msg task\r\n"); + return -1; + } + return 0; +} + +static void UartProcess(int uartFd, int Gpio1Fd, int Gpio2Fd, struct pollfd fdS1, struct pollfd fdS2) +{ + int ret = 0; + char buff[10] = {0}; + unsigned char writeBuffer[4] = {0, 2, 0, 3}; + unsigned char writeBuffer2[4] = {0, 2, 0, 4}; + unsigned char writeBuffer3[4] = {0, 2, 0, 5}; + unsigned char readBuff[16] = {0}; + + Uart1Config(uartFd); + while (1) { + /* 按键操作 */ + ret = read(Gpio1Fd, buff, 10); /* 10:read data lenght */ + if (ret == -1) { + MSG("gpio1 read error\n"); + } + ret = poll(&fdS1, 1, 0); /* 1: 监视一个文件描述符 */ + if (ret == -1) { + MSG("gpio1 poll error\n"); + } + if (fdS1.revents & POLLPRI) { + ret = lseek(Gpio1Fd, 0, SEEK_SET); + if (ret == -1) { + MSG("gpio1 lseek error\n"); + } + MSG("sw2 Pressed \n"); + /* 按键触发发送 */ + HisignallingMsgSend(uartFd, writeBuffer2, sizeof(writeBuffer2) / sizeof(writeBuffer2[0])); + } + ret = read(Gpio2Fd, buff, 10); /* 10:read data lenght */ + if (ret == -1) { + MSG("gpio2 read error\n"); + } + ret = poll(&fdS2, 1, 0); /* 1: 监视一个文件描述符 */ + if (ret == -1) { + MSG("gpio2 poll error\n"); + } + if (fdS2.revents & POLLPRI) { + ret = lseek(Gpio2Fd, 0, SEEK_SET); + if (ret == -1) { + MSG("gpio1 lseek error\n"); + } + MSG("sw1 Pressed \n"); + /* 按键触发发送 */ +#ifdef EXPANSION_BOARD + HisignallingMsgSend(uartFd, writeBuffer3, sizeof(writeBuffer3) / sizeof(writeBuffer3[0])); +#elif defined (ROBOT_BOARD) + HisignallingMsgSend(uartFd, writeBuffer, sizeof(writeBuffer) / sizeof(writeBuffer[0])); +#endif + } + /* 串口读写操作 */ + HisignallingMsgReceive(uartFd, readBuff, HISIGNALLING_MSG_MOTOR_ENGINE_LEN); + usleep(HISGNALLING_FREE_TASK_TIME); + } +} + +unsigned int UartOpenInit(void) +{ + int fd; + char *uart1 = "/dev/ttyAMA1"; + + if ((fd = open(uart1, O_RDWR | O_NOCTTY | O_NDELAY)) < 0) { + printf("open %s is failed", uart1); + return -1; + } else { + Uart1Config(fd); + } + return fd; +} + +void UartSendRead(int fd, refuseClassification refuseType) +{ + /* test buffer */ + unsigned char writeBuffer2[4] = {0, 2, 0, 1}; + unsigned char writeBuffer3[4] = {0, 2, 0, 2}; + unsigned char writeBuffer4[4] = {0, 2, 0, 3}; + unsigned char writeBuffer5[4] = {0, 2, 0, 4}; + unsigned char writeBuffer6[4] = {0, 2, 0, 5}; + unsigned char writeBuffer7[4] = {0, 2, 0, 6}; + unsigned char writeBuffer8[4] = {0, 2, 0, 7}; + unsigned char writeBuffer9[4] = {0, 2, 0, 8}; + unsigned char readBuff[16] = {0}; + +#ifdef EXPANSION_BOARD + switch (refuseType) { + case FistGesture: + HisignallingMsgSend(fd, writeBuffer2, sizeof(writeBuffer2)/sizeof(writeBuffer2[0])); + printf("send gesture status:FistGesture\r\n"); + break; + case ForefingerGesture: + HisignallingMsgSend(fd, writeBuffer3, sizeof(writeBuffer3)/sizeof(writeBuffer3[0])); + printf("send gesture status:ForefingerGesture\r\n"); + break; + case OkGesture: + HisignallingMsgSend(fd, writeBuffer4, sizeof(writeBuffer4)/sizeof(writeBuffer4[0])); + printf("send gesture status:OkGesture\r\n"); + break; + case PalmGesture: + HisignallingMsgSend(fd, writeBuffer5, sizeof(writeBuffer5)/sizeof(writeBuffer5[0])); + printf("send gesture status:PalmGesture\r\n"); + break; + case YesGesture: + HisignallingMsgSend(fd, writeBuffer6, sizeof(writeBuffer6)/sizeof(writeBuffer6[0])); + printf("send gesture status:YesGesture\r\n"); + break; + case ForefingerAndThumbGesture: + HisignallingMsgSend(fd, writeBuffer7, sizeof(writeBuffer7)/sizeof(writeBuffer7[0])); + printf("send gesture status:ForefingerAndThumbGesture\r\n"); + break; + case LittleFingerAndThumbGesture: + HisignallingMsgSend(fd, writeBuffer8, sizeof(writeBuffer8)/sizeof(writeBuffer8[0])); + printf("send gesture status:LittleFingerAndThumbGesture\r\n"); + break; + case InvalidGesture: + HisignallingMsgSend(fd, writeBuffer9, sizeof(writeBuffer9)/sizeof(writeBuffer9[0])); + printf("send gesture status:InvalidGesture\r\n"); + break; + } +#endif + /* 串口读操作 */ + if (readBuff[0] == HISIGNALLING_HEAD_1 && readBuff[1] == HISIGNALLING_HEAD_2) { + HisignallingMsgReceive(fd, readBuff, HISIGNALLING_MSG_MOTOR_ENGINE_LEN); + } +} + +int AiUartTransmit(void) +{ + /* 按键初始化定义 */ + int gpio1Fd = -1; + int gpio2Fd = -1; + int ret1 = -1; + int ret2 = -1; + struct pollfd fds1; + struct pollfd fds2; + /* 串口初始化定义 */ + int fd = 0; + char *uart1 = "/dev/ttyAMA1"; + + printf("hisignal task start\r\n"); + /* 按键操作 */ + InitGpio1(); + InitGpio2(); + gpio1Fd = open("/sys/class/gpio/gpio1/value", O_RDONLY); + if (gpio1Fd < 0) { + MSG("Failed to open gpio1 !\n"); + return -1; + } + fds1.fd = gpio1Fd; + fds1.events = POLLPRI; + + gpio2Fd = open("/sys/class/gpio/gpio2/value", O_RDONLY); + if (gpio2Fd < 0) { + MSG("Failed to open gpio1 !\n"); + return -1; + } + fds2.fd = gpio2Fd; + fds2.events = POLLPRI; + /* 串口读写 */ + if ((fd = open(uart1, O_RDWR | O_NOCTTY | O_NDELAY)) < 0) { + printf("open %s is failed", uart1); + return -1; + } else { + UartProcess(fd, gpio1Fd, gpio2Fd, fds1, fds2); + } + return 0; +} diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/interconnection_server/hisignalling.h b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/interconnection_server/hisignalling.h new file mode 100644 index 0000000..b326a69 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/interconnection_server/hisignalling.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HISIGNALLING_H +#define HISIGNALLING_H + +#define HISIGNALLING_MSG_HEADER_LEN (1) +#define HISGNALLING_MSG_FRAME_HEADER_LEN (2) +#define HISIGNALLING_MSG_HEADER_TAIL_LEN (3) +#define HISGNALLING_FREE_TASK_TIME (10) +#define HISIGNALLING_MSG_MOTOR_ENGINE_LEN (11) +#define HISIGNALLING_MSG_ONE_FRAME_LEN (16) +#define HISIGNALLING_MSG_BUFF_LEN (512) + +/* + @brief Adapter plate selection + 使用时选择打开宏,使用外设扩展板打开#define BOARD_SELECT_IS_EXPANSION_BOARD这个宏 + 使用Robot板打开#define BOARD_SELECT_IS_ROBOT_BOARD这个宏 +*/ +#define BOARD_SELECT_IS_EXPANSION_BOARD +#ifdef BOARD_SELECT_IS_EXPANSION_BOARD +#define EXPANSION_BOARD +#else +#define ROBOT_BOARD +#endif + +typedef enum { + EAGE_0 = 0, + EAGE_1, + EAGE_2, + EAGE_3 +} GPioEage; + +typedef enum { + FistGesture = 0x1, + ForefingerGesture, + OkGesture, + PalmGesture, + YesGesture, + ForefingerAndThumbGesture, + LittleFingerAndThumbGesture, + InvalidGesture +}refuseClassification; + +typedef struct { + unsigned char frameHeader[HISGNALLING_MSG_FRAME_HEADER_LEN]; + unsigned char hisignallingMsgBuf[HISIGNALLING_MSG_BUFF_LEN]; + unsigned int hisigallingMsgLen; + unsigned char endOfFrame; + unsigned int hisignallingCrc32Check; +}HisignallingProtocalType; + +typedef enum { + HISIGNALLING_RET_VAL_CORRECT = 0, + HISIGNALLING_RET_VAL_ERROR, + HISGNALLING_RET_VAL_MAX +}HisignallingErrorType; +/* +* hisignalling protocal Function declaration +*/ +unsigned int UartOpenInit(void); +void UartSendRead(int fd, refuseClassification refuseType); +static HisignallingErrorType HisignallingMsgReceive(int fd, unsigned char *buf, unsigned int len); +unsigned int HisignallingMsgSend(int fd, char *buf, unsigned int dataLen); +unsigned int HisignallingMsgTask(void); + +#endif diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/messaging/data_store.c b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/messaging/data_store.c new file mode 100644 index 0000000..c99f2a7 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/messaging/data_store.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2022 Sidi Liang. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "cJSON.h" +#include "messaging.h" +#include "json_helper.h" +#include "data_store.h" + +#define NUMBER_OF_SLOTS 4 +#define CONFIG_FILE_PATH "/userdata/vendor_data/vendor.json" +#define CONFIG_FILE_DIR "/userdata/vendor_data" + +SlotInfo vendorData[NUMBER_OF_SLOTS] = {0}; + +/* +SlotInfo testVendorData; +testVendorData.slot_num = 4; +strcpy(testVendorData.product_name, "N95 Mask"); +strcpy(testVendorData.product_price_string, "10.50 Yuan"); +testVendorData.product_price = 10.5; +testVendorData.remaining_num = 3; +*/ + +SlotInfo loadVendorDataFromFile() +{ + +} + +void saveVendorDataToFile(SlotInfo vendorData[], int len) +{ + char* jsonString = vendorDataToJson(vendorData, len); + FILE *fp = NULL; + fp = fopen(CONFIG_FILE_PATH, "w+"); + fputs(jsonString, fp); + fclose(fp); + return; +} + +void updateMemVendorData(SlotInfo newVendorData[]){ + for(int i = 0; i < NUMBER_OF_SLOTS; i += 1){ + vendorData[i] = newVendorData[i]; + } +} + +int remainingNumUpdate(int slotNum){ + if(vendorData[slotNum - 1].remaining_num - 1 >= 0){ + vendorData[slotNum - 1].remaining_num -= 1; + return 1; + }else{ + return -1; + } +} + +char* memVendorDataToShadow(){ + return vendorDataUpdateShadow(vendorData, (sizeof(vendorData)/sizeof(vendorData[0])), 1); +} + +void fileInit() +{ + struct stat st = {0}; + + if (stat(CONFIG_FILE_DIR, &st) == -1) { + mkdir(CONFIG_FILE_DIR, 0777); + + for(int i = 0; i < NUMBER_OF_SLOTS; i += 1){ // Initialize data + printf("i = %d\n", i); + vendorData[i].slot_num = i + 1; + strcpy(vendorData[i].product_name, "none"); + strcpy(vendorData[i].product_price_string, "0.00"); + vendorData[i].product_price = 0; + vendorData[i].remaining_num = 3; + } + saveVendorDataToFile(vendorData, (sizeof(vendorData)/sizeof(vendorData[0]))); + } + printf("\n%s\n", vendorDataUpdateShadow(vendorData, (sizeof(vendorData)/sizeof(vendorData[0])), 1)); + +} diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/messaging/data_store.h b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/messaging/data_store.h new file mode 100644 index 0000000..bdd2244 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/messaging/data_store.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2022 Sidi Liang. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "json_helper.h" + +#ifndef DATA_STORE_H +#define DATA_STORE_H + + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* End of #ifdef __cplusplus */ +void fileInit(); + + +/*---------------------------------------------------------------- +@brief Save vendor data to a json file +@param SlotInfo items[]: the array of SlotInfo object to be saved +@param int len: the length of the array +----------------------------------------------------------------*/ +void saveVendorDataToFile(SlotInfo vendorData[], int len); + +int remainingNumUpdate(int slotNum); + +char* memVendorDataToShadow(); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* End of #ifdef __cplusplus */ + +#endif /* End of #ifndef __SAMPLE_MEDIA_AI_H__ */ diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/messaging/json_helper.c b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/messaging/json_helper.c new file mode 100644 index 0000000..538f8d6 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/messaging/json_helper.c @@ -0,0 +1,267 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + Copyright (c) 2022 Sidi Liang + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#include +#include +#include +#include +#include "cJSON.h" +#include "json_helper.h" +#include "messaging.h" + +#define NUMBER_OF_SLOTS 4 + +int print_preallocated(cJSON *root) +{ + /* declarations */ + char *out = NULL; + char *buf = NULL; + char *buf_fail = NULL; + size_t len = 0; + size_t len_fail = 0; + + /* formatted print */ + out = cJSON_Print(root); + + /* create buffer to succeed */ + /* the extra 5 bytes are because of inaccuracies when reserving memory */ + len = strlen(out) + 5; + buf = (char*)malloc(len); + if (buf == NULL) + { + printf("Failed to allocate memory.\n"); + exit(1); + } + + /* create buffer to fail */ + len_fail = strlen(out); + buf_fail = (char*)malloc(len_fail); + if (buf_fail == NULL) + { + printf("Failed to allocate memory.\n"); + exit(1); + } + + /* Print to buffer */ + if (!cJSON_PrintPreallocated(root, buf, (int)len, 1)) { + printf("cJSON_PrintPreallocated failed!\n"); + if (strcmp(out, buf) != 0) { + printf("cJSON_PrintPreallocated not the same as cJSON_Print!\n"); + printf("cJSON_Print result:\n%s\n", out); + printf("cJSON_PrintPreallocated result:\n%s\n", buf); + } + free(out); + free(buf_fail); + free(buf); + return -1; + } + + /* success */ + printf("%s\n", buf); + + /* force it to fail */ + if (cJSON_PrintPreallocated(root, buf_fail, (int)len_fail, 1)) { + printf("cJSON_PrintPreallocated failed to show error with insufficient memory!\n"); + printf("cJSON_Print result:\n%s\n", out); + printf("cJSON_PrintPreallocated result:\n%s\n", buf_fail); + free(out); + free(buf_fail); + free(buf); + return -1; + } + + free(out); + free(buf_fail); + free(buf); + return 0; +} + +/* Create a bunch of objects as demonstration. */ +void create_objects(void) +{ + /* declare a few. */ + cJSON *root = NULL; + cJSON *fld = NULL; + int i = 0; + + /* Our array of "records": */ + SlotInfo testSlot; + testSlot.slot_num = 0; + //testSlot.product_name = "test"; + testSlot.product_price = 10; + //testSlot.product_price_string = "10.00"; + testSlot.remaining_num = 10; + + /* Here we construct some JSON standards, from the JSON site. */ + + /* Our array of "records": */ + root = cJSON_CreateArray(); + cJSON_AddItemToArray(root, fld = cJSON_CreateObject()); + cJSON_AddNumberToObject(fld, "slot_num", testSlot.slot_num); + cJSON_AddNumberToObject(fld, "product_price", testSlot.product_price); + cJSON_AddNumberToObject(fld, "remaining_num", testSlot.remaining_num); + //cJSON_AddStringToObject(fld, "product_name", testSlot.product_name); + //cJSON_AddStringToObject(fld, "product_price_string", testSlot.product_price_string); + + /* cJSON_ReplaceItemInObject(cJSON_GetArrayItem(root, 1), "City", cJSON_CreateIntArray(ids, 4)); */ + + if (print_preallocated(root) != 0) { + cJSON_Delete(root); + exit(EXIT_FAILURE); + } + +} + + +int printCJSONVersion(void) +{ + /* print the version */ + printf("Version: %s\n", cJSON_Version()); + return 0; +} + +char* SlotSelectionToJson(SlotSelection selectedSlot) +{ + cJSON *root = cJSON_CreateObject(); + char* ret; + cJSON_AddNumberToObject(root, "slot_num", selectedSlot.slot_num); + ret = cJSON_Print(root); + cJSON_Delete(root); + return ret; +} + +char* UIControlToJson(UIControl UIController) +{ + cJSON *root = cJSON_CreateObject(); + char* ret; + cJSON_AddNumberToObject(root, "ui_page_num", UIController.ui_page_num); + ret = cJSON_Print(root); + cJSON_Delete(root); + return ret; +} + +char* vendorDataToJson(SlotInfo items[], int len) +{ + cJSON *root = NULL; + cJSON *fld = NULL; + char *ret = NULL; + cJSON *productsArray = NULL; + + root = cJSON_CreateObject(); + productsArray = cJSON_AddArrayToObject(root, "product_info"); + for(int i = 0; i < len; i += 1){ + cJSON_AddItemToArray(productsArray, fld = cJSON_CreateObject()); + cJSON_AddNumberToObject(fld, "slot_num", items[i].slot_num); + cJSON_AddNumberToObject(fld, "product_price", items[i].product_price); + cJSON_AddNumberToObject(fld, "remaining_num", items[i].remaining_num); + cJSON_AddStringToObject(fld, "product_name", items[i].product_name); + cJSON_AddStringToObject(fld, "product_price_string", items[i].product_price_string); + } + ret = cJSON_Print(root); + cJSON_Delete(root); + return ret; +} + +int jsonToVendorData(char* jsonString, SlotInfo vendorDataPtr[]) +{ + const cJSON *item = NULL; + const cJSON *items = NULL; + const cJSON *slotNumJson = NULL; + const cJSON *productPriceJson = NULL; + const cJSON *remainingNumJson = NULL; + const cJSON *productNameJson = NULL; + const cJSON *productPriceStringJson = NULL; + + SlotInfo ret[NUMBER_OF_SLOTS] = {0}; + + cJSON *vendorDataJson = cJSON_Parse(jsonString); + if (vendorDataJson == NULL){ + const char *error_ptr = cJSON_GetErrorPtr(); + if (error_ptr != NULL){ + fprintf(stderr, "Error before: %s\n", error_ptr); + return 1; + } + } + + items = cJSON_GetObjectItemCaseSensitive(vendorDataJson, "product_info"); + int count = 0; + cJSON_ArrayForEach(item, items){ + if(count < NUMBER_OF_SLOTS){ + slotNumJson = cJSON_GetObjectItemCaseSensitive(item, "slot_num"); + if (cJSON_IsNumber(slotNumJson)){ + ret[count].slot_num = slotNumJson->valueint; + } + productPriceJson = cJSON_GetObjectItemCaseSensitive(item, "product_price"); + if (cJSON_IsNumber(productPriceJson)){ + ret[count].product_price = productPriceJson->valueint; + } + remainingNumJson = cJSON_GetObjectItemCaseSensitive(item, "remaining_num"); + if (cJSON_IsNumber(remainingNumJson)){ + ret[count].product_price = remainingNumJson->valueint; + } + productNameJson = cJSON_GetObjectItemCaseSensitive(item, "product_name"); + if (cJSON_IsString(productNameJson) && (productNameJson->valuestring != NULL)){ + strcpy(ret[count].product_name, productNameJson->valuestring); + } + productPriceStringJson = cJSON_GetObjectItemCaseSensitive(item, "product_price_string"); + if (cJSON_IsString(productPriceStringJson) && (productPriceStringJson->valuestring != NULL)){ + strcpy(ret[count].product_price_string, productPriceStringJson->valuestring); + } + count += 1; + }else{ + printf("Error: items in json is more than number of slots\n"); + return 1; + } + } + + vendorDataPtr = ret; + cJSON_Delete(vendorDataJson); + return 0; +} + +char* vendorDataUpdateShadow(SlotInfo items[], int len, int version) +{ + cJSON *root = cJSON_CreateObject(); + cJSON *fld = NULL; + cJSON *arr = NULL; + cJSON *state = NULL; + cJSON *reported = NULL; + char* ret = NULL; + cJSON_AddStringToObject(root, "type", "update"); + cJSON_AddItemToObject(root, "state", state = cJSON_CreateObject()); + cJSON_AddItemToObject(state, "reported", reported = cJSON_CreateObject()); + cJSON_AddItemToObject(reported, "product_info", arr = cJSON_CreateArray()); + for(int i = 0; i < len; i += 1){ + cJSON_AddItemToArray(arr, fld = cJSON_CreateObject()); + cJSON_AddNumberToObject(fld, "slot_num", items[i].slot_num); + cJSON_AddNumberToObject(fld, "product_price", items[i].product_price); + cJSON_AddNumberToObject(fld, "remaining_num", items[i].remaining_num); + cJSON_AddStringToObject(fld, "product_name", items[i].product_name); + cJSON_AddStringToObject(fld, "product_price_string", items[i].product_price_string); + } + cJSON_AddNumberToObject(root, "version", version); + cJSON_AddStringToObject(root, "clientToken", ""); + ret = cJSON_Print(root); + cJSON_Delete(root); + return ret; +} diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/messaging/json_helper.h b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/messaging/json_helper.h new file mode 100644 index 0000000..ae67756 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/messaging/json_helper.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2022 Sidi Liang. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#ifndef JSON_HELPER_H +#define JSON_HELPER_H + + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* End of #ifdef __cplusplus */ + +typedef struct SlotInfo +{ + int slot_num; + char product_name[32]; + double product_price; + char product_price_string[10]; + int remaining_num; + char imgPath[128]; + +} SlotInfo; + +typedef struct UIControl +{ + int ui_page_num; + +} UIControl; + + +typedef struct SlotSelection +{ + int slot_num; + +} SlotSelection; + +/*---------------------------------------------------------------- +@brief print the version of CJSON library +@return 0 on success +----------------------------------------------------------------*/ +int printCJSONVersion(void); + +/*---------------------------------------------------------------- +@brief create several CJSON objects for testing +----------------------------------------------------------------*/ +void create_objects(void); + +/*---------------------------------------------------------------- +@brief Convert SlotSelection object (see json_helper.h) to JSON string +@param SlotSelection selectedSlot: the SlotSelection object to be converted +@return The string containing JSON representation of selectedSlot +----------------------------------------------------------------*/ +char* SlotSelectionToJson(SlotSelection selectedSlot); + +/*---------------------------------------------------------------- +@brief Convert UIControl object (see json_helper.h) to JSON string +@param UIControl UIController: the SlotSelection object to be converted +@return The string containing JSON representation of UIController +----------------------------------------------------------------*/ +char* UIControlToJson(UIControl UIController); + +/*---------------------------------------------------------------- +@brief Convert a array of SlotInfo object (see json_helper.h) to JSON string +@param SlotInfo items[]: the array of SlotInfo object to be converted +@param int len: the length of the array +@return The string containing JSON representation of items[] +----------------------------------------------------------------*/ +char* vendorDataToJson(SlotInfo items[], int len); + +/*---------------------------------------------------------------- +@brief Convert a JSON string and save the result into vendorDataPtr[] +@param char* jsonString: the JSON string to be converted +@param SlotInfo vendorDataPtr[]: the result SlotInfo (see json_helper.h) +@return 0 if successful, 1 if unsuccessful +----------------------------------------------------------------*/ +int jsonToVendorData(char* jsonString, SlotInfo vendorDataPtr[]); + + +/*---------------------------------------------------------------- +@brief Convert a array of SlotInfo object (see json_helper.h) to JSON string for updating device shadow +@note clientID is hard coded, should be improved in the future +@param SlotInfo items[]: the array of SlotInfo object to be converted +@param int len: the length of the array +@return The string containing the message for updating device shadow +----------------------------------------------------------------*/ +char* vendorDataUpdateShadow(SlotInfo items[], int len, int version); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* End of #ifdef __cplusplus */ + +#endif /* End of #ifndef __SAMPLE_MEDIA_AI_H__ */ diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/messaging/messaging.c b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/messaging/messaging.c new file mode 100644 index 0000000..58a5f66 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/messaging/messaging.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2022 Sidi Liang. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include "cJSON.h" +#include "messaging.h" +#include "json_helper.h" +#include "data_store.h" + +#define START_COMMAND "start" +#define DATA_COMMAND "jdata" +#define SUCCESS_COMMAND "success" +#define NUMBER_OF_SLOTS 4 + +/* message receive */ +int messageUARTRcvData(int fd, unsigned char *buf, unsigned int len) +{ + int i = 0, readLen = 0; + unsigned int RecvLen = len; + + /* Hi3516dv300 uart read */ + readLen = UartRead(fd, buf, RecvLen, 5000); /* 5000 :time out */ + if (readLen <= 0) { + printf("\nWaiting for START signal from UART\r\n"); + return 0; + } + printf("read_len=%d\r\n", readLen); + + /* 输出收到的数据 */ + for (i = 0; i < RecvLen; i++) { + printf("%c", buf[i]); + } + printf("\r\n"); + + return 1; +} + +int waitForStartSignal() +{ + int uartFd = 0; + /* uart open init */ + uartFd = UartOpenInit(); + if (uartFd < 0) { + printf("uart1 open failed\r\n"); + } else { + printf("uart1 open successed\r\n"); + } + unsigned char* dataBuffer = (char *) malloc(5); + while (1){ + if(messageUARTRcvData(uartFd, dataBuffer, 5)){ + if(strstr(dataBuffer, START_COMMAND)){ + free(dataBuffer); + return 1; + }else if(strstr(dataBuffer, DATA_COMMAND)){ + unsigned char* jsonDataBuffer = (char *) malloc(255); + messageUARTRcvData(uartFd, jsonDataBuffer, 255); + SlotInfo recvVendorData[NUMBER_OF_SLOTS]; + jsonToVendorData(jsonDataBuffer, recvVendorData); + updateMemVendorData(recvVendorData); + saveVendorDataToFile(recvVendorData, + (sizeof(recvVendorData)/sizeof(recvVendorData[0]))); + free(jsonDataBuffer); + } + } + } +} + +int waitForSuccessSignal() +{ + int uartFd = 0; + /* uart open init */ + uartFd = UartOpenInit(); + if (uartFd < 0) { + printf("uart1 open failed\r\n"); + } else { + printf("uart1 open successed\r\n"); + } + unsigned char* dataBuffer = (char *) malloc(10);//To be confirmed + while (1){ + if(messageUARTRcvData(uartFd, dataBuffer, 10)){ + if(strstr(dataBuffer, SUCCESS_COMMAND)){ + free(dataBuffer); + //TBD: Update data + remainingNumUpdate(1); + //Sync data + messageUARTSendData(uartFd, memVendorDataToShadow()); + return 1; + } + } + } +} + +void messageUARTSendData(int fd, char *payload) +{ + int lengthInt = 0; + while(*(payload + lengthInt) != '\0'){ + printf("%c", *(payload + lengthInt)); + lengthInt += 1; + } + if(lengthInt > 255){ + printf("Error: payload too long! Max length is 255"); + return; + } + unsigned char len = (unsigned char)lengthInt; + //Data packging + unsigned char frameHeader[2] = {0xAA,0x55}; //Frame header + unsigned char *dataBuffer = (char *) malloc(lengthInt + 4); + + //Frame header + *dataBuffer = 0xAA; + *(dataBuffer + 1) = 0x55; + + //Payload length + *(dataBuffer + 2) = len; + + //Payload + for(int i = 3; i <= lengthInt + 3; i+=1){ + *(dataBuffer + i) = *(payload + i - 3); + } + + printf("\n"); + printf("length: %u\n", len); + for (int i = 0; i < len + 3; i++) { + printf("send data = 0x%x \r\n", *(dataBuffer + i)); + } + + UartSend(fd, dataBuffer, len + 3); //send frame via UART + free(dataBuffer); +} diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/messaging/messaging.h b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/messaging/messaging.h new file mode 100644 index 0000000..a9bbc1e --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/messaging/messaging.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#ifndef MESSAGING_H +#define MESSAGING_H + + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* End of #ifdef __cplusplus */ + +/*---------------------------------------------------------------- +@brief Send data to 3618 via UART +@param int fd: UART file descriptor +@param char *payload: The data to send +----------------------------------------------------------------*/ +void messageUARTSendData(int fd, char *payload); + +int messageUARTRcvData(int fd, unsigned char *buf, unsigned int len); + +int waitForStartSignal(); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* End of #ifdef __cplusplus */ + +#endif /* End of #ifndef __SAMPLE_MEDIA_AI_H__ */ diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/mpp_help/include/ive_img.h b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/mpp_help/include/ive_img.h new file mode 100644 index 0000000..dfd760e --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/mpp_help/include/ive_img.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IVE_IMG_H +#define IVE_IMG_H + +#include +#include + +#include "hi_common.h" +#include "hi_comm_ive.h" +#include "hi_comm_video.h" +#include "hi_comm_venc.h" +#include "hi_ive.h" +#include "mpi_ive.h" +#include "ai_infer_process.h" + +#if __cplusplus +extern "C" { +#endif + +/* consts */ +#define IMG_FULL_CHN 3 // Full channel / three channel, for YUV444, RGB888 +#define IMG_HALF_CHN 2 // Half channel, for YUV420/422 +#define THREE_TIMES 3 +#define TWO_TIMES 2 + +/* Byte alignment calculation */ +HI_U32 HiAlign16(HI_U32 num); +HI_U32 HiAlign32(HI_U32 num); + +/* Alignment type */ +typedef enum AlignType { + ALIGN_TYPE_2 = 2, // Align by 2 bytes + ALIGN_TYPE_16 = 16, // Align by 16 bytes + ALIGN_TYPE_32 = 32, // Align by 32 bytes +} AlignType; + +/* Create ive image buffer based on type and size */ +int IveImgCreate(IVE_IMAGE_S* img, + IVE_IMAGE_TYPE_E enType, uint32_t width, uint32_t height); + +/* + * video frame to ive image. + * Copy the data pointer, do not copy the data. + */ +int FrmToOrigImg(const VIDEO_FRAME_INFO_S* frm, IVE_IMAGE_S *img); + +/* yuv file crop */ +int ImgYuvCrop(const IVE_IMAGE_S *src, IVE_IMAGE_S *dst, const RectBox* origBox); + +/* Destory ive Image */ +void IveImgDestroy(IVE_IMAGE_S* img); + +int OrigImgToFrm(const IVE_IMAGE_S *img, VIDEO_FRAME_INFO_S* frm); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/mpp_help/include/osd_img.h b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/mpp_help/include/osd_img.h new file mode 100644 index 0000000..8340af5 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/mpp_help/include/osd_img.h @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OSD_IMG_H +#define OSD_IMG_H + +#include +#include +#include +#include "hi_comm_region.h" +#include "hi_common.h" + +#if __cplusplus +extern "C" { +#endif + +/* Maximum OSD Count */ +#define HI_OSD_MAX_CNT (16) + +/* Maximum Display Count for Each OSD */ +#define HI_OSD_MAX_DISP_CNT (2) + +/* String OSD Maximum Length */ +#define HI_OSD_MAX_STR_LEN (64) + +/* typedef */ +typedef HI_S32 HI_ERRNO; + +/* common error code */ +#define HI_ERRNO_COMMON_BASE 0 +#define HI_ERRNO_COMMON_COUNT 256 + +#define HI_EUNKNOWN (HI_ERRNO)(HI_ERRNO_COMMON_BASE + 1) +#define HI_EOTHER (HI_ERRNO)(HI_ERRNO_COMMON_BASE + 2) +#define HI_EINTER (HI_ERRNO)(HI_ERRNO_COMMON_BASE + 3) +#define HI_EVERSION (HI_ERRNO)(HI_ERRNO_COMMON_BASE + 4) +#define HI_EPAERM (HI_ERRNO)(HI_ERRNO_COMMON_BASE + 5) +#define HI_EINVAL (HI_ERRNO)(HI_ERRNO_COMMON_BASE + 6) +#define HI_ENOINIT (HI_ERRNO)(HI_ERRNO_COMMON_BASE + 7) +#define HI_ENOTREADY (HI_ERRNO)(HI_ERRNO_COMMON_BASE + 8) +#define HI_ENORES (HI_ERRNO)(HI_ERRNO_COMMON_BASE + 9) +#define HI_EEXIST (HI_ERRNO)(HI_ERRNO_COMMON_BASE + 10) +#define HI_ELOST (HI_ERRNO)(HI_ERRNO_COMMON_BASE + 11) +#define HI_ENOOP (HI_ERRNO)(HI_ERRNO_COMMON_BASE + 12) +#define HI_EBUSY (HI_ERRNO)(HI_ERRNO_COMMON_BASE + 13) +#define HI_EIDLE (HI_ERRNO)(HI_ERRNO_COMMON_BASE + 14) +#define HI_EFULL (HI_ERRNO)(HI_ERRNO_COMMON_BASE + 15) +#define HI_EEMPTY (HI_ERRNO)(HI_ERRNO_COMMON_BASE + 16) +#define HI_EUNDERFLOW (HI_ERRNO)(HI_ERRNO_COMMON_BASE + 17) +#define HI_EOVERFLOW (HI_ERRNO)(HI_ERRNO_COMMON_BASE + 18) +#define HI_EACCES (HI_ERRNO)(HI_ERRNO_COMMON_BASE + 19) +#define HI_EINTR (HI_ERRNO)(HI_ERRNO_COMMON_BASE + 20) +#define HI_ECONTINUE (HI_ERRNO)(HI_ERRNO_COMMON_BASE + 21) +#define HI_EOVER (HI_ERRNO)(HI_ERRNO_COMMON_BASE + 22) +#define HI_ERRNO_COMMON_BOTTOM (HI_ERRNO)(HI_ERRNO_COMMON_BASE + 23) + +/* custom error code */ +#define HI_ERRNO_BASE (HI_ERRNO)(HI_ERRNO_COMMON_BASE + HI_ERRNO_COMMON_COUNT) +#define HI_EINITIALIZED (HI_ERRNO)(HI_ERRNO_BASE + 1) // Repeated initialization +#define HI_ERRNO_CUSTOM_BOTTOM (HI_ERRNO)(HI_ERRNO_BASE + 2) // Number of error numbers that have been defined + +/* pthread mutex lock */ +static inline void MutexLock(pthread_mutex_t* mutex) +{ + if (pthread_mutex_lock(mutex) != 0) { + HI_ASSERT(0); + } +} + +/* pthread mutex lock */ +static inline void MutexUnlock(pthread_mutex_t* mutex) +{ + if (pthread_mutex_unlock(mutex) != 0) { + HI_ASSERT(0); + } +} + +typedef HI_S32 (*HI_OSD_GETFONTMOD_CALLBACK_FN_PTR)(HI_CHAR* Character, HI_U8** FontMod, HI_S32* FontModLen); + +/* OSD Fonts Lib */ +typedef struct hiOSD_FONTS_S { + /* OSD Lib Font Size, in pixel */ + HI_U32 u32FontWidth; + HI_U32 u32FontHeight; + HI_OSD_GETFONTMOD_CALLBACK_FN_PTR pfnGetFontMod; +} HI_OSD_FONTS_S; + +/* osd pixel format enum */ +typedef enum hiOSD_PIXEL_FMT_E { + HI_OSD_PIXEL_FMT_RGB1555 = 0, + HI_OSD_PIXEL_FMT_BUTT +} HI_OSD_PIXEL_FMT_E; + +/* OSD Bitmap Attribute */ +typedef struct hiOSD_BITMAP_ATTR_S { + HI_OSD_PIXEL_FMT_E enPixelFormat; + HI_U32 u32Width; + HI_U32 u32Height; + HI_U64 u64PhyAddr; + HI_VOID* pvData; +} HI_OSD_BITMAP_ATTR_S; + +/* OSD Type Enum */ +typedef enum hiOSD_TYPE_E { + HI_OSD_TYPE_TIME = 0, + HI_OSD_TYPE_STRING, + HI_OSD_TYPE_BITMAP, + HI_OSD_TYPE_BUTT +} HI_OSD_TYPE_E; + +/* OSD Time Format Enum */ +typedef enum hiOSD_TIMEFMT_E { + HI_OSD_TIMEFMT_YMD24H = 0, // eg. 2017-03-10 23:00:59 + HI_OSD_TIMEFMT_BUTT +} HI_OSD_TIMEFMT_E; + +/* OSD Binded Module enum */ +typedef enum hiOSD_BIND_MOD_E { + HI_OSD_BINDMOD_VI = 0, + HI_OSD_BINDMOD_VPSS, + HI_OSD_BINDMOD_AVS, + HI_OSD_BINDMOD_VENC, + HI_OSD_BINDMOD_VO, + HI_OSD_BINDMOD_BUTT +} HI_OSD_BIND_MOD_E; + +typedef enum hiOSD_COORDINATE_E { + HI_OSD_COORDINATE_RATIO_COOR = 0, + HI_OSD_COORDINATE_ABS_COOR +} HI_OSD_COORDINATE_E; + +/** OSD Display Attribute */ +typedef struct hiOSD_DISP_ATTR_S { + HI_BOOL bShow; + HI_OSD_BIND_MOD_E enBindedMod; + HI_HANDLE ModHdl; + HI_HANDLE ChnHdl; + HI_U32 u32FgAlpha; + HI_U32 u32BgAlpha; + HI_OSD_COORDINATE_E enCoordinate; // Coordinate mode of the osd start Position + POINT_S stStartPos; // OSD Start Position + ATTACH_DEST_E enAttachDest; // only for venc + HI_S32 s32Batch; +} HI_OSD_DISP_ATTR_S; + +/* OSD Content */ +typedef struct hiOSD_CONTENT_S { + HI_OSD_TYPE_E enType; + HI_OSD_TIMEFMT_E enTimeFmt; + HI_U32 u32Color; // string color + HI_U32 u32BgColor; + HI_CHAR szStr[HI_OSD_MAX_STR_LEN]; + SIZE_S stFontSize; + HI_OSD_BITMAP_ATTR_S stBitmap; // Pixel Format: Only Support RGB1555 for now +} HI_OSD_CONTENT_S; + +/* OSD Parameter */ +typedef struct hiOSD_ATTR_S { + HI_U32 u32DispNum; /* 1Binded Display Number for this OSD */ + HI_OSD_DISP_ATTR_S astDispAttr[HI_OSD_MAX_DISP_CNT]; + HI_OSD_CONTENT_S stContent; +} HI_OSD_ATTR_S; + +/* OSD Parameter */ +typedef struct tagOSD_PARAM_S { + HI_OSD_ATTR_S stAttr; + SIZE_S stMaxSize; + pthread_mutex_t mutexLock; + HI_BOOL bInit; /* OSD Attribute Set or not, Canbe modified only HI_OSD_SetAttr */ + HI_BOOL bOn; /* OSD On/Off Flag, Canbe modified only by HI_OSD_Start/HI_OSD_Stop */ +} OSD_PARAM_S; + +typedef struct hiOSD_TEXTBITMAP_S { + RGN_HANDLE rgnHdl; + HI_OSD_CONTENT_S pstContent; + RGN_CANVAS_INFO_S stCanvasInfo; +} HI_OSD_TEXTBITMAP_S; + +/* OSD region set */ +struct OsdSet { + // OSD Binded Module: Static + HI_OSD_BIND_MOD_E bindMod; + // Binded Module Handle: Static eg.VcapPipeHdl, VpssHdl, StitchHdl, DispHdl, 0 + HI_U32 modHnd; + // Binded Channel Handle: Static eg.PipeChnHdl, VPortHdl, StitchPortHdl, WndHdl, VencHdl + HI_U32 chnHnd; +}; + +typedef struct OsdSet OsdSet; + +/* Create a region in OsdSet */ +int OsdsCreateRgn(OsdSet* self); + +/* Set the attribute value of the text region */ +int TxtRgnInit(HI_OSD_ATTR_S* rgnAttr, const char* str, uint32_t begX, uint32_t begY, uint32_t color); + +/* Destroy all regions in OsdSet */ +void OsdsClear(OsdSet* self); + +/* Set attributes for the specified region in OsdSet */ +int OsdsSetRgn(OsdSet* self, int rgnHnd, const HI_OSD_ATTR_S* rgnAttr); + +/* Creat OsdSet */ +OsdSet* OsdsCreate(HI_OSD_BIND_MOD_E bindMod, HI_U32 modHnd, HI_U32 chnHnd); + +/* Destory OsdSet */ +void OsdsDestroy(OsdSet* self); + +/* Initialize OsdSet lib */ +int OsdLibInit(void); + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/mpp_help/include/simsunb_16x32.txt b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/mpp_help/include/simsunb_16x32.txt new file mode 100644 index 0000000..b4ec6a3 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/mpp_help/include/simsunb_16x32.txt @@ -0,0 +1,380 @@ +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x01 ,0x00 ,0x03 ,0x80 ,0x03 ,0x80 ,0x03 ,0x80 ,0x03 ,0x80 , +0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 , +0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x01 ,0x80 ,0x03 ,0x80 , +0x03 ,0x80 ,0x01 ,0x80 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x06 ,0x70 ,0x06 ,0x70 ,0x06 ,0x70 ,0x06 ,0x60 ,0x06 ,0x60 ,0x06 ,0x60 ,0x06 ,0x60 , +0x06 ,0x20 ,0x04 ,0x40 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x04 ,0x18 ,0x0c ,0x18 ,0x0c ,0x10 ,0x08 ,0x10 , +0x08 ,0x10 ,0x7f ,0xfe ,0x7f ,0xfe ,0x08 ,0x10 ,0x08 ,0x10 ,0x08 ,0x10 ,0x08 ,0x10 ,0x08 ,0x10 , +0x08 ,0x30 ,0x08 ,0x30 ,0x7f ,0xfe ,0x7f ,0xfe ,0x10 ,0x20 ,0x10 ,0x20 ,0x10 ,0x20 ,0x10 ,0x20 , +0x10 ,0x20 ,0x10 ,0x20 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x01 ,0x80 ,0x01 ,0x80 ,0x07 ,0xe0 ,0x0d ,0xb0 ,0x19 ,0x98 ,0x19 ,0x98 , +0x19 ,0xb8 ,0x19 ,0xb0 ,0x19 ,0x80 ,0x1d ,0x80 ,0x0f ,0x80 ,0x07 ,0x80 ,0x01 ,0xc0 ,0x01 ,0xe0 , +0x01 ,0xf0 ,0x01 ,0xb8 ,0x01 ,0x98 ,0x19 ,0x98 ,0x39 ,0x98 ,0x39 ,0x98 ,0x31 ,0x98 ,0x11 ,0x90 , +0x0d ,0xe0 ,0x03 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x38 ,0x10 ,0x44 ,0x10 ,0x46 ,0x20 ,0xc6 ,0x20 , +0xc6 ,0x20 ,0xc6 ,0x40 ,0xc6 ,0x40 ,0xc6 ,0x80 ,0x46 ,0x80 ,0x44 ,0x80 ,0x3d ,0x18 ,0x01 ,0x64 , +0x02 ,0x46 ,0x02 ,0x46 ,0x04 ,0xc6 ,0x04 ,0xc6 ,0x04 ,0xc6 ,0x08 ,0xc6 ,0x08 ,0x46 ,0x10 ,0x46 , +0x10 ,0x2c ,0x10 ,0x10 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x0f ,0x80 ,0x18 ,0x80 ,0x10 ,0xc0 ,0x10 ,0xc0 , +0x10 ,0xc0 ,0x10 ,0x80 ,0x19 ,0x80 ,0x19 ,0x00 ,0x1a ,0x00 ,0x1c ,0x7c ,0x1c ,0x18 ,0x2c ,0x10 , +0x66 ,0x10 ,0x46 ,0x10 ,0xc7 ,0x20 ,0xc3 ,0x20 ,0xc1 ,0xa0 ,0xc1 ,0xc0 ,0x60 ,0xe0 ,0x70 ,0xf2 , +0x3f ,0x3e ,0x0c ,0x18 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x03 ,0x00 ,0x03 ,0x80 ,0x03 ,0x00 ,0x03 ,0x00 ,0x03 ,0x00 ,0x03 ,0x00 ,0x03 ,0x00 ,0x02 ,0x00 , +0x02 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x04 ,0x00 ,0x0c ,0x00 ,0x18 ,0x00 ,0x10 ,0x00 ,0x20 ,0x00 ,0x60 ,0x00 ,0x40 ,0x00 ,0xc0 , +0x00 ,0xc0 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 , +0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x00 ,0x80 ,0x00 ,0xc0 ,0x00 ,0xc0 ,0x00 ,0x40 ,0x00 ,0x60 , +0x00 ,0x30 ,0x00 ,0x10 ,0x00 ,0x08 ,0x00 ,0x04 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x40 ,0x00 ,0x20 ,0x00 ,0x10 ,0x00 ,0x18 ,0x00 ,0x0c ,0x00 ,0x04 ,0x00 ,0x06 ,0x00 ,0x02 ,0x00 , +0x03 ,0x00 ,0x03 ,0x00 ,0x01 ,0x00 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 , +0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x00 ,0x03 ,0x00 ,0x03 ,0x00 ,0x02 ,0x00 ,0x06 ,0x00 ,0x04 ,0x00 , +0x0c ,0x00 ,0x18 ,0x00 ,0x10 ,0x00 ,0x20 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x01 ,0x80 , +0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x79 ,0x8e ,0x3d ,0xbe ,0x1e ,0xf0 ,0x01 ,0x80 ,0x03 ,0xc0 , +0x06 ,0x70 ,0x0c ,0x38 ,0x1c ,0x1c ,0x38 ,0x0c ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x01 ,0x80 ,0x01 ,0x80 , +0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x7f ,0xfe ,0x01 ,0x80 , +0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x1c ,0x00 ,0x1e ,0x00 , +0x0e ,0x00 ,0x06 ,0x00 ,0x06 ,0x00 ,0x0c ,0x00 ,0x18 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x7f ,0xfe ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x18 ,0x00 ,0x3c ,0x00 , +0x3c ,0x00 ,0x18 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x02 ,0x00 ,0x04 ,0x00 ,0x04 ,0x00 ,0x08 ,0x00 ,0x08 ,0x00 ,0x10 ,0x00 ,0x10 , +0x00 ,0x20 ,0x00 ,0x20 ,0x00 ,0x40 ,0x00 ,0x40 ,0x00 ,0x80 ,0x00 ,0x80 ,0x01 ,0x00 ,0x01 ,0x00 , +0x02 ,0x00 ,0x02 ,0x00 ,0x06 ,0x00 ,0x04 ,0x00 ,0x0c ,0x00 ,0x08 ,0x00 ,0x18 ,0x00 ,0x10 ,0x00 , +0x10 ,0x00 ,0x20 ,0x00 ,0x20 ,0x00 ,0x40 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x07 ,0xc0 ,0x0c ,0x30 ,0x18 ,0x30 ,0x18 ,0x18 , +0x38 ,0x18 ,0x30 ,0x1c ,0x30 ,0x0c ,0x30 ,0x0c ,0x70 ,0x0c ,0x70 ,0x0c ,0x70 ,0x0c ,0x70 ,0x0c , +0x70 ,0x0c ,0x30 ,0x0c ,0x30 ,0x0c ,0x30 ,0x1c ,0x30 ,0x18 ,0x18 ,0x18 ,0x18 ,0x18 ,0x0c ,0x30 , +0x06 ,0x60 ,0x01 ,0x80 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x80 ,0x03 ,0x80 ,0x07 ,0x80 ,0x01 ,0x80 , +0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 , +0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 , +0x07 ,0xf0 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x07 ,0xe0 ,0x18 ,0x30 ,0x10 ,0x18 ,0x30 ,0x18 , +0x30 ,0x1c ,0x38 ,0x1c ,0x38 ,0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 ,0x30 ,0x00 ,0x60 ,0x00 ,0x40 , +0x00 ,0x80 ,0x01 ,0x00 ,0x02 ,0x00 ,0x04 ,0x00 ,0x08 ,0x04 ,0x10 ,0x04 ,0x30 ,0x0c ,0x20 ,0x38 , +0x3f ,0xf8 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x0f ,0xc0 ,0x18 ,0x30 ,0x30 ,0x30 ,0x30 ,0x18 , +0x38 ,0x18 ,0x10 ,0x18 ,0x00 ,0x18 ,0x00 ,0x30 ,0x00 ,0x60 ,0x03 ,0xc0 ,0x01 ,0xe0 ,0x00 ,0x30 , +0x00 ,0x18 ,0x00 ,0x18 ,0x00 ,0x0c ,0x00 ,0x0c ,0x30 ,0x0c ,0x38 ,0x1c ,0x30 ,0x18 ,0x30 ,0x30 , +0x0c ,0x60 ,0x03 ,0x80 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x20 ,0x00 ,0x60 ,0x00 ,0xe0 ,0x00 ,0xe0 , +0x01 ,0x60 ,0x03 ,0x60 ,0x02 ,0x60 ,0x04 ,0x60 ,0x04 ,0x60 ,0x08 ,0x60 ,0x10 ,0x60 ,0x10 ,0x60 , +0x20 ,0x60 ,0x60 ,0x60 ,0x7f ,0xfe ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 , +0x01 ,0xfc ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x1f ,0xf8 ,0x1f ,0xf8 ,0x10 ,0x00 ,0x10 ,0x00 , +0x10 ,0x00 ,0x10 ,0x00 ,0x10 ,0x00 ,0x10 ,0x00 ,0x17 ,0xe0 ,0x18 ,0x30 ,0x10 ,0x18 ,0x00 ,0x18 , +0x00 ,0x0c ,0x00 ,0x0c ,0x00 ,0x0c ,0x10 ,0x0c ,0x38 ,0x0c ,0x30 ,0x18 ,0x30 ,0x18 ,0x10 ,0x30 , +0x0c ,0x60 ,0x03 ,0x80 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x03 ,0xf0 ,0x04 ,0x18 ,0x08 ,0x18 ,0x18 ,0x18 , +0x10 ,0x00 ,0x30 ,0x00 ,0x30 ,0x00 ,0x30 ,0x00 ,0x33 ,0xf0 ,0x74 ,0x38 ,0x78 ,0x18 ,0x70 ,0x0c , +0x70 ,0x0c ,0x70 ,0x0c ,0x30 ,0x0c ,0x30 ,0x0c ,0x30 ,0x0c ,0x30 ,0x0c ,0x18 ,0x08 ,0x1c ,0x18 , +0x0e ,0x70 ,0x01 ,0x80 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x1f ,0xfc ,0x3f ,0xfc ,0x30 ,0x08 ,0x20 ,0x10 , +0x20 ,0x10 ,0x00 ,0x20 ,0x00 ,0x20 ,0x00 ,0x60 ,0x00 ,0x40 ,0x00 ,0xc0 ,0x00 ,0x80 ,0x01 ,0x80 , +0x01 ,0x80 ,0x01 ,0x80 ,0x03 ,0x00 ,0x03 ,0x00 ,0x03 ,0x00 ,0x03 ,0x00 ,0x03 ,0x00 ,0x07 ,0x00 , +0x03 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x0f ,0xe0 ,0x18 ,0x10 ,0x30 ,0x18 ,0x30 ,0x0c , +0x30 ,0x0c ,0x30 ,0x0c ,0x30 ,0x08 ,0x38 ,0x18 ,0x1e ,0x30 ,0x0f ,0xe0 ,0x07 ,0xe0 ,0x18 ,0xf0 , +0x30 ,0x38 ,0x30 ,0x18 ,0x60 ,0x0c ,0x60 ,0x0c ,0x60 ,0x0c ,0x60 ,0x0c ,0x30 ,0x08 ,0x10 ,0x18 , +0x0c ,0x70 ,0x03 ,0x80 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x0f ,0xc0 ,0x18 ,0x30 ,0x30 ,0x18 ,0x30 ,0x18 , +0x70 ,0x18 ,0x60 ,0x0c ,0x60 ,0x0c ,0x60 ,0x0c ,0x70 ,0x0c ,0x30 ,0x1c ,0x30 ,0x2c ,0x38 ,0x6c , +0x0f ,0xcc ,0x00 ,0x1c ,0x00 ,0x1c ,0x00 ,0x18 ,0x00 ,0x18 ,0x10 ,0x30 ,0x38 ,0x30 ,0x38 ,0x60 , +0x18 ,0xc0 ,0x07 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x03 ,0x80 ,0x03 ,0x80 ,0x03 ,0x80 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x01 ,0x80 ,0x03 ,0x80 , +0x03 ,0x80 ,0x01 ,0x80 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x03 ,0x80 ,0x03 ,0x80 ,0x03 ,0x80 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x03 ,0x80 , +0x03 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x00 ,0x03 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x08 ,0x00 ,0x10 ,0x00 ,0x20 ,0x00 ,0x40 , +0x00 ,0x80 ,0x01 ,0x00 ,0x02 ,0x00 ,0x04 ,0x00 ,0x08 ,0x00 ,0x10 ,0x00 ,0x30 ,0x00 ,0x18 ,0x00 , +0x0c ,0x00 ,0x06 ,0x00 ,0x03 ,0x00 ,0x01 ,0x80 ,0x00 ,0xc0 ,0x00 ,0x60 ,0x00 ,0x30 ,0x00 ,0x18 , +0x00 ,0x0c ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x7f ,0xfe ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x7f ,0xfe ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x20 ,0x00 ,0x30 ,0x00 ,0x18 ,0x00 ,0x0c ,0x00 ,0x06 ,0x00 , +0x03 ,0x00 ,0x01 ,0x80 ,0x00 ,0xc0 ,0x00 ,0x60 ,0x00 ,0x30 ,0x00 ,0x18 ,0x00 ,0x0c ,0x00 ,0x18 , +0x00 ,0x30 ,0x00 ,0x60 ,0x00 ,0xc0 ,0x01 ,0x80 ,0x03 ,0x00 ,0x06 ,0x00 ,0x0c ,0x00 ,0x18 ,0x00 , +0x30 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x01 ,0x80 ,0x0f ,0xf0 ,0x10 ,0x18 ,0x30 ,0x1c ,0x20 ,0x0c , +0x20 ,0x0c ,0x30 ,0x0c ,0x38 ,0x0c ,0x10 ,0x1c ,0x00 ,0x18 ,0x00 ,0x30 ,0x00 ,0xe0 ,0x01 ,0x80 , +0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x01 ,0x80 ,0x03 ,0x80 , +0x03 ,0x80 ,0x01 ,0x80 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x03 ,0xf0 ,0x0c ,0x18 ,0x08 ,0x04 ,0x10 ,0x04 , +0x30 ,0xf2 ,0x21 ,0x12 ,0x23 ,0x32 ,0x62 ,0x32 ,0x66 ,0x32 ,0x66 ,0x32 ,0x64 ,0x22 ,0x64 ,0x22 , +0x64 ,0x22 ,0x64 ,0x64 ,0x64 ,0x64 ,0x26 ,0xb8 ,0x33 ,0x10 ,0x10 ,0x02 ,0x18 ,0x04 ,0x08 ,0x08 , +0x06 ,0x70 ,0x01 ,0x80 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x01 ,0x80 ,0x03 ,0x80 ,0x03 ,0x80 ,0x02 ,0xc0 , +0x02 ,0xc0 ,0x04 ,0xc0 ,0x04 ,0xc0 ,0x04 ,0x60 ,0x04 ,0x60 ,0x08 ,0x60 ,0x08 ,0x60 ,0x08 ,0x30 , +0x08 ,0x30 ,0x17 ,0xf0 ,0x10 ,0x30 ,0x10 ,0x30 ,0x10 ,0x18 ,0x20 ,0x18 ,0x20 ,0x18 ,0x20 ,0x18 , +0x70 ,0x3e ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x7f ,0xe0 ,0x38 ,0x38 ,0x38 ,0x18 ,0x38 ,0x1c , +0x38 ,0x0c ,0x38 ,0x0c ,0x38 ,0x1c ,0x38 ,0x18 ,0x38 ,0x30 ,0x3f ,0xc0 ,0x38 ,0x70 ,0x38 ,0x18 , +0x38 ,0x0c ,0x38 ,0x0c ,0x38 ,0x0e ,0x38 ,0x0e ,0x38 ,0x0e ,0x38 ,0x0e ,0x38 ,0x0c ,0x38 ,0x18 , +0x7f ,0xf0 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x03 ,0xfc ,0x0c ,0x0c ,0x18 ,0x04 ,0x18 ,0x04 , +0x30 ,0x02 ,0x30 ,0x00 ,0x70 ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 , +0x60 ,0x00 ,0x60 ,0x00 ,0x70 ,0x00 ,0x70 ,0x02 ,0x30 ,0x02 ,0x30 ,0x04 ,0x18 ,0x04 ,0x1c ,0x08 , +0x07 ,0xf0 ,0x01 ,0x80 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x7f ,0x80 ,0x38 ,0x60 ,0x38 ,0x30 ,0x38 ,0x18 , +0x38 ,0x0c ,0x38 ,0x0c ,0x38 ,0x0c ,0x38 ,0x0e ,0x38 ,0x0e ,0x38 ,0x0e ,0x38 ,0x0e ,0x38 ,0x0e , +0x38 ,0x0e ,0x38 ,0x0e ,0x38 ,0x0c ,0x38 ,0x0c ,0x38 ,0x0c ,0x38 ,0x18 ,0x38 ,0x18 ,0x38 ,0x70 , +0x3f ,0xc0 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x7f ,0xf8 ,0x18 ,0x1c ,0x18 ,0x04 ,0x18 ,0x04 , +0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x20 ,0x18 ,0x20 ,0x1f ,0xe0 ,0x18 ,0x60 ,0x18 ,0x20 , +0x18 ,0x20 ,0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x02 ,0x18 ,0x02 ,0x18 ,0x04 ,0x18 ,0x0c , +0x7f ,0xfc ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x7f ,0xfc ,0x18 ,0x0c ,0x18 ,0x06 ,0x18 ,0x02 , +0x18 ,0x02 ,0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x10 ,0x18 ,0x10 ,0x18 ,0x30 ,0x1f ,0xf0 ,0x18 ,0x10 , +0x18 ,0x10 ,0x18 ,0x10 ,0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 , +0x7c ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x07 ,0xf8 ,0x0c ,0x38 ,0x18 ,0x18 ,0x10 ,0x08 , +0x30 ,0x08 ,0x30 ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 , +0x60 ,0x7e ,0x60 ,0x18 ,0x60 ,0x18 ,0x70 ,0x18 ,0x30 ,0x18 ,0x30 ,0x18 ,0x18 ,0x18 ,0x18 ,0x18 , +0x0e ,0x20 ,0x01 ,0xc0 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0xfc ,0x3e ,0x30 ,0x1c ,0x30 ,0x1c ,0x30 ,0x1c , +0x30 ,0x1c ,0x30 ,0x1c ,0x30 ,0x1c ,0x30 ,0x1c ,0x30 ,0x1c ,0x30 ,0x1c ,0x3f ,0xfc ,0x30 ,0x1c , +0x30 ,0x1c ,0x30 ,0x1c ,0x30 ,0x1c ,0x30 ,0x1c ,0x30 ,0x1c ,0x30 ,0x1c ,0x30 ,0x1c ,0x30 ,0x1c , +0x78 ,0x3e ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x1f ,0xf8 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 , +0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 , +0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 , +0x1f ,0xf0 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x07 ,0xfe ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 , +0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 , +0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 ,0x30 ,0x40 ,0x30 ,0xc0 , +0x3f ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x7c ,0x7e ,0x38 ,0x18 ,0x38 ,0x30 ,0x38 ,0x20 , +0x38 ,0x40 ,0x38 ,0x80 ,0x38 ,0x80 ,0x39 ,0x00 ,0x3b ,0x00 ,0x3f ,0x80 ,0x3d ,0x80 ,0x39 ,0x80 , +0x38 ,0xc0 ,0x38 ,0xc0 ,0x38 ,0x60 ,0x38 ,0x60 ,0x38 ,0x30 ,0x38 ,0x30 ,0x38 ,0x18 ,0x38 ,0x18 , +0x7c ,0x3e ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x7e ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 , +0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 , +0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x02 ,0x18 ,0x02 ,0x18 ,0x04 ,0x18 ,0x0c , +0x7f ,0xfc ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0xf0 ,0x1f ,0x30 ,0x1c ,0x30 ,0x1c ,0x38 ,0x1c , +0x38 ,0x2c ,0x38 ,0x2c ,0x38 ,0x2c ,0x28 ,0x2c ,0x2c ,0x4c ,0x2c ,0x4c ,0x2c ,0x4c ,0x2c ,0x4c , +0x24 ,0x8c ,0x26 ,0x8c ,0x26 ,0x8c ,0x26 ,0x8c ,0x22 ,0x8c ,0x23 ,0x0c ,0x23 ,0x0c ,0x23 ,0x0c , +0x73 ,0x1e ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0xf0 ,0x1f ,0x38 ,0x04 ,0x38 ,0x04 ,0x2c ,0x04 , +0x2c ,0x04 ,0x26 ,0x04 ,0x26 ,0x04 ,0x23 ,0x04 ,0x23 ,0x04 ,0x21 ,0x84 ,0x21 ,0x84 ,0x20 ,0xc4 , +0x20 ,0xc4 ,0x20 ,0x64 ,0x20 ,0x74 ,0x20 ,0x34 ,0x20 ,0x3c ,0x20 ,0x1c ,0x20 ,0x1c ,0x20 ,0x0c , +0x78 ,0x0c ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x07 ,0xe0 ,0x0c ,0x30 ,0x18 ,0x18 ,0x30 ,0x08 , +0x30 ,0x0c ,0x30 ,0x0c ,0x70 ,0x0e ,0x70 ,0x0e ,0x60 ,0x06 ,0x60 ,0x06 ,0x60 ,0x06 ,0x60 ,0x06 , +0x60 ,0x06 ,0x60 ,0x06 ,0x70 ,0x0e ,0x30 ,0x0c ,0x30 ,0x0c ,0x30 ,0x0c ,0x18 ,0x18 ,0x08 ,0x10 , +0x06 ,0x60 ,0x01 ,0x80 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x7f ,0xe0 ,0x18 ,0x18 ,0x18 ,0x0c ,0x18 ,0x0c , +0x18 ,0x0e ,0x18 ,0x0e ,0x18 ,0x0e ,0x18 ,0x0c ,0x18 ,0x0c ,0x18 ,0x18 ,0x18 ,0x70 ,0x1f ,0x80 , +0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 , +0x7c ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x07 ,0xe0 ,0x0c ,0x30 ,0x18 ,0x18 ,0x30 ,0x08 , +0x30 ,0x0c ,0x30 ,0x0c ,0x70 ,0x0c ,0x60 ,0x0e ,0x60 ,0x0e ,0x60 ,0x0e ,0x60 ,0x0e ,0x60 ,0x0e , +0x60 ,0x0e ,0x60 ,0x0e ,0x60 ,0x0e ,0x77 ,0x8c ,0x3d ,0xcc ,0x38 ,0xcc ,0x18 ,0x58 ,0x18 ,0x70 , +0x06 ,0x60 ,0x01 ,0xf0 ,0x00 ,0x3c ,0x00 ,0x3c ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x7f ,0xe0 ,0x18 ,0x38 ,0x18 ,0x18 ,0x18 ,0x0c , +0x18 ,0x0c ,0x18 ,0x0c ,0x18 ,0x0c ,0x18 ,0x1c ,0x18 ,0x18 ,0x18 ,0x70 ,0x1f ,0xc0 ,0x18 ,0xc0 , +0x18 ,0xc0 ,0x18 ,0x60 ,0x18 ,0x60 ,0x18 ,0x30 ,0x18 ,0x30 ,0x18 ,0x30 ,0x18 ,0x18 ,0x18 ,0x18 , +0x7c ,0x1e ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x0f ,0xe8 ,0x10 ,0x38 ,0x30 ,0x18 ,0x20 ,0x08 , +0x20 ,0x08 ,0x20 ,0x00 ,0x30 ,0x00 ,0x38 ,0x00 ,0x1c ,0x00 ,0x0f ,0x80 ,0x03 ,0xe0 ,0x00 ,0xf0 , +0x00 ,0x38 ,0x00 ,0x18 ,0x00 ,0x0c ,0x40 ,0x0c ,0x40 ,0x0c ,0x20 ,0x0c ,0x20 ,0x08 ,0x30 ,0x18 , +0x3c ,0x70 ,0x03 ,0x80 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x3f ,0xfc ,0x21 ,0x8c ,0x61 ,0x84 ,0x41 ,0x84 , +0x41 ,0x82 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 , +0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 , +0x07 ,0xe0 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0xfc ,0x1e ,0x30 ,0x08 ,0x30 ,0x08 ,0x30 ,0x08 , +0x30 ,0x08 ,0x30 ,0x08 ,0x30 ,0x08 ,0x30 ,0x08 ,0x30 ,0x08 ,0x30 ,0x08 ,0x30 ,0x08 ,0x30 ,0x08 , +0x30 ,0x08 ,0x30 ,0x08 ,0x30 ,0x08 ,0x30 ,0x08 ,0x30 ,0x08 ,0x30 ,0x08 ,0x30 ,0x08 ,0x18 ,0x10 , +0x0e ,0x60 ,0x01 ,0x80 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0xfc ,0x3e ,0x30 ,0x08 ,0x30 ,0x08 ,0x18 ,0x08 , +0x18 ,0x10 ,0x18 ,0x10 ,0x18 ,0x10 ,0x0c ,0x10 ,0x0c ,0x20 ,0x0c ,0x20 ,0x0c ,0x20 ,0x06 ,0x40 , +0x06 ,0x40 ,0x06 ,0x40 ,0x06 ,0x40 ,0x03 ,0x80 ,0x03 ,0x80 ,0x03 ,0x80 ,0x03 ,0x80 ,0x01 ,0x00 , +0x01 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0xfb ,0xcf ,0x61 ,0x84 ,0x61 ,0x84 ,0x21 ,0x84 , +0x31 ,0x84 ,0x31 ,0x84 ,0x31 ,0xc8 ,0x31 ,0xc8 ,0x31 ,0xc8 ,0x12 ,0xc8 ,0x12 ,0xc8 ,0x1a ,0x50 , +0x1a ,0x50 ,0x1a ,0x70 ,0x1c ,0x70 ,0x1c ,0x70 ,0x0c ,0x70 ,0x0c ,0x60 ,0x0c ,0x20 ,0x0c ,0x20 , +0x08 ,0x20 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x7c ,0x3e ,0x18 ,0x18 ,0x18 ,0x10 ,0x0c ,0x10 , +0x0c ,0x20 ,0x06 ,0x20 ,0x06 ,0x40 ,0x02 ,0x40 ,0x03 ,0x80 ,0x03 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 , +0x02 ,0xc0 ,0x02 ,0xc0 ,0x04 ,0x60 ,0x04 ,0x60 ,0x0c ,0x30 ,0x08 ,0x30 ,0x08 ,0x18 ,0x10 ,0x18 , +0x78 ,0x3e ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x7c ,0x3e ,0x30 ,0x08 ,0x18 ,0x08 ,0x18 ,0x10 , +0x18 ,0x10 ,0x0c ,0x20 ,0x0c ,0x20 ,0x06 ,0x20 ,0x06 ,0x40 ,0x06 ,0x40 ,0x03 ,0x40 ,0x03 ,0x80 , +0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 , +0x07 ,0xe0 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x1f ,0xfc ,0x18 ,0x0c ,0x30 ,0x18 ,0x20 ,0x18 , +0x00 ,0x30 ,0x00 ,0x70 ,0x00 ,0x60 ,0x00 ,0xe0 ,0x00 ,0xc0 ,0x01 ,0x80 ,0x01 ,0x80 ,0x03 ,0x00 , +0x03 ,0x00 ,0x06 ,0x00 ,0x06 ,0x00 ,0x0c ,0x00 ,0x0c ,0x00 ,0x18 ,0x04 ,0x18 ,0x04 ,0x30 ,0x0c , +0x7f ,0xf8 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x03 ,0xfc ,0x03 ,0xfc ,0x02 ,0x00 ,0x02 ,0x00 ,0x02 ,0x00 ,0x02 ,0x00 ,0x02 ,0x00 ,0x02 ,0x00 , +0x02 ,0x00 ,0x02 ,0x00 ,0x02 ,0x00 ,0x02 ,0x00 ,0x02 ,0x00 ,0x02 ,0x00 ,0x02 ,0x00 ,0x02 ,0x00 , +0x02 ,0x00 ,0x02 ,0x00 ,0x02 ,0x00 ,0x02 ,0x00 ,0x02 ,0x00 ,0x02 ,0x00 ,0x02 ,0x00 ,0x02 ,0x00 , +0x02 ,0x00 ,0x02 ,0x00 ,0x02 ,0x00 ,0x03 ,0xfc ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x10 ,0x00 ,0x10 ,0x00 ,0x18 ,0x00 ,0x08 ,0x00 ,0x0c ,0x00 , +0x04 ,0x00 ,0x04 ,0x00 ,0x06 ,0x00 ,0x02 ,0x00 ,0x03 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x80 , +0x00 ,0x80 ,0x00 ,0xc0 ,0x00 ,0x40 ,0x00 ,0x40 ,0x00 ,0x60 ,0x00 ,0x20 ,0x00 ,0x30 ,0x00 ,0x10 , +0x00 ,0x10 ,0x00 ,0x18 ,0x00 ,0x08 ,0x00 ,0x0c ,0x00 ,0x04 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x3f ,0xc0 ,0x3f ,0xc0 ,0x00 ,0xc0 ,0x00 ,0xc0 ,0x00 ,0xc0 ,0x00 ,0xc0 ,0x00 ,0xc0 ,0x00 ,0xc0 , +0x00 ,0xc0 ,0x00 ,0xc0 ,0x00 ,0xc0 ,0x00 ,0xc0 ,0x00 ,0xc0 ,0x00 ,0xc0 ,0x00 ,0xc0 ,0x00 ,0xc0 , +0x00 ,0xc0 ,0x00 ,0xc0 ,0x00 ,0xc0 ,0x00 ,0xc0 ,0x00 ,0xc0 ,0x00 ,0xc0 ,0x00 ,0xc0 ,0x00 ,0xc0 , +0x00 ,0xc0 ,0x00 ,0xc0 ,0x00 ,0xc0 ,0x3f ,0xc0 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x03 ,0xc0 ,0x06 ,0xe0 ,0x0c ,0x20 ,0x00 ,0x10 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0xff ,0xff ,0x00 ,0x00 ,0x00 ,0x00 , +0x1e ,0x00 ,0x07 ,0x00 ,0x01 ,0x80 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x07 ,0xc0 ,0x18 ,0x30 ,0x30 ,0x10 ,0x30 ,0x18 ,0x00 ,0x18 , +0x00 ,0x78 ,0x07 ,0x98 ,0x18 ,0x18 ,0x30 ,0x18 ,0x70 ,0x18 ,0x60 ,0x18 ,0x60 ,0x18 ,0x30 ,0x3a , +0x1f ,0xde ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x10 ,0x00 ,0x70 ,0x00 ,0x30 ,0x00 ,0x30 ,0x00 ,0x30 ,0x00 , +0x30 ,0x00 ,0x30 ,0x00 ,0x30 ,0x00 ,0x31 ,0xc0 ,0x32 ,0x30 ,0x34 ,0x18 ,0x38 ,0x0c ,0x38 ,0x0c , +0x30 ,0x0c ,0x30 ,0x0c ,0x30 ,0x0c ,0x30 ,0x0c ,0x30 ,0x0c ,0x30 ,0x0c ,0x30 ,0x18 ,0x38 ,0x18 , +0x37 ,0xf0 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x03 ,0xe0 ,0x0c ,0x30 ,0x18 ,0x18 ,0x18 ,0x18 ,0x30 ,0x18 , +0x30 ,0x00 ,0x30 ,0x00 ,0x30 ,0x00 ,0x30 ,0x00 ,0x30 ,0x00 ,0x30 ,0x04 ,0x18 ,0x08 ,0x18 ,0x08 , +0x0f ,0x70 ,0x00 ,0xc0 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x08 ,0x00 ,0x78 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 ,0x18 , +0x00 ,0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x03 ,0x98 ,0x0e ,0x78 ,0x18 ,0x18 ,0x18 ,0x18 ,0x30 ,0x18 , +0x30 ,0x18 ,0x30 ,0x18 ,0x30 ,0x18 ,0x30 ,0x18 ,0x30 ,0x18 ,0x30 ,0x18 ,0x10 ,0x18 ,0x18 ,0x38 , +0x0f ,0xde ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x03 ,0xc0 ,0x0c ,0x30 ,0x18 ,0x18 ,0x10 ,0x18 ,0x30 ,0x0c , +0x30 ,0x0c ,0x30 ,0x0c ,0x3f ,0xf0 ,0x30 ,0x00 ,0x30 ,0x00 ,0x30 ,0x00 ,0x18 ,0x08 ,0x18 ,0x08 , +0x07 ,0x70 ,0x00 ,0xc0 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0xf8 ,0x01 ,0x06 ,0x03 ,0x06 ,0x02 ,0x04 , +0x02 ,0x00 ,0x06 ,0x00 ,0x06 ,0x00 ,0x3f ,0xf8 ,0x06 ,0x00 ,0x06 ,0x00 ,0x06 ,0x00 ,0x06 ,0x00 , +0x06 ,0x00 ,0x06 ,0x00 ,0x06 ,0x00 ,0x06 ,0x00 ,0x06 ,0x00 ,0x06 ,0x00 ,0x06 ,0x00 ,0x06 ,0x00 , +0x1f ,0xe0 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x03 ,0x8e ,0x0c ,0x76 ,0x18 ,0x30 ,0x10 ,0x10 ,0x10 ,0x10 , +0x10 ,0x10 ,0x18 ,0x10 ,0x08 ,0x30 ,0x0e ,0xe0 ,0x11 ,0x00 ,0x10 ,0x00 ,0x1f ,0x80 ,0x0f ,0xf8 , +0x10 ,0x3c ,0x20 ,0x0c ,0x20 ,0x0c ,0x20 ,0x0c ,0x10 ,0x18 ,0x0f ,0xf0 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x10 ,0x00 ,0x70 ,0x00 ,0x10 ,0x00 ,0x10 ,0x00 ,0x10 ,0x00 , +0x10 ,0x00 ,0x10 ,0x00 ,0x10 ,0x00 ,0x11 ,0xe0 ,0x17 ,0x30 ,0x1c ,0x18 ,0x18 ,0x18 ,0x10 ,0x18 , +0x10 ,0x18 ,0x10 ,0x18 ,0x10 ,0x18 ,0x10 ,0x18 ,0x10 ,0x18 ,0x10 ,0x18 ,0x10 ,0x18 ,0x10 ,0x18 , +0x7c ,0x3c ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x01 ,0x80 ,0x03 ,0xc0 ,0x01 ,0x80 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x80 ,0x1f ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 , +0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 , +0x0f ,0xf0 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x38 ,0x00 ,0x38 ,0x00 ,0x30 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x01 ,0xf0 ,0x00 ,0x30 ,0x00 ,0x30 ,0x00 ,0x30 ,0x00 ,0x30 , +0x00 ,0x30 ,0x00 ,0x30 ,0x00 ,0x30 ,0x00 ,0x30 ,0x00 ,0x30 ,0x00 ,0x30 ,0x00 ,0x30 ,0x00 ,0x30 , +0x00 ,0x30 ,0x00 ,0x30 ,0x00 ,0x30 ,0x38 ,0x20 ,0x18 ,0x60 ,0x0f ,0x80 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x08 ,0x00 ,0x78 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 , +0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x7c ,0x18 ,0x30 ,0x18 ,0x60 ,0x18 ,0x40 ,0x18 ,0x80 , +0x19 ,0x00 ,0x1b ,0x80 ,0x1c ,0xc0 ,0x18 ,0xc0 ,0x18 ,0x60 ,0x18 ,0x70 ,0x18 ,0x30 ,0x18 ,0x18 , +0x7c ,0x3c ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x01 ,0x80 ,0x1f ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 , +0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 , +0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 , +0x1f ,0xf0 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0xe7 ,0x38 ,0x69 ,0xcc ,0x71 ,0x84 ,0x61 ,0x86 ,0x61 ,0x86 , +0x61 ,0x86 ,0x61 ,0x86 ,0x61 ,0x86 ,0x61 ,0x86 ,0x61 ,0x86 ,0x61 ,0x86 ,0x61 ,0x86 ,0x61 ,0x86 , +0x73 ,0xce ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x71 ,0xe0 ,0x12 ,0x30 ,0x1c ,0x18 ,0x18 ,0x18 ,0x10 ,0x18 , +0x10 ,0x18 ,0x10 ,0x18 ,0x10 ,0x18 ,0x10 ,0x18 ,0x10 ,0x18 ,0x10 ,0x18 ,0x10 ,0x18 ,0x10 ,0x18 , +0x7c ,0x3c ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x03 ,0xc0 ,0x0c ,0x30 ,0x18 ,0x18 ,0x30 ,0x08 ,0x30 ,0x0c , +0x30 ,0x0c ,0x60 ,0x0c ,0x60 ,0x0c ,0x60 ,0x0c ,0x30 ,0x0c ,0x30 ,0x0c ,0x30 ,0x08 ,0x18 ,0x18 , +0x0c ,0x20 ,0x03 ,0xc0 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x71 ,0xc0 ,0x36 ,0x30 ,0x14 ,0x18 ,0x18 ,0x0c ,0x10 ,0x0c , +0x10 ,0x0c ,0x10 ,0x0c ,0x10 ,0x0c ,0x10 ,0x0c ,0x10 ,0x0c ,0x10 ,0x0c ,0x18 ,0x18 ,0x18 ,0x18 , +0x16 ,0x70 ,0x11 ,0x80 ,0x10 ,0x00 ,0x10 ,0x00 ,0x10 ,0x00 ,0x7e ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x03 ,0x88 ,0x0c ,0x68 ,0x18 ,0x18 ,0x30 ,0x18 ,0x30 ,0x18 , +0x30 ,0x18 ,0x30 ,0x18 ,0x30 ,0x18 ,0x30 ,0x18 ,0x30 ,0x18 ,0x30 ,0x18 ,0x30 ,0x18 ,0x18 ,0x38 , +0x0f ,0xd8 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 ,0x18 ,0x00 ,0x7e ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x7c ,0x38 ,0x0c ,0x4c ,0x0c ,0x8c ,0x0d ,0x00 ,0x0e ,0x00 , +0x0c ,0x00 ,0x0c ,0x00 ,0x0c ,0x00 ,0x0c ,0x00 ,0x0c ,0x00 ,0x0c ,0x00 ,0x0c ,0x00 ,0x0c ,0x00 , +0x7f ,0xc0 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x03 ,0xc8 ,0x0c ,0x38 ,0x18 ,0x18 ,0x18 ,0x08 ,0x18 ,0x00 , +0x1c ,0x00 ,0x0f ,0x80 ,0x01 ,0xe0 ,0x00 ,0x78 ,0x00 ,0x18 ,0x10 ,0x0c ,0x10 ,0x08 ,0x18 ,0x08 , +0x1f ,0xf0 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x02 ,0x00 , +0x02 ,0x00 ,0x02 ,0x00 ,0x06 ,0x00 ,0x3f ,0xf0 ,0x02 ,0x00 ,0x02 ,0x00 ,0x02 ,0x00 ,0x02 ,0x00 , +0x02 ,0x00 ,0x02 ,0x00 ,0x02 ,0x00 ,0x02 ,0x00 ,0x02 ,0x00 ,0x02 ,0x04 ,0x02 ,0x08 ,0x03 ,0x08 , +0x01 ,0xf0 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x70 ,0x78 ,0x30 ,0x18 ,0x30 ,0x18 ,0x30 ,0x18 ,0x30 ,0x18 , +0x30 ,0x18 ,0x30 ,0x18 ,0x30 ,0x18 ,0x30 ,0x18 ,0x30 ,0x18 ,0x10 ,0x18 ,0x10 ,0x18 ,0x18 ,0x38 , +0x0f ,0xde ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x7c ,0x3e ,0x18 ,0x18 ,0x18 ,0x10 ,0x18 ,0x10 ,0x0c ,0x10 , +0x0c ,0x20 ,0x0c ,0x20 ,0x06 ,0x20 ,0x06 ,0x40 ,0x02 ,0x40 ,0x03 ,0x80 ,0x03 ,0x80 ,0x01 ,0x80 , +0x01 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0xfb ,0xdf ,0x61 ,0x84 ,0x21 ,0x84 ,0x31 ,0x84 ,0x31 ,0x88 , +0x31 ,0xc8 ,0x12 ,0xc8 ,0x12 ,0xc8 ,0x1a ,0x50 ,0x1a ,0x50 ,0x0c ,0x70 ,0x0c ,0x70 ,0x0c ,0x20 , +0x0c ,0x20 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x3e ,0x7c ,0x1c ,0x10 ,0x0c ,0x30 ,0x06 ,0x20 ,0x06 ,0x40 , +0x03 ,0xc0 ,0x01 ,0x80 ,0x01 ,0x80 ,0x03 ,0xc0 ,0x02 ,0x40 ,0x04 ,0x60 ,0x08 ,0x30 ,0x08 ,0x30 , +0x78 ,0x7c ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x7e ,0x7e ,0x18 ,0x18 ,0x18 ,0x10 ,0x0c ,0x10 ,0x0c ,0x30 , +0x0c ,0x20 ,0x06 ,0x20 ,0x06 ,0x60 ,0x02 ,0x40 ,0x03 ,0x40 ,0x03 ,0x80 ,0x01 ,0x80 ,0x01 ,0x80 , +0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x02 ,0x00 ,0x3e ,0x00 ,0x1c ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x1f ,0xf8 ,0x38 ,0x30 ,0x30 ,0x30 ,0x20 ,0x60 ,0x20 ,0xc0 , +0x00 ,0xc0 ,0x01 ,0x80 ,0x03 ,0x00 ,0x03 ,0x00 ,0x06 ,0x04 ,0x0c ,0x08 ,0x0c ,0x08 ,0x18 ,0x08 , +0x3f ,0xf8 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x0c ,0x00 ,0x30 ,0x00 ,0x20 ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 , +0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x40 ,0x00 ,0x40 ,0x00 ,0xc0 ,0x01 ,0x00 ,0x00 ,0xc0 , +0x00 ,0x40 ,0x00 ,0x40 ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 ,0x00 ,0x60 , +0x00 ,0x60 ,0x00 ,0x20 ,0x00 ,0x20 ,0x00 ,0x38 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 , +0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 , +0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 , +0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x01 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x30 ,0x00 ,0x0c ,0x00 ,0x04 ,0x00 ,0x04 ,0x00 ,0x04 ,0x00 ,0x04 ,0x00 ,0x04 ,0x00 ,0x04 ,0x00 , +0x04 ,0x00 ,0x04 ,0x00 ,0x04 ,0x00 ,0x04 ,0x00 ,0x06 ,0x00 ,0x03 ,0x00 ,0x00 ,0x80 ,0x03 ,0x00 , +0x06 ,0x00 ,0x04 ,0x00 ,0x04 ,0x00 ,0x04 ,0x00 ,0x04 ,0x00 ,0x04 ,0x00 ,0x04 ,0x00 ,0x04 ,0x00 , +0x04 ,0x00 ,0x04 ,0x00 ,0x04 ,0x00 ,0x18 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x23 ,0x02 ,0x41 ,0x82 ,0x40 ,0xc4 ,0x00 ,0x6c ,0x00 ,0x30 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 , diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/mpp_help/include/vgs_img.h b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/mpp_help/include/vgs_img.h new file mode 100644 index 0000000..030aa9f --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/mpp_help/include/vgs_img.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VGS_IMG_H +#define VGS_IMG_H + +#include +#include + +#include "hi_common.h" +#include "hi_comm_video.h" +#include "hi_comm_venc.h" +#include "ai_infer_process.h" + +#if __cplusplus +extern "C" { +#endif + +/* Commonly used numerical units */ +#define HI_KB 1024 +#define HI_MB (1024 * 1024) +#define HI_MS_OF_SEC 1000 // 1s in milliseconds +#define HI_NS_OF_MS 1000000 // Nanoseconds in 1ms +#define HI_BYTE_BITS 8 // Number of bits in 1 byte +#define HI_INT8_BITS 8 // 8-bit integer number of bits +#define HI_INT16_BITS 16 // 16-bit integer number of bits +#define HI_INT32_BITS 32 // 32-bit integer number of bits +#define HI_INT64_BITS 64 // The number of bits of a 64-bit integer + +/* + * resize frame. + * Call vgs_resize multiple times to achieve arbitrary scaling. + * In order to simplify the implementation, it is agreed that each zoom is up to 14 times, + * and at this time, the width and height only need to be aligned by 2 pixels. + * When the zoom directions are different in the two directions, for example, + * one direction (such as X) zooms in and the other direction zooms in, no special processing is required. + * At this time, the zoom ratio in one direction or both directions exceeds the standard, + * and no special treatment is required. + */ +int MppFrmResize( + const VIDEO_FRAME_INFO_S* src, + VIDEO_FRAME_INFO_S* dst, + uint32_t dstWidth, uint32_t dstHeight); + +/* Destory frame */ +void MppFrmDestroy(VIDEO_FRAME_INFO_S* frm); + +/* Superimpose one or more rectangular boxes in the frame */ +int MppFrmDrawRects(VIDEO_FRAME_INFO_S *frm, + const RectBox *boxes, int boxesNum, uint32_t color, int thick); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/mpp_help/src/ive_img.c b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/mpp_help/src/ive_img.c new file mode 100644 index 0000000..3a55e67 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/mpp_help/src/ive_img.c @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +#include "hi_comm_vb.h" +#include "mpi_sys.h" +#include "ive_img.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* End of #ifdef __cplusplus */ + +#define HALF_THE_HEIGHT 2 // Half the height + +HI_U32 HiAlign16(HI_U32 num) +{ + return (((num) + 16 - 1) / 16 * 16); // 16: align 16 +} + +HI_U32 HiAlign32(HI_U32 num) +{ + return (((num) + 32 - 1) / 32 * 32); // 32: align 32 +} + +/* + * video frame to ive image. + * Copy the data pointer, do not copy the data. + */ +int FrmToOrigImg(const VIDEO_FRAME_INFO_S* frm, IVE_IMAGE_S *img) +{ + static const int chnNum = 2; // Currently only supports YUV420/422, so only the addresses of 2 channels are copied + PIXEL_FORMAT_E pixelFormat = frm->stVFrame.enPixelFormat; + + if (memset_s(img, sizeof(*img), 0, sizeof(*img)) != EOK) { + HI_ASSERT(0); + } + + img->u32Width = frm->stVFrame.u32Width; + img->u32Height = frm->stVFrame.u32Height; + + if (pixelFormat == PIXEL_FORMAT_YVU_SEMIPLANAR_420) { + img->enType = IVE_IMAGE_TYPE_YUV420SP; + } else if (pixelFormat == PIXEL_FORMAT_YVU_SEMIPLANAR_422) { + img->enType = IVE_IMAGE_TYPE_YUV422SP; + } else { + HI_ASSERT(0); + return -1; + } + + for (int i = 0; i < chnNum; i++) { + img->au64PhyAddr[i] = frm->stVFrame.u64PhyAddr[i]; + img->au64VirAddr[i] = frm->stVFrame.u64VirAddr[i]; + img->au32Stride[i] = frm->stVFrame.u32Stride[i]; + } + return 0; +} + +/* Calculate the stride of a channel */ +static uint32_t IveCalStride(IVE_IMAGE_TYPE_E enType, uint32_t width, AlignType align) +{ + uint32_t size = 1; + + switch (enType) { + case IVE_IMAGE_TYPE_U8C1: + case IVE_IMAGE_TYPE_S8C1: + case IVE_IMAGE_TYPE_S8C2_PACKAGE: + case IVE_IMAGE_TYPE_S8C2_PLANAR: + case IVE_IMAGE_TYPE_U8C3_PACKAGE: + case IVE_IMAGE_TYPE_U8C3_PLANAR: + size = sizeof(HI_U8); + break; + case IVE_IMAGE_TYPE_S16C1: + case IVE_IMAGE_TYPE_U16C1: + size = sizeof(HI_U16); + break; + case IVE_IMAGE_TYPE_S32C1: + case IVE_IMAGE_TYPE_U32C1: + size = sizeof(uint32_t); + break; + case IVE_IMAGE_TYPE_S64C1: + case IVE_IMAGE_TYPE_U64C1: + size = sizeof(uint64_t); + break; + default: + break; + } + + if (align == ALIGN_TYPE_16) { + return HiAlign16(width * size); + } else if (align == ALIGN_TYPE_32) { + return HiAlign32(width * size); + } else { + HI_ASSERT(0); + return 0; + } +} + +/* Create ive image buffer based on type and size */ +int IveImgCreate(IVE_IMAGE_S* img, + IVE_IMAGE_TYPE_E enType, uint32_t width, uint32_t height) +{ + HI_ASSERT(img); + uint32_t oneChnSize; + uint32_t size; + int ret; + + if (memset_s(img, sizeof(*img), 0, sizeof(*img)) != EOK) { + HI_ASSERT(0); + } + img->enType = enType; + img->u32Width = width; + img->u32Height = height; + img->au32Stride[0] = IveCalStride(img->enType, img->u32Width, ALIGN_TYPE_16); + + switch (enType) { + case IVE_IMAGE_TYPE_U8C1: + case IVE_IMAGE_TYPE_S8C1: // Only 1 channel + size = img->au32Stride[0] * img->u32Height; + ret = HI_MPI_SYS_MmzAlloc(&img->au64PhyAddr[0], (void**)&img->au64VirAddr[0], NULL, NULL, size); + SAMPLE_CHECK_EXPR_RET(HI_SUCCESS != ret, ret, "Error(%#x), HI_MPI_SYS_MmzAlloc!\n", ret); + break; + // The size is equivalent to 1.5 times (3/2) of the pixel, which is equivalent to 2 channels + case IVE_IMAGE_TYPE_YUV420SP: + // The size is equivalent to 2 times the pixel, which is equivalent to 2 channels + case IVE_IMAGE_TYPE_YUV422SP: + if (enType == IVE_IMAGE_TYPE_YUV420SP) { + size = img->au32Stride[0] * img->u32Height * THREE_TIMES / TWO_TIMES; + } else { + size = img->au32Stride[0] * img->u32Height * TWO_TIMES; + } + ret = HI_MPI_SYS_MmzAlloc(&img->au64PhyAddr[0], (void**)&img->au64VirAddr[0], NULL, NULL, size); + SAMPLE_CHECK_EXPR_RET(HI_SUCCESS != ret, ret, "Error(%#x), HI_MPI_SYS_MmzAlloc!\n", ret); + + // Set the stride of the address of channel 1, both of which require channel 1 + img->au32Stride[1] = img->au32Stride[0]; + img->au64PhyAddr[1] = img->au64PhyAddr[0] + img->au32Stride[0] * (uint64_t)img->u32Height; + img->au64VirAddr[1] = img->au64VirAddr[0] + img->au32Stride[0] * (uint64_t)img->u32Height; + break; + + case IVE_IMAGE_TYPE_U8C3_PLANAR: // 3 channels, often used for RGB + oneChnSize = img->au32Stride[0] * img->u32Height; + size = oneChnSize * 3; // 3 channels have the same size + ret = HI_MPI_SYS_MmzAlloc(&img->au64PhyAddr[0], (void**)&img->au64VirAddr[0], NULL, NULL, size); + SAMPLE_CHECK_EXPR_RET(HI_SUCCESS != ret, ret, "Error(%#x), HI_MPI_SYS_MmzAlloc!\n", ret); + + // Set the address and stride of channel 1 and channel 2 + img->au64VirAddr[1] = img->au64VirAddr[0] + oneChnSize; + img->au64PhyAddr[1] = img->au64PhyAddr[0] + oneChnSize; + img->au32Stride[1] = img->au32Stride[0]; + img->au64VirAddr[2] = img->au64VirAddr[1] + oneChnSize; // 2: au64VirAddr array subscript, not out of bounds + img->au64PhyAddr[2] = img->au64PhyAddr[1] + oneChnSize; // 2: au64VirAddr array subscript, not out of bounds + img->au32Stride[2] = img->au32Stride[0]; // 2: au64VirAddr array subscript, not out of bounds + break; + + // Types not currently supported: YVC420P, YUV422P, S8C2_PACKAGE, S8C2_PLANAR, + // S32C1, U32C1, S64C1, U64C1, S16C1, U16C1, U8C3_PACKAGE,etc. + default: + HI_ASSERT(0); + break; + } + return HI_SUCCESS; +} + +int ImgYuvCrop(const IVE_IMAGE_S *src, IVE_IMAGE_S *dst, const RectBox* origBox) +{ + RectBox box = *origBox; + int boxWidth = box.xmax - box.xmin; + int boxHeight = box.ymax - box.ymin; + int ret; + + HI_ASSERT(boxWidth > 0 && boxWidth <= src->u32Width); + HI_ASSERT(boxHeight > 0 && boxHeight <= src->u32Height); + HI_ASSERT(src->au64VirAddr[0]); + HI_ASSERT(src->au32Stride[0] >= src->u32Width); + + // Adjust the width/height of the box to a multiple of 2 + if (boxWidth == 1 || boxHeight == 1) { + SAMPLE_PRT("box dstWidth=1 && dstHeight=1\n"); + return -1; + } + if (boxWidth % HI_OVEN_BASE) { + box.xmax--; + boxWidth--; + } + if (boxHeight % HI_OVEN_BASE) { + box.ymax--; + boxHeight--; + } + // Create empty dst img + ret = IveImgCreate(dst, src->enType, boxWidth, boxHeight); + HI_ASSERT(!ret); + // Use IVE DMA to copy to improve performance + // copy box from src to dst + // Y + int srcStrideY = src->au32Stride[0]; + int dstStrideY = dst->au32Stride[0]; + uint8_t *srcBufY = (uint8_t*)((uintptr_t)src->au64VirAddr[0]); + uint8_t *dstBufY = (uint8_t*)((uintptr_t)dst->au64VirAddr[0]); + uint8_t *srcPtrY = &srcBufY[box.ymin * srcStrideY]; + uint8_t *dstPtrY = dstBufY; + for (int h = 0; h < boxHeight; h++, srcPtrY += srcStrideY, dstPtrY += dstStrideY) { + if (memcpy_s(dstPtrY, boxWidth, srcPtrY + box.xmin, boxWidth) != EOK) { + HI_ASSERT(0); + } + } + HI_ASSERT(dstPtrY - dstBufY == boxHeight * dstStrideY); + + // UV + int srcStrideUV = src->au32Stride[1]; + int dstStrideUV = dst->au32Stride[1]; + uint8_t *srcBufUV = (uint8_t*)((uintptr_t)src->au64VirAddr[1]); + uint8_t *dstBufUV = (uint8_t*)((uintptr_t)dst->au64VirAddr[1]); + uint8_t *srcPtrUV = &srcBufUV[(box.ymin / HALF_THE_HEIGHT) * srcStrideUV]; + uint8_t *dstPtrUV = dstBufUV; + for (int h = 0; h < (boxHeight / HALF_THE_HEIGHT); + h++, srcPtrUV += srcStrideUV, dstPtrUV += dstStrideUV) { + if (memcpy_s(dstPtrUV, boxWidth, srcPtrUV + box.xmin, boxWidth) != EOK) { + HI_ASSERT(0); + } + } + HI_ASSERT(dstPtrUV - dstBufUV == (boxHeight / HALF_THE_HEIGHT) * dstStrideUV); + + return ret; +} + +/* Destory ive Image */ +void IveImgDestroy(IVE_IMAGE_S* img) +{ + for (int i = 0; i < IMG_FULL_CHN; i++) { + if (img->au64PhyAddr[0] && img->au64VirAddr[0]) { + HI_MPI_SYS_MmzFree(img->au64PhyAddr[i], (void*)((uintptr_t)img->au64VirAddr[i])); + img->au64PhyAddr[i] = 0; + img->au64VirAddr[i] = 0; + } + } + if (memset_s(img, sizeof(*img), 0, sizeof(*img)) != EOK) { + HI_ASSERT(0); + } +} + +int OrigImgToFrm(const IVE_IMAGE_S *img, VIDEO_FRAME_INFO_S* frm) +{ + static const int chnNum = 2; + IVE_IMAGE_TYPE_E enType = img->enType; + if (memset_s(frm, sizeof(*frm), 0, sizeof(*frm)) != EOK) { + HI_ASSERT(0); + } + + frm->stVFrame.u32Width = img->u32Width; + frm->stVFrame.u32Height = img->u32Height; + + if (enType == IVE_IMAGE_TYPE_YUV420SP) { + frm->stVFrame.enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420; + } else if (enType == IVE_IMAGE_TYPE_YUV422SP) { + frm->stVFrame.enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_422; + } else { + HI_ASSERT(0); + return -1; + } + + for (int i = 0; i < chnNum; i++) { + frm->stVFrame.u64PhyAddr[i] = img->au64PhyAddr[i]; + frm->stVFrame.u64VirAddr[i] = img->au64VirAddr[i]; + frm->stVFrame.u32Stride[i] = img->au32Stride[i]; + } + return 0; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* End of #ifdef __cplusplus */ diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/mpp_help/src/osd_img.c b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/mpp_help/src/osd_img.c new file mode 100644 index 0000000..8e445d7 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/mpp_help/src/osd_img.c @@ -0,0 +1,1080 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include "mpi_vi.h" +#include "mpi_vpss.h" +#include "mpi_venc.h" +#include "mpi_vo.h" +#include "mpi_region.h" +#include "sample_comm_ive.h" +#include "sample_media_ai.h" +#include "vgs_img.h" +#include "osd_img.h" + +/* OSD font library */ +static const HI_U8 G_FONT_LIB[] __attribute__((aligned(4))) = { +#include "simsunb_16x32.txt" +}; + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* End of #ifdef __cplusplus */ + +#define OSD_FONT_WIDTH_DEF 40 // Default font width +#define OSD_FONT_HEIGHT_DEF 40 // The default font height +#define NOASCII_CHARACTER_BYTES (2) /* Number of bytes occupied by each Chinese character */ +#define BYTE_BITS (8) + +#define OSD_FONT_ASC +#define OSD_FONT_MOD_W 16 +#define OSD_FONT_MOD_H 32 +#define X_COORDINATE 100 +#define Y_COORDINATE 100 +#define BASE_YAER 1900 +#define MULTIPLE_NUM 100 + +/* + * Global object. + * Multiple OsdSet instances will allocate ids from the global pool. + */ +static void* g_osdHndPool[HI_OSD_MAX_CNT]; // Used to identify whether the index handle is used +static pthread_mutex_t g_osdMutex; // pool access lock +/* OSD Parameter Array */ +static OSD_PARAM_S s_stOSDParam[HI_OSD_MAX_CNT]; + +/* OSD Module Init Flag + * Canbe modified only by HI_PDT_OSD_Init/HI_PDT_OSD_DeInit + */ +static HI_BOOL s_bOSDInitFlg = HI_FALSE; + +/* OSD Fonts Lib, inited by HI_PDT_OSD_Init */ +static HI_OSD_FONTS_S s_stOSDFonts; + +/** OSD Time Update Runing Flag + Canbe modified only by HI_PDT_OSD_Init/HI_PDT_OSD_DeInit */ +static HI_BOOL s_bOSDTimeRun = HI_FALSE; + +/* Time OSD Update Task Thread ID, created by HI_PDT_OSD_Init, destroyed by HI_OSD_DeInit */ +static pthread_t s_OSDTimeTskId = 0; + +static HI_OSD_TEXTBITMAP_S s_stOSDTextBitMap; + +static HI_U8* FontMod = NULL; +static HI_S32 FontModLen = 0; + +/* Bitmap Row/Col Index */ +static HI_S32 s32BmRow; +static HI_S32 s32BmCol; +struct tm stTime = {0}; + +/* OSD Font Step In Lib, in bytes */ +#define OSD_LIB_FONT_W (s_stOSDFonts.u32FontWidth) +#define OSD_LIB_FONT_H (s_stOSDFonts.u32FontHeight) +#define OSD_LIB_FONT_STEP (OSD_LIB_FONT_W * OSD_LIB_FONT_H / BYTE_BITS) + +/* Value Align */ +HI_S32 HiAppcommAlign(HI_S32 value, HI_S32 base) +{ + return (((value) + (base)-1) / (base) * (base)); +} + +HI_U32 max(HI_U32 a, HI_U32 b) +{ + return (((a) < (b)) ? (b) : (a)); +} + +HI_U32 min(HI_U32 a, HI_U32 b) +{ + return (((a) > (b)) ? (b) : (a)); +} + +HI_S32 IsAscii(HI_S32 a) +{ + return (((a) >= 0x00 && (a) <= 0x7F) ? 1 : 0); +} + +static HI_S32 OSD_GetNonASCNum(HI_CHAR* string, HI_S32 len) +{ + HI_S32 i; + HI_S32 n = 0; + for (i = 0; i < len; i++) { + if (string[i] == '\0') { + break; + } + if (!IsAscii(string[i])) { + i++; + n++; + } + } + return n; +} + +/* Creat OsdSet */ +OsdSet* OsdsCreate(HI_OSD_BIND_MOD_E bindMod, HI_U32 modHnd, HI_U32 chnHnd) +{ + OsdSet *self = NULL; + + self = (OsdSet*)malloc(sizeof(*self)); + if (!self) { + HI_ASSERT(0); + } + if (memset_s(self, sizeof(*self), 0, sizeof(*self)) != EOK) { + HI_ASSERT(0); + } + + self->bindMod = bindMod; + self->modHnd = modHnd; + self->chnHnd = chnHnd; + return self; +} + +/* + * @brief get time string with given format + * @param[in]pstTime : time struct, get current system time if null + * @param[out]pazStr : time string buffer + * @param[in]s32Len : time string buffer length + */ +static HI_VOID OSD_GetTimeStr(struct tm* pstTime, HI_CHAR* pazStr, HI_S32 s32Len) +{ + /* Get Time */ + time_t nowTime; + + if (!pstTime) { + time(&nowTime); + localtime_r(&nowTime, pstTime); + } + + /* Generate Time String */ + if (snprintf_s(pazStr, s32Len, s32Len - 1, "%04d-%02d-%02d %02d:%02d:%02d", + pstTime->tm_year + BASE_YAER, pstTime->tm_mon + 1, pstTime->tm_mday, + pstTime->tm_hour, pstTime->tm_min, pstTime->tm_sec) < 0) { + HI_ASSERT(0); + } + + return; +} + +static HI_S32 OSD_RGNDetach(RGN_HANDLE RgnHdl, const HI_OSD_DISP_ATTR_S* pstDispAttr) +{ + HI_S32 s32Ret = HI_SUCCESS; + MPP_CHN_S stChn; + + stChn.s32DevId = pstDispAttr->ModHdl; + stChn.s32ChnId = pstDispAttr->ChnHdl; + switch (pstDispAttr->enBindedMod) { + case HI_OSD_BINDMOD_VI: + stChn.enModId = HI_ID_VI; + break; + case HI_OSD_BINDMOD_VPSS: + stChn.enModId = HI_ID_VPSS; + break; + case HI_OSD_BINDMOD_AVS: + stChn.enModId = HI_ID_AVS; + break; + case HI_OSD_BINDMOD_VENC: + stChn.s32DevId = 0; + stChn.enModId = HI_ID_VENC; + break; + case HI_OSD_BINDMOD_VO: + stChn.enModId = HI_ID_VO; + break; + default: + SAMPLE_PRT("RgnHdl[%d] invalide bind mode [%d]\n", RgnHdl, pstDispAttr->enBindedMod); + return HI_EINVAL; + } + + s32Ret = HI_MPI_RGN_DetachFromChn(RgnHdl, &stChn); + if (s32Ret != HI_SUCCESS) { + SAMPLE_PRT("HI_MPI_RGN_DetachFromChn fail,RgnHdl[%d] stChn[%d,%d,%d] Error Code: [0x%08X]\n", + RgnHdl, stChn.enModId, stChn.s32DevId, stChn.s32ChnId, s32Ret); + return s32Ret; + } + + return HI_SUCCESS; +} + +static HI_S32 OSD_DestroyRGN(RGN_HANDLE RgnHdl, const HI_OSD_ATTR_S* pstAttr) +{ + HI_S32 s32Ret = HI_SUCCESS; + HI_S32 s32DispIdx = 0; + + for (s32DispIdx = 0; s32DispIdx < pstAttr->u32DispNum ; ++s32DispIdx) { + if (pstAttr->astDispAttr[s32DispIdx].bShow) { + OSD_RGNDetach(RgnHdl, &pstAttr->astDispAttr[s32DispIdx]); + } + } + + s32Ret = HI_MPI_RGN_Destroy(RgnHdl); + if (s32Ret != HI_SUCCESS) { + SAMPLE_PRT("HI_MPI_RGN_Destroy fail, RgnHdl[%d] Error Code: [0x%08X]\n", RgnHdl, s32Ret); + return s32Ret; + } + + return HI_SUCCESS; +} + +/* Create a region in OsdSet */ +int OsdsCreateRgn(OsdSet* self) +{ + HI_ASSERT(self); + int ret = -1; + + MutexLock(&g_osdMutex); + for (int i = 0; i < HI_OSD_MAX_CNT; i++) { + if (!g_osdHndPool[i]) { + g_osdHndPool[i] = self; + ret = i; + break; + } + } + MutexUnlock(&g_osdMutex); + return ret; +} + +static HI_S32 OSD_Stop(HI_S32 s32OsdIdx) +{ + HI_S32 s32Ret = HI_SUCCESS; + OSD_PARAM_S* pstOsdParam = &s_stOSDParam[s32OsdIdx]; + + if (!pstOsdParam->bOn) { + return HI_SUCCESS; + } + + s32Ret = OSD_DestroyRGN(s32OsdIdx, &pstOsdParam->stAttr); + if (s32Ret != HI_SUCCESS) { + SAMPLE_PRT("OSD_DestroyRGN s32OsdIdx[%d] failed:[0x%08X]\n", s32OsdIdx, s32Ret); + return s32Ret; + } + + pstOsdParam->bOn = HI_FALSE; + return HI_SUCCESS; +} + +/* + * @brief stop osd by index. + * @param[in] s32OsdIdx:osd index, range[0,HI_OSD_MAX_CNT) + * @return 0 success,non-zero error code. + */ +HI_S32 HI_OSD_Stop(HI_S32 s32OsdIdx) +{ + /* Check Module Init or not */ + HI_ASSERT(HI_TRUE == s_bOSDInitFlg); + /* Check Input Param */ + HI_ASSERT(s32OsdIdx >= 0); + HI_ASSERT(HI_OSD_MAX_CNT > s32OsdIdx); + + HI_S32 s32Ret = HI_SUCCESS; + OSD_PARAM_S* pstOsdParam = &s_stOSDParam[s32OsdIdx]; + + pthread_mutex_lock(&pstOsdParam->mutexLock); + + /* Check OSD Attrbute init or not */ + if (!pstOsdParam->bInit) { + pthread_mutex_unlock(&pstOsdParam->mutexLock); + return HI_SUCCESS; + } + + /* Check OSD stop or not */ + if (!pstOsdParam->bOn) { + pthread_mutex_unlock(&pstOsdParam->mutexLock); + return HI_SUCCESS; + } + + s32Ret = OSD_Stop(s32OsdIdx); + pstOsdParam->stMaxSize.u32Width = 0; + pstOsdParam->stMaxSize.u32Height= 0; + pthread_mutex_unlock(&pstOsdParam->mutexLock); + return s32Ret; +} + +/* Destroy the region specified in the OsdSet */ +void OsdsDestroyRgn(OsdSet* self, int rgnHnd) +{ + HI_ASSERT(self); + HI_ASSERT(rgnHnd >= 0 && rgnHnd < HI_OSD_MAX_CNT); + + MutexLock(&g_osdMutex); + HI_ASSERT(g_osdHndPool[rgnHnd] && g_osdHndPool[rgnHnd] == (void*)self); + g_osdHndPool[rgnHnd] = NULL; + MutexUnlock(&g_osdMutex); + + HI_OSD_Stop(rgnHnd); +} + +/* Destroy all regions in OsdSet */ +void OsdsClear(OsdSet* self) +{ + MutexLock(&g_osdMutex); + for (int i = 0; i < HI_OSD_MAX_CNT; i++) { + if (g_osdHndPool[i] && g_osdHndPool[i] == (void*)self) { + OsdsDestroyRgn(self, i); + } + } + MutexUnlock(&g_osdMutex); +} + +/* Destory OsdSet */ +void OsdsDestroy(OsdSet* self) +{ + HI_ASSERT(self); + OsdsClear(self); + free(self); +} + +/* Set the attribute value of the text region */ +int TxtRgnInit(HI_OSD_ATTR_S* rgnAttr, const char* str, uint32_t begX, uint32_t begY, uint32_t color) +{ + HI_ASSERT(rgnAttr); + if (!str) { + HI_ASSERT(0); + } + // 64:[0,128], the transparency of the text background block, the larger the background block color, + // the darker the background block color, 0 means no background block, that is, completely transparent + static const uint32_t bgAlpha = 64; + // 128:[0,128], the brightness of the text, the larger the value, the brighter the text + static const uint32_t fgAlpha = 128; + + if (memset_s(rgnAttr, sizeof(*rgnAttr), 0, sizeof(*rgnAttr)) != EOK) { + HI_ASSERT(0); + } + rgnAttr->u32DispNum = 1; + rgnAttr->astDispAttr[0].bShow = (str && *str) ? HI_TRUE : HI_FALSE; + rgnAttr->astDispAttr[0].enBindedMod = HI_OSD_BINDMOD_BUTT; + rgnAttr->astDispAttr[0].ChnHdl = UINT32_MAX; + rgnAttr->astDispAttr[0].u32BgAlpha = bgAlpha; + rgnAttr->astDispAttr[0].u32FgAlpha = fgAlpha; + rgnAttr->astDispAttr[0].enCoordinate = HI_OSD_COORDINATE_ABS_COOR; + rgnAttr->astDispAttr[0].stStartPos.s32X = begX; + rgnAttr->astDispAttr[0].stStartPos.s32Y = begY; + rgnAttr->astDispAttr[0].enAttachDest = ATTACH_JPEG_MAIN; + rgnAttr->stContent.enType = HI_OSD_TYPE_STRING; + rgnAttr->stContent.u32Color = color; // ARGB #FFFF0000 Red + HiStrxfrm(rgnAttr->stContent.szStr, str, sizeof(rgnAttr->stContent.szStr)); + rgnAttr->stContent.stFontSize.u32Width = OSD_FONT_WIDTH_DEF; + rgnAttr->stContent.stFontSize.u32Height = OSD_FONT_HEIGHT_DEF; + return 0; +} + +static HI_S32 OSD_Ratio2Absolute(MPP_CHN_S stChn, const POINT_S* pstRatioCoor, POINT_S* pstAbsCoor) +{ + HI_S32 s32Ret = HI_SUCCESS; + SIZE_S stImageSize; + + if (pstRatioCoor->s32X < 0 || pstRatioCoor->s32X > X_COORDINATE || + pstRatioCoor->s32Y < 0 || pstRatioCoor->s32Y > Y_COORDINATE) { + SAMPLE_PRT("invalide Ratio coordinate(%d,%d)\n", pstRatioCoor->s32X, pstRatioCoor->s32Y); + return HI_EINVAL; + } + switch (stChn.enModId) { + case HI_ID_VI: { + VI_CHN_ATTR_S stChnAttr; + s32Ret = HI_MPI_VI_GetChnAttr(stChn.s32DevId, stChn.s32ChnId, &stChnAttr); + if (s32Ret != HI_SUCCESS) { + SAMPLE_PRT("HI_MPI_VI_GetChnAttr(%d,%d) fail,Error Code: [0x%08X]\n", + stChn.s32DevId, stChn.s32ChnId, s32Ret); + return s32Ret; + } + stImageSize = stChnAttr.stSize; + break; + } + case HI_ID_VPSS: { + VPSS_CHN_ATTR_S stChnAttr; + s32Ret = HI_MPI_VPSS_GetChnAttr(stChn.s32DevId, stChn.s32ChnId, &stChnAttr); + if (s32Ret != HI_SUCCESS) { + SAMPLE_PRT("HI_MPI_VPSS_GetChnAttr(%d,%d) fail, Error Code: [0x%08X]\n", + stChn.s32DevId, stChn.s32ChnId, s32Ret); + return s32Ret; + } + stImageSize.u32Width = stChnAttr.u32Width; + stImageSize.u32Height = stChnAttr.u32Height; + break; + } + case HI_ID_VO: { + VO_CHN_ATTR_S stChnAttr; + s32Ret = HI_MPI_VO_GetChnAttr(stChn.s32DevId, stChn.s32ChnId, &stChnAttr); + if (s32Ret != HI_SUCCESS) { + SAMPLE_PRT("HI_MPI_VO_GetChnAttr(%d,%d) fail,Error Code: [0x%08X]\n", + stChn.s32DevId, stChn.s32ChnId, s32Ret); + return s32Ret; + } + stImageSize.u32Width = stChnAttr.stRect.u32Width; + stImageSize.u32Height = stChnAttr.stRect.u32Height; + break; + } + default: + SAMPLE_PRT("invalide mode id [%d]\n", stChn.enModId); + return HI_EINVAL; + } + + // 2: HiAppcommAlign api base param + pstAbsCoor->s32X = HiAppcommAlign(stImageSize.u32Width * pstRatioCoor->s32X / MULTIPLE_NUM, 2); + // 2: HiAppcommAlign api base param + pstAbsCoor->s32Y = HiAppcommAlign(stImageSize.u32Height * pstRatioCoor->s32Y / MULTIPLE_NUM, 2); + return HI_SUCCESS; +} + +static HI_S32 OSD_Update(RGN_HANDLE RgnHdl, const HI_OSD_ATTR_S* pstAttr) +{ + HI_S32 s32Ret = HI_SUCCESS; + HI_S32 s32DispIdx = 0; + RGN_CHN_ATTR_S stRgnChnAttr; + MPP_CHN_S stChn; + + for (s32DispIdx = 0; s32DispIdx < pstAttr->u32DispNum ; ++s32DispIdx) { + if (!pstAttr->astDispAttr[s32DispIdx].bShow) { + /* not no show,no need to update */ + continue; + } + + stChn.s32DevId = pstAttr->astDispAttr[s32DispIdx].ModHdl; + stChn.s32ChnId = pstAttr->astDispAttr[s32DispIdx].ChnHdl; + switch (pstAttr->astDispAttr[s32DispIdx].enBindedMod) { + case HI_OSD_BINDMOD_VI: + stChn.enModId = HI_ID_VI; + break; + case HI_OSD_BINDMOD_VPSS: + stChn.enModId = HI_ID_VPSS; + break; + case HI_OSD_BINDMOD_VO: + stChn.enModId = HI_ID_VO; + break; + default: + SAMPLE_PRT("invalide bind mode [%d]\n", pstAttr->astDispAttr[s32DispIdx].enBindedMod); + return HI_EINVAL; + } + + s32Ret = HI_MPI_RGN_GetDisplayAttr(RgnHdl, &stChn, &stRgnChnAttr); + SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "GetDisplayAttr fail, s32Ret:[0x%08X]\n", s32Ret); + + stRgnChnAttr.bShow = pstAttr->astDispAttr[s32DispIdx].bShow; + POINT_S stStartPos; + if (pstAttr->astDispAttr[s32DispIdx].enCoordinate == HI_OSD_COORDINATE_RATIO_COOR) { + s32Ret = OSD_Ratio2Absolute(stChn, &pstAttr->astDispAttr[s32DispIdx].stStartPos, &stStartPos); + SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "Ratio2Absolute fail, s32Ret:[0x%08X]\n", s32Ret); + } else { + stStartPos = pstAttr->astDispAttr[s32DispIdx].stStartPos; + } + + if (stRgnChnAttr.enType == OVERLAYEX_RGN) { + stRgnChnAttr.unChnAttr.stOverlayExChn.stPoint.s32X = stStartPos.s32X; + stRgnChnAttr.unChnAttr.stOverlayExChn.stPoint.s32Y = stStartPos.s32Y; + stRgnChnAttr.unChnAttr.stOverlayExChn.u32BgAlpha = pstAttr->astDispAttr[s32DispIdx].u32BgAlpha; + stRgnChnAttr.unChnAttr.stOverlayExChn.u32FgAlpha = pstAttr->astDispAttr[s32DispIdx].u32FgAlpha; + } else { + stRgnChnAttr.unChnAttr.stOverlayChn.stPoint.s32X = stStartPos.s32X; + stRgnChnAttr.unChnAttr.stOverlayChn.stPoint.s32Y = stStartPos.s32Y; + stRgnChnAttr.unChnAttr.stOverlayChn.u32BgAlpha = pstAttr->astDispAttr[s32DispIdx].u32BgAlpha; + stRgnChnAttr.unChnAttr.stOverlayChn.u32FgAlpha = pstAttr->astDispAttr[s32DispIdx].u32FgAlpha; + } + + s32Ret = HI_MPI_RGN_SetDisplayAttr(RgnHdl, &stChn, &stRgnChnAttr); + SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "SetDisplayAttr fail, s32Ret:[0x%08X]\n", s32Ret); + } + + return HI_SUCCESS; +} + +HI_VOID OSD_PuBmData_Cal(HI_OSD_CONTENT_S* pstContent, HI_U16* puBmData, HI_S32 s32HexOffset, + HI_S32 s32BmDataIdx, HI_S32 s32BitOffset) +{ + HI_U8 temp = FontMod[s32HexOffset]; + if ((temp >> ((BYTE_BITS - 1) - s32BitOffset)) & 0x1) { + puBmData[s32BmDataIdx] = (HI_U16)pstContent->u32Color; + } else { + puBmData[s32BmDataIdx] = (HI_U16)pstContent->u32BgColor; + } + + return; +} + +HI_S32 OSD_Bitmap_Cal(HI_OSD_CONTENT_S* pstContent, HI_S32 NonASCNum, HI_U16* puBmData) +{ + HI_S32 NonASCShow = 0; + for (s32BmCol = 0; s32BmCol < pstContent->stBitmap.u32Width; ++s32BmCol) { + /* Bitmap Data Offset for the point */ + HI_S32 s32BmDataIdx = s32BmRow * s_stOSDTextBitMap.stCanvasInfo.u32Stride / 2 + s32BmCol; + /* Character Index in Text String */ + HI_S32 s32CharIdx = s32BmCol / pstContent->stFontSize.u32Width; + HI_S32 s32StringIdx = s32CharIdx+NonASCShow * (NOASCII_CHARACTER_BYTES - 1); + if (NonASCNum > 0 && s32CharIdx > 0) { + NonASCShow = OSD_GetNonASCNum(pstContent->szStr, s32StringIdx); + s32StringIdx = s32CharIdx+NonASCShow * (NOASCII_CHARACTER_BYTES - 1); + } + /* Point Row/Col Index in Character */ + HI_S32 s32CharCol = (s32BmCol - (pstContent->stFontSize.u32Width * s32CharIdx)) * + OSD_LIB_FONT_W / pstContent->stFontSize.u32Width; + HI_S32 s32CharRow = s32BmRow * OSD_LIB_FONT_H / pstContent->stFontSize.u32Height; + HI_S32 s32HexOffset = s32CharRow * OSD_LIB_FONT_W / BYTE_BITS + s32CharCol / BYTE_BITS; + HI_S32 s32BitOffset = s32CharCol % BYTE_BITS; + + if (s_stOSDFonts.pfnGetFontMod(&pstContent->szStr[s32StringIdx], &FontMod, &FontModLen) + == HI_SUCCESS) { + if (FontMod != NULL && s32HexOffset < FontModLen) { + OSD_PuBmData_Cal(pstContent, puBmData, s32HexOffset, s32BmDataIdx, s32BitOffset); + continue; + } + } + SAMPLE_PRT("GetFontMod Fail\n"); + return HI_FAILURE; + } +} + +HI_S32 OSD_Generate_Bitmap(RGN_HANDLE RgnHdl, HI_OSD_CONTENT_S* pstContent) +{ + HI_S32 s32Ret; + HI_S32 s32StrLen = strnlen(pstContent->szStr, HI_OSD_MAX_STR_LEN); + HI_S32 NonASCNum = OSD_GetNonASCNum(pstContent->szStr, s32StrLen); + + s32Ret = HI_MPI_RGN_GetCanvasInfo(RgnHdl, &s_stOSDTextBitMap.stCanvasInfo); + SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "RGN_GetCanvasInfo FAIL, s32Ret=%x\n", s32Ret); + + /* Generate Bitmap */ + pstContent->stBitmap.u32Width = pstContent->stFontSize.u32Width * + (s32StrLen - NonASCNum * (NOASCII_CHARACTER_BYTES - 1)); + pstContent->stBitmap.u32Height = pstContent->stFontSize.u32Height; + HI_U16* puBmData = (HI_U16*)(HI_UL)s_stOSDTextBitMap.stCanvasInfo.u64VirtAddr; + + for (s32BmRow = 0; s32BmRow < pstContent->stBitmap.u32Height; ++s32BmRow) { + OSD_Bitmap_Cal(pstContent, NonASCNum, puBmData); + for (s32BmCol = pstContent->stBitmap.u32Width; + s32BmCol < s_stOSDParam[RgnHdl].stMaxSize.u32Width; ++s32BmCol) { + HI_S32 s32BmDataIdx = s32BmRow * s_stOSDTextBitMap.stCanvasInfo.u32Stride / 2 + s32BmCol; + puBmData[s32BmDataIdx] = 0; + } + } + + for (s32BmRow = pstContent->stBitmap.u32Height; + s32BmRow < s_stOSDParam[RgnHdl].stMaxSize.u32Height; ++s32BmRow) { + for (s32BmCol = 0; s32BmCol < s_stOSDParam[RgnHdl].stMaxSize.u32Width; ++s32BmCol) { + HI_S32 s32BmDataIdx = s32BmRow * s_stOSDTextBitMap.stCanvasInfo.u32Stride / 2 + s32BmCol; + puBmData[s32BmDataIdx] = 0; + } + } + + return s32Ret; +} + +static HI_S32 OSD_UpdateTextBitmap(RGN_HANDLE RgnHdl, HI_OSD_CONTENT_S* pstContent) +{ + HI_S32 s32Ret = HI_SUCCESS; + + OSD_Generate_Bitmap(RgnHdl, pstContent); + s_stOSDTextBitMap.stCanvasInfo.enPixelFmt = PIXEL_FORMAT_ARGB_1555; + s_stOSDTextBitMap.stCanvasInfo.stSize.u32Width = pstContent->stBitmap.u32Width; + s_stOSDTextBitMap.stCanvasInfo.stSize.u32Height = pstContent->stBitmap.u32Height; + + s32Ret = HI_MPI_RGN_UpdateCanvas(RgnHdl); + SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "RGN_UpdateCanvas FAIL, s32Ret=%x\n", s32Ret); + + return s32Ret; +} + +static HI_S32 OSD_RGNAttach(RGN_HANDLE RgnHdl, const HI_OSD_DISP_ATTR_S* pstDispAttr) +{ + HI_S32 s32Ret = HI_SUCCESS; + RGN_CHN_ATTR_S stRgnChnAttr; + MPP_CHN_S stChn; + + stChn.s32DevId = pstDispAttr->ModHdl; + stChn.s32ChnId = pstDispAttr->ChnHdl; + memset_s(&stRgnChnAttr, sizeof(RGN_CHN_ATTR_S), 0x0, sizeof(RGN_CHN_ATTR_S)); + stRgnChnAttr.bShow = pstDispAttr->bShow; + stRgnChnAttr.enType = OVERLAYEX_RGN; + switch (pstDispAttr->enBindedMod) { + case HI_OSD_BINDMOD_VI: + stChn.enModId = HI_ID_VI; + break; + case HI_OSD_BINDMOD_VPSS: + stChn.enModId = HI_ID_VPSS; + break; + case HI_OSD_BINDMOD_VO: + stChn.enModId = HI_ID_VO; + break; + default: + SAMPLE_PRT("RgnHdl[%d] invalide bind mode [%d]\n", RgnHdl, pstDispAttr->enBindedMod); + return HI_EINVAL; + } + + POINT_S stStartPos; + if (pstDispAttr->enCoordinate == HI_OSD_COORDINATE_RATIO_COOR) { + s32Ret = OSD_Ratio2Absolute(stChn, &pstDispAttr->stStartPos, &stStartPos); + SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "Ratio2Absolute FAIL, s32Ret=%x\n", s32Ret); + } else { + stStartPos = pstDispAttr->stStartPos; + } + + if (stRgnChnAttr.enType == OVERLAYEX_RGN) { + stRgnChnAttr.unChnAttr.stOverlayExChn.stPoint.s32X = stStartPos.s32X; + stRgnChnAttr.unChnAttr.stOverlayExChn.stPoint.s32Y = stStartPos.s32Y; + stRgnChnAttr.unChnAttr.stOverlayExChn.u32BgAlpha = pstDispAttr->u32BgAlpha; + stRgnChnAttr.unChnAttr.stOverlayExChn.u32FgAlpha = pstDispAttr->u32FgAlpha; + stRgnChnAttr.unChnAttr.stOverlayExChn.u32Layer = 0; + } else { + stRgnChnAttr.unChnAttr.stOverlayChn.stPoint.s32X = stStartPos.s32X; + stRgnChnAttr.unChnAttr.stOverlayChn.stPoint.s32Y = stStartPos.s32Y; + stRgnChnAttr.unChnAttr.stOverlayChn.u32BgAlpha = pstDispAttr->u32BgAlpha; + stRgnChnAttr.unChnAttr.stOverlayChn.u32FgAlpha = pstDispAttr->u32FgAlpha; + stRgnChnAttr.unChnAttr.stOverlayChn.u32Layer = 0; + } + + s32Ret = HI_MPI_RGN_AttachToChn(RgnHdl, &stChn, &stRgnChnAttr); + SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "RGN_AttachToChn FAIL, s32Ret=%x\n", s32Ret); + + return HI_SUCCESS; +} + +static HI_S32 OSD_CreateRGN(RGN_HANDLE RgnHdl, const HI_OSD_ATTR_S* pstAttr) +{ + HI_S32 s32Ret = HI_SUCCESS; + HI_S32 s32DispIdx = 0; + RGN_ATTR_S stRgnAttr; + stRgnAttr.enType = OVERLAY_RGN; + + for (s32DispIdx = 0; s32DispIdx < pstAttr->u32DispNum ; ++s32DispIdx) { + if (pstAttr->astDispAttr[s32DispIdx].enBindedMod != HI_OSD_BINDMOD_VENC) { + stRgnAttr.enType = OVERLAYEX_RGN; + break; + } + } + + if (stRgnAttr.enType == OVERLAYEX_RGN) { + stRgnAttr.unAttr.stOverlayEx.enPixelFmt = PIXEL_FORMAT_ARGB_1555; + stRgnAttr.unAttr.stOverlayEx.u32BgColor = pstAttr->stContent.u32Color; + stRgnAttr.unAttr.stOverlayEx.stSize.u32Width = pstAttr->stContent.stBitmap.u32Width; + stRgnAttr.unAttr.stOverlayEx.stSize.u32Height = pstAttr->stContent.stBitmap.u32Height; + stRgnAttr.unAttr.stOverlayEx.u32CanvasNum = + (HI_OSD_TYPE_BITMAP == pstAttr->stContent.enType) ? 1 : 2; // 2: u32CanvasNum + } else { + stRgnAttr.unAttr.stOverlay.enPixelFmt = PIXEL_FORMAT_ARGB_1555; + stRgnAttr.unAttr.stOverlay.u32BgColor = pstAttr->stContent.u32Color; + stRgnAttr.unAttr.stOverlay.stSize.u32Width = pstAttr->stContent.stBitmap.u32Width; + stRgnAttr.unAttr.stOverlay.stSize.u32Height = pstAttr->stContent.stBitmap.u32Height; + stRgnAttr.unAttr.stOverlay.u32CanvasNum = + (HI_OSD_TYPE_BITMAP == pstAttr->stContent.enType) ? 1 : 2; // 2: u32CanvasNum + } + + s32Ret = HI_MPI_RGN_Create(RgnHdl, &stRgnAttr); + SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, + "HI_MPI_RGN_Create fail,RgnHdl[%d] Error Code: [0x%08X]\n", RgnHdl, s32Ret); + + if (pstAttr->stContent.enType == HI_OSD_TYPE_BITMAP) { + BITMAP_S stBitmap; + stBitmap.enPixelFormat = PIXEL_FORMAT_ARGB_1555; + stBitmap.u32Width = pstAttr->stContent.stBitmap.u32Width; + stBitmap.u32Height = pstAttr->stContent.stBitmap.u32Height; + stBitmap.pData = pstAttr->stContent.stBitmap.pvData; + s32Ret = HI_MPI_RGN_SetBitMap(RgnHdl, &stBitmap); + SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, + "HI_MPI_RGN_SetBitMap fail,RgnHdl[%d] Error Code: [0x%08X]\n", RgnHdl, s32Ret); + } else { + s32Ret = OSD_UpdateTextBitmap(RgnHdl, (HI_OSD_CONTENT_S*)&pstAttr->stContent); + SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "UpdateTextBitmap fail, ret=%x\n", s32Ret); + } + + for (s32DispIdx = 0; s32DispIdx < pstAttr->u32DispNum; ++s32DispIdx) { + if (pstAttr->astDispAttr[s32DispIdx].bShow) { + OSD_RGNAttach(RgnHdl, &pstAttr->astDispAttr[s32DispIdx]); + } + } + + return HI_SUCCESS; +} + +HI_VOID OSD_Update_Relate_Info(HI_S32 s32OsdIdx) +{ + HI_S32 s32Ret = 0; + + for (s32OsdIdx = 0; s32OsdIdx < HI_OSD_MAX_CNT; ++s32OsdIdx) { + pthread_mutex_lock(&s_stOSDParam[s32OsdIdx].mutexLock); + if (s_stOSDParam[s32OsdIdx].stAttr.stContent.enType == + HI_OSD_TYPE_TIME && s_stOSDParam[s32OsdIdx].bOn) { + /* Update OSD Time String */ + OSD_GetTimeStr(&stTime, + s_stOSDParam[s32OsdIdx].stAttr.stContent.szStr, HI_OSD_MAX_STR_LEN); + /* Update OSD Text Bitmap */ + s32Ret = OSD_UpdateTextBitmap(s32OsdIdx, &s_stOSDParam[s32OsdIdx].stAttr.stContent); + if (HI_SUCCESS != s32Ret) { + pthread_mutex_unlock(&s_stOSDParam[s32OsdIdx].mutexLock); + SAMPLE_PRT("Update Text Bitmap failed\n"); + continue; + } + /* Update OSD Attribute */ + s32Ret = OSD_Update(s32OsdIdx, &s_stOSDParam[s32OsdIdx].stAttr); + if (HI_SUCCESS != s32Ret) { + SAMPLE_PRT("Update Attribute failed\n"); + } + } + pthread_mutex_unlock(&s_stOSDParam[s32OsdIdx].mutexLock); + } + + return; +} + +/** + * @brief time osd update task + * @param[in]pvParam : nonuse + * @return 0 success,non-zero error code. + */ +static HI_VOID* OSD_TimeUpdate(HI_VOID* pvParam) +{ + HI_S32 s32Ret = 0; + HI_S32 s32OsdIdx = 0; + time_t nowTime = 0; + time_t lastTime = 0; + prctl(PR_SET_NAME, __FUNCTION__, 0, 0, 0); + + while (s_bOSDTimeRun) { + nowTime = time(NULL); // also means time(&nowTime) + if (nowTime == lastTime) { + usleep(10000); // 10000:usleep time + continue; + } else { + localtime_r(&nowTime, &stTime); + OSD_Update_Relate_Info(s32OsdIdx); + lastTime = nowTime; /* update time */ + } + usleep(500000); // 500000: usleep time + } + + return NULL; +} + +/** + * @brief osd module initialization, eg. create time osd update task. + * @param[in] pstFonts:osd fonts lib + * @return 0 success,non-zero error code. + */ +HI_S32 HI_OSD_Init(const HI_OSD_FONTS_S* pstFonts) +{ + if (!(HI_TRUE != s_bOSDInitFlg)) { + return HI_EINITIALIZED; + } + if (pstFonts != NULL) { + if (!pstFonts->pfnGetFontMod) { + return HI_EINVAL; + } + if (pstFonts->u32FontWidth % BYTE_BITS) { + SAMPLE_PRT("FontWidth must be a multiple of %d.", BYTE_BITS); + return HI_EINVAL; + } + memcpy_s(&s_stOSDFonts, sizeof(HI_OSD_FONTS_S), pstFonts, sizeof(HI_OSD_FONTS_S)); + } else { + memset_s(&s_stOSDFonts, sizeof(HI_OSD_FONTS_S), 0, sizeof(HI_OSD_FONTS_S)); + } + HI_S32 s32Idx = 0; + HI_S32 s32Ret = HI_SUCCESS; + + /* Init OSD Param */ + for (s32Idx = 0; s32Idx < HI_OSD_MAX_CNT; ++s32Idx) { + pthread_mutex_init(&s_stOSDParam[s32Idx].mutexLock, NULL); + pthread_mutex_lock(&s_stOSDParam[s32Idx].mutexLock); + memset_s(&s_stOSDParam[s32Idx], sizeof(OSD_PARAM_S), 0, sizeof(OSD_PARAM_S)); + pthread_mutex_unlock(&s_stOSDParam[s32Idx].mutexLock); + } + + if (pstFonts != NULL) { + /* Create Time OSD Update Thread */ + s_bOSDTimeRun = HI_TRUE; + s32Ret = pthread_create(&s_OSDTimeTskId, NULL, OSD_TimeUpdate, NULL); + if (HI_SUCCESS != s32Ret) { + SAMPLE_PRT("create OSD_TimeUpdate failed:%s\n", strerror(errno)); + return HI_ENORES; + } + } + + s_bOSDInitFlg = HI_TRUE; + return HI_SUCCESS; +} + +/* Initialize OSD font */ +static int OsdInitFont(HI_CHAR *character, HI_U8 **fontMod, HI_S32 *fontModLen) +{ + static const HI_CHAR baseChar = 0x20; + + // Get Font Mod in ASCII Fontlib + if (!character || !fontMod || !fontModLen) { + return HI_FAILURE; + } + // Return true if the parameter is an ASCII character, otherwise NULL (0) + if (!IsAscii(character[0])) { + return HI_FAILURE; + } + HI_U32 offset = (character[0] - baseChar) * (OSD_FONT_MOD_H * OSD_FONT_MOD_W / HI_BYTE_BITS); + *fontMod = (HI_U8 *)G_FONT_LIB + offset; + *fontModLen = OSD_FONT_MOD_H * OSD_FONT_MOD_W / HI_BYTE_BITS; + return HI_SUCCESS; +} + +/* Initialize OsdSet lib */ +int OsdLibInit(void) +{ + RecurMutexInit(&g_osdMutex); + +# if defined(OSD_FONT_HZK) || defined(OSD_FONT_ASC) + SAMPLE_PRT("==================success=================\n"); + HI_OSD_FONTS_S stOsdFonts; + stOsdFonts.u32FontWidth = OSD_FONT_MOD_W; + stOsdFonts.u32FontHeight = OSD_FONT_MOD_H; + stOsdFonts.pfnGetFontMod = OsdInitFont; + return HI_OSD_Init(&stOsdFonts); +# else + SAMPLE_PRT("##################success##################\n"); + return HI_OSD_Init(NULL); +# endif +} + +HI_VOID Osd_Param_Config(const HI_OSD_ATTR_S* pstAttr, OSD_PARAM_S* pstOsdParam) +{ + /* Update Attribute */ + pstOsdParam->stAttr.stContent.u32Color = pstAttr->stContent.u32Color; + pstOsdParam->stAttr.stContent.u32BgColor = pstAttr->stContent.u32BgColor; + + if (HI_OSD_TYPE_BITMAP != pstAttr->stContent.enType) { + if (HI_OSD_TYPE_TIME == pstAttr->stContent.enType) { + /* Time Type: Update time string */ + pstOsdParam->stAttr.stContent.enTimeFmt = pstAttr->stContent.enTimeFmt; + OSD_GetTimeStr(NULL, ((HI_OSD_ATTR_S*)pstAttr)->stContent.szStr, HI_OSD_MAX_STR_LEN); + } + + /* Update string */ + if (snprintf_s(pstOsdParam->stAttr.stContent.szStr, HI_OSD_MAX_STR_LEN, + HI_OSD_MAX_STR_LEN - 1, "%s", pstAttr->stContent.szStr) < 0) { + HI_ASSERT(0); + } + + pstOsdParam->stAttr.stContent.stBitmap.enPixelFormat = PIXEL_FORMAT_ARGB_1555; + ((HI_OSD_ATTR_S*)pstAttr)->stContent.stBitmap.u32Width = + pstAttr->stContent.stFontSize.u32Width * strnlen(pstOsdParam->stAttr.stContent.szStr, HI_OSD_MAX_STR_LEN); + ((HI_OSD_ATTR_S*)pstAttr)->stContent.stBitmap.u32Height= pstAttr->stContent.stFontSize.u32Height; + pstOsdParam->stAttr.stContent.stFontSize = pstAttr->stContent.stFontSize; + } else { + pstOsdParam->stAttr.stContent.stBitmap.enPixelFormat = pstAttr->stContent.stBitmap.enPixelFormat; + pstOsdParam->stAttr.stContent.stBitmap.u64PhyAddr = pstAttr->stContent.stBitmap.u64PhyAddr; + pstOsdParam->stAttr.stContent.stBitmap.pvData = pstAttr->stContent.stBitmap.pvData; + } + pstOsdParam->stAttr.stContent.stBitmap.u32Width = pstAttr->stContent.stBitmap.u32Width; + pstOsdParam->stAttr.stContent.stBitmap.u32Height = pstAttr->stContent.stBitmap.u32Height; + pstOsdParam->stAttr.stContent.enType = pstAttr->stContent.enType; + + return; +} + +static HI_S32 OSD_Update_RGN_Content(const HI_OSD_ATTR_S* pstAttr, OSD_PARAM_S* pstOsdParam, HI_S32 s32OsdIdx) +{ + HI_S32 s32Ret = HI_SUCCESS; + /* Update RGN Content */ + if (pstAttr->stContent.enType == HI_OSD_TYPE_BITMAP) { + BITMAP_S stBitmap; + stBitmap.enPixelFormat = PIXEL_FORMAT_ARGB_1555; + stBitmap.u32Width = pstAttr->stContent.stBitmap.u32Width; + stBitmap.u32Height = pstAttr->stContent.stBitmap.u32Height; + stBitmap.pData = pstAttr->stContent.stBitmap.pvData; + s32Ret = HI_MPI_RGN_SetBitMap(s32OsdIdx, &stBitmap); + SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, FAIL, "HI_MPI_RGN_SetBitMap. s32Ret: 0x%x\n", s32Ret); + } else { + /* Time/String Type: Update text bitmap */ + s32Ret = OSD_UpdateTextBitmap(s32OsdIdx, (HI_OSD_CONTENT_S*)&pstOsdParam->stAttr.stContent); + SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, FAIL, "OSD_UpdateTextBitmap fail, err(%#x)\n", s32Ret); + } + + HI_S32 s32DispIdx = 0; + for (s32DispIdx = 0; s32DispIdx < pstAttr->u32DispNum ; ++s32DispIdx) { + if (HI_TRUE == pstAttr->astDispAttr[s32DispIdx].bShow && HI_FALSE == + pstOsdParam->stAttr.astDispAttr[s32DispIdx].bShow) { + OSD_RGNAttach(s32OsdIdx, &pstAttr->astDispAttr[s32DispIdx]); + } else if (HI_FALSE == pstAttr->astDispAttr[s32DispIdx].bShow && HI_TRUE == + pstOsdParam->stAttr.astDispAttr[s32DispIdx].bShow) { + OSD_RGNDetach(s32OsdIdx, &pstOsdParam->stAttr.astDispAttr[s32DispIdx]); + } + } + s32Ret = OSD_Update(s32OsdIdx, pstAttr); + SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, FAIL, "OSD_Update fail, err(%#x)\n", s32Ret); + + return s32Ret; + +FAIL: + pthread_mutex_unlock(&pstOsdParam->mutexLock); + return s32Ret; +} + +/* + * @brief set osd attribute. + * @param[in] s32OsdIdx:osd index, range[0,HI_OSD_MAX_CNT) + * @param[in] pstAttr:osd configure attribute + * @return 0 success,non-zero error code. + */ +HI_S32 HI_OSD_SetAttr(HI_S32 s32OsdIdx, const HI_OSD_ATTR_S* pstAttr) +{ + /* Check Module Init or not */ + HI_ASSERT(HI_TRUE == s_bOSDInitFlg); + /* Check Input Param */ + HI_ASSERT(s32OsdIdx >= 0); + HI_ASSERT(HI_OSD_MAX_CNT > s32OsdIdx); + HI_ASSERT(pstAttr); + HI_ASSERT(HI_OSD_MAX_DISP_CNT >= pstAttr->u32DispNum); + + if (HI_OSD_TYPE_BITMAP == pstAttr->stContent.enType) { + if (!pstAttr->stContent.stBitmap.pvData) { + return HI_FAILURE; + } + } else { + if (s_stOSDFonts.pfnGetFontMod == NULL) { + SAMPLE_PRT("The font library is not registered,only support bitmaps OSD\n"); + return HI_FAILURE; + } + } + + HI_S32 s32Ret = HI_SUCCESS; + OSD_PARAM_S* pstOsdParam = &s_stOSDParam[s32OsdIdx]; + pthread_mutex_lock(&pstOsdParam->mutexLock); + HI_BOOL bOn = pstOsdParam->bOn; + + /* Update Attribute */ + Osd_Param_Config(pstAttr, pstOsdParam); + if (bOn) { + if (pstOsdParam->stMaxSize.u32Width < pstOsdParam->stAttr.stContent.stBitmap.u32Width + || pstOsdParam->stMaxSize.u32Height < pstOsdParam->stAttr.stContent.stBitmap.u32Height) { + SAMPLE_PRT("RGN(%d) size increase[%d,%d->%d,%d], rebuild\n", s32OsdIdx, + pstOsdParam->stMaxSize.u32Width, pstOsdParam->stMaxSize.u32Height, + pstAttr->stContent.stBitmap.u32Width, pstAttr->stContent.stBitmap.u32Height); + /* rebuild RGN */ + s32Ret = OSD_DestroyRGN(s32OsdIdx, &pstOsdParam->stAttr); + if (s32Ret != HI_SUCCESS) { + pthread_mutex_unlock(&pstOsdParam->mutexLock); + return s32Ret; + } + + s32Ret = OSD_CreateRGN(s32OsdIdx, pstAttr); + if (s32Ret != HI_SUCCESS) { + pthread_mutex_unlock(&pstOsdParam->mutexLock); + return s32Ret; + } + } else { + OSD_Update_RGN_Content(pstAttr, pstOsdParam, s32OsdIdx); + } + } + + memcpy_s(pstOsdParam->stAttr.astDispAttr, sizeof(HI_OSD_DISP_ATTR_S) * HI_OSD_MAX_DISP_CNT, + pstAttr->astDispAttr, sizeof(HI_OSD_DISP_ATTR_S) * HI_OSD_MAX_DISP_CNT); + pstOsdParam->stAttr.u32DispNum = pstAttr->u32DispNum; + pstOsdParam->stMaxSize.u32Width = + max(pstOsdParam->stMaxSize.u32Width, pstOsdParam->stAttr.stContent.stBitmap.u32Width); + pstOsdParam->stMaxSize.u32Height= + max(pstOsdParam->stMaxSize.u32Height, pstOsdParam->stAttr.stContent.stBitmap.u32Height); + pstOsdParam->bInit = HI_TRUE; + pthread_mutex_unlock(&pstOsdParam->mutexLock); + + return HI_SUCCESS; +} + +static HI_S32 OSD_Start(HI_S32 s32OsdIdx) +{ + HI_S32 s32Ret = HI_SUCCESS; + OSD_PARAM_S* pstOsdParam = &s_stOSDParam[s32OsdIdx]; + + /* Time OSD: Update time string and bitmap */ + if (HI_OSD_TYPE_TIME == pstOsdParam->stAttr.stContent.enType) { + OSD_GetTimeStr(NULL, pstOsdParam->stAttr.stContent.szStr, HI_OSD_MAX_STR_LEN); + } + + s32Ret = OSD_CreateRGN(s32OsdIdx, &pstOsdParam->stAttr); + if (HI_SUCCESS != s32Ret) { + SAMPLE_PRT("OSD_CreateRGN s32OsdIdx[%d] failed:[0x%08X]\n", s32OsdIdx, s32Ret); + return s32Ret; + } + pstOsdParam->bOn = HI_TRUE; + return HI_SUCCESS; +} + +/* + * @brief start osd by index. + * @param[in] s32OsdIdx:osd index, range[0,HI_OSD_MAX_CNT) + * @return 0 success,non-zero error code. + */ +HI_S32 HI_OSD_Start(HI_S32 s32OsdIdx) +{ + /* Check Module Init or not */ + HI_ASSERT(HI_TRUE == s_bOSDInitFlg); + /* Check Input Param */ + HI_ASSERT(s32OsdIdx >= 0); + HI_ASSERT(HI_OSD_MAX_CNT > s32OsdIdx); + + HI_S32 s32Ret = HI_SUCCESS; + OSD_PARAM_S* pstOsdParam = &s_stOSDParam[s32OsdIdx]; + + pthread_mutex_lock(&pstOsdParam->mutexLock); + + /* Check OSD Attrbute init or not */ + if (!pstOsdParam->bInit) { + pthread_mutex_unlock(&pstOsdParam->mutexLock); + SAMPLE_PRT("OSD[%d] not init yet!\n", s32OsdIdx); + return HI_EINVAL; + } + + /* Check OSD stop or not */ + if (pstOsdParam->bOn) { + pthread_mutex_unlock(&pstOsdParam->mutexLock); + SAMPLE_PRT("OSD[%d] has already started!\n", s32OsdIdx); + return HI_SUCCESS; + } + + s32Ret = OSD_Start(s32OsdIdx); + pthread_mutex_unlock(&pstOsdParam->mutexLock); + return s32Ret; +} + +/* Set attributes for the specified region in OsdSet */ +int OsdsSetRgn(OsdSet* self, int rgnHnd, const HI_OSD_ATTR_S* rgnAttr) +{ + HI_ASSERT(self); + HI_ASSERT(rgnHnd >= 0 && rgnHnd < HI_OSD_MAX_CNT); + HI_ASSERT(g_osdHndPool[rgnHnd] && g_osdHndPool[rgnHnd] == (void*)self); // not need lock + HI_OSD_ATTR_S attr; + int ret; + + if (!rgnAttr) { // hidden the region + if (memset_s(&attr, sizeof(attr), 0, sizeof(attr)) != EOK) { + HI_ASSERT(0); + } + attr.u32DispNum = 1; + attr.astDispAttr[0].bShow = HI_FALSE; + } else { + attr = *rgnAttr; + } + + attr.astDispAttr[0].enBindedMod = self->bindMod; + attr.astDispAttr[0].ModHdl = self->modHnd; + attr.astDispAttr[0].ChnHdl = self->chnHnd; + + ret = HI_OSD_SetAttr(rgnHnd, &attr); + SAMPLE_CHECK_EXPR_RET(ret, "HI_OSD_SetAttr FAIL, ret=%d\n", ret); + + ret = HI_OSD_Start(rgnHnd); + SAMPLE_CHECK_EXPR_RET(ret, "HI_OSD_Start FAIL, ret=%d\n", ret); + return 0; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* End of #ifdef __cplusplus */ \ No newline at end of file diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/mpp_help/src/vgs_img.c b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/mpp_help/src/vgs_img.c new file mode 100644 index 0000000..6f81249 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/mpp_help/src/vgs_img.c @@ -0,0 +1,393 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "hi_comm_vb.h" +#include "hi_comm_vgs.h" +#include "hi_comm_region.h" +#include "mpi_sys.h" +#include "mpi_vgs.h" +#include "hi_buffer.h" + +#include "misc_util.h" +#include "ai_infer_process.h" +#include "vgs_img.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* End of #ifdef __cplusplus */ + +#define VGS_MAX_LINE 100 // The maximum number of lines for a superimposed graphics operation +#define RECT_LINES 4 // The number of lines in a rectangle + +#define RECT_LINE1 1 +#define RECT_LINE2 2 +#define RECT_LINE3 3 + +/* Set the buf of the frame */ +static void MppFrmSetBuf(VIDEO_FRAME_INFO_S* frm, + const VB_CAL_CONFIG_S *vbCfg, HI_U64 phyAddr, uint8_t *virAddr) +{ + // Currently only SP422/SP420 is supported, SP444 is not supported + frm->stVFrame.u32HeaderStride[0] = vbCfg->u32HeadStride; + frm->stVFrame.u32HeaderStride[1] = vbCfg->u32HeadStride; + frm->stVFrame.u32HeaderStride[2] = vbCfg->u32HeadStride; // 2: Array subscript, not out of bounds + frm->stVFrame.u64HeaderPhyAddr[0] = phyAddr; + frm->stVFrame.u64HeaderPhyAddr[1] = frm->stVFrame.u64HeaderPhyAddr[0] + vbCfg->u32HeadYSize; + frm->stVFrame.u64HeaderPhyAddr[2] = frm->stVFrame.u64HeaderPhyAddr[1]; // 2: Array subscript, not out of bounds + frm->stVFrame.u64HeaderVirAddr[0] = (HI_U64)(HI_UL)virAddr; + frm->stVFrame.u64HeaderVirAddr[1] = frm->stVFrame.u64HeaderVirAddr[0] + vbCfg->u32HeadYSize; + frm->stVFrame.u64HeaderVirAddr[2] = frm->stVFrame.u64HeaderVirAddr[1]; // 2: Array subscript, not out of bounds + + frm->stVFrame.u32Stride[0] = vbCfg->u32MainStride; + frm->stVFrame.u32Stride[1] = vbCfg->u32MainStride; + frm->stVFrame.u32Stride[2] = vbCfg->u32MainStride; // 2: Array subscript, not out of bounds + frm->stVFrame.u64PhyAddr[0] = frm->stVFrame.u64HeaderPhyAddr[0] + vbCfg->u32HeadSize; + frm->stVFrame.u64PhyAddr[1] = frm->stVFrame.u64PhyAddr[0] + vbCfg->u32MainYSize; + frm->stVFrame.u64PhyAddr[2] = frm->stVFrame.u64PhyAddr[1]; // 2: Array subscript, not out of bounds + frm->stVFrame.u64VirAddr[0] = frm->stVFrame.u64HeaderVirAddr[0] + vbCfg->u32HeadSize; + frm->stVFrame.u64VirAddr[1] = frm->stVFrame.u64VirAddr[0] + vbCfg->u32MainYSize; + frm->stVFrame.u64VirAddr[2] = frm->stVFrame.u64VirAddr[1]; // 2: Array subscript, not out of bounds +} + +/* Create an empty frame buf */ +int MppFrmCreate( + VIDEO_FRAME_INFO_S* frm, + int width, int height, + PIXEL_FORMAT_E pixelFormat, + DATA_BITWIDTH_E bitWidth, + COMPRESS_MODE_E compressMode, + int align) +{ + HI_ASSERT(frm); + VB_CAL_CONFIG_S vbCfg; + + if (memset_s(frm, sizeof(*frm), 0, sizeof(*frm)) != EOK) { + HI_ASSERT(0); + } + + HI_ASSERT(width > 0 && height > 0); + if ((int)pixelFormat < 0) { + pixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420; + } + if ((int)bitWidth < 0) { + bitWidth = DATA_BITWIDTH_8; + } + if ((int)compressMode < 0) { + compressMode = COMPRESS_MODE_NONE; + } + if (align < 0) { + HI_ASSERT(0); + } + + COMMON_GetPicBufferConfig(width, height, pixelFormat, bitWidth, compressMode, align, &vbCfg); + + VB_BLK vbHnd = HI_MPI_VB_GetBlock(VB_INVALID_POOLID, vbCfg.u32VBSize, NULL); + if (vbHnd == VB_INVALID_HANDLE) { + SAMPLE_PRT("HI_MPI_VB_GetBlock FAIL\n"); + return HI_FAILURE; + } + + HI_U64 phyAddr = HI_MPI_VB_Handle2PhysAddr(vbHnd); + HI_ASSERT(phyAddr); + uint8_t* virAddr = (uint8_t*)HI_MPI_SYS_Mmap(phyAddr, vbCfg.u32VBSize); + HI_ASSERT(virAddr); + + /* u64PrivateData is used to store the length of the mapped memory area and vbHnd, + which will be used when destroying */ + frm->stVFrame.u64PrivateData = ((uint64_t)(uint32_t)vbHnd) << HI_INT32_BITS; + frm->stVFrame.u64PrivateData |= (uint64_t)vbCfg.u32VBSize; + + frm->enModId = HI_ID_VGS; + frm->u32PoolId = HI_MPI_VB_Handle2PoolId(vbHnd); + + frm->stVFrame.u32Width = width; + frm->stVFrame.u32Height = height; + frm->stVFrame.enField = VIDEO_FIELD_FRAME; + frm->stVFrame.enPixelFormat = pixelFormat; + frm->stVFrame.enVideoFormat = VIDEO_FORMAT_LINEAR; + frm->stVFrame.enCompressMode = compressMode; + frm->stVFrame.enDynamicRange = DYNAMIC_RANGE_SDR8; + frm->stVFrame.enColorGamut = COLOR_GAMUT_BT601; + + MppFrmSetBuf(frm, &vbCfg, phyAddr, virAddr); + return HI_SUCCESS; +} + +/* Determine whether the frame is available. That is, whether the memory is allocated */ +bool MppFrmValid(const VIDEO_FRAME_INFO_S* frm) +{ + // The frame output by VPSS does not map virtual addresses by default + return frm->stVFrame.u64PhyAddr[0]; +} + +/* Destory frame */ +void MppFrmDestroy(VIDEO_FRAME_INFO_S* frm) +{ + if (!MppFrmValid(frm)) { + return; + } + + // u64PrivateData is used to store the length of the mapped memory area and vbHnd, which is set at create + uint32_t memSize = (uint32_t)(frm->stVFrame.u64PrivateData); + uint32_t vbHnd = (uint32_t)(frm->stVFrame.u64PrivateData >> HI_INT32_BITS); + HI_S32 ret; + + ret = HI_MPI_SYS_Munmap((void*)(uintptr_t)frm->stVFrame.u64VirAddr[0], memSize); + HI_ASSERT(ret == HI_SUCCESS); + ret = HI_MPI_VB_ReleaseBlock(vbHnd); + HI_ASSERT(ret == HI_SUCCESS); + if (memset_s(frm, sizeof(*frm), 0, sizeof(*frm)) != EOK) { + HI_ASSERT(0); + } +} + +/* + * Perform a VGS resize. + * The zoom factor of each VGS resize is limited. VGS supports zooming of an image. + * The width and height are both enlarged by 16 times and reduced by 30 times.Support single-component (Y) scaling. + */ +static int VgsResizeOnce(const VIDEO_FRAME_INFO_S* src, VIDEO_FRAME_INFO_S* dst, uint32_t dstWidth, uint32_t dstHeight) +{ + HI_ASSERT(src && dst); + HI_ASSERT(dstWidth > 0 && dstHeight > 0); + VGS_HANDLE jobHnd = -1; + VGS_TASK_ATTR_S task; + int ret; + + ret = MppFrmCreate(dst, dstWidth, dstHeight, src->stVFrame.enPixelFormat, DATA_BITWIDTH_8, + src->stVFrame.enCompressMode, 0); + if (ret != 0) { + SAMPLE_PRT("frm resize FAIL, for create dstFrm FAIL\n"); + return ret; + } + + if (memset_s(&task, sizeof(task), 0, sizeof(task)) != EOK) { + HI_ASSERT(0); + } + task.stImgIn = *src; + task.stImgOut = *dst; + + ret = HI_MPI_VGS_BeginJob(&jobHnd); + if (ret != 0) { + SAMPLE_PRT("HI_MPI_VGS_BeginJob FAIL, ret=%08X\n", ret); + if (jobHnd >= 0 && HI_MPI_VGS_CancelJob(jobHnd) != HI_SUCCESS) { + HI_ASSERT(0); + } + MppFrmDestroy(dst); + return ret; + } + HI_ASSERT(jobHnd >= 0); + + ret = HI_MPI_VGS_AddScaleTask(jobHnd, &task, VGS_SCLCOEF_NORMAL); + if (ret != 0) { + SAMPLE_PRT("HI_MPI_VGS_AddScaleTask FAIL, ret=%08X\n", ret); + if (jobHnd >= 0 && HI_MPI_VGS_CancelJob(jobHnd) != HI_SUCCESS) { + HI_ASSERT(0); + } + MppFrmDestroy(dst); + return ret; + } + + ret = HI_MPI_VGS_EndJob(jobHnd); + if (ret != 0) { + SAMPLE_PRT("HI_MPI_VGS_EndJob FAIL, ret=%08X\n", ret); + if (jobHnd >= 0 && HI_MPI_VGS_CancelJob(jobHnd) != HI_SUCCESS) { + HI_ASSERT(0); + } + MppFrmDestroy(dst); + return ret; + } + return 0; +} + +/* + * resize frame. + * Call vgs_resize multiple times to achieve arbitrary scaling. + * In order to simplify the implementation, it is agreed that each zoom is up to 14 times, + * and at this time, the width and height only need to be aligned by 2 pixels. + * When the zoom directions are different in the two directions, for example, + * one direction (such as X) zooms in and the other direction zooms in, no special processing is required. + * At this time, the zoom ratio in one direction or both directions exceeds the standard, + * and no special treatment is required. + */ +int MppFrmResize( + const VIDEO_FRAME_INFO_S* src, + VIDEO_FRAME_INFO_S* dst, + uint32_t dstWidth, uint32_t dstHeight) +{ + static const double rateMax = 14.0; // Maximum magnification + static const double rateMin = 1.0 / rateMax; // The smallest magnification, that is, the largest reduction + + uint32_t srcWidth = src->stVFrame.u32Width; + uint32_t srcHeight = src->stVFrame.u32Height; + HI_ASSERT(srcWidth > 0 && srcHeight > 0); + HI_ASSERT(!(srcWidth % HI_OVEN_BASE) && !(srcHeight % HI_OVEN_BASE)); + HI_ASSERT(dstWidth > 0 && dstHeight > 0); + HI_ASSERT(!(dstWidth % HI_OVEN_BASE) && !(dstHeight % HI_OVEN_BASE)); + int ret; + + // magnification + double widthRate = ((double)dstWidth) / (double)srcWidth; // >1 means zoom in, <1 means zoom out + double heightRate = ((double)dstHeight) / (double)srcHeight; // >1 means zoom in, <1 means zoom out + + // Separate processing according to zoom factor + if (widthRate > rateMax || widthRate < rateMin || + heightRate > rateMax || heightRate < rateMin) { + // When the zoom factor exceeds the maximum value of one VGS, recursive processing... + uint32_t midWidth = (uint32_t)IntZoomTo((int)srcWidth, widthRate, rateMin, rateMax); + uint32_t midHeight = (uint32_t)IntZoomTo((int)srcHeight, heightRate, rateMin, rateMax); + /* Make sure it is an even number. When it is an odd number, + the zoom is reduced by one, otherwise it is increased by one */ + if (midWidth % HI_OVEN_BASE) { + midWidth += widthRate > 1 ? -1 : 1; + } + if (midHeight % HI_OVEN_BASE) { + midHeight += heightRate > 1 ? -1 : 1; + } + + SAMPLE_PRT("@@@ multi-lev vgs resize, src={%u, %u}, mid={%u, %u}, dst={%u, %u}, rate={%.4f, %.4f}\n", + srcWidth, srcHeight, midWidth, midHeight, dstWidth, dstHeight, widthRate, heightRate); + + // Zoom once + VIDEO_FRAME_INFO_S midFrm; + ret = VgsResizeOnce(src, &midFrm, midWidth, midHeight); + if (ret != 0) { + SAMPLE_PRT("VgsResizeOnce(dw=%u, dh=%u) FAIL\n", midWidth, midHeight); + return ret; + } + + // Recursively call midFrm as src + ret = MppFrmResize(&midFrm, dst, dstWidth, dstHeight); + MppFrmDestroy(&midFrm); + if (ret != 0) { + SAMPLE_PRT("sub call MppFrmResize(dw=%u, dh=%u) FAIL\n", dstWidth, dstHeight); + return ret; + } + } else { // The zoom factor does not exceed the maximum value of VGS once, and it is done directly + ret = VgsResizeOnce(src, dst, dstWidth, dstHeight); + if (ret != 0) { + SAMPLE_PRT("VgsResizeOnce(dw=%u, dh=%u) FAIL\n", dstWidth, dstHeight); + return ret; + } + } + return ret; +} + +/* Round up integers to even numbers */ +static inline int IntToOven(int x) +{ + if (x % HI_OVEN_BASE == 0) { + return x; + } else { + return x + 1; + } +} + +/* Create and execute VGS draw lines job */ +static HI_S32 VgsDrawLines(VIDEO_FRAME_INFO_S *frm, const VGS_DRAW_LINE_S lines[], int lineNum) +{ + VGS_HANDLE jobHnd = -1; + VGS_TASK_ATTR_S task; + int ret; + + if (memset_s(&task, sizeof(task), 0, sizeof(task)) != EOK) { + HI_ASSERT(0); + } + task.stImgIn = *frm; + task.stImgOut = *frm; + + ret = HI_MPI_VGS_BeginJob(&jobHnd); + if (ret != 0) { + SAMPLE_PRT("HI_MPI_VGS_BeginJob FAIL, ret=%08X\n", ret); + if (jobHnd >= 0 && HI_MPI_VGS_CancelJob(jobHnd) != HI_SUCCESS) { + HI_ASSERT(0); + } + return ret; + } + HI_ASSERT(jobHnd >= 0); + + ret = HI_MPI_VGS_AddDrawLineTaskArray(jobHnd, &task, lines, lineNum); + if (ret != 0) { + SAMPLE_PRT("HI_MPI_VGS_AddDrawLineTaskArray FAIL, ret=%08X\n", ret); + if (jobHnd >= 0 && HI_MPI_VGS_CancelJob(jobHnd) != HI_SUCCESS) { + HI_ASSERT(0); + } + return ret; + } + + ret = HI_MPI_VGS_EndJob(jobHnd); + if (ret != 0) { + SAMPLE_PRT("HI_MPI_VGS_EndJob FAIL, ret=%08X\n", ret); + if (jobHnd >= 0 && HI_MPI_VGS_CancelJob(jobHnd) != HI_SUCCESS) { + HI_ASSERT(0); + } + return ret; + } + return 0; +} + +/* Superimpose one or more rectangular boxes in the frame */ +int MppFrmDrawRects(VIDEO_FRAME_INFO_S *frm, + const RectBox *boxes, int boxesNum, uint32_t color, int thick) +{ + VGS_DRAW_LINE_S lines[VGS_MAX_LINE]; + int i; + + if (thick <= 0) { + HI_ASSERT(0); + } + + // Plan the four sides of each rectangle into lines + for (i = 0; i < boxesNum; i++) { + lines[RECT_LINES * i].stStartPoint.s32X = IntToOven(boxes[i].xmin); + lines[RECT_LINES * i].stStartPoint.s32Y = IntToOven(boxes[i].ymin); + lines[RECT_LINES * i].stEndPoint.s32X = IntToOven(boxes[i].xmax); + lines[RECT_LINES * i].stEndPoint.s32Y = IntToOven(boxes[i].ymin); + lines[RECT_LINES * i].u32Color = color; + lines[RECT_LINES * i].u32Thick = thick; + lines[RECT_LINES * i + RECT_LINE1].stStartPoint.s32X = IntToOven(boxes[i].xmax); + lines[RECT_LINES * i + RECT_LINE1].stStartPoint.s32Y = IntToOven(boxes[i].ymin); + lines[RECT_LINES * i + RECT_LINE1].stEndPoint.s32X = IntToOven(boxes[i].xmax); + lines[RECT_LINES * i + RECT_LINE1].stEndPoint.s32Y = IntToOven(boxes[i].ymax); + lines[RECT_LINES * i + RECT_LINE1].u32Color = color; + lines[RECT_LINES * i + RECT_LINE1].u32Thick = thick; + lines[RECT_LINES * i + RECT_LINE2].stStartPoint.s32X = IntToOven(boxes[i].xmax); + lines[RECT_LINES * i + RECT_LINE2].stStartPoint.s32Y = IntToOven(boxes[i].ymax); + lines[RECT_LINES * i + RECT_LINE2].stEndPoint.s32X = IntToOven(boxes[i].xmin); + lines[RECT_LINES * i + RECT_LINE2].stEndPoint.s32Y = IntToOven(boxes[i].ymax); + lines[RECT_LINES * i + RECT_LINE2].u32Color = color; + lines[RECT_LINES * i + RECT_LINE2].u32Thick = thick; + lines[RECT_LINES * i + RECT_LINE3].stStartPoint.s32X = IntToOven(boxes[i].xmin); + lines[RECT_LINES * i + RECT_LINE3].stStartPoint.s32Y = IntToOven(boxes[i].ymax); + lines[RECT_LINES * i + RECT_LINE3].stEndPoint.s32X = IntToOven(boxes[i].xmin); + lines[RECT_LINES * i + RECT_LINE3].stEndPoint.s32Y = IntToOven(boxes[i].ymin); + lines[RECT_LINES * i + RECT_LINE3].u32Color = color; + lines[RECT_LINES * i + RECT_LINE3].u32Thick = thick; + } + return VgsDrawLines(frm, lines, i * RECT_LINES); +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* End of #ifdef __cplusplus */ diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/scenario/hand_classify/README.md b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/scenario/hand_classify/README.md new file mode 100644 index 0000000..d350b27 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/scenario/hand_classify/README.md @@ -0,0 +1,70 @@ +# 5.2、手部检测+手势识别实验功能验证 + +* 步骤1:在SD卡或Windows的nfs共享目录下,创建一个**sample_ai.conf**的文件,然后把下面的内容拷贝到此文件中 + +```cobol +; ai sample configuration file + +[audio_player] +support_audio = true ; 垃圾识别语音播放 + +[ai_function] +support_ai = true ; 是否支持AI + +[trash_classify_switch] +support_trash_classify = false ; 是否支持垃圾分类功能 + +[hand_classify_switch] +support_hand_classify = true ; 是否手势检测识别功能 +``` + +![](https://gitee.com/wgm2022/mypic/raw/master/hispark_taurus_ai_sample/038%E4%BF%AE%E6%94%B9conf%E6%96%87%E4%BB%B6%E4%BD%BF%E8%83%BD%E6%89%8B%E5%8A%BF%E8%AF%86%E5%88%AB.png) + +* 步骤2:再通过下面的挂载命令,把SD卡或者Windows的nfs共享目录挂载到开发板上 + + * 方式1:SD卡 + + ``` + mount -t vfat /dev/mmcblk1p1 /mnt + # 其中/dev/mmcblk1p1需要根据实际块设备号修改 + ``` + + * 方式2:Windows的nfs共享目录 + + ``` + mount -o nolock,addr=192.168.200.1 -t nfs 192.168.200.1:/d/nfs /mnt + ``` + +* 步骤3:将/mnt目录下的sample_ai.conf文件复制到userdata目录下。 + +``` +cp /mnt/sample_ai.conf /userdata +``` + +![](https://gitee.com/wgm2022/mypic/raw/master/hispark_taurus_ai_sample/039%E6%8B%B7%E8%B4%9Dai%20sample%20config%E8%87%B3userdata.png) + +* 步骤4:执行下面的命令:进入/ko目录,加载mipi_tx驱动。 + +``` +cd /ko +insmod hi_mipi_tx.ko +``` + +![](https://gitee.com/wgm2022/mypic/raw/master/hispark_taurus_ai_sample/040%E5%8A%A0%E8%BD%BDmipi_txko.png) + +* 执行下面的命令,进行手势识别sample的验证 + +``` +cd /userdata +./ohos_camera_ai_demo 1 +``` + +![](https://gitee.com/wgm2022/mypic/raw/master/hispark_taurus_ai_sample/041%E6%89%A7%E8%A1%8C%E6%89%8B%E5%8A%BF%E8%AF%86%E5%88%AB.png) + + + +![](https://gitee.com/wgm2022/mypic/raw/master/hispark_taurus_ai_sample/045%E6%89%8B%E5%8A%BF%E8%AF%86%E5%88%AB%E7%9A%84%E7%BB%93%E6%9E%9C%E5%9B%BE.png) + +* 敲两下回车即可关闭程序 + +![](https://gitee.com/wgm2022/mypic/raw/master/hispark_taurus_helloworld_sample/0007-helloworld%20log.png) diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/scenario/hand_classify/hand_classify.c b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/scenario/hand_classify/hand_classify.c new file mode 100644 index 0000000..5e59a71 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/scenario/hand_classify/hand_classify.c @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Copyright (c) 2022 Sidi Liang. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "sample_comm_nnie.h" +#include "sample_media_ai.h" +#include "ai_infer_process.h" +#include "yolov2_hand_detect.h" +#include "vgs_img.h" +#include "ive_img.h" +#include "misc_util.h" +#include "hisignalling.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* End of #ifdef __cplusplus */ + +#define HAND_FRM_WIDTH 640 +#define HAND_FRM_HEIGHT 384 +#define DETECT_OBJ_MAX 32 +#define RET_NUM_MAX 4 +#define DRAW_RETC_THICK 2 // Draw the width of the line +#define WIDTH_LIMIT 32 +#define HEIGHT_LIMIT 32 +#define IMAGE_WIDTH 224 // The resolution of the model IMAGE sent to the classification is 224*224 +#define IMAGE_HEIGHT 224 +#define MODEL_FILE_GESTURE "/userdata/models/smart_vendor_ai/gesture_classification_v6.wk" // darknet framework wk model +#define MODEL_FILE_GESTURE_SAMPLE "/userdata/models/hand_classify/hand_gesture.wk" // darknet framework wk model + +static int biggestBoxIndex; +static IVE_IMAGE_S img; +static DetectObjInfo objs[DETECT_OBJ_MAX] = {0}; +static RectBox boxs[DETECT_OBJ_MAX] = {0}; +static RectBox objBoxs[DETECT_OBJ_MAX] = {0}; +static RectBox remainingBoxs[DETECT_OBJ_MAX] = {0}; +static RectBox cnnBoxs[DETECT_OBJ_MAX] = {0}; // Store the results of the classification network +static RecogNumInfo numInfo[RET_NUM_MAX] = {0}; +static IVE_IMAGE_S imgIn; +static IVE_IMAGE_S imgDst; +static VIDEO_FRAME_INFO_S frmIn; +static VIDEO_FRAME_INFO_S frmDst; + +HI_S32 Yolo2HandDetectResnetClassifyLoad(uintptr_t* model) +{ + SAMPLE_SVP_NNIE_CFG_S *self = NULL; + HI_S32 ret; + + ret = CnnCreate(&self, MODEL_FILE_GESTURE); // Use sample model for the school contest + *model = ret < 0 ? 0 : (uintptr_t)self; + HandDetectInit(); // Initialize the hand detection model + SAMPLE_PRT("Hand gesture classification model loaded\n"); + return ret; +} + +HI_S32 Yolo2HandDetectResnetClassifyUnload(uintptr_t model) +{ + CnnDestroy((SAMPLE_SVP_NNIE_CFG_S*)model); + HandDetectExit(); // Uninitialize the hand detection model + //SAMPLE_PRT("Unload hand detect claasify model success\n"); + + return 0; +} + +/* Get the maximum hand */ +static HI_S32 GetBiggestHandIndex(RectBox boxs[], int detectNum) +{ + HI_S32 handIndex = 0; + HI_S32 biggestBoxIndex = handIndex; + HI_S32 biggestBoxWidth = boxs[handIndex].xmax - boxs[handIndex].xmin + 1; + HI_S32 biggestBoxHeight = boxs[handIndex].ymax - boxs[handIndex].ymin + 1; + HI_S32 biggestBoxArea = biggestBoxWidth * biggestBoxHeight; + + for (handIndex = 1; handIndex < detectNum; handIndex++) { + HI_S32 boxWidth = boxs[handIndex].xmax - boxs[handIndex].xmin + 1; + HI_S32 boxHeight = boxs[handIndex].ymax - boxs[handIndex].ymin + 1; + HI_S32 boxArea = boxWidth * boxHeight; + if (biggestBoxArea < boxArea) { + biggestBoxArea = boxArea; + biggestBoxIndex = handIndex; + } + biggestBoxWidth = boxs[biggestBoxIndex].xmax - boxs[biggestBoxIndex].xmin + 1; + biggestBoxHeight = boxs[biggestBoxIndex].ymax - boxs[biggestBoxIndex].ymin + 1; + } + + if ((biggestBoxWidth == 1) || (biggestBoxHeight == 1) || (detectNum == 0)) { + biggestBoxIndex = -1; + } + + return biggestBoxIndex; +} + +HI_S32 Yolo2HandDetectResnetClassifyCal(uintptr_t model, VIDEO_FRAME_INFO_S *srcFrm, VIDEO_FRAME_INFO_S *dstFrm, RecogNumInfo *numInfoArg) +{ + SAMPLE_SVP_NNIE_CFG_S *self = (SAMPLE_SVP_NNIE_CFG_S*)model; + HI_S32 resLen = 0; + int objNum; + int ret; + int num = 0; + + ret = FrmToOrigImg((VIDEO_FRAME_INFO_S*)srcFrm, &img); + SAMPLE_CHECK_EXPR_RET(ret != HI_SUCCESS, ret, "hand detect for YUV Frm to Img FAIL, ret=%#x\n", ret); + + objNum = HandDetectCal(&img, objs); // Send IMG to the detection net for reasoning + for (int i = 0; i < objNum; i++) { + cnnBoxs[i] = objs[i].box; + RectBox *box = &objs[i].box; + RectBoxTran(box, HAND_FRM_WIDTH, HAND_FRM_HEIGHT, + dstFrm->stVFrame.u32Width, dstFrm->stVFrame.u32Height); + //SAMPLE_PRT("yolo2_out: {%d, %d, %d, %d}\n", box->xmin, box->ymin, box->xmax, box->ymax); + boxs[i] = *box; + } + biggestBoxIndex = GetBiggestHandIndex(boxs, objNum); + //SAMPLE_PRT("biggestBoxIndex:%d, objNum:%d\n", biggestBoxIndex, objNum); + + // When an object is detected, a rectangle is drawn in the DSTFRM + if (biggestBoxIndex >= 0) { + objBoxs[0] = boxs[biggestBoxIndex]; + MppFrmDrawRects(dstFrm, objBoxs, 1, RGB888_GREEN, DRAW_RETC_THICK); // Target hand objnum is equal to 1 + + for (int j = 0; (j < objNum) && (objNum > 1); j++) { + if (j != biggestBoxIndex) { + remainingBoxs[num++] = boxs[j]; + // others hand objnum is equal to objnum -1 + MppFrmDrawRects(dstFrm, remainingBoxs, objNum - 1, RGB888_RED, DRAW_RETC_THICK); + } + } + + // Crop the image to classification network + RectBox targetBox = cnnBoxs[biggestBoxIndex]; + ret = ImgYuvCrop(&img, &imgIn, &targetBox); + + //Print this info to check what size of images are being cropped + /* + SAMPLE_PRT("\nxmax: %d xmin: %d ymax: %d ymin: %d\n",targetBox.xmax, + targetBox.xmin, targetBox.ymax, targetBox.ymin); + */ + + SAMPLE_CHECK_EXPR_RET(ret < 0, ret, "ImgYuvCrop FAIL, ret=%#x\n", ret); + + if ((imgIn.u32Width >= WIDTH_LIMIT) && (imgIn.u32Height >= HEIGHT_LIMIT)) { + COMPRESS_MODE_E enCompressMode = srcFrm->stVFrame.enCompressMode; + ret = OrigImgToFrm(&imgIn, &frmIn); + frmIn.stVFrame.enCompressMode = enCompressMode; + //SAMPLE_PRT("crop u32Width = %d, img.u32Height = %d\n", imgIn.u32Width, imgIn.u32Height); + ret = MppFrmResize(&frmIn, &frmDst, IMAGE_WIDTH, IMAGE_HEIGHT); + ret = FrmToOrigImg(&frmDst, &imgDst); + ret = CnnCalU8c1Img(self, &imgDst, numInfo, sizeof(numInfo) / sizeof((numInfo)[0]), &resLen); + SAMPLE_CHECK_EXPR_RET(ret < 0, ret, "CnnCalU8c1Img FAIL, ret=%#x\n", ret); + HI_ASSERT(resLen <= sizeof(numInfo) / sizeof(numInfo[0])); + *numInfoArg = numInfo[0]; + MppFrmDestroy(&frmDst); + } + IveImgDestroy(&imgIn); + } + + return ret; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* End of #ifdef __cplusplus */ diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/scenario/hand_classify/hand_classify.h b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/scenario/hand_classify/hand_classify.h new file mode 100644 index 0000000..58148d1 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/scenario/hand_classify/hand_classify.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Copyright (c) 2022 Sidi Liang. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAND_CLASSIFY_H +#define HAND_CLASSIFY_H + +#include +#include +#include +#include +#include "hi_comm_video.h" + +#if __cplusplus +extern "C" { +#endif + +/* load hand detect and classify model */ +HI_S32 Yolo2HandDetectResnetClassifyLoad(uintptr_t* model); + +/* unload hand detect and classify model */ +HI_S32 Yolo2HandDetectResnetClassifyUnload(uintptr_t model); + +/* hand detect and classify calculation */ +HI_S32 Yolo2HandDetectResnetClassifyCal(uintptr_t model, VIDEO_FRAME_INFO_S *srcFrm, VIDEO_FRAME_INFO_S *dstFrm, RecogNumInfo *numInfoArg); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/scenario/hand_classify/yolov2_hand_detect.c b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/scenario/hand_classify/yolov2_hand_detect.c new file mode 100644 index 0000000..af2e65d --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/scenario/hand_classify/yolov2_hand_detect.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "sample_comm_nnie.h" +#include "ai_infer_process.h" +#include "sample_media_ai.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* End of #ifdef __cplusplus */ + +#define MODEL_FILE_HAND "/userdata/models/hand_classify/hand_detect.wk" // darknet framework wk model +#define PIRIOD_NUM_MAX 49 // Logs are printed when the number of targets is detected +#define DETECT_OBJ_MAX 32 // detect max obj + +static uintptr_t g_handModel = 0; + +static HI_S32 Yolo2FdLoad(uintptr_t* model) +{ + SAMPLE_SVP_NNIE_CFG_S *self = NULL; + HI_S32 ret; + + ret = Yolo2Create(&self, MODEL_FILE_HAND); + *model = ret < 0 ? 0 : (uintptr_t)self; + SAMPLE_PRT("Yolo2FdLoad ret:%d\n", ret); + + return ret; +} + +HI_S32 HandDetectInit() +{ + return Yolo2FdLoad(&g_handModel); +} + +static HI_S32 Yolo2FdUnload(uintptr_t model) +{ + Yolo2Destory((SAMPLE_SVP_NNIE_CFG_S*)model); + return 0; +} + +HI_S32 HandDetectExit() +{ + return Yolo2FdUnload(g_handModel); +} + +static HI_S32 HandDetect(uintptr_t model, IVE_IMAGE_S *srcYuv, DetectObjInfo boxs[]) +{ + SAMPLE_SVP_NNIE_CFG_S *self = (SAMPLE_SVP_NNIE_CFG_S*)model; + int objNum; + int ret = Yolo2CalImg(self, srcYuv, boxs, DETECT_OBJ_MAX, &objNum); + if (ret < 0) { + SAMPLE_PRT("Hand detect Yolo2CalImg FAIL, for cal FAIL, ret:%d\n", ret); + return ret; + } + + return objNum; +} + +HI_S32 HandDetectCal(IVE_IMAGE_S *srcYuv, DetectObjInfo resArr[]) +{ + int ret = HandDetect(g_handModel, srcYuv, resArr); + return ret; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* End of #ifdef __cplusplus */ diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/scenario/hand_classify/yolov2_hand_detect.h b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/scenario/hand_classify/yolov2_hand_detect.h new file mode 100644 index 0000000..5f2d0a7 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/scenario/hand_classify/yolov2_hand_detect.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef YOLOV2_HAND_DETECT_H +#define YOLOV2_HAND_DETECT_H + +#include "hi_type.h" + +#if __cplusplus +extern "C" { +#endif + +HI_S32 HandDetectInit(); +HI_S32 HandDetectExit(); +HI_S32 HandDetectCal(IVE_IMAGE_S *srcYuv, DetectObjInfo resArr[]); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/smp/sample_media_ai.c b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/smp/sample_media_ai.c new file mode 100644 index 0000000..2843cc1 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/smp/sample_media_ai.c @@ -0,0 +1,1791 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Copyright (c) 2022 Sidi Liang. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hi_mipi_tx.h" +#include "sdk.h" +#include "sample_comm.h" +#include "ai_infer_process.h" +#include "hand_classify.h" +#include "vgs_img.h" +#include "osd_img.h" +#include "posix_help.h" +#include "sample_media_ai.h" +#include "smart_vendor_classification.h" +#include "hisignalling.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* End of #ifdef __cplusplus */ + +HI_BOOL g_bAiProcessStopSignal = HI_FALSE; +static HI_U32 g_num = 0; +AicMediaInfo g_aicMediaInfo = { 0 }; +static pthread_t g_aiProcessThread = 0; +AiPlugLib g_workPlug = {0}; + +#define HAND_FRM_WIDTH 640 +#define HAND_FRM_HEIGHT 384 +#define AI_SAMPLE_CFG_FILE "./sample_ai.conf" +#define BUFFER_SIZE 16 // buffer size + +#define USLEEP_TIME 1000 // 1000: usleep time, in microseconds +#define G_MBUF_LENGTH 50 // 50: length of g_mbuf +#define ALIGN_DOWN_SIZE 2 + +#define G_MBUF_ARRAY_SUBSCRIPT_0 0 +#define G_MBUF_ARRAY_SUBSCRIPT_1 1 +#define G_MBUF_ARRAY_SUBSCRIPT_2 2 +#define G_MBUF_ARRAY_SUBSCRIPT_3 3 +#define G_MBUF_ARRAY_SUBSCRIPT_4 4 +#define G_MBUF_ARRAY_SUBSCRIPT_5 5 +#define G_MBUF_ARRAY_SUBSCRIPT_6 6 +#define G_MBUF_ARRAY_SUBSCRIPT_7 7 +#define G_MBUF_ARRAY_SUBSCRIPT_8 8 +#define G_MBUF_ARRAY_SUBSCRIPT_9 9 +#define G_MBUF_ARRAY_SUBSCRIPT_10 10 +#define G_MBUF_ARRAY_SUBSCRIPT_11 11 +#define G_MBUF_ARRAY_SUBSCRIPT_12 12 +#define G_MBUF_ARRAY_SUBSCRIPT_13 13 +#define G_MBUF_ARRAY_SUBSCRIPT_14 14 +#define G_MBUF_ARRAY_SUBSCRIPT_15 15 +#define G_MBUF_ARRAY_SUBSCRIPT_16 16 + +#define LANE_ID_SUBSCRIPT_0 0 +#define LANE_ID_SUBSCRIPT_1 1 +#define LANE_ID_SUBSCRIPT_2 2 +#define LANE_ID_SUBSCRIPT_3 3 + +static unsigned char g_mBuf[G_MBUF_LENGTH]; +static SampleVoModeMux g_sampleVoModeMux = {0}; +static VO_PUB_ATTR_S stVoPubAttr = {0}; +static VO_VIDEO_LAYER_ATTR_S stLayerAttr = {0}; +static VO_CSC_S stVideoCSC = {0}; +static RECT_S stDefDispRect = {0, 0, 800, 480}; +static SIZE_S stDefImageSize = {800, 480}; + +HI_CHAR acThreadName[16] = {0}; + +typedef struct StSampleUserVoConfigs { + VO_SYNC_INFO_S stSyncInfo; + VO_USER_INTFSYNC_ATTR_S stUserIntfSyncAttr; + HI_U32 u32PreDiv; + HI_U32 u32DevDiv; + HI_U32 u32Framerate; + combo_dev_cfg_t stcombo_dev_cfgl; +} SAMPLE_USER_VO_CONFIG_S; + +static HI_S32 VendorHandClassificationCreateThread(HI_VOID) +{ + //BUFFER_SIZE = 16 + HI_S32 s32Ret; + if (snprintf_s(acThreadName, 16, 15, "AIProcess") < 0) { + HI_ASSERT(0); + } + prctl(PR_SET_NAME, (unsigned long)acThreadName, 0, 0, 0); + struct arg_struct { + AiPlugLib* g_workPlug; + AicMediaInfo* g_aicMediaInfo; + }; + struct arg_struct *args = malloc(sizeof(struct arg_struct)); + args->g_workPlug = &g_workPlug; + args->g_aicMediaInfo = &g_aicMediaInfo; + s32Ret = pthread_create(&g_aiProcessThread, NULL, VendorGetVpssChnFrameAndClassify, args); + + return s32Ret; +} + +HI_VOID SAMPLE_VOU_SYS_Exit(void) +{ + HI_MPI_SYS_Exit(); + HI_MPI_VB_Exit(); +} + +HI_VOID SAMPLE_VO_GetUserLayerAttr(VO_VIDEO_LAYER_ATTR_S *pstLayerAttr, SIZE_S *pstDevSize) +{ + pstLayerAttr->bClusterMode = HI_FALSE; + pstLayerAttr->bDoubleFrame = HI_FALSE; + pstLayerAttr->enDstDynamicRange = DYNAMIC_RANGE_SDR8; + pstLayerAttr->enPixFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420; + + pstLayerAttr->stDispRect.s32X = 0; + pstLayerAttr->stDispRect.s32Y = 0; + pstLayerAttr->stDispRect.u32Height = pstDevSize->u32Height; + pstLayerAttr->stDispRect.u32Width = pstDevSize->u32Width; + + pstLayerAttr->stImageSize.u32Height = pstDevSize->u32Height; + pstLayerAttr->stImageSize.u32Width = pstDevSize->u32Width; + + return; +} + +HI_VOID SAMPLE_VO_GetUserChnAttr(VO_CHN_ATTR_S *pstChnAttr, SIZE_S *pstDevSize, HI_S32 VoChnNum) +{ + HI_S32 i; + for (i = 0; i < VoChnNum; i++) { + pstChnAttr[i].bDeflicker = HI_FALSE; + pstChnAttr[i].u32Priority = 0; + pstChnAttr[i].stRect.s32X = 0; + pstChnAttr[i].stRect.s32Y = 0; + pstChnAttr[i].stRect.u32Height = pstDevSize->u32Height; + pstChnAttr[i].stRect.u32Width = pstDevSize->u32Width; + } + + return; +} + +/* open mipi_tx device */ +HI_S32 SampleOpenMipiTxFd(HI_VOID) +{ + HI_S32 fd; + + fd = open("/dev/hi_mipi_tx", O_RDWR); + if (fd < 0) { + printf("open hi_mipi_tx dev failed\n"); + } + return fd; +} + +/* close mipi_tx device */ +HI_VOID SampleCloseMipiTxFd(HI_S32 fd) +{ + close(fd); + return; +} + +/* get mipi tx config information */ +HI_VOID SAMPLE_GetMipiTxConfig(combo_dev_cfg_t *pstMipiTxConfig) +{ + /* USER NEED SET MIPI DEV CONFIG */ + pstMipiTxConfig->devno = 0; + pstMipiTxConfig->lane_id[LANE_ID_SUBSCRIPT_0] = 0; + pstMipiTxConfig->lane_id[LANE_ID_SUBSCRIPT_1] = 1; + // -1: 2 lane mode configuration,lane_id[4] = {0, 1, -1, -1} + pstMipiTxConfig->lane_id[LANE_ID_SUBSCRIPT_2] = -1; + // -1: 2 lane mode configuration,lane_id[4] = {0, 1, -1, -1} + pstMipiTxConfig->lane_id[LANE_ID_SUBSCRIPT_3] = -1; + pstMipiTxConfig->output_mode = OUTPUT_MODE_DSI_VIDEO; + pstMipiTxConfig->output_format = OUT_FORMAT_RGB_24_BIT; + pstMipiTxConfig->video_mode = BURST_MODE; + pstMipiTxConfig->sync_info.vid_pkt_size = 480; // 480: received packet size + pstMipiTxConfig->sync_info.vid_hsa_pixels = 10; // 10: The number of pixels in the input line sync pulse area + pstMipiTxConfig->sync_info.vid_hbp_pixels = 50; // 50: Number of pixels in blanking area after input + pstMipiTxConfig->sync_info.vid_hline_pixels = 590; // 590: The total number of pixels detected per line + pstMipiTxConfig->sync_info.vid_vsa_lines = 4; // 4: Number of frame sync pulse lines detected + pstMipiTxConfig->sync_info.vid_vbp_lines = 20; // 20: Number of blanking area lines after frame sync pulse + pstMipiTxConfig->sync_info.vid_vfp_lines = 20; // 20: Number of blanking area lines before frame sync pulse + pstMipiTxConfig->sync_info.vid_active_lines = 800; // 800: VACTIVE rows + pstMipiTxConfig->sync_info.edpi_cmd_size = 0; // 0: Write memory command bytes + pstMipiTxConfig->phy_data_rate = 359; // 359: MIPI Tx output rate + pstMipiTxConfig->pixel_clk = 29878; // 29878: pixel clock. The unit is KHz + + return; +} + +/* set mipi tx config information */ +HI_S32 SAMPLE_SetMipiTxConfig(HI_S32 fd, combo_dev_cfg_t *pstMipiTxConfig) +{ + HI_S32 s32Ret = ioctl(fd, HI_MIPI_TX_SET_DEV_CFG, pstMipiTxConfig); + if (s32Ret != HI_SUCCESS) { + printf("MIPI_TX SET_DEV_CONFIG failed\n"); + SampleCloseMipiTxFd(fd); + return s32Ret; + } + return s32Ret; +} + +/* set mipi tx device config */ +HI_S32 SampleSetMipiTxDevAttr(HI_S32 fd) +{ + HI_S32 s32Ret; + combo_dev_cfg_t stMipiTxConfig; + + /* USER SET MIPI DEV CONFIG */ + SAMPLE_GetMipiTxConfig(&stMipiTxConfig); + + /* USER SET MIPI DEV CONFIG */ + s32Ret = SAMPLE_SetMipiTxConfig(fd, &stMipiTxConfig); + + return s32Ret; +} + +/* init mipi tx device */ +HI_S32 SAMPLE_USER_INIT_MIPITx(HI_S32 fd, cmd_info_t *pcmd_info) +{ + HI_S32 s32Ret = ioctl(fd, HI_MIPI_TX_SET_CMD, pcmd_info); + if (s32Ret != HI_SUCCESS) { + printf("MIPI_TX SET CMD failed\n"); + SampleCloseMipiTxFd(fd); + return s32Ret; + } + + return HI_SUCCESS; +} + +/* set mipi tx device init screen */ +HI_S32 SampleVoInitMipiTxScreen(HI_S32 fd) +{ + HI_S32 s32Ret; + cmd_info_t cmd_info; + memset_s(g_mBuf, G_MBUF_LENGTH, 0, G_MBUF_LENGTH); + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_0] = 0xFF; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_1] = 0x77; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_2] = 0x01; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_3] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_4] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_5] = 0x13; + cmd_info.devno = 0; + cmd_info.cmd_size = 6; // 6: command data size + cmd_info.data_type = 0x29; + cmd_info.cmd = g_mBuf; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + cmd_info.devno = 0; + cmd_info.cmd_size = 0x08ef; + cmd_info.data_type = 0x23; + cmd_info.cmd = NULL; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + memset_s(g_mBuf, G_MBUF_LENGTH, 0, G_MBUF_LENGTH); + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_0] = 0xFF; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_1] = 0x77; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_2] = 0x01; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_3] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_4] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_5] = 0x10; + cmd_info.devno = 0; + cmd_info.cmd_size = 6; // 6: command data size + cmd_info.data_type = 0x29; + cmd_info.cmd = g_mBuf; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + memset_s(g_mBuf, G_MBUF_LENGTH, 0, G_MBUF_LENGTH); + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_0] = 0xC0; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_1] = 0x63; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_2] = 0x00; + cmd_info.devno = 0; + cmd_info.cmd_size = 3; // 3: command data size + cmd_info.data_type = 0x29; + cmd_info.cmd = g_mBuf; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + memset_s(g_mBuf, G_MBUF_LENGTH, 0, G_MBUF_LENGTH); + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_0] = 0xC1; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_1] = 0x10; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_2] = 0x02; + cmd_info.devno = 0; + cmd_info.cmd_size = 3; // 3: command data size + cmd_info.data_type = 0x29; + cmd_info.cmd = g_mBuf; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + memset_s(g_mBuf, G_MBUF_LENGTH, 0, G_MBUF_LENGTH); + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_0] = 0xC2; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_1] = 0x01; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_2] = 0x08; + cmd_info.devno = 0; + cmd_info.cmd_size = 3; // 3: command data size + cmd_info.data_type = 0x29; + cmd_info.cmd = g_mBuf; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + cmd_info.devno = 0; + cmd_info.cmd_size = 0x18CC; + cmd_info.data_type = 0x23; + cmd_info.cmd = NULL; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + memset_s(g_mBuf, G_MBUF_LENGTH, 0, G_MBUF_LENGTH); + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_0] = 0xB0; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_1] = 0x40; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_2] = 0xC9; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_3] = 0x8F; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_4] = 0x0D; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_5] = 0x11; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_6] = 0x07; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_7] = 0x02; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_8] = 0x09; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_9] = 0x09; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_10] = 0x1F; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_11] = 0x04; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_12] = 0x50; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_13] = 0x0F; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_14] = 0xE4; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_15] = 0x29; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_16] = 0xDF; + cmd_info.devno = 0; + cmd_info.cmd_size = 17; // 17: command data size + cmd_info.data_type = 0x29; + cmd_info.cmd = g_mBuf; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + memset_s(g_mBuf, G_MBUF_LENGTH, 0, G_MBUF_LENGTH); + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_0] = 0xB1; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_1] = 0x40; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_2] = 0xCB; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_3] = 0xD3; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_4] = 0x11; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_5] = 0x8F; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_6] = 0x04; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_7] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_8] = 0x08; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_9] = 0x07; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_10] = 0x1C; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_11] = 0x06; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_12] = 0x53; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_13] = 0x12; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_14] = 0x63; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_15] = 0xEB; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_16] = 0xDF; + cmd_info.devno = 0; + cmd_info.cmd_size = 17; // 17: command data size + cmd_info.data_type = 0x29; + cmd_info.cmd = g_mBuf; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + memset_s(g_mBuf, G_MBUF_LENGTH, 0, G_MBUF_LENGTH); + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_0] = 0xFF; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_1] = 0x77; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_2] = 0x01; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_3] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_4] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_5] = 0x11; + cmd_info.devno = 0; + cmd_info.cmd_size = 6; // 6: command data size + cmd_info.data_type = 0x29; + cmd_info.cmd = g_mBuf; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + cmd_info.devno = 0; + cmd_info.cmd_size = 0x65b0; + cmd_info.data_type = 0x23; + cmd_info.cmd = NULL; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + cmd_info.devno = 0; + cmd_info.cmd_size = 0x34b1; + cmd_info.data_type = 0x23; + cmd_info.cmd = NULL; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + cmd_info.devno = 0; + cmd_info.cmd_size = 0x87b2; + cmd_info.data_type = 0x23; + cmd_info.cmd = NULL; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + cmd_info.devno = 0; + cmd_info.cmd_size = 0x80b3; + cmd_info.data_type = 0x23; + cmd_info.cmd = NULL; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + cmd_info.devno = 0; + cmd_info.cmd_size = 0x49b5; + cmd_info.data_type = 0x23; + cmd_info.cmd = NULL; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + cmd_info.devno = 0; + cmd_info.cmd_size = 0x85b7; + cmd_info.data_type = 0x23; + cmd_info.cmd = NULL; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + cmd_info.devno = 0; + cmd_info.cmd_size = 0x20b8; + cmd_info.data_type = 0x23; + cmd_info.cmd = NULL; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + cmd_info.devno = 0; + cmd_info.cmd_size = 0x10b9; + cmd_info.data_type = 0x23; + cmd_info.cmd = NULL; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + cmd_info.devno = 0; + cmd_info.cmd_size = 0x78c1; + cmd_info.data_type = 0x23; + cmd_info.cmd = NULL; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + cmd_info.devno = 0; + cmd_info.cmd_size = 0x78c2; + cmd_info.data_type = 0x23; + cmd_info.cmd = NULL; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + cmd_info.devno = 0; + cmd_info.cmd_size = 0x88d0; + cmd_info.data_type = 0x23; + cmd_info.cmd = NULL; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + usleep(100000); // 100000: The process hangs for a period of time, in microseconds + + memset_s(g_mBuf, G_MBUF_LENGTH, 0, G_MBUF_LENGTH); + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_0] = 0xE0; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_1] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_2] = 0x19; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_3] = 0x02; + cmd_info.devno = 0; + cmd_info.cmd_size = 4; // 4: command data size + cmd_info.data_type = 0x29; + cmd_info.cmd = g_mBuf; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + usleep(USLEEP_TIME); + + memset_s(g_mBuf, G_MBUF_LENGTH, 0, G_MBUF_LENGTH); + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_0] = 0xE1; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_1] = 0x05; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_2] = 0xA0; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_3] = 0x07; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_4] = 0xA0; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_5] = 0x04; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_6] = 0xA0; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_7] = 0x06; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_8] = 0xA0; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_9] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_10] = 0x44; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_11] = 0x44; + cmd_info.devno = 0; + cmd_info.cmd_size = 12; // 12: command data size + cmd_info.data_type = 0x29; + cmd_info.cmd = g_mBuf; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + memset_s(g_mBuf, G_MBUF_LENGTH, 0, G_MBUF_LENGTH); + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_0] = 0xE2; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_1] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_2] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_3] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_4] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_5] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_6] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_7] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_8] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_9] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_10] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_11] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_12] = 0x00; + cmd_info.devno = 0; + cmd_info.cmd_size = 13; // 13: command data size + cmd_info.data_type = 0x29; + cmd_info.cmd = g_mBuf; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + memset_s(g_mBuf, G_MBUF_LENGTH, 0, G_MBUF_LENGTH); + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_0] = 0xE3; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_1] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_2] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_3] = 0x33; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_4] = 0x33; + cmd_info.devno = 0; + cmd_info.cmd_size = 5; // 5: command data size + cmd_info.data_type = 0x29; + cmd_info.cmd = g_mBuf; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + memset_s(g_mBuf, G_MBUF_LENGTH, 0, G_MBUF_LENGTH); + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_0] = 0xE4; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_1] = 0x44; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_2] = 0x44; + cmd_info.devno = 0; + cmd_info.cmd_size = 3; // 3: command data size + cmd_info.data_type = 0x29; + cmd_info.cmd = g_mBuf; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + memset_s(g_mBuf, G_MBUF_LENGTH, 0, G_MBUF_LENGTH); + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_0] = 0xE5; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_1] = 0x0D; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_2] = 0x31; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_3] = 0xC8; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_4] = 0xAF; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_5] = 0x0F; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_6] = 0x33; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_7] = 0xC8; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_8] = 0xAF; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_9] = 0x09; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_10] = 0x2D; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_11] = 0xC8; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_12] = 0xAF; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_13] = 0x0B; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_14] = 0x2F; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_15] = 0xC8; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_16] = 0xAF; + cmd_info.devno = 0; + cmd_info.cmd_size = 17; // 17: command data size + cmd_info.data_type = 0x29; + cmd_info.cmd = g_mBuf; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + memset_s(g_mBuf, G_MBUF_LENGTH, 0, G_MBUF_LENGTH); + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_0] = 0xE6; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_1] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_2] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_3] = 0x33; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_4] = 0x33; + cmd_info.devno = 0; + cmd_info.cmd_size = 5; // 5: command data size + cmd_info.data_type = 0x29; + cmd_info.cmd = g_mBuf; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + memset_s(g_mBuf, G_MBUF_LENGTH, 0, G_MBUF_LENGTH); + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_0] = 0xE7; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_1] = 0x44; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_2] = 0x44; + cmd_info.devno = 0; + cmd_info.cmd_size = 3; // 3: command data size + cmd_info.data_type = 0x29; + cmd_info.cmd = g_mBuf; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + memset_s(g_mBuf, G_MBUF_LENGTH, 0, G_MBUF_LENGTH); + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_0] = 0xE8; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_1] = 0x0C; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_2] = 0x30; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_3] = 0xC8; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_4] = 0xAF; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_5] = 0x0E; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_6] = 0x32; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_7] = 0xC8; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_8] = 0xAF; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_9] = 0x08; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_10] = 0x2C; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_11] = 0xC8; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_12] = 0xAF; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_13] = 0x0A; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_14] = 0x2E; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_15] = 0xC8; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_16] = 0xAF; + cmd_info.devno = 0; + cmd_info.cmd_size = 17; // 17: command data size + cmd_info.data_type = 0x29; + cmd_info.cmd = g_mBuf; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + memset_s(g_mBuf, G_MBUF_LENGTH, 0, G_MBUF_LENGTH); + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_0] = 0xEB; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_1] = 0x02; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_2] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_3] = 0xE4; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_4] = 0xE4; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_5] = 0x44; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_6] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_7] = 0x40; + cmd_info.devno = 0; + cmd_info.cmd_size = 8; // 8: command data size + cmd_info.data_type = 0x29; + cmd_info.cmd = g_mBuf; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + memset_s(g_mBuf, G_MBUF_LENGTH, 0, G_MBUF_LENGTH); + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_0] = 0xEC; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_1] = 0x3C; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_2] = 0x00; + cmd_info.devno = 0; + cmd_info.cmd_size = 3; // 3: command data size + cmd_info.data_type = 0x29; + cmd_info.cmd = g_mBuf; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + memset_s(g_mBuf, G_MBUF_LENGTH, 0, G_MBUF_LENGTH); + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_0] = 0xED; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_1] = 0xAB; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_2] = 0x89; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_3] = 0x76; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_4] = 0x54; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_5] = 0x01; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_6] = 0xFF; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_7] = 0xFF; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_8] = 0xFF; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_9] = 0xFF; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_10] = 0xFF; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_11] = 0xFF; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_12] = 0x10; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_13] = 0x45; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_14] = 0x67; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_15] = 0x98; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_16] = 0xBA; + cmd_info.devno = 0; + cmd_info.cmd_size = 17; // 17: command data size + cmd_info.data_type = 0x29; + cmd_info.cmd = g_mBuf; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + memset_s(g_mBuf, G_MBUF_LENGTH, 0, G_MBUF_LENGTH); + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_0] = 0xEF; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_1] = 0x08; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_2] = 0x08; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_3] = 0x08; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_4] = 0x45; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_5] = 0x3F; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_6] = 0x54; + cmd_info.devno = 0; + cmd_info.cmd_size = 7; // 7: command data size + cmd_info.data_type = 0x29; + cmd_info.cmd = g_mBuf; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + memset_s(g_mBuf, G_MBUF_LENGTH, 0, G_MBUF_LENGTH); + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_0] = 0xFF; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_1] = 0x77; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_2] = 0x01; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_3] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_4] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_5] = 0x00; + cmd_info.devno = 0; + cmd_info.cmd_size = 6; // 6: command data size + cmd_info.data_type = 0x29; + cmd_info.cmd = g_mBuf; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + memset_s(g_mBuf, G_MBUF_LENGTH, 0, G_MBUF_LENGTH); + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_0] = 0xFF; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_1] = 0x77; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_2] = 0x01; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_3] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_4] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_5] = 0x13; + cmd_info.devno = 0; + cmd_info.cmd_size = 6; // 6: command data size + cmd_info.data_type = 0x29; + cmd_info.cmd = g_mBuf; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + + memset_s(g_mBuf, G_MBUF_LENGTH, 0, G_MBUF_LENGTH); + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_0] = 0xE8; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_1] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_2] = 0x0E; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_3] = 0x11; + cmd_info.devno = 0; + cmd_info.cmd_size = 4; // 4: command data size + cmd_info.data_type = 0x29; + cmd_info.cmd = g_mBuf; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + usleep(120000); // 120000: The process hangs for a period of time, in microseconds + + memset_s(g_mBuf, G_MBUF_LENGTH, 0, G_MBUF_LENGTH); + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_0] = 0xE8; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_1] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_2] = 0x0C; + cmd_info.devno = 0; + cmd_info.cmd_size = 3; // 3: command data size + cmd_info.data_type = 0x29; + cmd_info.cmd = g_mBuf; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + usleep(10000); // 10000: The process hangs for a period of time, in microseconds + + memset_s(g_mBuf, G_MBUF_LENGTH, 0, G_MBUF_LENGTH); + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_0] = 0xE8; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_1] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_2] = 0x00; + cmd_info.devno = 0; + cmd_info.cmd_size = 3; // 3: command data size + cmd_info.data_type = 0x29; + cmd_info.cmd = g_mBuf; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + usleep(10000); // 10000: The process hangs for a period of time, in microseconds + + memset_s(g_mBuf, G_MBUF_LENGTH, 0, G_MBUF_LENGTH); + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_0] = 0xFF; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_1] = 0x77; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_2] = 0x01; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_3] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_4] = 0x00; + g_mBuf[G_MBUF_ARRAY_SUBSCRIPT_5] = 0x00; + cmd_info.devno = 0; + cmd_info.cmd_size = 6; // 6: command data size + cmd_info.data_type = 0x29; + cmd_info.cmd = g_mBuf; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + usleep(10000); // 10000: The process hangs for a period of time, in microseconds + + cmd_info.devno = 0; + cmd_info.cmd_size = 0x11; + cmd_info.data_type = 0x05; + cmd_info.cmd = NULL; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + usleep(150000); // 150000: The process hangs for a period of time, in microseconds + + cmd_info.devno = 0; + cmd_info.cmd_size = 0x29; + cmd_info.data_type = 0x05; + cmd_info.cmd = NULL; + s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + usleep(USLEEP_TIME); + usleep(50000); // 50000: The process hangs for a period of time, in microseconds + + return HI_SUCCESS; +} + +/* enable mipi tx */ +HI_S32 SAMPLE_VO_ENABLE_MIPITx(HI_S32 fd) +{ + HI_S32 s32Ret = ioctl(fd, HI_MIPI_TX_ENABLE); + if (s32Ret != HI_SUCCESS) { + printf("MIPI_TX enable failed\n"); + return s32Ret; + } + + return s32Ret; +} + +/* disable mipi tx */ +HI_S32 SAMPLE_VO_DISABLE_MIPITx(HI_S32 fd) +{ + HI_S32 s32Ret = ioctl(fd, HI_MIPI_TX_DISABLE); + if (s32Ret != HI_SUCCESS) { + printf("MIPI_TX disable failed\n"); + return s32Ret; + } + + return s32Ret; +} + +/* config mipi */ +HI_S32 SAMPLE_VO_CONFIG_MIPI(HI_S32* mipiFD) +{ + HI_S32 s32Ret; + /* SET MIPI BAKCLIGHT */ + HI_S32 fd; + /* CONFIG MIPI PINUMX */ + + /* Reset MIPI */ + /* OPEN MIPI FD */ + fd = SampleOpenMipiTxFd(); + if (fd < 0) { + return HI_FAILURE; + } + *mipiFD = fd; + + /* SET MIPI Tx Dev ATTR */ + s32Ret = SampleSetMipiTxDevAttr(fd); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + + usleep(10000); // 10000: The process hangs for a period of time, in microseconds + system("cd /sys/class/gpio/;echo 5 > export;echo out > gpio5/direction;echo 1 > gpio5/value"); + usleep(200000); // 200000: The process hangs for a period of time, in microseconds + system("echo 0 > /sys/class/gpio/gpio5/value"); + usleep(200000); // 200000: The process hangs for a period of time, in microseconds + system("echo 1 > /sys/class/gpio/gpio5/value"); + usleep(20000); // 20000: The process hangs for a period of time, in microseconds + + /* CONFIG MIPI Tx INITIALIZATION SEQUENCE */ + s32Ret = SampleVoInitMipiTxScreen(fd); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + + /* ENABLE MIPI Tx DEV */ + s32Ret = SAMPLE_VO_ENABLE_MIPITx(fd); + if (s32Ret != HI_SUCCESS) { + return s32Ret; + } + + return s32Ret; +} + +/* get mipi device Height and width */ +HI_S32 SampleCommVoGetWhMipi(VO_INTF_SYNC_E enIntfSync, HI_U32* pu32W, HI_U32* pu32H, HI_U32* pu32Frm) +{ + switch (enIntfSync) { + case VO_OUTPUT_1080P24: + *pu32W = 1920; // 1920: VO_OUTPUT_1080P24-Width + *pu32H = 1080; // 1080: VO_OUTPUT_1080P24-Height + *pu32Frm = 24; // 24: VO_OUTPUT_1080P24-Frame rate + break; + case VO_OUTPUT_1080P25: + *pu32W = 1920; // 1920: VO_OUTPUT_1080P25-Width + *pu32H = 1080; // 1080: VO_OUTPUT_1080P25-Height + *pu32Frm = 25; // 25: VO_OUTPUT_1080P25-Frame rate + break; + case VO_OUTPUT_1080P30: + *pu32W = 1920; // 1920: VO_OUTPUT_1080P30-Width + *pu32H = 1080; // 1080: VO_OUTPUT_1080P30-Height + *pu32Frm = 30; // 30: VO_OUTPUT_1080P30-Frame rate + break; + case VO_OUTPUT_720P50: + *pu32W = 1280; // 1280: VO_OUTPUT_720P50-Width + *pu32H = 720; // 720: VO_OUTPUT_720P50-Height + *pu32Frm = 50; // 50: VO_OUTPUT_720P50-Frame rate + break; + case VO_OUTPUT_720P60: + *pu32W = 1280; // 1280: VO_OUTPUT_720P60-Width + *pu32H = 720; // 720: VO_OUTPUT_720P60-Height + *pu32Frm = 60; // 60: VO_OUTPUT_720P60-Frame rate + break; + case VO_OUTPUT_1080P50: + *pu32W = 1920; // 1920: VO_OUTPUT_1080P50-Width + *pu32H = 1080; // 1080: VO_OUTPUT_1080P50-Height + *pu32Frm = 50; // 50: VO_OUTPUT_1080P50-Frame rate + break; + case VO_OUTPUT_1080P60: + *pu32W = 1920; // 1920: VO_OUTPUT_1080P60-Width + *pu32H = 1080; // 1080: VO_OUTPUT_1080P60-Height + *pu32Frm = 60; // 60: VO_OUTPUT_1080P60-Frame rate + break; + case VO_OUTPUT_USER: + *pu32W = 800; // 800: VO_OUTPUT_USER-Width + *pu32H = 480; // 480: VO_OUTPUT_USER-Height + *pu32Frm = 60; // 60: VO_OUTPUT_USER-Frame rate + break; + default: + SAMPLE_PRT("vo enIntfSync %d not support, please config self!\n", enIntfSync); + return HI_FAILURE; + } + + return HI_SUCCESS; +} + +HI_S32 SampleCommVoStartDevMipi(VO_DEV VoDev, VO_PUB_ATTR_S* pstPubAttr) +{ + HI_S32 s32Ret; + VO_USER_INTFSYNC_INFO_S stUserInfo = {0}; + + stUserInfo.bClkReverse = HI_TRUE; + stUserInfo.u32DevDiv = 1; + stUserInfo.u32PreDiv = 1; + stUserInfo.stUserIntfSyncAttr.enClkSource = VO_CLK_SOURCE_PLL; + stUserInfo.stUserIntfSyncAttr.stUserSyncPll.u32Fbdiv = 244; // 244: PLL integer frequency multiplier coefficient + stUserInfo.stUserIntfSyncAttr.stUserSyncPll.u32Frac = 0x1A36; + stUserInfo.stUserIntfSyncAttr.stUserSyncPll.u32Refdiv = 4; // 4: PLL reference clock frequency division coefficient + // 7: PLL first stage output frequency division coefficient + stUserInfo.stUserIntfSyncAttr.stUserSyncPll.u32Postdiv1 = 7; + // 7: PLL second stage output frequency division coefficient + stUserInfo.stUserIntfSyncAttr.stUserSyncPll.u32Postdiv2 = 7; + HI_U32 u32Framerate = 60; // 60: device frame rate + + /* Set the common properties of the video output device */ + s32Ret = HI_MPI_VO_SetPubAttr(VoDev, pstPubAttr); + if (s32Ret != HI_SUCCESS) { + SAMPLE_PRT("failed with %#x!\n", s32Ret); + return HI_FAILURE; + } + + /* Set the device frame rate under the device user timing */ + s32Ret = HI_MPI_VO_SetDevFrameRate(VoDev, u32Framerate); + if (s32Ret != HI_SUCCESS) { + SAMPLE_PRT("failed with %#x!\n", s32Ret); + return HI_FAILURE; + } + + /* Set user interface timing information */ + s32Ret = HI_MPI_VO_SetUserIntfSyncInfo(VoDev, &stUserInfo); + if (s32Ret != HI_SUCCESS) { + SAMPLE_PRT("failed with %#x!\n", s32Ret); + return HI_FAILURE; + } + + /* Enable video output device */ + s32Ret = HI_MPI_VO_Enable(VoDev); + if (s32Ret != HI_SUCCESS) { + SAMPLE_PRT("failed with %#x!\n", s32Ret); + return HI_FAILURE; + } + + return s32Ret; +} + +HI_S32 SampleCommVoStartChnModeMux(SAMPLE_VO_MODE_E enMode) +{ + int s32Ret; + switch (enMode) { + case VO_MODE_1MUX: + g_sampleVoModeMux.u32WndNum = 1; + g_sampleVoModeMux.u32Square = 1; + break; + case VO_MODE_2MUX: + g_sampleVoModeMux.u32WndNum = 2; // 2: 2MUX-WndNum + g_sampleVoModeMux.u32Square = 2; // 2: 2MUX-Square + break; + case VO_MODE_4MUX: + g_sampleVoModeMux.u32WndNum = 4; // 4: 4MUX-WndNum + g_sampleVoModeMux.u32Square = 2; // 2: 4MUX-Square + break; + case VO_MODE_8MUX: + g_sampleVoModeMux.u32WndNum = 8; // 8: 8MUX-WndNum + g_sampleVoModeMux.u32Square = 3; // 3: 8MUX-Square + break; + case VO_MODE_9MUX: + g_sampleVoModeMux.u32WndNum = 9; // 9: 9MUX-WndNum + g_sampleVoModeMux.u32Square = 3; // 3: 9MUX-Square + break; + case VO_MODE_16MUX: + g_sampleVoModeMux.u32WndNum = 16; // 16: 16MUX-WndNum + g_sampleVoModeMux.u32Square = 4; // 4: 16MUX-Square + break; + case VO_MODE_25MUX: + g_sampleVoModeMux.u32WndNum = 25; // 25: 25MUX-WndNum + g_sampleVoModeMux.u32Square = 5; // 5: 25MUX-Square + break; + case VO_MODE_36MUX: + g_sampleVoModeMux.u32WndNum = 36; // 36: 36MUX-WndNum + g_sampleVoModeMux.u32Square = 6; // 6: 36MUX-Square + break; + case VO_MODE_49MUX: + g_sampleVoModeMux.u32WndNum = 49; // 49: 49MUX-WndNum + g_sampleVoModeMux.u32Square = 7; // 7: 49MUX-Square + break; + case VO_MODE_2X4: + g_sampleVoModeMux.u32WndNum = 8; // 8: 2X4-WndNum + g_sampleVoModeMux.u32Square = 3; // 3: 2X4-Square + g_sampleVoModeMux.u32Row = 4; // 4: 2X4-Row + g_sampleVoModeMux.u32Col = 2; // 2: 2X4-Col + break; + default: + SAMPLE_PRT("failed with %#x!\n", s32Ret); + return HI_FAILURE; + } + + return HI_SUCCESS; +} + +HI_S32 SampleCommVoStartChnMipi(VO_LAYER VoLayer, SAMPLE_VO_MODE_E enMode) +{ + HI_S32 i; + HI_S32 s32Ret = HI_SUCCESS; + HI_U32 u32Width = 0; + HI_U32 u32Height = 0; + VO_CHN_ATTR_S stChnAttr; + VO_VIDEO_LAYER_ATTR_S stLayerAttr; + + s32Ret = SampleCommVoStartChnModeMux(enMode); + SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "for SampleCommVoStartChnModeMux FAIL, s32Ret=%x\n", s32Ret); + + /* Get video layer properties */ + s32Ret = HI_MPI_VO_GetVideoLayerAttr(VoLayer, &stLayerAttr); + SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "for HI_MPI_VO_GetVideoLayerAttr FAIL, s32Ret=%x\n", s32Ret); + u32Width = stLayerAttr.stImageSize.u32Width; + u32Height = stLayerAttr.stImageSize.u32Height; + SAMPLE_PRT("enMode:%d, u32Width:%d, u32Height:%d, u32Square:%d\n", enMode, + u32Width, u32Height, g_sampleVoModeMux.u32Square); + + for (i = 0; i < g_sampleVoModeMux.u32WndNum; i++) { + if (enMode == VO_MODE_1MUX || enMode == VO_MODE_2MUX || enMode == VO_MODE_4MUX || + enMode == VO_MODE_8MUX || enMode == VO_MODE_9MUX || enMode == VO_MODE_16MUX || + enMode == VO_MODE_25MUX || enMode == VO_MODE_36MUX || enMode == VO_MODE_49MUX) { + stChnAttr.stRect.s32X = HI_ALIGN_DOWN((u32Width / g_sampleVoModeMux.u32Square) * + (i % g_sampleVoModeMux.u32Square), ALIGN_DOWN_SIZE); + stChnAttr.stRect.s32Y = HI_ALIGN_DOWN((u32Height / g_sampleVoModeMux.u32Square) * + (i / g_sampleVoModeMux.u32Square), ALIGN_DOWN_SIZE); + stChnAttr.stRect.u32Width = HI_ALIGN_DOWN(u32Width / g_sampleVoModeMux.u32Square, ALIGN_DOWN_SIZE); + stChnAttr.stRect.u32Height = HI_ALIGN_DOWN(u32Height / g_sampleVoModeMux.u32Square, ALIGN_DOWN_SIZE); + stChnAttr.u32Priority = 0; + stChnAttr.bDeflicker = HI_FALSE; + } else if (enMode == VO_MODE_2X4) { + stChnAttr.stRect.s32X = HI_ALIGN_DOWN((u32Width / g_sampleVoModeMux.u32Col) * + (i % g_sampleVoModeMux.u32Col), ALIGN_DOWN_SIZE); + stChnAttr.stRect.s32Y = HI_ALIGN_DOWN((u32Height / g_sampleVoModeMux.u32Row) * + (i / g_sampleVoModeMux.u32Col), ALIGN_DOWN_SIZE); + stChnAttr.stRect.u32Width = HI_ALIGN_DOWN(u32Width / g_sampleVoModeMux.u32Col, ALIGN_DOWN_SIZE); + stChnAttr.stRect.u32Height = HI_ALIGN_DOWN(u32Height / g_sampleVoModeMux.u32Row, ALIGN_DOWN_SIZE); + stChnAttr.u32Priority = 0; + stChnAttr.bDeflicker = HI_FALSE; + } + + /* Set properties for the specified video output channel */ + s32Ret = HI_MPI_VO_SetChnAttr(VoLayer, i, &stChnAttr); + SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "for HI_MPI_VO_SetChnAttr FAIL, s32Ret=%x\n", s32Ret); + + /* Set video output channel rotation angle */ + s32Ret = HI_MPI_VO_SetChnRotation(VoLayer, i, ROTATION_90); + SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "for HI_MPI_VO_SetChnRotation FAIL, s32Ret=%x\n", s32Ret); + + /* Enables the specified video output channel */ + s32Ret = HI_MPI_VO_EnableChn(VoLayer, i); + SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "for HI_MPI_VO_EnableChn FAIL, s32Ret=%x\n", s32Ret); + } + + return HI_SUCCESS; +} + +static HI_VOID StVoPubAttrCfg(SAMPLE_VO_CONFIG_S *pstVoConfig) +{ + HI_ASSERT(pstVoConfig); + /* Set and start VO device VoDev */ + stVoPubAttr.enIntfType = VO_INTF_MIPI; + stVoPubAttr.enIntfSync = VO_OUTPUT_USER; + stVoPubAttr.stSyncInfo.bSynm = 0; + stVoPubAttr.stSyncInfo.bIop = 1; + stVoPubAttr.stSyncInfo.u8Intfb = 0; + + stVoPubAttr.stSyncInfo.u16Hmid = 1; + stVoPubAttr.stSyncInfo.u16Bvact = 1; + stVoPubAttr.stSyncInfo.u16Bvbb = 1; + stVoPubAttr.stSyncInfo.u16Bvfb = 1; + + stVoPubAttr.stSyncInfo.bIdv = 0; + stVoPubAttr.stSyncInfo.bIhs = 0; + stVoPubAttr.stSyncInfo.bIvs = 0; + + stVoPubAttr.stSyncInfo.u16Hact = 480; // 480: Horizontal effective area. Unit: pixel + stVoPubAttr.stSyncInfo.u16Hbb = 60; // 60: Horizontal blanking of the rear shoulder. Unit: pixel + stVoPubAttr.stSyncInfo.u16Hfb = 50; // 50: Horizontal blanking of the front shoulder. Unit: pixel + stVoPubAttr.stSyncInfo.u16Hpw = 10; // 10: The width of the horizontal sync signal. Unit: pixel + stVoPubAttr.stSyncInfo.u16Vact = 800; // 800: Vertical effective area. Unit: line + stVoPubAttr.stSyncInfo.u16Vbb = 24; // 24: Vertical blanking of the rear shoulder. Unit: line + stVoPubAttr.stSyncInfo.u16Vfb = 20; // 20: Vertical blanking of the front shoulder. Unit: line + stVoPubAttr.stSyncInfo.u16Vpw = 4; // 4: The width of the vertical sync signal. Unit: line + stVoPubAttr.u32BgColor = pstVoConfig->u32BgColor; +} + +static HI_VOID StLayerAttrCfg(SAMPLE_VO_CONFIG_S *pstVoConfig) +{ + HI_ASSERT(pstVoConfig); + stLayerAttr.bClusterMode = HI_FALSE; + stLayerAttr.bDoubleFrame = HI_FALSE; + stLayerAttr.enPixFormat = pstVoConfig->enPixFormat; + + stLayerAttr.stDispRect.s32X = 0; + stLayerAttr.stDispRect.s32Y = 0; + stLayerAttr.enDstDynamicRange = pstVoConfig->enDstDynamicRange; +} + +/* start vo to mipi lcd */ +HI_S32 SampleCommVoStartMipi(SAMPLE_VO_CONFIG_S *pstVoConfig) +{ + HI_S32 s32Ret; + + HI_ASSERT(pstVoConfig); + StVoPubAttrCfg(pstVoConfig); + s32Ret = SampleCommVoStartDevMipi(pstVoConfig->VoDev, &stVoPubAttr); + SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "StartDevMipi FAIL, ret=%x\n", s32Ret); + /* Set and start layer VoDev */ + s32Ret = SampleCommVoGetWhMipi(stVoPubAttr.enIntfSync, + &stLayerAttr.stDispRect.u32Width, &stLayerAttr.stDispRect.u32Height, &stLayerAttr.u32DispFrmRt); + SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, FAIL, "VoGetWhMipi fail, err(%#x)\n", s32Ret); + + StLayerAttrCfg(pstVoConfig); + + /* Set display rectangle if changed */ + if (memcmp(&pstVoConfig->stDispRect, &stDefDispRect, sizeof(RECT_S)) != 0) { + memcpy_s(&stLayerAttr.stDispRect, sizeof(stLayerAttr.stDispRect), + &pstVoConfig->stDispRect, sizeof(RECT_S)); + } + + /* Set image size if changed */ + if (memcmp(&pstVoConfig->stImageSize, &stDefImageSize, sizeof(SIZE_S)) != 0) { + memcpy_s(&stLayerAttr.stImageSize, sizeof(stLayerAttr.stImageSize), + &pstVoConfig->stImageSize, sizeof(SIZE_S)); + } + stLayerAttr.stImageSize.u32Width = stLayerAttr.stDispRect.u32Width = 480; // 480: video layer canvas Width + stLayerAttr.stImageSize.u32Height = stLayerAttr.stDispRect.u32Height = 800; // 800: video layer canvas Height + + if (pstVoConfig->u32DisBufLen) { + /* Set buffer length */ + s32Ret = HI_MPI_VO_SetDisplayBufLen(pstVoConfig->VoDev, pstVoConfig->u32DisBufLen); + SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, FAIL, "HI_MPI_VO_SetDisplayBufLen fail, err(%#x)\n", s32Ret); + } + if (VO_PART_MODE_MULTI == pstVoConfig->enVoPartMode) { + /* Set the segmentation mode of the video layer */ + s32Ret = HI_MPI_VO_SetVideoLayerPartitionMode(pstVoConfig->VoDev, pstVoConfig->enVoPartMode); + SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, FAIL, "SetVideoLayerMode fail, err(%#x)\n", s32Ret); + } + + s32Ret = SAMPLE_COMM_VO_StartLayer(pstVoConfig->VoDev, &stLayerAttr); // start layer + SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, FAIL, "VO_StartLayer fail, err(%#x)\n", s32Ret); + + if (VO_INTF_MIPI == pstVoConfig->enVoIntfType) { + s32Ret = HI_MPI_VO_GetVideoLayerCSC(pstVoConfig->VoDev, &stVideoCSC); // get video layerCSC + SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, FAIL, "GetVideoLayerCSC fail, err(%#x)\n", s32Ret); + stVideoCSC.enCscMatrix = VO_CSC_MATRIX_BT709_TO_RGB_PC; + s32Ret = HI_MPI_VO_SetVideoLayerCSC(pstVoConfig->VoDev, &stVideoCSC); // Set video layer CSC + SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, FAIL, "SetVideoLayerCSC fail, err(%#x)\n", s32Ret); + } + + s32Ret = SampleCommVoStartChnMipi(pstVoConfig->VoDev, pstVoConfig->enVoMode); // start vo channels + SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, FAIL1, "VoStartChnMipi fail, err(%#x)\n", s32Ret); + return HI_SUCCESS; + +FAIL1: + SAMPLE_COMM_VO_StopLayer(pstVoConfig->VoDev); +FAIL: + SAMPLE_COMM_VO_StopDev(pstVoConfig->VoDev); + return s32Ret; +} + +/* init ViCfg */ +void ViCfgInit(ViCfg* self) +{ + HI_ASSERT(self); + if (memset_s(self, sizeof(*self), 0, sizeof(*self)) != EOK) { + HI_ASSERT(0); + } + + SAMPLE_COMM_VI_GetSensorInfo(self); + self->s32WorkingViNum = 1; + self->as32WorkingViId[0] = 0; + + self->astViInfo[0].stSnsInfo.MipiDev = + SAMPLE_COMM_VI_GetComboDevBySensor(self->astViInfo[0].stSnsInfo.enSnsType, 0); + self->astViInfo[0].stSnsInfo.s32BusId = 0; +} + +/* Set VI DEV information */ +void ViCfgSetDev(ViCfg* self, int devId, WDR_MODE_E wdrMode) +{ + HI_ASSERT(self); + HI_ASSERT((int)wdrMode < WDR_MODE_BUTT); + + self->astViInfo[0].stDevInfo.ViDev = devId; + self->astViInfo[0].stDevInfo.enWDRMode = (int)wdrMode < 0 ? WDR_MODE_NONE : wdrMode; +} + +/* Set the PIPE information of the VI */ +void ViCfgSetPipe(ViCfg* self, int pipe0Id, int pipe1Id, int pipe2Id, int pipe3Id) +{ + HI_ASSERT(self); + + self->astViInfo[0].stPipeInfo.aPipe[APIPE0] = pipe0Id; + self->astViInfo[0].stPipeInfo.aPipe[APIPE1] = pipe1Id; + self->astViInfo[0].stPipeInfo.aPipe[APIPE2] = pipe2Id; + self->astViInfo[0].stPipeInfo.aPipe[APIPE3] = pipe3Id; +} + +/* Set up the VI channel */ +void ViCfgSetChn(ViCfg* self, int chnId, PIXEL_FORMAT_E pixFormat, + VIDEO_FORMAT_E videoFormat, DYNAMIC_RANGE_E dynamicRange) +{ + HI_ASSERT(self); + HI_ASSERT((int)pixFormat < PIXEL_FORMAT_BUTT); + HI_ASSERT((int)videoFormat < VIDEO_FORMAT_BUTT); + HI_ASSERT((int)dynamicRange < DYNAMIC_RANGE_BUTT); + + self->astViInfo[0].stChnInfo.ViChn = chnId; + self->astViInfo[0].stChnInfo.enPixFormat = + (int)pixFormat < 0 ? PIXEL_FORMAT_YVU_SEMIPLANAR_420 : pixFormat; + self->astViInfo[0].stChnInfo.enVideoFormat = + (int)videoFormat < 0 ? VIDEO_FORMAT_LINEAR : videoFormat; + self->astViInfo[0].stChnInfo.enDynamicRange = + (int)dynamicRange < 0 ? DYNAMIC_RANGE_SDR8 : dynamicRange; +} + +/* Initialize VpssCfg */ +void VpssCfgInit(VpssCfg* self) +{ + HI_ASSERT(self); + if (memset_s(self, sizeof(*self), 0, sizeof(*self)) != EOK) { + HI_ASSERT(0); + } + self->grpId = -1; + self->chnNum = 0; +} + +/* Set up VPSS Group */ +void VpssCfgSetGrp(VpssCfg* self, + int grpId, const VPSS_GRP_ATTR_S* grpAttr, int maxWidth, int maxHeight) +{ + HI_ASSERT(self); + HI_ASSERT(grpId >= 0); + + self->grpId = grpId; + + if (grpAttr) { + self->grpAttr = *grpAttr; + } else { // Set as default + self->grpAttr.u32MaxW = maxWidth < 0 ? 0 : maxWidth; + self->grpAttr.u32MaxH = maxHeight < 0 ? 0 : maxHeight; + self->grpAttr.enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420; + self->grpAttr.enDynamicRange = DYNAMIC_RANGE_SDR8; + self->grpAttr.stFrameRate.s32SrcFrameRate = -1; + self->grpAttr.stFrameRate.s32DstFrameRate = -1; + self->grpAttr.bNrEn = HI_TRUE; + } +} + +/* Add a VPSS channel */ +VPSS_CHN_ATTR_S* VpssCfgAddChn(VpssCfg* self, + int chnId, const VPSS_CHN_ATTR_S* chnAttr, int width, int height) +{ + HI_ASSERT(self); + HI_ASSERT(self->chnNum < (sizeof(self->chnCfgs) / sizeof((self->chnCfgs)[0]))); + static const uint32_t depthDef = 2; + VpssChnCfg *chnCfg = &self->chnCfgs[self->chnNum]; + + if (chnAttr) { + chnCfg->attr = *chnAttr; + } else { // Set as default + chnCfg->attr.u32Width = width < 0 ? 0 : width; + chnCfg->attr.u32Height = height < 0 ? 0 : height; + chnCfg->attr.enChnMode = VPSS_CHN_MODE_USER; + chnCfg->attr.enVideoFormat = VIDEO_FORMAT_LINEAR; + chnCfg->attr.enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420; + chnCfg->attr.enDynamicRange = DYNAMIC_RANGE_SDR8; + chnCfg->attr.enCompressMode = COMPRESS_MODE_NONE; + chnCfg->attr.stFrameRate.s32SrcFrameRate = -1; + chnCfg->attr.stFrameRate.s32DstFrameRate = -1; + chnCfg->attr.u32Depth = depthDef; + chnCfg->attr.bMirror = HI_FALSE; + chnCfg->attr.bFlip = HI_FALSE; + chnCfg->attr.stAspectRatio.enMode = ASPECT_RATIO_NONE; + } + chnCfg->id = chnId; + + self->chnNum++; + return &chnCfg->attr; +} + +/* Start VPSS according to VpssCfg */ +int VpssStart(const VpssCfg* cfg) +{ + HI_ASSERT(cfg); + VPSS_GRP grpId = cfg->grpId; + HI_S32 ret; + + ret = HI_MPI_VPSS_CreateGrp(grpId, &cfg->grpAttr); + if (ret != 0) { + SAMPLE_PRT("HI_MPI_VPSS_CreateGrp(%d) FAIL, ret=%#x\n", grpId, ret); + return ret; + } + + for (int i = 0; i < cfg->chnNum; i++) { + ret = HI_MPI_VPSS_SetChnAttr(grpId, cfg->chnCfgs[i].id, &cfg->chnCfgs[i].attr); + if (ret != 0) { + SAMPLE_PRT("HI_MPI_VPSS_SetChnAttr(%d) FAIL, ret=%#x\n", cfg->chnCfgs[i].id, ret); + return ret; + } + + ret = HI_MPI_VPSS_EnableChn(grpId, cfg->chnCfgs[i].id); + if (ret != 0) { + SAMPLE_PRT("HI_MPI_VPSS_EnableChn(%d) FAIL, ret=%#x\n", cfg->chnCfgs[i].id, ret); + return ret; + } + } + + ret = HI_MPI_VPSS_StartGrp(grpId); + if (ret != 0) { + SAMPLE_PRT("HI_MPI_VPSS_StartGrp(%d) FAIL, ret=%#x\n", grpId, ret); + return ret; + } + return HI_SUCCESS; +} + +/* Terminate VIs started with ViCfg */ +int ViStop(const ViCfg* viCfg) +{ + return SAMPLE_COMM_VI_StopVi((ViCfg*)viCfg); +} + +/* Terminate VPSS started with VpssCfg */ +int VpssStop(const VpssCfg* cfg) +{ + HI_ASSERT(cfg); + VPSS_GRP grpId = cfg->grpId; + HI_S32 ret; + + for (int i = 0; i < cfg->chnNum; i++) { + ret = HI_MPI_VPSS_DisableChn(grpId, cfg->chnCfgs[i].id); + if (ret != 0) { + SAMPLE_PRT("HI_MPI_VPSS_DisableChn(%d, %d) FAIL, ret=%#x\n", grpId, cfg->chnCfgs[i].id, ret); + return ret; + } + } + + ret = HI_MPI_VPSS_StopGrp(grpId); + if (ret != 0) { + SAMPLE_PRT("HI_MPI_VPSS_StopGrp(%d) FAIL, ret=%#x\n", grpId, ret); + return ret; + } + + ret = HI_MPI_VPSS_DestroyGrp(grpId); + if (ret != 0) { + SAMPLE_PRT("HI_MPI_VPSS_DestroyGrp(%d) FAIL, ret=%#x\n", grpId, ret); + return ret; + } + return HI_SUCCESS; +} + +/* Start VI according to ViCfg */ +int ViStart(const ViCfg* viCfg) +{ + static const uint32_t frmRateDef = 30; + SAMPLE_SNS_TYPE_E snsType = viCfg->astViInfo[0].stSnsInfo.enSnsType; + ISP_CTRL_PARAM_S ispCtrlParam; + HI_U32 frmRate; + HI_S32 ret; + + ret = SAMPLE_COMM_VI_SetParam((ViCfg*)viCfg); + if (ret != 0) { + SAMPLE_PRT("SAMPLE_COMM_VI_SetParam FAIL, ret=%#x\n", ret); + return ret; + } + + // Set ISP statistics interval, from histm.sample_enc + SAMPLE_COMM_VI_GetFrameRateBySensor(snsType, &frmRate); + ret = HI_MPI_ISP_GetCtrlParam(viCfg->astViInfo[0].stPipeInfo.aPipe[0], &ispCtrlParam); + if (ret != 0) { + SAMPLE_PRT("HI_MPI_ISP_GetCtrlParam FAIL, ret=%#x\n", ret); + return ret; + } + + ispCtrlParam.u32StatIntvl = frmRate / frmRateDef; + ret = HI_MPI_ISP_SetCtrlParam(viCfg->astViInfo[0].stPipeInfo.aPipe[0], &ispCtrlParam); + if (ret != 0) { + SAMPLE_PRT("HI_MPI_ISP_SetCtrlParam FAIL, ret=%#x\n", ret); + return ret; + } + + ret = SAMPLE_COMM_VI_StartVi((ViCfg*)viCfg); + if (ret != 0) { + SAMPLE_PRT("SAMPLE_COMM_VI_StartVi FAIL, ret=%#x\n", ret); + return ret; + } + + return HI_SUCCESS; +} + +/* bind VI to VPSS */ +int ViBindVpss(VI_PIPE viPipe, VI_CHN viChn, VPSS_GRP vpssGrp) +{ + MPP_CHN_S srcChn; + MPP_CHN_S dstChn; + + srcChn.enModId = HI_ID_VI; + srcChn.s32DevId = viPipe; + srcChn.s32ChnId = viChn; + + dstChn.enModId = HI_ID_VPSS; + dstChn.s32DevId = vpssGrp; + dstChn.s32ChnId = 0; + + int ret = HI_MPI_SYS_Bind(&srcChn, &dstChn); + if (ret != 0) { + SAMPLE_PRT("HI_MPI_SYS_Bind(VI:%d, VPSS:%d) FAIL, ret=%#x\n", viChn, vpssGrp, ret); + return ret; + } + + return ret; +} + +/* new MppSess */ +static MppSess* MppSessNew(void) +{ + MppSess *sess = (MppSess*)malloc(sizeof(*sess)); + if (sess == NULL) { + SAMPLE_PRT("%s: malloc failed!\n", __FUNCTION__); + HI_ASSERT(sess); + } + + if (memset_s(sess, sizeof(*sess), 0, sizeof(*sess)) != EOK) { + HI_ASSERT(0); + } + + sess->vpssGrp = -1; + sess->vpssChn0 = -1; + sess->vpssChn1 = -1; + + return sess; +} + +/* Create and start {VI->VPSS}MppSess */ +int ViVpssCreate(MppSess** sess, const ViCfg* viCfg, const VpssCfg* vpssCfg) +{ + HI_ASSERT(sess && viCfg && vpssCfg); + *sess = NULL; + int res; + int ret; + + ret = ViStart(viCfg); + SAMPLE_CHECK_EXPR_GOTO(ret != HI_SUCCESS, FAIL1, + "vi start fail, err(%#x)\n", ret); + + ret = VpssStart(vpssCfg); + SAMPLE_CHECK_EXPR_GOTO(ret != HI_SUCCESS, FAIL2, + "vpss start fail, err(%#x)\n", ret); + + VI_PIPE pipeId = viCfg->astViInfo[0].stPipeInfo.aPipe[0]; + VI_CHN chnId = viCfg->astViInfo[0].stChnInfo.ViChn; + ret = ViBindVpss(pipeId, chnId, vpssCfg->grpId); + SAMPLE_CHECK_EXPR_GOTO(ret != HI_SUCCESS, FAIL3, + "vi bind vpss fail, err(%#x)\n", ret); + + MppSess *self = MppSessNew(); // todo:realease malloc + *sess = self; + self->viCfg = *viCfg; + self->vpssCfg = *vpssCfg; + self->used |= MPP_VI; + self->used |= MPP_VPSS; + self->vpssGrp = vpssCfg->grpId; + self->vpssChn0 = vpssCfg->chnCfgs[0].id; + self->vpssChn1 = vpssCfg->chnNum > 1 ? vpssCfg->chnCfgs[1].id : -1; + return 0; + + FAIL3: + res = VpssStop(vpssCfg); + SAMPLE_PRT("ViVpssCreate\n"); + if (res != 0) { + SAMPLE_PRT("VpssStop FAIL, ret=%#x\n", res); + } + FAIL2: + ViStop(viCfg); + FAIL1: + return ret; +} + +static HI_VOID Pause(HI_VOID) +{ + printf("---------------press Enter key to exit!---------------\n"); + (void)getchar(); +} + +HI_VOID ViPramCfg(HI_VOID) +{ + ViCfgInit(&g_aicMediaInfo.viCfg); + ViCfgSetDev(&g_aicMediaInfo.viCfg, 0, -1); + ViCfgSetPipe(&g_aicMediaInfo.viCfg, 0, -1, -1, -1); + g_aicMediaInfo.viCfg.astViInfo[0].stPipeInfo.enMastPipeMode = 0; + ViCfgSetChn(&g_aicMediaInfo.viCfg, 0, -1, -1, -1); + g_aicMediaInfo.viCfg.astViInfo[0].stChnInfo.enCompressMode = 1; +} + +static HI_VOID StVbParamCfg(VbCfg *self) +{ + memset_s(&g_aicMediaInfo.vbCfg, sizeof(VB_CONFIG_S), 0, sizeof(VB_CONFIG_S)); + // 2: The number of buffer pools that can be accommodated in the entire system + self->u32MaxPoolCnt = 2; + + /* get picture buffer size */ + g_aicMediaInfo.u32BlkSize = COMMON_GetPicBufferSize(g_aicMediaInfo.stSize.u32Width, g_aicMediaInfo.stSize.u32Height, + SAMPLE_PIXEL_FORMAT, DATA_BITWIDTH_8, COMPRESS_MODE_SEG, DEFAULT_ALIGN); + self->astCommPool[0].u64BlkSize = g_aicMediaInfo.u32BlkSize; + // 10: Number of cache blocks per cache pool. Value range: (0, 10240] + self->astCommPool[0].u32BlkCnt = 10; + + /* get raw buffer size */ + g_aicMediaInfo.u32BlkSize = VI_GetRawBufferSize(g_aicMediaInfo.stSize.u32Width, g_aicMediaInfo.stSize.u32Height, + PIXEL_FORMAT_RGB_BAYER_16BPP, COMPRESS_MODE_NONE, DEFAULT_ALIGN); + self->astCommPool[1].u64BlkSize = g_aicMediaInfo.u32BlkSize; + // 4: Number of cache blocks per cache pool. Value range: (0, 10240] + self->astCommPool[1].u32BlkCnt = 4; +} + +static HI_VOID StVoParamCfg(VoCfg *self) +{ + SAMPLE_COMM_VO_GetDefConfig(self); + self->enDstDynamicRange = DYNAMIC_RANGE_SDR8; + + self->enVoIntfType = VO_INTF_MIPI; /* set VO int type */ + self->enIntfSync = VO_OUTPUT_USER; /* set VO output information */ + + self->enPicSize = g_aicMediaInfo.enPicSize; +} + +static HI_VOID VpssParamCfg(HI_VOID) +{ + VpssCfgInit(&g_aicMediaInfo.vpssCfg); + VpssCfgSetGrp(&g_aicMediaInfo.vpssCfg, AIC_VPSS_GRP, NULL, + g_aicMediaInfo.stSize.u32Width, g_aicMediaInfo.stSize.u32Width); + g_aicMediaInfo.vpssCfg.grpAttr.enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420; + VpssCfgAddChn(&g_aicMediaInfo.vpssCfg, AIC_VPSS_ZOUT_CHN, NULL, AICSTART_VI_OUTWIDTH, AICSTART_VI_OUTHEIGHT); + HI_ASSERT(!g_aicMediaInfo.viSess); +} + + + +static HI_S32 PauseDoUnloadHandClassifyModel(HI_VOID) +{ + HI_S32 s32Ret = HI_SUCCESS; + + if (GetCfgBool("hand_classify_switch:support_hand_classify", true)) { + if (memset_s(&g_workPlug, sizeof(g_workPlug), 0x00, sizeof(g_workPlug)) != EOK) { + HI_ASSERT(0); + } + /* when pause operation, should unload model */ + s32Ret = Yolo2HandDetectResnetClassifyUnload(g_workPlug.model); + SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "unload hand model err:%x\n", s32Ret); + ConfBaseExt(); + g_num = 0; + } + + return s32Ret; +} + +/* + * Display the data collected by sensor to LCD screen + * VI->VPSS->VO->MIPI + */ +HI_S32 SMART_VENDOR_HAND_CLASSIFY(HI_VOID) +{ + + HI_S32 s32Ret; + HI_S32 fd = 0; + g_bAiProcessStopSignal = HI_FALSE; + /* config vi */ + ViPramCfg(); + + /* get picture size */ + s32Ret = SAMPLE_COMM_VI_GetSizeBySensor(g_aicMediaInfo.viCfg.astViInfo[0].stSnsInfo.enSnsType, + &g_aicMediaInfo.enPicSize); + SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "get pic size by sensor fail, s32Ret=%#x\n", s32Ret); + + /* get picture size(w*h), according enPicSize */ + s32Ret = SAMPLE_COMM_SYS_GetPicSize(g_aicMediaInfo.enPicSize, &g_aicMediaInfo.stSize); + SAMPLE_PRT("AIC: snsMaxSize=%ux%u\n", g_aicMediaInfo.stSize.u32Width, g_aicMediaInfo.stSize.u32Height); + SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "get picture size failed, s32Ret=%#x\n", s32Ret); + + /* config vb */ + StVbParamCfg(&g_aicMediaInfo.vbCfg); + + /* vb init & MPI system init */ + s32Ret = SAMPLE_COMM_SYS_Init(&g_aicMediaInfo.vbCfg); + SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "system init failed, s32Ret=%#x\n", s32Ret); + + /* set VO config to mipi, get mipi device */ + s32Ret = SAMPLE_VO_CONFIG_MIPI(&fd); + SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, EXIT, "CONFIG MIPI FAIL.s32Ret:0x%x\n", s32Ret); + + /* config vpss */ + VpssParamCfg(); + s32Ret = ViVpssCreate(&g_aicMediaInfo.viSess, &g_aicMediaInfo.viCfg, &g_aicMediaInfo.vpssCfg); + SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, EXIT1, "ViVpss Sess create FAIL, ret=%#x\n", s32Ret); + g_aicMediaInfo.vpssGrp = AIC_VPSS_GRP; + g_aicMediaInfo.vpssChn0 = AIC_VPSS_ZOUT_CHN; + + /* config vo */ + StVoParamCfg(&g_aicMediaInfo.voCfg); + + /* start vo */ + s32Ret = SampleCommVoStartMipi(&g_aicMediaInfo.voCfg); + SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, EXIT1, "start vo FAIL. s32Ret: 0x%x\n", s32Ret); + + /* vpss bind vo */ + s32Ret = SAMPLE_COMM_VPSS_Bind_VO(g_aicMediaInfo.vpssGrp, g_aicMediaInfo.vpssChn0, g_aicMediaInfo.voCfg.VoDev, 0); + SAMPLE_CHECK_EXPR_GOTO(s32Ret != HI_SUCCESS, EXIT2, "vo bind vpss FAIL. s32Ret: 0x%x\n", s32Ret); + SAMPLE_PRT("vpssGrp:%d, vpssChn:%d\n", g_aicMediaInfo.vpssGrp, g_aicMediaInfo.vpssChn0); + + /* create work thread to run ai */ + s32Ret = VendorHandClassificationCreateThread(); + SAMPLE_CHECK_EXPR_RET(s32Ret != HI_SUCCESS, s32Ret, "failed to create ai proccess thread: %s\n", strerror(s32Ret)); + + //Pause(); + //g_bAiProcessStopSignal = HI_TRUE; + + // Waiting for the end of a thread, the operation of synchronization between threads + pthread_join(g_aiProcessThread, NULL); + g_aiProcessThread = 0; + PauseDoUnloadHandClassifyModel(); + + SAMPLE_COMM_VPSS_UnBind_VO(g_aicMediaInfo.vpssGrp, g_aicMediaInfo.vpssChn0, g_aicMediaInfo.voCfg.VoDev, 0); + SAMPLE_VO_DISABLE_MIPITx(fd); + SampleCloseMipiTxFd(fd); + system("echo 0 > /sys/class/gpio/gpio55/value"); + +EXIT2: + SAMPLE_COMM_VO_StopVO(&g_aicMediaInfo.voCfg); +EXIT1: + VpssStop(&g_aicMediaInfo.vpssCfg); + SAMPLE_COMM_VI_UnBind_VPSS(g_aicMediaInfo.viCfg.astViInfo[0].stPipeInfo.aPipe[0], + g_aicMediaInfo.viCfg.astViInfo[0].stChnInfo.ViChn, g_aicMediaInfo.vpssGrp); + ViStop(&g_aicMediaInfo.viCfg); + SAMPLE_PRT("viSess freed!"); + free(g_aicMediaInfo.viSess); + g_aicMediaInfo.viSess = NULL; +EXIT: + SAMPLE_COMM_SYS_Exit(); + return s32Ret; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* End of #ifdef __cplusplus */ diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/smp/sample_media_ai.h b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/smp/sample_media_ai.h new file mode 100644 index 0000000..0b83fb4 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/smp/sample_media_ai.h @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Copyright (c) 2022 Sidi Liang. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SAMPLE_MEDIA_AI_H +#define SAMPLE_MEDIA_AI_H + +#include "sample_comm.h" +#include "list.h" +#include "osd_img.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* End of #ifdef __cplusplus */ + +#ifndef SAMPLE_PRT +#define SAMPLE_PRT(fmt...) \ + do { \ + printf("[%s]-%d: ", __FUNCTION__, __LINE__); \ + printf(fmt); \ + } while (0) +#endif + +#define APIPE0 0 +#define APIPE1 1 +#define APIPE2 2 +#define APIPE3 3 + +#define AIC_VPSS_GRP 0 // default use VPSS group +#define AIC_VPSS_ZIN_CHN 0 // default use VPSS amplification channel +#define AIC_VPSS_ZOUT_CHN 1 // default use VPSS narrowing channel + +#define AICSTART_VI_OUTWIDTH 1920 +#define AICSTART_VI_OUTHEIGHT 1080 + +/* bit constant */ +#define HI_BIT0 0x01U +#define HI_BIT1 0x02U +#define HI_BIT2 0x04U +#define HI_BIT3 0x08U +#define HI_BIT4 0x10U +#define HI_BIT5 0x20U +#define HI_BIT6 0x40U +#define HI_BIT7 0x80U +#define HI_BIT8 0x0100U +#define HI_BIT9 0x0200U +#define HI_BIT10 0x0400U +#define HI_BIT11 0x0800U +#define HI_BIT12 0x1000U +#define HI_BIT13 0x2000U +#define HI_BIT14 0x4000U +#define HI_BIT15 0x8000U + +/* Flags to mark whether the component is enabled */ +#define MPP_VI HI_BIT0 +#define MPP_VDEC HI_BIT1 +#define MPP_VPSS HI_BIT2 +#define MPP_VENC HI_BIT3 +#define MPP_VO HI_BIT5 + +typedef SAMPLE_VI_CONFIG_S ViCfg; +typedef SAMPLE_VO_CONFIG_S VoCfg; +typedef VB_CONFIG_S VbCfg; + +typedef struct SampleVoModeMux { + HI_U32 u32WndNum; + HI_U32 u32Square; + HI_U32 u32Row; + HI_U32 u32Col; +} SampleVoModeMux; + +/* + * VPSS channel config. + * Used to set the attributes of a channel. + */ +typedef struct VpssChnCfg { + int id; // VpssChn ID + VPSS_CHN_ATTR_S attr; // VpssChn attributes +} VpssChnCfg; + +/* + * VPSS config. + * Each VpssCfg corresponds to 1 VPSS group and 1 or more VPSS channels. + */ +typedef struct VpssCfg { + VPSS_GRP grpId; // VpssGrp ID + VPSS_GRP_ATTR_S grpAttr; // VpssGrp attributes + + int chnNum; // Configure the number of chnnels used + VpssChnCfg chnCfgs[VPSS_MAX_PHY_CHN_NUM]; // pssChnCfg array, the first chnNum-1 elements are valid +} VpssCfg; + +/* + * MppSess superset. + * The create() function corresponding to MppSess will copy the required cfg value to the object and start the session. + * MppSess does not provide a constructor. The user can only create an object through the create() function + * and destroy the object with MppSess_destroy(). + * MppSess defines the resource ID, vpssGrp, vpssChn0, vpssChn1, vdecChn, vencChn currently used by MppSess. + * These values are set by create(), and the corresponding IDs of components not identified by used will be set to -1. + * These resource IDs are obtained from the parameter xxxCfg passed in by create() + * and copied to the object to simplify APP use. + * There is currently no defined channel ID of the VI, it will always be used after being bound to the VPSS, + * and the VI data can be obtained through the VPSS chn. + */ +typedef struct MppSess { + uint32_t used; // The set of enabled components, set by the create() function + + ViCfg viCfg; // Optional ViCfg + VpssCfg vpssCfg; // Optional VpssCfg + + VPSS_GRP vpssGrp; // VPSS group ID, -1 means that the corresponding MPP component is not started. + VPSS_CHN vpssChn0; // VPSS channel[0] ID, -1 means that the corresponding MPP component is not started. + VPSS_CHN vpssChn1; // VPSS channel[1] ID, -1 means that the corresponding MPP component is not started. +} MppSess; + +typedef struct AicMediaInfo { + VPSS_GRP vpssGrp; + VPSS_CHN vpssChn0; + VPSS_CHN vpssChn1; + VDEC_CHN vdecChn; + VENC_CHN vencChn; + + ViCfg viCfg; + VpssCfg vpssCfg; + VoCfg voCfg; + VbCfg vbCfg; + + // MppSess + MppSess *viSess; // VI(sensor)+VPSS + int vpssFd; + SIZE_S stSize; + PIC_SIZE_E enPicSize; + HI_U32 u32BlkSize; + + OsdSet *osds; // OSD set for Plug to output OSD in resFrm +} AicMediaInfo; + +extern HI_BOOL g_bAiProcessStopSignal; + +HI_S32 SampleCommVoStartDevMipi(VO_DEV VoDev, VO_PUB_ATTR_S* pstPubAttr); +HI_S32 SAMPLE_MEDIA_HAND_CLASSIFY(HI_VOID); +HI_S32 SMART_VENDOR_HAND_CLASSIFY(HI_VOID); + +/* init ViCfg */ +void ViCfgInit(ViCfg* self); + +/* Initialize VpssCfg */ +void VpssCfgInit(VpssCfg* self); + +/* Set up VPSS Group */ +void VpssCfgSetGrp(VpssCfg* self, + int grpId, const VPSS_GRP_ATTR_S* grpAttr, int maxWidth, int maxHeight); + +/* Add a VPSS channel */ +VPSS_CHN_ATTR_S* VpssCfgAddChn(VpssCfg* self, + int chnId, const VPSS_CHN_ATTR_S* chnAttr, int width, int height); + +/* Set VI DEV information */ +void ViCfgSetDev(ViCfg* self, int devId, WDR_MODE_E wdrMode); + +/* Set the PIPE information of the VI */ +void ViCfgSetPipe(ViCfg* self, int pipe0Id, int pipe1Id, int pipe2Id, int pipe3Id); + +/* Set up the VI channel */ +void ViCfgSetChn(ViCfg* self, int chnId, PIXEL_FORMAT_E pixFormat, + VIDEO_FORMAT_E videoFormat, DYNAMIC_RANGE_E dynamicRange); + +/* Create and start {VI->VPSS}MppSess */ +int ViVpssCreate(MppSess** sess, const ViCfg* viCfg, const VpssCfg* vpssCfg); + +/* Terminate VPSS started with VpssCfg */ +int VpssStop(const VpssCfg* cfg); + +/* Terminate VIs started with ViCfg */ +int ViStop(const ViCfg* viCfg); + +/* start vo to mipi lcd */ +HI_S32 SampleCommVoStartMipi(SAMPLE_VO_CONFIG_S *pstVoConfig); + +/* onfig mipi */ +HI_S32 SAMPLE_VO_CONFIG_MIPI(HI_S32* mipiFD); + +/* disable mipi tx */ +HI_S32 SAMPLE_VO_DISABLE_MIPITx(HI_S32 fd); + +/* close mipi_tx device */ +HI_VOID SampleCloseMipiTxFd(HI_S32 fd); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* End of #ifdef __cplusplus */ + +#endif /* End of #ifndef __SAMPLE_MEDIA_AI_H__ */ diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/smp/smart_vendor_classification.c b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/smp/smart_vendor_classification.c new file mode 100644 index 0000000..41dfb65 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/smp/smart_vendor_classification.c @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Copyright (c) 2022 Sidi Liang. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hi_mipi_tx.h" +#include "sdk.h" +#include "sample_comm.h" +#include "ai_infer_process.h" +#include "hand_classify.h" +#include "vgs_img.h" +#include "osd_img.h" +#include "posix_help.h" +#include "sample_media_ai.h" +#include "smart_vendor_classification.h" +#include "hisignalling.h" +#include "messaging.h" +#include "json_helper.h" + + +#define HAND_FRM_WIDTH 640 +#define HAND_FRM_HEIGHT 384 + +RecogNumInfo g_numInfo; + + +/*---------------------------------------------------------------- +@brief Send the product selection result to 3618 via UART +@param int fd: UART file descriptor +@param SlotSelection selectedSlot: The selected slot +----------------------------------------------------------------*/ +void UARTSendResult(SlotSelection selectedSlot) +{ + int uartFd = 0; + /* uart open init */ + uartFd = UartOpenInit(); + if (uartFd < 0) { + printf("uart1 open failed\r\n"); + } else { + printf("uart1 open successed\r\n"); + } + char* payload = SlotSelectionToJson(selectedSlot); + + #ifdef EXPANSION_BOARD + + messageUARTSendData(uartFd, payload); + printf("Product selection result sent\r\n"); + + #endif +} + +/*---------------------------------------------------------------- +@brief Send the UI control message to 3618 via UART +@param int fd: UART file descriptor +@param SlotSelection selectedSlot: The selected slot +----------------------------------------------------------------*/ +void UARTSendUIControl(UIControl UIController) +{ + int uartFd = 0; + /* uart open init */ + uartFd = UartOpenInit(); + if (uartFd < 0) { + printf("uart1 open failed\r\n"); + } else { + printf("uart1 open successed\r\n"); + } + //char* payload = slotSelectionToJson(UIController); + + #ifdef EXPANSION_BOARD + + //messageUARTSendData(payload); + printf("UIController sent\r\n"); + + #endif +} + +/* hand gesture recognition info */ +static int HandDetectFlag(const RecogNumInfo resBuf) +{ + HI_CHAR *gestureName = NULL; + SAMPLE_PRT("resBuf.num: %u\n",resBuf.num); + if(resBuf.num == 1000) //No hand was detected + return 0; + + switch (resBuf.num) { + case 0u: + gestureName = "gesture one"; + SAMPLE_PRT("----gesture name----:%s\n", gestureName); + return 1; + case 1u: + gestureName = "gesture two"; + SAMPLE_PRT("----gesture name----:%s\n", gestureName); + return 2; + case 2u: + gestureName = "gesture three"; + SAMPLE_PRT("----gesture name----:%s\n", gestureName); + return 3; + case 3u: + gestureName = "gesture four"; + SAMPLE_PRT("----gesture name----:%s\n", gestureName); + return 4; + case 4u: + gestureName = "gesture five"; + SAMPLE_PRT("----gesture name----:%s\n", gestureName); + return 5; + case 5u: + gestureName = "gesture six"; + SAMPLE_PRT("----gesture name----:%s\n", gestureName); + return 6; + case 6u: + gestureName = "gesture seven"; + SAMPLE_PRT("----gesture name----:%s\n", gestureName); + return 7; + case 7u: + gestureName = "gesture eight"; + SAMPLE_PRT("----gesture name----:%s\n", gestureName); + return 8; + case 8u: + gestureName = "gesture nine"; + SAMPLE_PRT("----gesture name----:%s\n", gestureName); + return 9; + case 9u: + gestureName = "gesture fist"; + SAMPLE_PRT("----gesture name----:%s\n", gestureName); + return 10; + case 10u: + gestureName = "gesture rh_left"; + SAMPLE_PRT("----gesture name----:%s\n", gestureName); + return 11; + case 11u: + gestureName = "gesture rh_right"; + SAMPLE_PRT("----gesture name----:%s\n", gestureName); + return 12; + case 12u: + gestureName = "gesture lh_left"; + SAMPLE_PRT("----gesture name----:%s\n", gestureName); + return 13; + case 13u: + gestureName = "gesture lh_right"; + SAMPLE_PRT("----gesture name----:%s\n", gestureName); + return 14; + case 14u: + gestureName = "gesture empty"; + SAMPLE_PRT("----gesture name----:%s\n", gestureName); + return 15; + default: + gestureName = "gesture others"; + SAMPLE_PRT("----gesture name----:%s\n", gestureName); + return 16; + } + return 1; +} + + +int cmpfunc (const void * a, const void * b) { + return ( *(int*)a - *(int*)b ); +} + +static HI_VOID VendorHandClassificationProcess(VIDEO_FRAME_INFO_S frm, VO_LAYER voLayer, + VO_CHN voChn, AiPlugLib* g_workPlug, AicMediaInfo* g_aicMediaInfo) +{ + int ret; + if (GetCfgBool("hand_classify_switch:support_hand_classify", true)) { + if (g_workPlug->model == 0) { + ret = Yolo2HandDetectResnetClassifyLoad(&(g_workPlug->model)); + if (ret < 0) { + g_workPlug->model = 0; + SAMPLE_CHECK_EXPR_GOTO(ret < 0, HAND_RELEASE, + "load hand classify model err, ret=%#x\n", ret); + } + } + + VIDEO_FRAME_INFO_S resizeFrm; + ret = MppFrmResize(&frm, &resizeFrm, HAND_FRM_WIDTH, HAND_FRM_HEIGHT); + + g_numInfo.num = 1000; + g_numInfo.score = 1000;//Use 1000 to denote the case of no hand + + //Get result from model, returns the return value of CnnCalU8c1Img() + ret = Yolo2HandDetectResnetClassifyCal(g_workPlug->model, &resizeFrm, + &frm, &g_numInfo); + + //system("cat /proc/umap/vi"); + + + SAMPLE_CHECK_EXPR_GOTO(ret < 0, HAND_RELEASE, + "hand classify plug cal FAIL, ret=%#x\n", ret); + + ret = HI_MPI_VO_SendFrame(voLayer, voChn, &frm, 0); + SAMPLE_CHECK_EXPR_GOTO(ret != HI_SUCCESS, HAND_RELEASE, + "HI_MPI_VO_SendFrame fail, Error(%#x)\n", ret); + + MppFrmDestroy(&resizeFrm); + } + + HAND_RELEASE: + ret = HI_MPI_VPSS_ReleaseChnFrame(g_aicMediaInfo->vpssGrp, + g_aicMediaInfo->vpssChn0, &frm); + if (ret != HI_SUCCESS) { + SAMPLE_PRT("Error(%#x),HI_MPI_VPSS_ReleaseChnFrame failed, Grp(%d) chn(%d)!\n", + ret, g_aicMediaInfo->vpssGrp, g_aicMediaInfo->vpssChn0); + } + +} + +HI_VOID* VendorGetVpssChnFrameAndClassify(void* arguments) +{ + struct arg_struct { + AiPlugLib* g_workPlug; + AicMediaInfo* g_aicMediaInfo; + }; + struct arg_struct *args = arguments; + AiPlugLib* g_workPlug = args -> g_workPlug; + AicMediaInfo* g_aicMediaInfo = args -> g_aicMediaInfo; + int ret; + VIDEO_FRAME_INFO_S frm; + HI_S32 s32MilliSec = 2000; + VO_LAYER voLayer = 0; + VO_CHN voChn = 0; + + SAMPLE_PRT("vpssGrp:%d, vpssChn0:%d\n", g_aicMediaInfo->vpssGrp, g_aicMediaInfo->vpssChn0); + int timeoutCount = 0; + int timeoutStop = 0; + while (HI_FALSE == g_bAiProcessStopSignal) { + timeoutCount += 1; + printf("\n timeoutCount = %d \n", timeoutCount); + system("sleep 0.1"); + if(timeoutCount > 200){ + g_bAiProcessStopSignal = HI_TRUE; + SAMPLE_PRT("Timeout!\n"); + break; + } + int retResult = 0; + int lastResult = 5000;//initial value + for(int i = 0; i < 5; i += 1){ + timeoutCount += 1; + printf("\n timeoutCount = %d \n", timeoutCount); + system("sleep 0.1"); + if(timeoutCount > 200){ + g_bAiProcessStopSignal = HI_TRUE; + timeoutStop = 1; + SAMPLE_PRT("Timeout!\n"); + break; + } + ret = HI_MPI_VPSS_GetChnFrame(g_aicMediaInfo->vpssGrp, g_aicMediaInfo->vpssChn0, + &frm, s32MilliSec); + if (ret != 0) { + SAMPLE_PRT("HI_MPI_VPSS_GetChnFrame FAIL, err=%#x, grp=%d, chn=%d\n", + ret, g_aicMediaInfo->vpssGrp, g_aicMediaInfo->vpssChn0); + ret = HI_MPI_VPSS_ReleaseChnFrame(g_aicMediaInfo->vpssGrp, + g_aicMediaInfo->vpssChn0, &frm); + if (ret != HI_SUCCESS) { + SAMPLE_PRT("Error(%#x),HI_MPI_VPSS_ReleaseChnFrame failed, grp(%d) chn(%d)!\n", + ret, g_aicMediaInfo->vpssGrp, g_aicMediaInfo->vpssChn0); + } + continue; + } + SAMPLE_PRT("get vpss frame success, weight:%d, height:%d\n", frm.stVFrame.u32Width, + frm.stVFrame.u32Height); + + VendorHandClassificationProcess(frm, voLayer, voChn, g_workPlug, g_aicMediaInfo); + + if(lastResult == 5000) + lastResult = HandDetectFlag(g_numInfo); + + retResult = HandDetectFlag(g_numInfo); + if(!retResult || retResult == 15){//No hand + i = 0; + continue; + } + if(retResult != lastResult){ + i = 0; + lastResult = retResult; + } + } + if(timeoutStop) + break; + SlotSelection selectedSlot; + selectedSlot.slot_num = retResult; + UARTSendResult(selectedSlot); //Send result to 3861 via UART + g_bAiProcessStopSignal = HI_TRUE; + } + + return HI_NULL; +} diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/smp/smart_vendor_classification.h b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/smp/smart_vendor_classification.h new file mode 100644 index 0000000..25e6533 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/smp/smart_vendor_classification.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. + * Copyright (c) 2022 Sidi Liang. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SMART_VENDOR_AI_CLASSIFICATION_H +#define SMART_VENDOR_AI_CLASSIFICATION_H + +#include "sample_media_ai.h" +#include "ai_infer_process.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* End of #ifdef __cplusplus */ + +static HI_VOID VendorHandClassificationProcess(VIDEO_FRAME_INFO_S frm, VO_LAYER voLayer, VO_CHN voChn, AiPlugLib* g_workPlug, AicMediaInfo* g_aicMediaInfo); +HI_VOID* VendorGetVpssChnFrameAndClassify(HI_VOID* arg); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* End of #ifdef __cplusplus */ + +#endif /* End of #ifndef __SAMPLE_MEDIA_AI_H__ */ diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/smp/vendor_main.cpp b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/smp/vendor_main.cpp new file mode 100644 index 0000000..8a38308 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/smp/vendor_main.cpp @@ -0,0 +1,84 @@ +/* + * _____ __ __ _____ _______ __ ________ _ _ _____ ____ _____ + * / ____| \/ | /\ | __ \__ __| \ \ / / ____| \ | | __ \ / __ \| __ \ + * | (___ | \ / | / \ | |__) | | | \ \ / /| |__ | \| | | | | | | | |__) | + * \___ \| |\/| | / /\ \ | _ / | | \ \/ / | __| | . ` | | | | | | | _ / + * ____) | | | |/ ____ \| | \ \ | | \ / | |____| |\ | |__| | |__| | | \ \ + * |_____/|_| |_/_/ \_\_| \_\ |_| \/ |______|_| \_|_____/ \____/|_| \_\ + * + * Copyright (c) 2022 Sidi Liang. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "unistd.h" +#include "sdk.h" +#include "smart_vendor_classification.h" +#include "messaging.h" +#include "data_store.h" + +/* Display help info */ +static void SmartVendorHelp() +{ + printf("\n*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n"); + puts("\n" + " ________ _____ ______ ________ ________ _________ ___ ___ _______ ________ ________ ________ ________ \n" + "|\\ ____\\|\\ _ \\ _ \\|\\ __ \\|\\ __ \\|\\___ ___\\ |\\ \\ / /|\\ ___ \\ |\\ ___ \\|\\ ___ \\|\\ __ \\|\\ __ \\ \n" + "\\ \\ \\___|\\ \\ \\\\\\__\\ \\ \\ \\ \\|\\ \\ \\ \\|\\ \\|___ \\ \\_| \\ \\ \\ / / | \\ __/|\\ \\ \\\\ \\ \\ \\ \\_|\\ \\ \\ \\|\\ \\ \\ \\|\\ \\ \n" + " \\ \\_____ \\ \\ \\\\|__| \\ \\ \\ __ \\ \\ _ _\\ \\ \\ \\ \\ \\ \\/ / / \\ \\ \\_|/_\\ \\ \\\\ \\ \\ \\ \\ \\\\ \\ \\ \\\\\\ \\ \\ _ _\\ \n" + " \\|____|\\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\\\ \\| \\ \\ \\ \\ \\ / / \\ \\ \\_|\\ \\ \\ \\\\ \\ \\ \\ \\_\\\\ \\ \\ \\\\\\ \\ \\ \\\\ \\| \n" + " ____\\_\\ \\ \\__\\ \\ \\__\\ \\__\\ \\__\\ \\__\\\\ _\\ \\ \\__\\ \\ \\__/ / \\ \\_______\\ \\__\\\\ \\__\\ \\_______\\ \\_______\\ \\__\\\\ _\\ \n" + " |\\_________\\|__| \\|__|\\|__|\\|__|\\|__|\\|__| \\|__| \\|__|/ \\|_______|\\|__| \\|__|\\|_______|\\|_______|\\|__|\\|__|\n" + " \\|_________| \n" + ); + printf("\n SMART VENDING MACHINE 3516-VISION CLIENT \n"); + printf(" Version 1.0\n"); + printf(" Developed by: Sidi Liang\n"); + printf(" Copyright (c) 2022 Sidi Liang\n"); + printf(" Licensed under the Apache License, Version 2.0\n"); + printf(" Part of the Smart Vendor Project:\n"); + printf("\t Sidi Liang, Yi Liu, Yicong Liu\n"); + printf("\n*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n"); +} + +/* + * Main Entry + */ +int main(int argc, char *argv[]) +{ + HI_S32 s32Ret = HI_FAILURE; + sdk_init(); + /* MIPI is GPIO55, Turn on the backlight of the LCD screen */ + system("cd /sys/class/gpio/;echo 55 > export;echo out > gpio55/direction;echo 1 > gpio55/value"); + SmartVendorHelp(); + + fileInit(); + + + /* Main Loop */ + while(true){ + //Stage 1 + waitForStartSignal(); + //Stage 2 + SMART_VENDOR_HAND_CLASSIFY(); + SAMPLE_PRT("\nHand classification ended, restarting!\n"); + //(void)getchar(); + } + + + + sdk_exit(); + SAMPLE_PRT("\n Program exited. Bye.\n"); + return s32Ret; +} diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/.gitignore b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/.gitignore new file mode 100644 index 0000000..8fc7b85 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/.gitignore @@ -0,0 +1,11 @@ +### Ignore all files created by make +# +*.a +*.o +*.so +*.so.* +/example/iniexample +/example/parse +# Autogenerate source file +/test/AllTests.c +/test/testrun diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/.travis.yml b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/.travis.yml new file mode 100644 index 0000000..22a61fa --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/.travis.yml @@ -0,0 +1,9 @@ +language: c + +env: + - ENV_CC=clang + - ENV_CC=clang++ + - ENV_CC=gcc + - ENV_CC=g++ + +script: CC=$ENV_CC make && CC=$ENV_CC make check diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/AUTHORS b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/AUTHORS new file mode 100644 index 0000000..d5a3f6b --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/AUTHORS @@ -0,0 +1,6 @@ +Author: Nicolas Devillard + +This tiny library has received countless contributions and I have +not kept track of all the people who contributed. Let them be thanked +for their ideas, code, suggestions, corrections, enhancements! + diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/BUILD.gn b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/BUILD.gn new file mode 100644 index 0000000..f4ef13c --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/BUILD.gn @@ -0,0 +1,18 @@ +# Copyright (C) 2019. Huawei Technologies Co., Ltd. All rights reserved. + +if (defined(ohos_lite)) { + import("//build/lite/config/component/lite_component.gni") +} else { + import("//build/ohos.gni") +} + +shared_library("iniparser") { + sources = [ + "src/dictionary.c", + "src/iniparser.c", + ] + public_configs = [ ":iniparser_external_library_config" ] +} +config("iniparser_external_library_config") { + include_dirs = [ "//third_party/iniparser/src" ] +} diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/COPYRIGHT.OpenSource b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/COPYRIGHT.OpenSource new file mode 100644 index 0000000..a359c75 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/COPYRIGHT.OpenSource @@ -0,0 +1 @@ +Copyright (c) 2000-2011 by Nicolas Devillard. \ No newline at end of file diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/FAQ-en.md b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/FAQ-en.md new file mode 100644 index 0000000..0bb43ba --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/FAQ-en.md @@ -0,0 +1,37 @@ +# iniparser FAQ # + +## Is iniparser thread safe ? + +Starting from version 4, iniparser is designed to be thread-safe, provided +you surround it with your own mutex logic. The choice to not add thread +safety inside the library has been made to provide more freedom for the +developer, especially when dealing with their own custom reading logic +e.g. acquiring the mutex, reading entries with iniparser, then releasing +the mutex. + +## Your build system isn't portable, let me help you... + +We have received countless contributions from distrib people to modify the +Makefile into what they think is the "standard", which we had to reject. +The default, standard Makefile for Debian bears absolutely no relationship +with the one from SuSE or RedHat and there is no possible way to merge them +all. A build system is something so specific to each environment that it +is completely pointless to try and push anything that claims to be +standard. The provided Makefile in this project is purely here to have +something to play with quickly. + +## iniparser_dump() is slow + +The dumping functions are based on fprintf, which can turn out to be +surprisingly slow on some embedded platforms. You can replace fprintf by a +combined use of sprintf and fwrite, or you can use setvbuf() to change +buffering parameters to accomodate fprintf(). Something like: + +setvbuf(f, NULL, _IOFBF, 0); + +## iniparser does not compile with my C++ compiler! + +See the docs: iniparser is a C library. C++ is quite a different language, +despite the promises of compatibility. You will have to modify iniparser +quite heavily to make it work with a C++ compiler. Good luck! + diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/FAQ-zhcn.md b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/FAQ-zhcn.md new file mode 100644 index 0000000..ad0286d --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/FAQ-zhcn.md @@ -0,0 +1,27 @@ +# iniparser FAQ # + +## iniparser线程安全吗 ? + +从版本4开始,iniparser被设计成线程安全的,你需要围绕它处理你自己的互斥逻辑。 +选择不在库中添加线程安全,是为开发者提供更多的自由,特别是在处理他们自己的读 +逻辑。如获取互斥锁,用iniparser阅读条目,然后释放互斥体。 + +## 你的构建系统不可移植,让我来帮助你... + +我们已经收到了来各地的开发人员的无数贡献,将Makefile修改为他们认为是“标准”的 +内容,但是我们不得不拒绝。 默认情况下,Debian的标准Makefile与SuSE或RedHat完 +全没有关系,没有可能的方式将它们全部合并。 构建系统对于每个环境来说都是特别的, +尝试推动任何声称是标准的东西是完全没有意义的。 在这个项目中提供的Makefile纯粹 +是为了快速的把库跑起来。 + +## iniparser_dump() 速度慢 + +dump函数是基于fprintf的,在嵌入式平台上它可能导致很慢。你可以把fprintf换成 +sprintf和fwrite的组合,或者可以使用setvbfu()来改变fprintf的缓存参数。比如: + +setvbuf(f, NULL, _IOFBF, 0); + +## 用我的c++编译器不能编译iniparser! + +看文档:iniparser是一个C库。虽然C++兼容C,但它却是另外一门语言。让iniparser在 +C++编译器下工作,会是一份繁重的工作。祝你好运! diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/INSTALL b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/INSTALL new file mode 100644 index 0000000..a5b05d0 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/INSTALL @@ -0,0 +1,15 @@ + +iniParser installation instructions +----------------------------------- + +- Modify the Makefile to suit your environment. +- Type 'make' to make the library. +- Type 'make check' to make the test program. +- Type 'test/iniexample' to launch the test program. +- Type 'test/parse' to launch torture tests. + + + +Enjoy! +N. Devillard +Wed Mar 2 21:14:17 CET 2011 diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/LICENSE b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/LICENSE new file mode 100644 index 0000000..5a3a80b --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/LICENSE @@ -0,0 +1,21 @@ +Copyright (c) 2000-2011 by Nicolas Devillard. +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/Makefile b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/Makefile new file mode 100644 index 0000000..a5a4ab2 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/Makefile @@ -0,0 +1,86 @@ +# +# iniparser Makefile +# +.PHONY: example + +# Compiler settings +CC ?= gcc + +CFLAGS += -fPIC -Wall -Wextra -ansi -pedantic +ifndef DEBUG +ADDITIONAL_CFLAGS ?= -O2 +else +ADDITIONAL_CFLAGS ?= -g +endif + +CFLAGS += ${ADDITIONAL_CFLAGS} + +# Ar settings to build the library +AR ?= ar +ARFLAGS = rcv + +SHLD = ${CC} ${CFLAGS} +LDSHFLAGS = -shared -Wl,-Bsymbolic +LDFLAGS += -Wl,-rpath -Wl,/usr/lib -Wl,-rpath,/usr/lib + +# .so.0 is for version 3.x, .so.1 is 4.x +SO_TARGET ?= libiniparser.so.1 + +# Set RANLIB to ranlib on systems that require it (Sun OS < 4, Mac OSX) +# RANLIB = ranlib +RANLIB = true + +RM ?= rm -f + + +# Implicit rules + +SUFFIXES = .o .c .h .a .so .sl + +COMPILE.c ?= $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c + +ifndef V +QUIET_AR = @echo "AR $@"; +QUIET_CC = @echo "CC $@"; +QUIET_LINK = @echo "LINK $@"; +QUIET_RANLIB = @echo "RANLIB $@"; +endif + +.c.o: + $(QUIET_CC)$(COMPILE.c) $(OUTPUT_OPTION) $< + + +SRCS = src/iniparser.c \ + src/dictionary.c + +OBJS = $(SRCS:.c=.o) + + +default: libiniparser.a $(SO_TARGET) + +libiniparser.a: $(OBJS) + $(QUIET_AR)$(AR) $(ARFLAGS) $@ $^ + $(QUIET_RANLIB)$(RANLIB) $@ + +$(SO_TARGET): $(OBJS) + $(QUIET_LINK)$(SHLD) $(LDSHFLAGS) $(LDFLAGS) -o $(SO_TARGET) $(OBJS) \ + -Wl,-soname=`basename $(SO_TARGET)` + +clean: + $(RM) $(OBJS) + @(cd test ; $(MAKE) clean) + +veryclean: + $(RM) $(OBJS) libiniparser.a $(SO_TARGET) + rm -rf ./html ; mkdir html + cd example ; $(MAKE) veryclean + cd test ; $(MAKE) veryclean + +docs: + @(cd doc ; $(MAKE)) + +check: $(SO_TARGET) + @(cd test ; $(MAKE)) + +example: libiniparser.a + @(cd example ; $(MAKE)) diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/NOTICE b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/NOTICE new file mode 100644 index 0000000..7a694c9 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/NOTICE @@ -0,0 +1 @@ +LICENSE \ No newline at end of file diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/OAT.xml b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/OAT.xml new file mode 100644 index 0000000..07878ba --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/OAT.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/README.OpenSource b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/README.OpenSource new file mode 100644 index 0000000..1e6ff17 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/README.OpenSource @@ -0,0 +1,11 @@ +[ + { + "Name": "iniparser", + "License": "MIT License", + "License File": "LICENSE", + "Version Number": "4.1", + "Owner": "yinzhongyi@huawei.com", + "Upstream URL": "https://github.com/ndevilla/iniparser/@http://ndevilla.free.fr/iniparser", + "Description": "This modules offers parsing of ini files from the C level. See a complete documentation in HTML format, from this directory open the file html/index.html with any HTML-capable browser." + } +] diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/README.md b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/README.md new file mode 100644 index 0000000..dbc30d0 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/README.md @@ -0,0 +1,44 @@ +[![Build Status](https://travis-ci.org/ndevilla/iniparser.svg?branch=master)](https://travis-ci.org/ndevilla/iniparser) + +# Iniparser 4 # + + +## I - Overview + +This modules offers parsing of ini files from the C level. +See a complete documentation in HTML format, from this directory +open the file html/index.html with any HTML-capable browser. + +Key features : + + - Small : around 1500 sloc inside 4 files (2 .c and 2 .h) + - Portable : no dependancies, written in `-ansi -pedantic` C89 + - Fully reintrant : easy to make it thread-safe (just surround + library calls by mutex) + +## II - Building project + +A simple `make` at the root of the project should be enough to get the static +(i.e. `libiniparser.a`) and shared (i.e. `libiniparser.so.0`) libraries compiled. + +You should consider trying the following rules too : + + - `make check` : run the unitary tests + - `make example` : compile the example, run it with `./example/iniexample` + +## III - License + +This software is released under MIT License. +See LICENSE for full informations + +## IV - Versions + +Current version is 4.1. Version 4.0 introduces breaking changes in the api. +Older versions 3.1 and 3.2 with the legacy api are available as tags. + + +## V - FAQ + +See [FAQ-en.md](FAQ-en.md) in this directory for answers to Frequently Asked Questions. + +还有简化中国翻译在[FAQ-zhcn.md](FAQ-zhcn.md). diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/bundle.json b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/bundle.json new file mode 100644 index 0000000..beb4186 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/bundle.json @@ -0,0 +1,30 @@ +{ + "name": "@ohos/iniparser", + "description": "This modules offers parsing of ini files from the C level. See a complete documentation in HTML format, from this directory open the file html/index.html with any HTML-capable browser.", + "version": "3.1", + "license": "MIT License", + "publishAs": "code-segment", + "segment": { + "destPath": "third_party/iniparser" + }, + "dirs": {}, + "scripts": {}, + "component": { + "name": "thirdparty_iniparser", + "subsystem": "", + "syscap": [], + "features": [], + "adapted_system_type": [], + "rom": "", + "ram": "", + "deps": { + "components": [], + "third_party": [] + }, + "build": { + "sub_component": [], + "inner_kits": [], + "test": [] + } + } +} \ No newline at end of file diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/doc/Makefile b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/doc/Makefile new file mode 100644 index 0000000..db925ec --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/doc/Makefile @@ -0,0 +1,16 @@ +# +# iniparser doc Makefile +# + +all: html + +html: + doxygen iniparser.dox + rm -f ../html/annotated.html + rm -f ../html/classes.html + rm -f ../html/doxygen.gif + rm -f ../html/files.html + rm -f ../html/functions.html + rm -f ../html/globals.html + rm -f ../html/iniparser_main.html + diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/doc/iniparser.dox b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/doc/iniparser.dox new file mode 100644 index 0000000..e4b2242 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/doc/iniparser.dox @@ -0,0 +1,81 @@ +PROJECT_NAME = iniparser +PROJECT_NUMBER = 4.1 +OUTPUT_DIRECTORY = .. +OUTPUT_LANGUAGE = English +EXTRACT_ALL = YES +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +HIDE_UNDOC_MEMBERS = NO +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ALWAYS_DETAILED_SEC = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = +INTERNAL_DOCS = NO +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +VERBATIM_HEADERS = NO +SHOW_INCLUDE_FILES = NO +JAVADOC_AUTOBRIEF = NO +INHERIT_DOCS = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +DISTRIBUTE_GROUP_DOC = NO +TAB_SIZE = 4 +ENABLED_SECTIONS = +GENERATE_TODOLIST = NO +GENERATE_TESTLIST = NO +ALIASES = +MAX_INITIALIZER_LINES = 30 +OPTIMIZE_OUTPUT_FOR_C = YES +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +INPUT = iniparser.main ../src +FILE_PATTERNS = iniparser.h +RECURSIVE = NO +EXCLUDE = +EXCLUDE_PATTERNS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +IMAGE_PATH = +INPUT_FILTER = +FILTER_SOURCE_FILES = NO +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +DISABLE_INDEX = YES +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 + +GENERATE_LATEX = NO +GENERATE_RTF = NO +GENERATE_MAN = NO + +ENABLE_PREPROCESSING = NO +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = NO +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +PERL_PATH = /usr/bin/perl +HAVE_DOT = NO +SEARCHENGINE = NO diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/doc/iniparser.main b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/doc/iniparser.main new file mode 100644 index 0000000..47747c1 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/doc/iniparser.main @@ -0,0 +1,207 @@ + +/** + + @mainpage iniparser documentation + + + @section welcome Introduction + + iniParser is a simple C library offering ini file parsing services. + The library is pretty small (less than 1500 lines of C) and robust, and + does not depend on any other external library to compile. It is written + in ANSI C and should compile on most platforms without difficulty. + + + @section inidef What is an ini file? + + An ini file is an ASCII file describing simple parameters + (character strings, integers, floating-point values or booleans) + in an explicit format, easy to use and modify for users. + + An ini file is segmented into Sections, declared by the following + syntax: + + @verbatim + [Section Name] + @endverbatim + + i.e. the section name enclosed in square brackets, alone on a + line. Sections names are allowed to contain any character but + square brackets or linefeeds. + + In any section are zero or more variables, declared with the + following syntax: + + @verbatim + Key = value ; comment + @endverbatim + + The key is any string (possibly containing blanks). The value is + any character on the right side of the equal sign. Values can be + given enclosed with quotes. If no quotes are present, the value is + understood as containing all characters between the first and the + last non-blank characters before the comment. The following + declarations are identical: + + @verbatim + Hello = "this is a long string value" ; comment + Hello = this is a long string value ; comment + @endverbatim + + The semicolon and comment at the end of the line are optional. If + there is a comment, it starts from the first character after the + semicolon up to the end of the line. + + Multi-line values can be provided by ending the line with a + backslash (\). + + @verbatim + Multiple = Line 1 \ + Line 2 \ + Line 3 \ + Line 4 ; comment + @endverbatim + + This would yield: "multiple" <- "Line1 Line2 Line3 Line4" + + Comments in an ini file are: + + - Lines starting with a hash sign + - Blank lines (only blanks or tabs) + - Comments given on value lines after the semicolon (if present) + + + @section install Compiling/installing the library + + Edit the Makefile to indicate the C compiler you want to use, the + options to provide to compile ANSI C, and possibly the options to pass + to the ar program on your machine to build a library (.a) from a set + of object (.o) files. + + Defaults are set for the gcc compiler and the standard ar library + builder. + + Type 'make', that should do it. + + To use the library in your programs, add the following line on top + of your module: + + @code + #include "iniparser.h" + @endcode + + And link your program with the iniparser library by adding + @c -liniparser.a to the compile line. + + See the file test/initest.c for an example. + + iniparser is an ANSI C library. If you want to compile it + with a C++ compiler you will likely run into compatibility + issues. Headers probably have to include the extern "C" + hack and function prototypes will want to add some const + here and there to keep the compiler happy. This job is left + to the reader as there are too many C++ compilers around, each + with its own requirements as to what represents acceptable + C code in a C++ environment. You have been warned. + + + @section reference Library reference + + The library is completely documented in its header file. On-line + documentation has been generated and can be consulted here: + + - iniparser.h + + + @section usage Using the parser + + Comments are discarded by the parser. Then sections are + identified, and in each section a new entry is created for every + keyword found. The keywords are stored with the following syntax: + + @verbatim + [Section] + Keyword = value ; comment + @endverbatim + + is converted to the following key pair: + + @verbatim + ("section:keyword", "value") + @endverbatim + + This means that if you want to retrieve the value that was stored + in the section called @c Pizza, in the keyword @c Cheese, + you would make a request to the dictionary for + @c "pizza:cheese". All section and keyword names are converted + to lowercase before storage in the structure. The value side is + conserved as it has been parsed, though. + + Section names are also stored in the structure. They are stored + using as key the section name, and a NULL associated value. They + can be queried through iniparser_find_entry(). + + To launch the parser, use the function called iniparser_load(), which + takes an input file name and returns a newly allocated @e dictionary + structure. This latter object should remain opaque to the user and only + accessed through the following accessor functions: + + - iniparser_getstring() + - iniparser_getint() + - iniparser_getdouble() + - iniparser_getboolean() + + Finally, discard this structure using iniparser_freedict(). + + All values parsed from the ini file are stored as strings. The + accessors are just converting these strings to the requested type on + the fly, but you could basically perform this conversion by yourself + after having called the string accessor. + + Notice that iniparser_getboolean() will return an integer (0 or 1), + trying to make sense of what was found in the file. Strings starting + with "y", "Y", "t", "T" or "1" are considered true values (return 1), + strings starting with "n", "N", "f", "F", "0" are considered false + (return 0). This allows some flexibility in handling of boolean + answers. + + If you want to add extra information into the structure that was not + present in the ini file, you can use iniparser_set() to insert a + string. + + If you want to add a section to the structure, add a key + with a NULL value. Example: + @verbatim + iniparser_set(ini, "section", NULL); + iniparser_set(ini, "section:key1", NULL); + iniparser_set(ini, "section:key2", NULL); + @endverbatim + + + @section implementation A word about the implementation + + The dictionary structure is a pretty simple dictionary + implementation which might find some uses in other applications. + If you are curious, look into the source. + + + @section defects Known defects + + The dictionary structure is extremely unefficient for searching + as keys are sorted in the same order as they are read from the + ini file, which is convenient when dumping back to a file. The + simplistic first-approach linear search implemented there can + become a bottleneck if you have a very large number of keys. + + People who need to load large amounts of data from an ini file + should definitely turn to more appropriate solutions: sqlite3 or + similar. There are otherwise many other dictionary implementations + available on the net to replace this one. + + + @section authors Authors + + Nicolas Devillard (ndevilla AT free DOT fr). + + +*/ diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/example/Makefile b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/example/Makefile new file mode 100644 index 0000000..f09a94e --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/example/Makefile @@ -0,0 +1,27 @@ +# +# iniparser tests Makefile +# + +CC ?= gcc +CFLAGS += -g -I../src +LFLAGS += -L.. -liniparser +AR ?= ar +ARFLAGS += rcv +RM ?= rm -f + + +default: all + +all: iniexample parse + +iniexample: iniexample.c + $(CC) $(CFLAGS) -o iniexample iniexample.c -I../src -L.. -liniparser + +parse: parse.c + $(CC) $(CFLAGS) -o parse parse.c -I../src -L.. -liniparser + +clean veryclean: + $(RM) iniexample example.ini parse + + + diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/example/iniexample.c b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/example/iniexample.c new file mode 100644 index 0000000..81013f0 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/example/iniexample.c @@ -0,0 +1,104 @@ +#include +#include +#include +#include + +#include "iniparser.h" + +void create_example_ini_file(void); +int parse_ini_file(char * ini_name); + +int main(int argc, char * argv[]) +{ + int status ; + + if (argc<2) { + create_example_ini_file(); + status = parse_ini_file("example.ini"); + } else { + status = parse_ini_file(argv[1]); + } + return status ; +} + +void create_example_ini_file(void) +{ + FILE * ini ; + + if ((ini=fopen("example.ini", "w"))==NULL) { + fprintf(stderr, "iniparser: cannot create example.ini\n"); + return ; + } + + fprintf(ini, + "#\n" + "# This is an example of ini file\n" + "#\n" + "\n" + "[Pizza]\n" + "\n" + "Ham = yes ;\n" + "Mushrooms = TRUE ;\n" + "Capres = 0 ;\n" + "Cheese = Non ;\n" + "\n" + "\n" + "[Wine]\n" + "\n" + "Grape = Cabernet Sauvignon ;\n" + "Year = 1989 ;\n" + "Country = Spain ;\n" + "Alcohol = 12.5 ;\n" + "\n"); + fclose(ini); +} + + +int parse_ini_file(char * ini_name) +{ + dictionary * ini ; + + /* Some temporary variables to hold query results */ + int b ; + int i ; + double d ; + const char * s ; + + ini = iniparser_load(ini_name); + if (ini==NULL) { + fprintf(stderr, "cannot parse file: %s\n", ini_name); + return -1 ; + } + iniparser_dump(ini, stderr); + + /* Get pizza attributes */ + printf("Pizza:\n"); + + b = iniparser_getboolean(ini, "pizza:ham", -1); + printf("Ham: [%d]\n", b); + b = iniparser_getboolean(ini, "pizza:mushrooms", -1); + printf("Mushrooms: [%d]\n", b); + b = iniparser_getboolean(ini, "pizza:capres", -1); + printf("Capres: [%d]\n", b); + b = iniparser_getboolean(ini, "pizza:cheese", -1); + printf("Cheese: [%d]\n", b); + + /* Get wine attributes */ + printf("Wine:\n"); + s = iniparser_getstring(ini, "wine:grape", NULL); + printf("Grape: [%s]\n", s ? s : "UNDEF"); + + i = iniparser_getint(ini, "wine:year", -1); + printf("Year: [%d]\n", i); + + s = iniparser_getstring(ini, "wine:country", NULL); + printf("Country: [%s]\n", s ? s : "UNDEF"); + + d = iniparser_getdouble(ini, "wine:alcohol", -1.0); + printf("Alcohol: [%g]\n", d); + + iniparser_freedict(ini); + return 0 ; +} + + diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/example/parse.c b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/example/parse.c new file mode 100644 index 0000000..37d07aa --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/example/parse.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include + +#include "iniparser.h" + +int main(int argc, char * argv[]) +{ + dictionary * ini ; + char * ini_name ; + + if (argc<2) { + ini_name = "twisted.ini"; + } else { + ini_name = argv[1] ; + } + + ini = iniparser_load(ini_name); + iniparser_dump(ini, stdout); + iniparser_freedict(ini); + + return 0 ; +} diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/example/twisted-errors.ini b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/example/twisted-errors.ini new file mode 100644 index 0000000..4dc3bbe --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/example/twisted-errors.ini @@ -0,0 +1,9 @@ +# +# All of these should trigger syntax errors +# +[section] +hello +world +hello \ +world +a + b ; diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/example/twisted-genhuge.py b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/example/twisted-genhuge.py new file mode 100644 index 0000000..570973c --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/example/twisted-genhuge.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +import os +import sys + +if __name__=="__main__": + f=open('twisted-massive.ini', 'w') + for i in range(100): + f.write('[%03d]\n' % i) + for j in range(100): + f.write('key-%03d=1;\n' % j) + f.close() + diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/example/twisted-ofkey.ini b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/example/twisted-ofkey.ini new file mode 100644 index 0000000..4f2e72e --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/example/twisted-ofkey.ini @@ -0,0 +1,66 @@ +# Stress testing buffers for overflows +[long] +# Shitload key size +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=1 + diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/example/twisted-ofval.ini b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/example/twisted-ofval.ini new file mode 100644 index 0000000..2a3cedf --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/example/twisted-ofval.ini @@ -0,0 +1,56 @@ +# Shitload data size +[long] +a=\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890; + diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/example/twisted.ini b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/example/twisted.ini new file mode 100644 index 0000000..86e549f --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/example/twisted.ini @@ -0,0 +1,131 @@ +# +# Twisted.ini +# This file is meant for regression tests + +# Different blank settings around the equal sign +[blanks] +a=1 +b=1; +c=1; comment +d=1# comment + +e =1 +f =1; +g =1; comment +h =1# comment + +i= 1 +j= 1; +k= 1; comment +l= 1# comment + +m = 1 +n = 1; +o = 1; comment +p = 1# comment + +q=1 ; +r=1 ; comment +s=1 ;comment +t=1 #comment + +# Empty values +[empty] +a = '' +b = "" + +c = '' ; +d = "" ; + +e = '' ; comment +f = "" ; comment + +g = +h = ; +i = ; comment +j = # comment + +k= +l=; +m=;comment +n=# + +# Peculiar values +[peculiar] +a=';'; +b='#'# +c=';';comment +d='#'#comment +e=\; +f=\# +g=\;comment +h=\#comment +i=;; +j=## +k=;;;;;;;;;; +l=########## + +# Quotes +[quotes] +s1=' +s2='' +s3=''' +s4='''' + +d1=" +d2="" +d3=""" +d4="""" + +m1='"' +m2="'" + +h1=hello'world +h2='hello'world +h3='hello'world' + +h4=hello"world +h5="hello"world +h6="hello"world" + +# Section names +[a] +[ b] +[c ] +[ d ] +[ begin end ] +[ open[ ] + +# Multi-line inputs +[multi] +a = begin\ +end +b = begin \ +end +c = begin \ + end +d = 1\ +2\ +3\ +4 +e = 1 \ + 2 \ + 3 \ + 4 +f = 1 ; \ +hidden = because of the preceding backslash multi-lining the comment ; +visible = 1 +g = 1 #\ +and now this comment is hidden too \ +and this one too +h = 1 +multi \ +line \ +key = 1 +multi \ +line \ +key = \ +multi \ +line \ +value ; +# end of file diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/doxygen.css b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/doxygen.css new file mode 100644 index 0000000..d6aaf28 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/doxygen.css @@ -0,0 +1,545 @@ +/* The standard CSS for doxygen */ + +body, table, div, p, dl { + font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif; + font-size: 12px; +} + +/* @group Heading Levels */ + +h1 { + text-align: center; + font-size: 150%; +} + +h2 { + font-size: 120%; +} + +h3 { + font-size: 100%; +} + +dt { + font-weight: bold; +} + +div.multicol { + -moz-column-gap: 1em; + -webkit-column-gap: 1em; + -moz-column-count: 3; + -webkit-column-count: 3; +} + +p.startli, p.startdd, p.starttd { + margin-top: 2px; +} + +p.endli { + margin-bottom: 0px; +} + +p.enddd { + margin-bottom: 4px; +} + +p.endtd { + margin-bottom: 2px; +} + +/* @end */ + +caption { + font-weight: bold; +} + +span.legend { + font-size: 70%; + text-align: center; +} + +h3.version { + font-size: 90%; + text-align: center; +} + +div.qindex, div.navtab{ + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + padding: 2px; +} + +div.qindex, div.navpath { + width: 100%; + line-height: 140%; +} + +div.navtab { + margin-right: 15px; +} + +/* @group Link Styling */ + +a { + color: #153788; + font-weight: normal; + text-decoration: none; +} + +.contents a:visited { + color: #1b77c5; +} + +a:hover { + text-decoration: underline; +} + +a.qindex { + font-weight: bold; +} + +a.qindexHL { + font-weight: bold; + background-color: #6666cc; + color: #ffffff; + border: 1px double #9295C2; +} + +.contents a.qindexHL:visited { + color: #ffffff; +} + +a.el { + font-weight: bold; +} + +a.elRef { +} + +a.code { + color: #3030f0; +} + +a.codeRef { + color: #3030f0; +} + +/* @end */ + +dl.el { + margin-left: -1cm; +} + +.fragment { + font-family: monospace, fixed; + font-size: 105%; +} + +pre.fragment { + border: 1px solid #CCCCCC; + background-color: #f5f5f5; + padding: 4px 6px; + margin: 4px 8px 4px 2px; + overflow: auto; + word-wrap: break-word; + font-size: 9pt; + line-height: 125%; +} + +div.ah { + background-color: black; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px +} + +div.groupHeader { + margin-left: 16px; + margin-top: 12px; + margin-bottom: 6px; + font-weight: bold; +} + +div.groupText { + margin-left: 16px; + font-style: italic; +} + +body { + background: white; + color: black; + margin-right: 20px; + margin-left: 20px; +} + +td.indexkey { + background-color: #e8eef2; + font-weight: bold; + border: 1px solid #CCCCCC; + margin: 2px 0px 2px 0; + padding: 2px 10px; +} + +td.indexvalue { + background-color: #e8eef2; + border: 1px solid #CCCCCC; + padding: 2px 10px; + margin: 2px 0px; +} + +tr.memlist { + background-color: #f0f0f0; +} + +p.formulaDsp { + text-align: center; +} + +img.formulaDsp { + +} + +img.formulaInl { + vertical-align: middle; +} + +div.center { + text-align: center; + margin-top: 0px; + margin-bottom: 0px; + padding: 0px; +} + +div.center img { + border: 0px; +} + +img.footer { + border: 0px; + vertical-align: middle; +} + +/* @group Code Colorization */ + +span.keyword { + color: #008000 +} + +span.keywordtype { + color: #604020 +} + +span.keywordflow { + color: #e08000 +} + +span.comment { + color: #800000 +} + +span.preprocessor { + color: #806020 +} + +span.stringliteral { + color: #002080 +} + +span.charliteral { + color: #008080 +} + +span.vhdldigit { + color: #ff00ff +} + +span.vhdlchar { + color: #000000 +} + +span.vhdlkeyword { + color: #700070 +} + +span.vhdllogic { + color: #ff0000 +} + +/* @end */ + +.search { + color: #003399; + font-weight: bold; +} + +form.search { + margin-bottom: 0px; + margin-top: 0px; +} + +input.search { + font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} + +td.tiny { + font-size: 75%; +} + +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #84b0c7; +} + +th.dirtab { + background: #e8eef2; + font-weight: bold; +} + +hr { + height: 0px; + border: none; + border-top: 1px solid #666; +} + +hr.footer { + height: 1px; +} + +/* @group Member Descriptions */ + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight, +.memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background-color: #FAFAFA; + border: none; + margin: 4px; + padding: 1px 0 0 8px; +} + +.mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + color: #555; +} + +.memItemLeft, .memItemRight, .memTemplParams { + border-top: 1px solid #ccc; +} + +.memItemLeft, .memTemplItemLeft { + white-space: nowrap; +} + +.memTemplParams { + color: #606060; + white-space: nowrap; +} + +/* @end */ + +/* @group Member Details */ + +/* Styles for detailed member documentation */ + +.memtemplate { + font-size: 80%; + color: #606060; + font-weight: normal; + margin-left: 3px; +} + +.memnav { + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} + +.memitem { + padding: 0; + margin-bottom: 10px; +} + +.memname { + white-space: nowrap; + font-weight: bold; + margin-left: 6px; +} + +.memproto { + border-top: 1px solid #84b0c7; + border-left: 1px solid #84b0c7; + border-right: 1px solid #84b0c7; + padding: 0; + background-color: #d5e1e8; + font-weight: bold; + /* firefox specific markup */ + background-image: -moz-linear-gradient(rgba(228, 233, 245, 1.0) 0%, rgba(193, 205, 232, 1.0) 100%); + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + -moz-border-radius-topright: 8px; + -moz-border-radius-topleft: 8px; + /* webkit specific markup */ + background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(228, 233, 245, 1.0)), to(rgba(193, 205, 232, 1.0))); + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -webkit-border-top-right-radius: 8px; + -webkit-border-top-left-radius: 8px; + +} + +.memdoc { + border-bottom: 1px solid #84b0c7; + border-left: 1px solid #84b0c7; + border-right: 1px solid #84b0c7; + padding: 2px 5px; + background-color: #eef3f5; + border-top-width: 0; + /* firefox specific markup */ + -moz-border-radius-bottomleft: 8px; + -moz-border-radius-bottomright: 8px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + /* webkit specific markup */ + -webkit-border-bottom-left-radius: 8px; + -webkit-border-bottom-right-radius: 8px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); +} + +.paramkey { + text-align: right; +} + +.paramtype { + white-space: nowrap; +} + +.paramname { + color: #602020; + white-space: nowrap; +} +.paramname em { + font-style: normal; +} + +/* @end */ + +/* @group Directory (tree) */ + +/* for the tree view */ + +.ftvtree { + font-family: sans-serif; + margin: 0.5em; +} + +/* these are for tree view when used as main index */ + +.directory { + font-size: 9pt; + font-weight: bold; +} + +.directory h3 { + margin: 0px; + margin-top: 1em; + font-size: 11pt; +} + +/* +The following two styles can be used to replace the root node title +with an image of your choice. Simply uncomment the next two styles, +specify the name of your image and be sure to set 'height' to the +proper pixel height of your image. +*/ + +/* +.directory h3.swap { + height: 61px; + background-repeat: no-repeat; + background-image: url("yourimage.gif"); +} +.directory h3.swap span { + display: none; +} +*/ + +.directory > h3 { + margin-top: 0; +} + +.directory p { + margin: 0px; + white-space: nowrap; +} + +.directory div { + display: none; + margin: 0px; +} + +.directory img { + vertical-align: -30%; +} + +/* these are for tree view when not used as main index */ + +.directory-alt { + font-size: 100%; + font-weight: bold; +} + +.directory-alt h3 { + margin: 0px; + margin-top: 1em; + font-size: 11pt; +} + +.directory-alt > h3 { + margin-top: 0; +} + +.directory-alt p { + margin: 0px; + white-space: nowrap; +} + +.directory-alt div { + display: none; + margin: 0px; +} + +.directory-alt img { + vertical-align: -30%; +} + +/* @end */ + +address { + font-style: normal; + color: #333; +} + +table.doxtable { + border-collapse:collapse; +} + +table.doxtable td, table.doxtable th { + border: 1px solid #153788; + padding: 3px 7px 2px; +} + +table.doxtable th { + background-color: #254798; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; + text-align:left; +} + diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/doxygen.png b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/doxygen.png new file mode 100644 index 0000000..f0a274b Binary files /dev/null and b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/doxygen.png differ diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/globals_func.html b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/globals_func.html new file mode 100644 index 0000000..429cf31 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/globals_func.html @@ -0,0 +1,64 @@ + + + + +iniparser: Data Fields + + + + + +
+ +
+
+
+
Generated on Wed Mar 2 22:04:59 2011 for iniparser by  + +doxygen 1.6.3
+ + diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/index.html b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/index.html new file mode 100644 index 0000000..92b5684 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/index.html @@ -0,0 +1,101 @@ + + + + +iniparser: iniparser documentation + + + + + +
+

iniparser documentation

4.0

+Introduction

+

iniParser is a simple C library offering ini file parsing services. The library is pretty small (less than 1500 lines of C) and robust, and does not depend on any other external library to compile. It is written in ANSI C and should compile on most platforms without difficulty.

+

+What is an ini file?

+

An ini file is an ASCII file describing simple parameters (character strings, integers, floating-point values or booleans) in an explicit format, easy to use and modify for users.

+

An ini file is segmented into Sections, declared by the following syntax:

+
+    [Section Name]
+	

i.e. the section name enclosed in square brackets, alone on a line. Sections names are allowed to contain any character but square brackets or linefeeds.

+

In any section are zero or more variables, declared with the following syntax:

+
+    Key = value ; comment
+	

The key is any string (possibly containing blanks). The value is any character on the right side of the equal sign. Values can be given enclosed with quotes. If no quotes are present, the value is understood as containing all characters between the first and the last non-blank characters before the comment. The following declarations are identical:

+
+    Hello = "this is a long string value" ; comment
+    Hello = this is a long string value ; comment
+	

The semicolon and comment at the end of the line are optional. If there is a comment, it starts from the first character after the semicolon up to the end of the line.

+

Multi-line values can be provided by ending the line with a backslash (\).

+
+    Multiple = Line 1 \
+    Line 2 \
+    Line 3 \
+    Line 4 ; comment
+    

This would yield: "multiple" <- "Line1 Line2 Line3 Line4"

+

Comments in an ini file are:

+
    +
  • Lines starting with a hash sign
  • +
  • Blank lines (only blanks or tabs)
  • +
  • Comments given on value lines after the semicolon (if present)
  • +
+

+Compiling/installing the library

+

Edit the Makefile to indicate the C compiler you want to use, the options to provide to compile ANSI C, and possibly the options to pass to the ar program on your machine to build a library (.a) from a set of object (.o) files.

+

Defaults are set for the gcc compiler and the standard ar library builder.

+

Type 'make', that should do it.

+

To use the library in your programs, add the following line on top of your module:

+
    #include "iniparser.h"
+

And link your program with the iniparser library by adding -liniparser.a to the compile line.

+

See the file test/initest.c for an example.

+

iniparser is an ANSI C library. If you want to compile it with a C++ compiler you will likely run into compatibility issues. Headers probably have to include the extern "C" hack and function prototypes will want to add some const here and there to keep the compiler happy. This job is left to the reader as there are too many C++ compilers around, each with its own requirements as to what represents acceptable C code in a C++ environment. You have been warned.

+

+Library reference

+

The library is completely documented in its header file. On-line documentation has been generated and can be consulted here:

+ +

+Using the parser

+

Comments are discarded by the parser. Then sections are identified, and in each section a new entry is created for every keyword found. The keywords are stored with the following syntax:

+
+    [Section]
+    Keyword = value ; comment
+	

is converted to the following key pair:

+
+    ("section:keyword", "value")
+	

This means that if you want to retrieve the value that was stored in the section called Pizza, in the keyword Cheese, you would make a request to the dictionary for "pizza:cheese". All section and keyword names are converted to lowercase before storage in the structure. The value side is conserved as it has been parsed, though.

+

Section names are also stored in the structure. They are stored using as key the section name, and a NULL associated value. They can be queried through iniparser_find_entry().

+

To launch the parser, use the function called iniparser_load(), which takes an input file name and returns a newly allocated dictionary structure. This latter object should remain opaque to the user and only accessed through the following accessor functions:

+ +

Finally, discard this structure using iniparser_freedict().

+

All values parsed from the ini file are stored as strings. The accessors are just converting these strings to the requested type on the fly, but you could basically perform this conversion by yourself after having called the string accessor.

+

Notice that iniparser_getboolean() will return an integer (0 or 1), trying to make sense of what was found in the file. Strings starting with "y", "Y", "t", "T" or "1" are considered true values (return 1), strings starting with "n", "N", "f", "F", "0" are considered false (return 0). This allows some flexibility in handling of boolean answers.

+

If you want to add extra information into the structure that was not present in the ini file, you can use iniparser_set() to insert a string.

+

If you want to add a section to the structure, add a key with a NULL value. Example:

+
+    iniparser_set(ini, "section", NULL);
+    iniparser_set(ini, "section:key1", NULL);
+    iniparser_set(ini, "section:key2", NULL);
+    

+A word about the implementation

+

The dictionary structure is a pretty simple dictionary implementation which might find some uses in other applications. If you are curious, look into the source.

+

+Known defects

+

The dictionary structure is extremely unefficient for searching as keys are sorted in the same order as they are read from the ini file, which is convenient when dumping back to a file. The simplistic first-approach linear search implemented there can become a bottleneck if you have a very large number of keys.

+

People who need to load large amounts of data from an ini file should definitely turn to more appropriate solutions: sqlite3 or similar. There are otherwise many other dictionary implementations available on the net to replace this one.

+

+Authors

+

Nicolas Devillard (ndevilla AT free DOT fr).

+
+
Generated on Sun Jun 12 19:07:18 2016 for iniparser by  + +doxygen 1.8.11
+ + diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/iniparser_8h.html b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/iniparser_8h.html new file mode 100644 index 0000000..a909c4b --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/iniparser_8h.html @@ -0,0 +1,583 @@ + + + + +iniparser: iniparser.h File Reference + + + + + +
+

iniparser.h File Reference

+

Parser for ini files. +More...

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Functions

int iniparser_getnsec (dictionary *d)
 Get number of sections in a dictionary.
char * iniparser_getsecname (dictionary *d, int n)
 Get name for section n in a dictionary.
void iniparser_dump_ini (dictionary *d, FILE *f)
 Save a dictionary to a loadable ini file.
void iniparser_dump (dictionary *d, FILE *f)
 Dump a dictionary to an opened file pointer.
char * iniparser_getstring (dictionary *d, char *key, char *def)
 Get the string associated to a key.
int iniparser_getint (dictionary *d, char *key, int notfound)
 Get the string associated to a key, convert to an int.
double iniparser_getdouble (dictionary *d, char *key, double notfound)
 Get the string associated to a key, convert to a double.
int iniparser_getboolean (dictionary *d, char *key, int notfound)
 Get the string associated to a key, convert to a boolean.
int iniparser_set (dictionary *ini, char *entry, char *val)
 Set an entry in a dictionary.
void iniparser_unset (dictionary *ini, char *entry)
 Delete an entry in a dictionary.
int iniparser_find_entry (dictionary *ini, char *entry)
 Finds out if a given entry exists in a dictionary.
dictionary * iniparser_load (char *ininame)
 Parse an ini file and return an allocated dictionary object.
void iniparser_freedict (dictionary *d)
 Free all memory associated to an ini dictionary.
+

Detailed Description

+

Parser for ini files.

+
Author:
N. Devillard
+
Date:
Sep 2007
+
Version:
3.0
+

Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
void iniparser_dump (dictionary *  d,
FILE *  f 
)
+
+
+ +

Dump a dictionary to an opened file pointer.

+
Parameters:
+ + + +
d Dictionary to dump.
f Opened file pointer to dump to.
+
+
+
Returns:
void
+

This function prints out the contents of a dictionary, one element by line, onto the provided file pointer. It is OK to specify stderr or stdout as output files. This function is meant for debugging purposes mostly.

+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
void iniparser_dump_ini (dictionary *  d,
FILE *  f 
)
+
+
+ +

Save a dictionary to a loadable ini file.

+
Parameters:
+ + + +
d Dictionary to dump
f Opened file pointer to dump to
+
+
+
Returns:
void
+

This function dumps a given dictionary into a loadable ini file. It is Ok to specify stderr or stdout as output files.

+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
int iniparser_find_entry (dictionary *  ini,
char *  entry 
)
+
+
+ +

Finds out if a given entry exists in a dictionary.

+
Parameters:
+ + + +
ini Dictionary to search
entry Name of the entry to look for
+
+
+
Returns:
integer 1 if entry exists, 0 otherwise
+

Finds out if a given entry exists in the dictionary. Since sections are stored as keys with NULL associated values, this is the only way of querying for the presence of sections in a dictionary.

+ +
+
+ +
+
+ + + + + + + + + +
void iniparser_freedict (dictionary *  d ) 
+
+
+ +

Free all memory associated to an ini dictionary.

+
Parameters:
+ + +
d Dictionary to free
+
+
+
Returns:
void
+

Free all memory associated to an ini dictionary. It is mandatory to call this function before the dictionary object gets out of the current context.

+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
int iniparser_getboolean (dictionary *  d,
char *  key,
int  notfound 
)
+
+
+ +

Get the string associated to a key, convert to a boolean.

+
Parameters:
+ + + + +
d Dictionary to search
key Key string to look for
notfound Value to return in case of error
+
+
+
Returns:
integer
+

This function queries a dictionary for a key. A key as read from an ini file is given as "section:key". If the key cannot be found, the notfound value is returned.

+

A true boolean is found if one of the following is matched:

+
    +
  • A string starting with 'y'
  • +
  • A string starting with 'Y'
  • +
  • A string starting with 't'
  • +
  • A string starting with 'T'
  • +
  • A string starting with '1'
  • +
+

A false boolean is found if one of the following is matched:

+
    +
  • A string starting with 'n'
  • +
  • A string starting with 'N'
  • +
  • A string starting with 'f'
  • +
  • A string starting with 'F'
  • +
  • A string starting with '0'
  • +
+

The notfound value returned if no boolean is identified, does not necessarily have to be 0 or 1.

+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
double iniparser_getdouble (dictionary *  d,
char *  key,
double  notfound 
)
+
+
+ +

Get the string associated to a key, convert to a double.

+
Parameters:
+ + + + +
d Dictionary to search
key Key string to look for
notfound Value to return in case of error
+
+
+
Returns:
double
+

This function queries a dictionary for a key. A key as read from an ini file is given as "section:key". If the key cannot be found, the notfound value is returned.

+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
int iniparser_getint (dictionary *  d,
char *  key,
int  notfound 
)
+
+
+ +

Get the string associated to a key, convert to an int.

+
Parameters:
+ + + + +
d Dictionary to search
key Key string to look for
notfound Value to return in case of error
+
+
+
Returns:
integer
+

This function queries a dictionary for a key. A key as read from an ini file is given as "section:key". If the key cannot be found, the notfound value is returned.

+

Supported values for integers include the usual C notation so decimal, octal (starting with 0) and hexadecimal (starting with 0x) are supported. Examples:

+
    +
  • "42" -> 42
  • +
  • "042" -> 34 (octal -> decimal)
  • +
  • "0x42" -> 66 (hexa -> decimal)
  • +
+

Warning: the conversion may overflow in various ways. Conversion is totally outsourced to strtol(), see the associated man page for overflow handling.

+

Credits: Thanks to A. Becker for suggesting strtol()

+ +
+
+ +
+
+ + + + + + + + + +
int iniparser_getnsec (dictionary *  d ) 
+
+
+ +

Get number of sections in a dictionary.

+
Parameters:
+ + +
d Dictionary to examine
+
+
+
Returns:
int Number of sections found in dictionary
+

This function returns the number of sections found in a dictionary. The test to recognize sections is done on the string stored in the dictionary: a section name is given as "section" whereas a key is stored as "section:key", thus the test looks for entries that do not contain a colon.

+

This clearly fails in the case a section name contains a colon, but this should simply be avoided.

+

This function returns -1 in case of error.

+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
char* iniparser_getsecname (dictionary *  d,
int  n 
)
+
+
+ +

Get name for section n in a dictionary.

+
Parameters:
+ + + +
d Dictionary to examine
n Section number (from 0 to nsec-1).
+
+
+
Returns:
Pointer to char string
+

This function locates the n-th section in a dictionary and returns its name as a pointer to a string statically allocated inside the dictionary. Do not free or modify the returned string!

+

This function returns NULL in case of error.

+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
char* iniparser_getstring (dictionary *  d,
char *  key,
char *  def 
)
+
+
+ +

Get the string associated to a key.

+
Parameters:
+ + + + +
d Dictionary to search
key Key string to look for
def Default value to return if key not found.
+
+
+
Returns:
pointer to statically allocated character string
+

This function queries a dictionary for a key. A key as read from an ini file is given as "section:key". If the key cannot be found, the pointer passed as 'def' is returned. The returned char pointer is pointing to a string allocated in the dictionary, do not free or modify it.

+ +
+
+ +
+
+ + + + + + + + + +
dictionary* iniparser_load (char *  ininame ) 
+
+
+ +

Parse an ini file and return an allocated dictionary object.

+
Parameters:
+ + +
ininame Name of the ini file to read.
+
+
+
Returns:
Pointer to newly allocated dictionary
+

This is the parser for ini files. This function is called, providing the name of the file to be read. It returns a dictionary object that should not be accessed directly, but through accessor functions instead.

+

The returned dictionary must be freed using iniparser_freedict().

+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
int iniparser_set (dictionary *  ini,
char *  entry,
char *  val 
)
+
+
+ +

Set an entry in a dictionary.

+
Parameters:
+ + + + +
ini Dictionary to modify.
entry Entry to modify (entry name)
val New value to associate to the entry.
+
+
+
Returns:
int 0 if Ok, -1 otherwise.
+

If the given entry can be found in the dictionary, it is modified to contain the provided value. If it cannot be found, -1 is returned. It is Ok to set val to NULL.

+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
void iniparser_unset (dictionary *  ini,
char *  entry 
)
+
+
+ +

Delete an entry in a dictionary.

+
Parameters:
+ + + +
ini Dictionary to modify
entry Entry to delete (entry name)
+
+
+
Returns:
void
+

If the given entry can be found, it is deleted from the dictionary.

+ +
+
+
+
Generated on Wed Mar 2 22:04:59 2011 for iniparser by  + +doxygen 1.6.3
+ + diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/iniparser_8main.html b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/iniparser_8main.html new file mode 100644 index 0000000..3761667 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/iniparser_8main.html @@ -0,0 +1,19 @@ + + + + +iniparser: iniparser.main File Reference + + + + + +
+

iniparser.main File Reference

+
+
+
Generated on Wed Mar 2 22:04:59 2011 for iniparser by  + +doxygen 1.6.3
+ + diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/tab_b.gif b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/tab_b.gif new file mode 100644 index 0000000..0d62348 Binary files /dev/null and b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/tab_b.gif differ diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/tab_l.gif b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/tab_l.gif new file mode 100644 index 0000000..9b1e633 Binary files /dev/null and b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/tab_l.gif differ diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/tab_r.gif b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/tab_r.gif new file mode 100644 index 0000000..ce9dd9f Binary files /dev/null and b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/tab_r.gif differ diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/tabs.css b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/tabs.css new file mode 100644 index 0000000..a444163 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/html/tabs.css @@ -0,0 +1,105 @@ +/* tabs styles, based on http://www.alistapart.com/articles/slidingdoors */ + +DIV.tabs +{ + float : left; + width : 100%; + background : url("tab_b.gif") repeat-x bottom; + margin-bottom : 4px; +} + +DIV.tabs UL +{ + margin : 0px; + padding-left : 10px; + list-style : none; +} + +DIV.tabs LI, DIV.tabs FORM +{ + display : inline; + margin : 0px; + padding : 0px; +} + +DIV.tabs FORM +{ + float : right; +} + +DIV.tabs A +{ + float : left; + background : url("tab_r.gif") no-repeat right top; + border-bottom : 1px solid #84B0C7; + font-size : 80%; + font-weight : bold; + text-decoration : none; +} + +DIV.tabs A:hover +{ + background-position: 100% -150px; +} + +DIV.tabs A:link, DIV.tabs A:visited, +DIV.tabs A:active, DIV.tabs A:hover +{ + color: #1A419D; +} + +DIV.tabs SPAN +{ + float : left; + display : block; + background : url("tab_l.gif") no-repeat left top; + padding : 5px 9px; + white-space : nowrap; +} + +DIV.tabs #MSearchBox +{ + float : right; + display : inline; + font-size : 1em; +} + +DIV.tabs TD +{ + font-size : 80%; + font-weight : bold; + text-decoration : none; +} + + + +/* Commented Backslash Hack hides rule from IE5-Mac \*/ +DIV.tabs SPAN {float : none;} +/* End IE5-Mac hack */ + +DIV.tabs A:hover SPAN +{ + background-position: 0% -150px; +} + +DIV.tabs LI.current A +{ + background-position: 100% -150px; + border-width : 0px; +} + +DIV.tabs LI.current SPAN +{ + background-position: 0% -150px; + padding-bottom : 6px; +} + +DIV.navpath +{ + background : none; + border : none; + border-bottom : 1px solid #84B0C7; + text-align : center; + margin : 2px; + padding : 2px; +} diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/src/dictionary.c b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/src/dictionary.c new file mode 100644 index 0000000..cb7ccd4 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/src/dictionary.c @@ -0,0 +1,380 @@ +/*-------------------------------------------------------------------------*/ +/** + @file dictionary.c + @author N. Devillard + @brief Implements a dictionary for string variables. + + This module implements a simple dictionary object, i.e. a list + of string/string associations. This object is useful to store e.g. + informations retrieved from a configuration file (ini files). +*/ +/*--------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + Includes + ---------------------------------------------------------------------------*/ +#include "dictionary.h" + +#include +#include +#include +#include + +/** Maximum value size for integers and doubles. */ +#define MAXVALSZ 1024 + +/** Minimal allocated number of entries in a dictionary */ +#define DICTMINSZ 128 + +/** Invalid key token */ +#define DICT_INVALID_KEY ((char*)-1) + +/*--------------------------------------------------------------------------- + Private functions + ---------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------*/ +/** + @brief Duplicate a string + @param s String to duplicate + @return Pointer to a newly allocated string, to be freed with free() + + This is a replacement for strdup(). This implementation is provided + for systems that do not have it. + */ +/*--------------------------------------------------------------------------*/ +static char * xstrdup(const char * s) +{ + char * t ; + size_t len ; + if (!s) + return NULL ; + + len = strlen(s) + 1 ; + t = (char*) malloc(len) ; + if (t) { + memcpy(t, s, len) ; + } + return t ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Double the size of the dictionary + @param d Dictionary to grow + @return This function returns non-zero in case of failure + */ +/*--------------------------------------------------------------------------*/ +static int dictionary_grow(dictionary * d) +{ + char ** new_val ; + char ** new_key ; + unsigned * new_hash ; + + new_val = (char**) calloc(d->size * 2, sizeof *d->val); + new_key = (char**) calloc(d->size * 2, sizeof *d->key); + new_hash = (unsigned*) calloc(d->size * 2, sizeof *d->hash); + if (!new_val || !new_key || !new_hash) { + /* An allocation failed, leave the dictionary unchanged */ + if (new_val) + free(new_val); + if (new_key) + free(new_key); + if (new_hash) + free(new_hash); + return -1 ; + } + /* Initialize the newly allocated space */ + memcpy(new_val, d->val, d->size * sizeof(char *)); + memcpy(new_key, d->key, d->size * sizeof(char *)); + memcpy(new_hash, d->hash, d->size * sizeof(unsigned)); + /* Delete previous data */ + free(d->val); + free(d->key); + free(d->hash); + /* Actually update the dictionary */ + d->size *= 2 ; + d->val = new_val; + d->key = new_key; + d->hash = new_hash; + return 0 ; +} + +/*--------------------------------------------------------------------------- + Function codes + ---------------------------------------------------------------------------*/ +/*-------------------------------------------------------------------------*/ +/** + @brief Compute the hash key for a string. + @param key Character string to use for key. + @return 1 unsigned int on at least 32 bits. + + This hash function has been taken from an Article in Dr Dobbs Journal. + This is normally a collision-free function, distributing keys evenly. + The key is stored anyway in the struct so that collision can be avoided + by comparing the key itself in last resort. + */ +/*--------------------------------------------------------------------------*/ +unsigned dictionary_hash(const char * key) +{ + size_t len ; + unsigned hash ; + size_t i ; + + if (!key) + return 0 ; + + len = strlen(key); + for (hash=0, i=0 ; i>6) ; + } + hash += (hash <<3); + hash ^= (hash >>11); + hash += (hash <<15); + return hash ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Create a new dictionary object. + @param size Optional initial size of the dictionary. + @return 1 newly allocated dictionary objet. + + This function allocates a new dictionary object of given size and returns + it. If you do not know in advance (roughly) the number of entries in the + dictionary, give size=0. + */ +/*-------------------------------------------------------------------------*/ +dictionary * dictionary_new(size_t size) +{ + dictionary * d ; + + /* If no size was specified, allocate space for DICTMINSZ */ + if (sizesize = size ; + d->val = (char**) calloc(size, sizeof *d->val); + d->key = (char**) calloc(size, sizeof *d->key); + d->hash = (unsigned*) calloc(size, sizeof *d->hash); + } + return d ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Delete a dictionary object + @param d dictionary object to deallocate. + @return void + + Deallocate a dictionary object and all memory associated to it. + */ +/*--------------------------------------------------------------------------*/ +void dictionary_del(dictionary * d) +{ + ssize_t i ; + + if (d==NULL) return ; + for (i=0 ; isize ; i++) { + if (d->key[i]!=NULL) + free(d->key[i]); + if (d->val[i]!=NULL) + free(d->val[i]); + } + free(d->val); + free(d->key); + free(d->hash); + free(d); + return ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Get a value from a dictionary. + @param d dictionary object to search. + @param key Key to look for in the dictionary. + @param def Default value to return if key not found. + @return 1 pointer to internally allocated character string. + + This function locates a key in a dictionary and returns a pointer to its + value, or the passed 'def' pointer if no such key can be found in + dictionary. The returned character pointer points to data internal to the + dictionary object, you should not try to free it or modify it. + */ +/*--------------------------------------------------------------------------*/ +const char * dictionary_get(const dictionary * d, const char * key, const char * def) +{ + unsigned hash ; + ssize_t i ; + + hash = dictionary_hash(key); + for (i=0 ; isize ; i++) { + if (d->key[i]==NULL) + continue ; + /* Compare hash */ + if (hash==d->hash[i]) { + /* Compare string, to avoid hash collisions */ + if (!strcmp(key, d->key[i])) { + return d->val[i] ; + } + } + } + return def ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Set a value in a dictionary. + @param d dictionary object to modify. + @param key Key to modify or add. + @param val Value to add. + @return int 0 if Ok, anything else otherwise + + If the given key is found in the dictionary, the associated value is + replaced by the provided one. If the key cannot be found in the + dictionary, it is added to it. + + It is Ok to provide a NULL value for val, but NULL values for the dictionary + or the key are considered as errors: the function will return immediately + in such a case. + + Notice that if you dictionary_set a variable to NULL, a call to + dictionary_get will return a NULL value: the variable will be found, and + its value (NULL) is returned. In other words, setting the variable + content to NULL is equivalent to deleting the variable from the + dictionary. It is not possible (in this implementation) to have a key in + the dictionary without value. + + This function returns non-zero in case of failure. + */ +/*--------------------------------------------------------------------------*/ +int dictionary_set(dictionary * d, const char * key, const char * val) +{ + ssize_t i ; + unsigned hash ; + + if (d==NULL || key==NULL) return -1 ; + + /* Compute hash for this key */ + hash = dictionary_hash(key) ; + /* Find if value is already in dictionary */ + if (d->n>0) { + for (i=0 ; isize ; i++) { + if (d->key[i]==NULL) + continue ; + if (hash==d->hash[i]) { /* Same hash value */ + if (!strcmp(key, d->key[i])) { /* Same key */ + /* Found a value: modify and return */ + if (d->val[i]!=NULL) + free(d->val[i]); + d->val[i] = (val ? xstrdup(val) : NULL); + /* Value has been modified: return */ + return 0 ; + } + } + } + } + /* Add a new value */ + /* See if dictionary needs to grow */ + if (d->n==d->size) { + /* Reached maximum size: reallocate dictionary */ + if (dictionary_grow(d) != 0) + return -1; + } + + /* Insert key in the first empty slot. Start at d->n and wrap at + d->size. Because d->n < d->size this will necessarily + terminate. */ + for (i=d->n ; d->key[i] ; ) { + if(++i == d->size) i = 0; + } + /* Copy key */ + d->key[i] = xstrdup(key); + d->val[i] = (val ? xstrdup(val) : NULL) ; + d->hash[i] = hash; + d->n ++ ; + return 0 ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Delete a key in a dictionary + @param d dictionary object to modify. + @param key Key to remove. + @return void + + This function deletes a key in a dictionary. Nothing is done if the + key cannot be found. + */ +/*--------------------------------------------------------------------------*/ +void dictionary_unset(dictionary * d, const char * key) +{ + unsigned hash ; + ssize_t i ; + + if (key == NULL || d == NULL) { + return; + } + + hash = dictionary_hash(key); + for (i=0 ; isize ; i++) { + if (d->key[i]==NULL) + continue ; + /* Compare hash */ + if (hash==d->hash[i]) { + /* Compare string, to avoid hash collisions */ + if (!strcmp(key, d->key[i])) { + /* Found key */ + break ; + } + } + } + if (i>=d->size) + /* Key not found */ + return ; + + free(d->key[i]); + d->key[i] = NULL ; + if (d->val[i]!=NULL) { + free(d->val[i]); + d->val[i] = NULL ; + } + d->hash[i] = 0 ; + d->n -- ; + return ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Dump a dictionary to an opened file pointer. + @param d Dictionary to dump + @param f Opened file pointer. + @return void + + Dumps a dictionary onto an opened file pointer. Key pairs are printed out + as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as + output file pointers. + */ +/*--------------------------------------------------------------------------*/ +void dictionary_dump(const dictionary * d, FILE * out) +{ + ssize_t i ; + + if (d==NULL || out==NULL) return ; + if (d->n<1) { + fprintf(out, "empty dictionary\n"); + return ; + } + for (i=0 ; isize ; i++) { + if (d->key[i]) { + fprintf(out, "%20s\t[%s]\n", + d->key[i], + d->val[i] ? d->val[i] : "UNDEF"); + } + } + return ; +} diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/src/dictionary.h b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/src/dictionary.h new file mode 100644 index 0000000..d04b6ce --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/src/dictionary.h @@ -0,0 +1,173 @@ + +/*-------------------------------------------------------------------------*/ +/** + @file dictionary.h + @author N. Devillard + @brief Implements a dictionary for string variables. + + This module implements a simple dictionary object, i.e. a list + of string/string associations. This object is useful to store e.g. + informations retrieved from a configuration file (ini files). +*/ +/*--------------------------------------------------------------------------*/ + +#ifndef _DICTIONARY_H_ +#define _DICTIONARY_H_ + +/*--------------------------------------------------------------------------- + Includes + ---------------------------------------------------------------------------*/ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*--------------------------------------------------------------------------- + New types + ---------------------------------------------------------------------------*/ + + +/*-------------------------------------------------------------------------*/ +/** + @brief Dictionary object + + This object contains a list of string/string associations. Each + association is identified by a unique string key. Looking up values + in the dictionary is speeded up by the use of a (hopefully collision-free) + hash function. + */ +/*-------------------------------------------------------------------------*/ +typedef struct _dictionary_ { + int n ; /** Number of entries in dictionary */ + ssize_t size ; /** Storage size */ + char ** val ; /** List of string values */ + char ** key ; /** List of string keys */ + unsigned * hash ; /** List of hash values for keys */ +} dictionary ; + + +/*--------------------------------------------------------------------------- + Function prototypes + ---------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------*/ +/** + @brief Compute the hash key for a string. + @param key Character string to use for key. + @return 1 unsigned int on at least 32 bits. + + This hash function has been taken from an Article in Dr Dobbs Journal. + This is normally a collision-free function, distributing keys evenly. + The key is stored anyway in the struct so that collision can be avoided + by comparing the key itself in last resort. + */ +/*--------------------------------------------------------------------------*/ +unsigned dictionary_hash(const char * key); + +/*-------------------------------------------------------------------------*/ +/** + @brief Create a new dictionary object. + @param size Optional initial size of the dictionary. + @return 1 newly allocated dictionary objet. + + This function allocates a new dictionary object of given size and returns + it. If you do not know in advance (roughly) the number of entries in the + dictionary, give size=0. + */ +/*--------------------------------------------------------------------------*/ +dictionary * dictionary_new(size_t size); + +/*-------------------------------------------------------------------------*/ +/** + @brief Delete a dictionary object + @param d dictionary object to deallocate. + @return void + + Deallocate a dictionary object and all memory associated to it. + */ +/*--------------------------------------------------------------------------*/ +void dictionary_del(dictionary * vd); + +/*-------------------------------------------------------------------------*/ +/** + @brief Get a value from a dictionary. + @param d dictionary object to search. + @param key Key to look for in the dictionary. + @param def Default value to return if key not found. + @return 1 pointer to internally allocated character string. + + This function locates a key in a dictionary and returns a pointer to its + value, or the passed 'def' pointer if no such key can be found in + dictionary. The returned character pointer points to data internal to the + dictionary object, you should not try to free it or modify it. + */ +/*--------------------------------------------------------------------------*/ +const char * dictionary_get(const dictionary * d, const char * key, const char * def); + + +/*-------------------------------------------------------------------------*/ +/** + @brief Set a value in a dictionary. + @param d dictionary object to modify. + @param key Key to modify or add. + @param val Value to add. + @return int 0 if Ok, anything else otherwise + + If the given key is found in the dictionary, the associated value is + replaced by the provided one. If the key cannot be found in the + dictionary, it is added to it. + + It is Ok to provide a NULL value for val, but NULL values for the dictionary + or the key are considered as errors: the function will return immediately + in such a case. + + Notice that if you dictionary_set a variable to NULL, a call to + dictionary_get will return a NULL value: the variable will be found, and + its value (NULL) is returned. In other words, setting the variable + content to NULL is equivalent to deleting the variable from the + dictionary. It is not possible (in this implementation) to have a key in + the dictionary without value. + + This function returns non-zero in case of failure. + */ +/*--------------------------------------------------------------------------*/ +int dictionary_set(dictionary * vd, const char * key, const char * val); + +/*-------------------------------------------------------------------------*/ +/** + @brief Delete a key in a dictionary + @param d dictionary object to modify. + @param key Key to remove. + @return void + + This function deletes a key in a dictionary. Nothing is done if the + key cannot be found. + */ +/*--------------------------------------------------------------------------*/ +void dictionary_unset(dictionary * d, const char * key); + + +/*-------------------------------------------------------------------------*/ +/** + @brief Dump a dictionary to an opened file pointer. + @param d Dictionary to dump + @param f Opened file pointer. + @return void + + Dumps a dictionary onto an opened file pointer. Key pairs are printed out + as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as + output file pointers. + */ +/*--------------------------------------------------------------------------*/ +void dictionary_dump(const dictionary * d, FILE * out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/src/iniparser.c b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/src/iniparser.c new file mode 100644 index 0000000..2a0bf4e --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/src/iniparser.c @@ -0,0 +1,836 @@ + +/*-------------------------------------------------------------------------*/ +/** + @file iniparser.c + @author N. Devillard + @brief Parser for ini files. +*/ +/*--------------------------------------------------------------------------*/ +/*---------------------------- Includes ------------------------------------*/ +#include +#include +#include "iniparser.h" + +/*---------------------------- Defines -------------------------------------*/ +#define ASCIILINESZ (8192) +#define INI_INVALID_KEY ((char*)-1) + +/*--------------------------------------------------------------------------- + Private to this module + ---------------------------------------------------------------------------*/ +/** + * This enum stores the status for each parsed line (internal use only). + */ +typedef enum _line_status_ { + LINE_UNPROCESSED, + LINE_ERROR, + LINE_EMPTY, + LINE_COMMENT, + LINE_SECTION, + LINE_VALUE +} line_status ; + +/*-------------------------------------------------------------------------*/ +/** + @brief Convert a string to lowercase. + @param in String to convert. + @param out Output buffer. + @param len Size of the out buffer. + @return ptr to the out buffer or NULL if an error occured. + + This function convert a string into lowercase. + At most len - 1 elements of the input string will be converted. + */ +/*--------------------------------------------------------------------------*/ +static const char * strlwc(const char * in, char *out, unsigned len) +{ + unsigned i ; + + if (in==NULL || out == NULL || len==0) return NULL ; + i=0 ; + while (in[i] != '\0' && i < len-1) { + out[i] = (char)tolower((int)in[i]); + i++ ; + } + out[i] = '\0'; + return out ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Duplicate a string + @param s String to duplicate + @return Pointer to a newly allocated string, to be freed with free() + + This is a replacement for strdup(). This implementation is provided + for systems that do not have it. + */ +/*--------------------------------------------------------------------------*/ +static char * xstrdup(const char * s) +{ + char * t ; + size_t len ; + if (!s) + return NULL ; + + len = strlen(s) + 1 ; + t = (char*) malloc(len) ; + if (t) { + memcpy(t, s, len) ; + } + return t ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Remove blanks at the beginning and the end of a string. + @param str String to parse and alter. + @return unsigned New size of the string. + */ +/*--------------------------------------------------------------------------*/ +static unsigned strstrip(char * s) +{ + char *last = NULL ; + char *dest = s; + + if (s==NULL) return 0; + + last = s + strlen(s); + while (isspace((int)*s) && *s) s++; + while (last > s) { + if (!isspace((int)*(last-1))) + break ; + last -- ; + } + *last = (char)0; + + memmove(dest,s,last - s + 1); + return last - s; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Default error callback for iniparser: wraps `fprintf(stderr, ...)`. + */ +/*--------------------------------------------------------------------------*/ +static int default_error_callback(const char *format, ...) +{ + int ret; + va_list argptr; + va_start(argptr, format); + ret = vfprintf(stderr, format, argptr); + va_end(argptr); + return ret; +} + +static int (*iniparser_error_callback)(const char*, ...) = default_error_callback; + +/*-------------------------------------------------------------------------*/ +/** + @brief Configure a function to receive the error messages. + @param errback Function to call. + + By default, the error will be printed on stderr. If a null pointer is passed + as errback the error callback will be switched back to default. + */ +/*--------------------------------------------------------------------------*/ +void iniparser_set_error_callback(int (*errback)(const char *, ...)) +{ + if (errback) { + iniparser_error_callback = errback; + } else { + iniparser_error_callback = default_error_callback; + } +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Get number of sections in a dictionary + @param d Dictionary to examine + @return int Number of sections found in dictionary + + This function returns the number of sections found in a dictionary. + The test to recognize sections is done on the string stored in the + dictionary: a section name is given as "section" whereas a key is + stored as "section:key", thus the test looks for entries that do not + contain a colon. + + This clearly fails in the case a section name contains a colon, but + this should simply be avoided. + + This function returns -1 in case of error. + */ +/*--------------------------------------------------------------------------*/ +int iniparser_getnsec(const dictionary * d) +{ + int i ; + int nsec ; + + if (d==NULL) return -1 ; + nsec=0 ; + for (i=0 ; isize ; i++) { + if (d->key[i]==NULL) + continue ; + if (strchr(d->key[i], ':')==NULL) { + nsec ++ ; + } + } + return nsec ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Get name for section n in a dictionary. + @param d Dictionary to examine + @param n Section number (from 0 to nsec-1). + @return Pointer to char string + + This function locates the n-th section in a dictionary and returns + its name as a pointer to a string statically allocated inside the + dictionary. Do not free or modify the returned string! + + This function returns NULL in case of error. + */ +/*--------------------------------------------------------------------------*/ +const char * iniparser_getsecname(const dictionary * d, int n) +{ + int i ; + int foundsec ; + + if (d==NULL || n<0) return NULL ; + foundsec=0 ; + for (i=0 ; isize ; i++) { + if (d->key[i]==NULL) + continue ; + if (strchr(d->key[i], ':')==NULL) { + foundsec++ ; + if (foundsec>n) + break ; + } + } + if (foundsec<=n) { + return NULL ; + } + return d->key[i] ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Dump a dictionary to an opened file pointer. + @param d Dictionary to dump. + @param f Opened file pointer to dump to. + @return void + + This function prints out the contents of a dictionary, one element by + line, onto the provided file pointer. It is OK to specify @c stderr + or @c stdout as output files. This function is meant for debugging + purposes mostly. + */ +/*--------------------------------------------------------------------------*/ +void iniparser_dump(const dictionary * d, FILE * f) +{ + int i ; + + if (d==NULL || f==NULL) return ; + for (i=0 ; isize ; i++) { + if (d->key[i]==NULL) + continue ; + if (d->val[i]!=NULL) { + fprintf(f, "[%s]=[%s]\n", d->key[i], d->val[i]); + } else { + fprintf(f, "[%s]=UNDEF\n", d->key[i]); + } + } + return ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Save a dictionary to a loadable ini file + @param d Dictionary to dump + @param f Opened file pointer to dump to + @return void + + This function dumps a given dictionary into a loadable ini file. + It is Ok to specify @c stderr or @c stdout as output files. + */ +/*--------------------------------------------------------------------------*/ +void iniparser_dump_ini(const dictionary * d, FILE * f) +{ + int i ; + int nsec ; + const char * secname ; + + if (d==NULL || f==NULL) return ; + + nsec = iniparser_getnsec(d); + if (nsec<1) { + /* No section in file: dump all keys as they are */ + for (i=0 ; isize ; i++) { + if (d->key[i]==NULL) + continue ; + fprintf(f, "%s = %s\n", d->key[i], d->val[i]); + } + return ; + } + for (i=0 ; isize ; j++) { + if (d->key[j]==NULL) + continue ; + if (!strncmp(d->key[j], keym, seclen+1)) { + fprintf(f, + "%-30s = %s\n", + d->key[j]+seclen+1, + d->val[j] ? d->val[j] : ""); + } + } + fprintf(f, "\n"); + return ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Get the number of keys in a section of a dictionary. + @param d Dictionary to examine + @param s Section name of dictionary to examine + @return Number of keys in section + */ +/*--------------------------------------------------------------------------*/ +int iniparser_getsecnkeys(const dictionary * d, const char * s) +{ + int seclen, nkeys ; + char keym[ASCIILINESZ+1]; + int j ; + + nkeys = 0; + + if (d==NULL) return nkeys; + if (! iniparser_find_entry(d, s)) return nkeys; + + seclen = (int)strlen(s); + strlwc(s, keym, sizeof(keym)); + keym[seclen] = ':'; + + for (j=0 ; jsize ; j++) { + if (d->key[j]==NULL) + continue ; + if (!strncmp(d->key[j], keym, seclen+1)) + nkeys++; + } + + return nkeys; + +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Get the number of keys in a section of a dictionary. + @param d Dictionary to examine + @param s Section name of dictionary to examine + @param keys Already allocated array to store the keys in + @return The pointer passed as `keys` argument or NULL in case of error + + This function queries a dictionary and finds all keys in a given section. + The keys argument should be an array of pointers which size has been + determined by calling `iniparser_getsecnkeys` function prior to this one. + + Each pointer in the returned char pointer-to-pointer is pointing to + a string allocated in the dictionary; do not free or modify them. + */ +/*--------------------------------------------------------------------------*/ +const char ** iniparser_getseckeys(const dictionary * d, const char * s, const char ** keys) +{ + int i, j, seclen ; + char keym[ASCIILINESZ+1]; + + if (d==NULL || keys==NULL) return NULL; + if (! iniparser_find_entry(d, s)) return NULL; + + seclen = (int)strlen(s); + strlwc(s, keym, sizeof(keym)); + keym[seclen] = ':'; + + i = 0; + + for (j=0 ; jsize ; j++) { + if (d->key[j]==NULL) + continue ; + if (!strncmp(d->key[j], keym, seclen+1)) { + keys[i] = d->key[j]; + i++; + } + } + + return keys; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Get the string associated to a key + @param d Dictionary to search + @param key Key string to look for + @param def Default value to return if key not found. + @return pointer to statically allocated character string + + This function queries a dictionary for a key. A key as read from an + ini file is given as "section:key". If the key cannot be found, + the pointer passed as 'def' is returned. + The returned char pointer is pointing to a string allocated in + the dictionary, do not free or modify it. + */ +/*--------------------------------------------------------------------------*/ +const char * iniparser_getstring(const dictionary * d, const char * key, const char * def) +{ + const char * lc_key ; + const char * sval ; + char tmp_str[ASCIILINESZ+1]; + + if (d==NULL || key==NULL) + return def ; + + lc_key = strlwc(key, tmp_str, sizeof(tmp_str)); + sval = dictionary_get(d, lc_key, def); + return sval ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Get the string associated to a key, convert to an long int + @param d Dictionary to search + @param key Key string to look for + @param notfound Value to return in case of error + @return long integer + + This function queries a dictionary for a key. A key as read from an + ini file is given as "section:key". If the key cannot be found, + the notfound value is returned. + + Supported values for integers include the usual C notation + so decimal, octal (starting with 0) and hexadecimal (starting with 0x) + are supported. Examples: + + "42" -> 42 + "042" -> 34 (octal -> decimal) + "0x42" -> 66 (hexa -> decimal) + + Warning: the conversion may overflow in various ways. Conversion is + totally outsourced to strtol(), see the associated man page for overflow + handling. + + Credits: Thanks to A. Becker for suggesting strtol() + */ +/*--------------------------------------------------------------------------*/ +long int iniparser_getlongint(const dictionary * d, const char * key, long int notfound) +{ + const char * str ; + + str = iniparser_getstring(d, key, INI_INVALID_KEY); + if (str==INI_INVALID_KEY) return notfound ; + return strtol(str, NULL, 0); +} + + +/*-------------------------------------------------------------------------*/ +/** + @brief Get the string associated to a key, convert to an int + @param d Dictionary to search + @param key Key string to look for + @param notfound Value to return in case of error + @return integer + + This function queries a dictionary for a key. A key as read from an + ini file is given as "section:key". If the key cannot be found, + the notfound value is returned. + + Supported values for integers include the usual C notation + so decimal, octal (starting with 0) and hexadecimal (starting with 0x) + are supported. Examples: + + "42" -> 42 + "042" -> 34 (octal -> decimal) + "0x42" -> 66 (hexa -> decimal) + + Warning: the conversion may overflow in various ways. Conversion is + totally outsourced to strtol(), see the associated man page for overflow + handling. + + Credits: Thanks to A. Becker for suggesting strtol() + */ +/*--------------------------------------------------------------------------*/ +int iniparser_getint(const dictionary * d, const char * key, int notfound) +{ + return (int)iniparser_getlongint(d, key, notfound); +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Get the string associated to a key, convert to a double + @param d Dictionary to search + @param key Key string to look for + @param notfound Value to return in case of error + @return double + + This function queries a dictionary for a key. A key as read from an + ini file is given as "section:key". If the key cannot be found, + the notfound value is returned. + */ +/*--------------------------------------------------------------------------*/ +double iniparser_getdouble(const dictionary * d, const char * key, double notfound) +{ + const char * str ; + + str = iniparser_getstring(d, key, INI_INVALID_KEY); + if (str==INI_INVALID_KEY) return notfound ; + return atof(str); +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Get the string associated to a key, convert to a boolean + @param d Dictionary to search + @param key Key string to look for + @param notfound Value to return in case of error + @return integer + + This function queries a dictionary for a key. A key as read from an + ini file is given as "section:key". If the key cannot be found, + the notfound value is returned. + + A true boolean is found if one of the following is matched: + + - A string starting with 'y' + - A string starting with 'Y' + - A string starting with 't' + - A string starting with 'T' + - A string starting with '1' + + A false boolean is found if one of the following is matched: + + - A string starting with 'n' + - A string starting with 'N' + - A string starting with 'f' + - A string starting with 'F' + - A string starting with '0' + + The notfound value returned if no boolean is identified, does not + necessarily have to be 0 or 1. + */ +/*--------------------------------------------------------------------------*/ +int iniparser_getboolean(const dictionary * d, const char * key, int notfound) +{ + int ret ; + const char * c ; + + c = iniparser_getstring(d, key, INI_INVALID_KEY); + if (c==INI_INVALID_KEY) return notfound ; + if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') { + ret = 1 ; + } else if (c[0]=='n' || c[0]=='N' || c[0]=='0' || c[0]=='f' || c[0]=='F') { + ret = 0 ; + } else { + ret = notfound ; + } + return ret; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Finds out if a given entry exists in a dictionary + @param ini Dictionary to search + @param entry Name of the entry to look for + @return integer 1 if entry exists, 0 otherwise + + Finds out if a given entry exists in the dictionary. Since sections + are stored as keys with NULL associated values, this is the only way + of querying for the presence of sections in a dictionary. + */ +/*--------------------------------------------------------------------------*/ +int iniparser_find_entry(const dictionary * ini, const char * entry) +{ + int found=0 ; + if (iniparser_getstring(ini, entry, INI_INVALID_KEY)!=INI_INVALID_KEY) { + found = 1 ; + } + return found ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Set an entry in a dictionary. + @param ini Dictionary to modify. + @param entry Entry to modify (entry name) + @param val New value to associate to the entry. + @return int 0 if Ok, -1 otherwise. + + If the given entry can be found in the dictionary, it is modified to + contain the provided value. If it cannot be found, the entry is created. + It is Ok to set val to NULL. + */ +/*--------------------------------------------------------------------------*/ +int iniparser_set(dictionary * ini, const char * entry, const char * val) +{ + char tmp_str[ASCIILINESZ+1]; + return dictionary_set(ini, strlwc(entry, tmp_str, sizeof(tmp_str)), val) ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Delete an entry in a dictionary + @param ini Dictionary to modify + @param entry Entry to delete (entry name) + @return void + + If the given entry can be found, it is deleted from the dictionary. + */ +/*--------------------------------------------------------------------------*/ +void iniparser_unset(dictionary * ini, const char * entry) +{ + char tmp_str[ASCIILINESZ+1]; + dictionary_unset(ini, strlwc(entry, tmp_str, sizeof(tmp_str))); +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Load a single line from an INI file + @param input_line Input line, may be concatenated multi-line input + @param section Output space to store section + @param key Output space to store key + @param value Output space to store value + @return line_status value + */ +/*--------------------------------------------------------------------------*/ +static line_status iniparser_line( + const char * input_line, + char * section, + char * key, + char * value) +{ + line_status sta ; + char * line = NULL; + size_t len ; + + line = xstrdup(input_line); + len = strstrip(line); + + sta = LINE_UNPROCESSED ; + if (len<1) { + /* Empty line */ + sta = LINE_EMPTY ; + } else if (line[0]=='#' || line[0]==';') { + /* Comment line */ + sta = LINE_COMMENT ; + } else if (line[0]=='[' && line[len-1]==']') { + /* Section name */ + sscanf(line, "[%[^]]", section); + strstrip(section); + strlwc(section, section, len); + sta = LINE_SECTION ; + } else if (sscanf (line, "%[^=] = \"%[^\"]\"", key, value) == 2 + || sscanf (line, "%[^=] = '%[^\']'", key, value) == 2) { + /* Usual key=value with quotes, with or without comments */ + strstrip(key); + strlwc(key, key, len); + /* Don't strip spaces from values surrounded with quotes */ + sta = LINE_VALUE ; + } else if (sscanf (line, "%[^=] = %[^;#]", key, value) == 2) { + /* Usual key=value without quotes, with or without comments */ + strstrip(key); + strlwc(key, key, len); + strstrip(value); + /* + * sscanf cannot handle '' or "" as empty values + * this is done here + */ + if (!strcmp(value, "\"\"") || (!strcmp(value, "''"))) { + value[0]=0 ; + } + sta = LINE_VALUE ; + } else if (sscanf(line, "%[^=] = %[;#]", key, value)==2 + || sscanf(line, "%[^=] %[=]", key, value) == 2) { + /* + * Special cases: + * key= + * key=; + * key=# + */ + strstrip(key); + strlwc(key, key, len); + value[0]=0 ; + sta = LINE_VALUE ; + } else { + /* Generate syntax error */ + sta = LINE_ERROR ; + } + + free(line); + return sta ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Parse an ini file and return an allocated dictionary object + @param ininame Name of the ini file to read. + @return Pointer to newly allocated dictionary + + This is the parser for ini files. This function is called, providing + the name of the file to be read. It returns a dictionary object that + should not be accessed directly, but through accessor functions + instead. + + The returned dictionary must be freed using iniparser_freedict(). + */ +/*--------------------------------------------------------------------------*/ +dictionary * iniparser_load(const char * ininame) +{ + FILE * in ; + + char line [ASCIILINESZ+1] ; + char section [ASCIILINESZ+1] ; + char key [ASCIILINESZ+1] ; + char tmp [(ASCIILINESZ * 2) + 2] ; + char val [ASCIILINESZ+1] ; + + int last=0 ; + int len ; + int lineno=0 ; + int errs=0; + int mem_err=0; + + dictionary * dict ; + + if ((in=fopen(ininame, "r"))==NULL) { + iniparser_error_callback("iniparser: cannot open %s\n", ininame); + return NULL ; + } + + dict = dictionary_new(0) ; + if (!dict) { + fclose(in); + return NULL ; + } + + memset(line, 0, ASCIILINESZ); + memset(section, 0, ASCIILINESZ); + memset(key, 0, ASCIILINESZ); + memset(val, 0, ASCIILINESZ); + last=0 ; + + while (fgets(line+last, ASCIILINESZ-last, in)!=NULL) { + lineno++ ; + len = (int)strlen(line)-1; + if (len<=0) + continue; + /* Safety check against buffer overflows */ + if (line[len]!='\n' && !feof(in)) { + iniparser_error_callback( + "iniparser: input line too long in %s (%d)\n", + ininame, + lineno); + dictionary_del(dict); + fclose(in); + return NULL ; + } + /* Get rid of \n and spaces at end of line */ + while ((len>=0) && + ((line[len]=='\n') || (isspace(line[len])))) { + line[len]=0 ; + len-- ; + } + if (len < 0) { /* Line was entirely \n and/or spaces */ + len = 0; + } + /* Detect multi-line */ + if (line[len]=='\\') { + /* Multi-line value */ + last=len ; + continue ; + } else { + last=0 ; + } + switch (iniparser_line(line, section, key, val)) { + case LINE_EMPTY: + case LINE_COMMENT: + break ; + + case LINE_SECTION: + mem_err = dictionary_set(dict, section, NULL); + break ; + + case LINE_VALUE: + sprintf(tmp, "%s:%s", section, key); + mem_err = dictionary_set(dict, tmp, val); + break ; + + case LINE_ERROR: + iniparser_error_callback( + "iniparser: syntax error in %s (%d):\n-> %s\n", + ininame, + lineno, + line); + errs++ ; + break; + + default: + break ; + } + memset(line, 0, ASCIILINESZ); + last=0; + if (mem_err<0) { + iniparser_error_callback("iniparser: memory allocation failure\n"); + break ; + } + } + if (errs) { + dictionary_del(dict); + dict = NULL ; + } + fclose(in); + return dict ; +} + +/*-------------------------------------------------------------------------*/ +/** + @brief Free all memory associated to an ini dictionary + @param d Dictionary to free + @return void + + Free all memory associated to an ini dictionary. + It is mandatory to call this function before the dictionary object + gets out of the current context. + */ +/*--------------------------------------------------------------------------*/ +void iniparser_freedict(dictionary * d) +{ + dictionary_del(d); +} diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/src/iniparser.h b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/src/iniparser.h new file mode 100644 index 0000000..37ff7b7 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/src/iniparser.h @@ -0,0 +1,358 @@ + +/*-------------------------------------------------------------------------*/ +/** + @file iniparser.h + @author N. Devillard + @brief Parser for ini files. +*/ +/*--------------------------------------------------------------------------*/ + +#ifndef _INIPARSER_H_ +#define _INIPARSER_H_ + +/*--------------------------------------------------------------------------- + Includes + ---------------------------------------------------------------------------*/ + +#include +#include +#include + +/* + * The following #include is necessary on many Unixes but not Linux. + * It is not needed for Windows platforms. + * Uncomment it if needed. + */ +/* #include */ + +#include "dictionary.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*-------------------------------------------------------------------------*/ +/** + @brief Configure a function to receive the error messages. + @param errback Function to call. + + By default, the error will be printed on stderr. If a null pointer is passed + as errback the error callback will be switched back to default. + */ +/*--------------------------------------------------------------------------*/ + +void iniparser_set_error_callback(int (*errback)(const char *, ...)); + +/*-------------------------------------------------------------------------*/ +/** + @brief Get number of sections in a dictionary + @param d Dictionary to examine + @return int Number of sections found in dictionary + + This function returns the number of sections found in a dictionary. + The test to recognize sections is done on the string stored in the + dictionary: a section name is given as "section" whereas a key is + stored as "section:key", thus the test looks for entries that do not + contain a colon. + + This clearly fails in the case a section name contains a colon, but + this should simply be avoided. + + This function returns -1 in case of error. + */ +/*--------------------------------------------------------------------------*/ + +int iniparser_getnsec(const dictionary * d); + + +/*-------------------------------------------------------------------------*/ +/** + @brief Get name for section n in a dictionary. + @param d Dictionary to examine + @param n Section number (from 0 to nsec-1). + @return Pointer to char string + + This function locates the n-th section in a dictionary and returns + its name as a pointer to a string statically allocated inside the + dictionary. Do not free or modify the returned string! + + This function returns NULL in case of error. + */ +/*--------------------------------------------------------------------------*/ + +const char * iniparser_getsecname(const dictionary * d, int n); + + +/*-------------------------------------------------------------------------*/ +/** + @brief Save a dictionary to a loadable ini file + @param d Dictionary to dump + @param f Opened file pointer to dump to + @return void + + This function dumps a given dictionary into a loadable ini file. + It is Ok to specify @c stderr or @c stdout as output files. + */ +/*--------------------------------------------------------------------------*/ + +void iniparser_dump_ini(const dictionary * d, FILE * f); + +/*-------------------------------------------------------------------------*/ +/** + @brief Save a dictionary section to a loadable ini file + @param d Dictionary to dump + @param s Section name of dictionary to dump + @param f Opened file pointer to dump to + @return void + + This function dumps a given section of a given dictionary into a loadable ini + file. It is Ok to specify @c stderr or @c stdout as output files. + */ +/*--------------------------------------------------------------------------*/ + +void iniparser_dumpsection_ini(const dictionary * d, const char * s, FILE * f); + +/*-------------------------------------------------------------------------*/ +/** + @brief Dump a dictionary to an opened file pointer. + @param d Dictionary to dump. + @param f Opened file pointer to dump to. + @return void + + This function prints out the contents of a dictionary, one element by + line, onto the provided file pointer. It is OK to specify @c stderr + or @c stdout as output files. This function is meant for debugging + purposes mostly. + */ +/*--------------------------------------------------------------------------*/ +void iniparser_dump(const dictionary * d, FILE * f); + +/*-------------------------------------------------------------------------*/ +/** + @brief Get the number of keys in a section of a dictionary. + @param d Dictionary to examine + @param s Section name of dictionary to examine + @return Number of keys in section + */ +/*--------------------------------------------------------------------------*/ +int iniparser_getsecnkeys(const dictionary * d, const char * s); + +/*-------------------------------------------------------------------------*/ +/** + @brief Get the number of keys in a section of a dictionary. + @param d Dictionary to examine + @param s Section name of dictionary to examine + @param keys Already allocated array to store the keys in + @return The pointer passed as `keys` argument or NULL in case of error + + This function queries a dictionary and finds all keys in a given section. + The keys argument should be an array of pointers which size has been + determined by calling `iniparser_getsecnkeys` function prior to this one. + + Each pointer in the returned char pointer-to-pointer is pointing to + a string allocated in the dictionary; do not free or modify them. + */ +/*--------------------------------------------------------------------------*/ +const char ** iniparser_getseckeys(const dictionary * d, const char * s, const char ** keys); + + +/*-------------------------------------------------------------------------*/ +/** + @brief Get the string associated to a key + @param d Dictionary to search + @param key Key string to look for + @param def Default value to return if key not found. + @return pointer to statically allocated character string + + This function queries a dictionary for a key. A key as read from an + ini file is given as "section:key". If the key cannot be found, + the pointer passed as 'def' is returned. + The returned char pointer is pointing to a string allocated in + the dictionary, do not free or modify it. + */ +/*--------------------------------------------------------------------------*/ +const char * iniparser_getstring(const dictionary * d, const char * key, const char * def); + +/*-------------------------------------------------------------------------*/ +/** + @brief Get the string associated to a key, convert to an int + @param d Dictionary to search + @param key Key string to look for + @param notfound Value to return in case of error + @return integer + + This function queries a dictionary for a key. A key as read from an + ini file is given as "section:key". If the key cannot be found, + the notfound value is returned. + + Supported values for integers include the usual C notation + so decimal, octal (starting with 0) and hexadecimal (starting with 0x) + are supported. Examples: + + - "42" -> 42 + - "042" -> 34 (octal -> decimal) + - "0x42" -> 66 (hexa -> decimal) + + Warning: the conversion may overflow in various ways. Conversion is + totally outsourced to strtol(), see the associated man page for overflow + handling. + + Credits: Thanks to A. Becker for suggesting strtol() + */ +/*--------------------------------------------------------------------------*/ +int iniparser_getint(const dictionary * d, const char * key, int notfound); + +/*-------------------------------------------------------------------------*/ +/** + @brief Get the string associated to a key, convert to an long int + @param d Dictionary to search + @param key Key string to look for + @param notfound Value to return in case of error + @return integer + + This function queries a dictionary for a key. A key as read from an + ini file is given as "section:key". If the key cannot be found, + the notfound value is returned. + + Supported values for integers include the usual C notation + so decimal, octal (starting with 0) and hexadecimal (starting with 0x) + are supported. Examples: + + - "42" -> 42 + - "042" -> 34 (octal -> decimal) + - "0x42" -> 66 (hexa -> decimal) + + Warning: the conversion may overflow in various ways. Conversion is + totally outsourced to strtol(), see the associated man page for overflow + handling. + */ +/*--------------------------------------------------------------------------*/ +long int iniparser_getlongint(const dictionary * d, const char * key, long int notfound); + + +/*-------------------------------------------------------------------------*/ +/** + @brief Get the string associated to a key, convert to a double + @param d Dictionary to search + @param key Key string to look for + @param notfound Value to return in case of error + @return double + + This function queries a dictionary for a key. A key as read from an + ini file is given as "section:key". If the key cannot be found, + the notfound value is returned. + */ +/*--------------------------------------------------------------------------*/ +double iniparser_getdouble(const dictionary * d, const char * key, double notfound); + +/*-------------------------------------------------------------------------*/ +/** + @brief Get the string associated to a key, convert to a boolean + @param d Dictionary to search + @param key Key string to look for + @param notfound Value to return in case of error + @return integer + + This function queries a dictionary for a key. A key as read from an + ini file is given as "section:key". If the key cannot be found, + the notfound value is returned. + + A true boolean is found if one of the following is matched: + + - A string starting with 'y' + - A string starting with 'Y' + - A string starting with 't' + - A string starting with 'T' + - A string starting with '1' + + A false boolean is found if one of the following is matched: + + - A string starting with 'n' + - A string starting with 'N' + - A string starting with 'f' + - A string starting with 'F' + - A string starting with '0' + + The notfound value returned if no boolean is identified, does not + necessarily have to be 0 or 1. + */ +/*--------------------------------------------------------------------------*/ +int iniparser_getboolean(const dictionary * d, const char * key, int notfound); + + +/*-------------------------------------------------------------------------*/ +/** + @brief Set an entry in a dictionary. + @param ini Dictionary to modify. + @param entry Entry to modify (entry name) + @param val New value to associate to the entry. + @return int 0 if Ok, -1 otherwise. + + If the given entry can be found in the dictionary, it is modified to + contain the provided value. If it cannot be found, the entry is created. + It is Ok to set val to NULL. + */ +/*--------------------------------------------------------------------------*/ +int iniparser_set(dictionary * ini, const char * entry, const char * val); + + +/*-------------------------------------------------------------------------*/ +/** + @brief Delete an entry in a dictionary + @param ini Dictionary to modify + @param entry Entry to delete (entry name) + @return void + + If the given entry can be found, it is deleted from the dictionary. + */ +/*--------------------------------------------------------------------------*/ +void iniparser_unset(dictionary * ini, const char * entry); + +/*-------------------------------------------------------------------------*/ +/** + @brief Finds out if a given entry exists in a dictionary + @param ini Dictionary to search + @param entry Name of the entry to look for + @return integer 1 if entry exists, 0 otherwise + + Finds out if a given entry exists in the dictionary. Since sections + are stored as keys with NULL associated values, this is the only way + of querying for the presence of sections in a dictionary. + */ +/*--------------------------------------------------------------------------*/ +int iniparser_find_entry(const dictionary * ini, const char * entry) ; + +/*-------------------------------------------------------------------------*/ +/** + @brief Parse an ini file and return an allocated dictionary object + @param ininame Name of the ini file to read. + @return Pointer to newly allocated dictionary + + This is the parser for ini files. This function is called, providing + the name of the file to be read. It returns a dictionary object that + should not be accessed directly, but through accessor functions + instead. + + The returned dictionary must be freed using iniparser_freedict(). + */ +/*--------------------------------------------------------------------------*/ +dictionary * iniparser_load(const char * ininame); + +/*-------------------------------------------------------------------------*/ +/** + @brief Free all memory associated to an ini dictionary + @param d Dictionary to free + @return void + + Free all memory associated to an ini dictionary. + It is mandatory to call this function before the dictionary object + gets out of the current context. + */ +/*--------------------------------------------------------------------------*/ +void iniparser_freedict(dictionary * d); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/CuTest.c b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/CuTest.c new file mode 100644 index 0000000..463f170 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/CuTest.c @@ -0,0 +1,348 @@ +#include +#include +#include +#include +#include +#include + +#include "CuTest.h" + +/*-------------------------------------------------------------------------* + * CuStr + *-------------------------------------------------------------------------*/ + +char* CuStrAlloc(int size) +{ + char* newStr = (char*) malloc( sizeof(char) * (size) ); + return newStr; +} + +char* CuStrCopy(const char* old) +{ + int len = strlen(old); + char* newStr = CuStrAlloc(len + 1); + strcpy(newStr, old); + return newStr; +} + +/*-------------------------------------------------------------------------* + * CuString + *-------------------------------------------------------------------------*/ + +void CuStringInit(CuString* str) +{ + str->length = 0; + str->size = STRING_MAX; + str->buffer = (char*) malloc(sizeof(char) * str->size); + str->buffer[0] = '\0'; +} + +CuString* CuStringNew(void) +{ + CuString* str = (CuString*) malloc(sizeof(CuString)); + str->length = 0; + str->size = STRING_MAX; + str->buffer = (char*) malloc(sizeof(char) * str->size); + str->buffer[0] = '\0'; + return str; +} + +void CuStringDelete(CuString *str) +{ + if (!str) return; + free(str->buffer); + free(str); +} + +void CuStringResize(CuString* str, int newSize) +{ + str->buffer = (char*) realloc(str->buffer, sizeof(char) * newSize); + str->size = newSize; +} + +void CuStringAppend(CuString* str, const char* text) +{ + int length; + + if (text == NULL) { + text = "NULL"; + } + + length = strlen(text); + if (str->length + length + 1 >= str->size) + CuStringResize(str, str->length + length + 1 + STRING_INC); + str->length += length; + strcat(str->buffer, text); +} + +void CuStringAppendChar(CuString* str, char ch) +{ + char text[2]; + text[0] = ch; + text[1] = '\0'; + CuStringAppend(str, text); +} + +void CuStringAppendFormat(CuString* str, const char* format, ...) +{ + va_list argp; + char buf[HUGE_STRING_LEN]; + va_start(argp, format); + vsprintf(buf, format, argp); + va_end(argp); + CuStringAppend(str, buf); +} + +void CuStringInsert(CuString* str, const char* text, int pos) +{ + int length = strlen(text); + if (pos > str->length) + pos = str->length; + if (str->length + length + 1 >= str->size) + CuStringResize(str, str->length + length + 1 + STRING_INC); + memmove(str->buffer + pos + length, str->buffer + pos, (str->length - pos) + 1); + str->length += length; + memcpy(str->buffer + pos, text, length); +} + +/*-------------------------------------------------------------------------* + * CuTest + *-------------------------------------------------------------------------*/ + +void CuTestInit(CuTest* t, const char* name, TestFunction function) +{ + t->name = CuStrCopy(name); + t->failed = 0; + t->ran = 0; + t->message = NULL; + t->function = function; + t->jumpBuf = NULL; +} + +CuTest* CuTestNew(const char* name, TestFunction function) +{ + CuTest* tc = CU_ALLOC(CuTest); + CuTestInit(tc, name, function); + return tc; +} + +void CuTestDelete(CuTest *t) +{ + if (!t) return; + free(t->name); + free(t); +} + +void CuTestRun(CuTest* tc) +{ + jmp_buf buf; + tc->jumpBuf = &buf; + if (setjmp(buf) == 0) + { + tc->ran = 1; + (tc->function)(tc); + } + tc->jumpBuf = 0; +} + +static void CuFailInternal(CuTest* tc, const char* file, int line, CuString* string) +{ + char buf[HUGE_STRING_LEN]; + + sprintf(buf, "%s:%d: ", file, line); + CuStringInsert(string, buf, 0); + + tc->failed = 1; + tc->message = string->buffer; + if (tc->jumpBuf != 0) longjmp(*(tc->jumpBuf), 0); +} + +void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message) +{ + CuString string; + + CuStringInit(&string); + if (message2 != NULL) + { + CuStringAppend(&string, message2); + CuStringAppend(&string, ": "); + } + CuStringAppend(&string, message); + CuFailInternal(tc, file, line, &string); +} + +void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition) +{ + if (condition) return; + CuFail_Line(tc, file, line, NULL, message); +} + +void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, + const char* expected, const char* actual) +{ + CuString string; + if ((expected == NULL && actual == NULL) || + (expected != NULL && actual != NULL && + strcmp(expected, actual) == 0)) + { + return; + } + + CuStringInit(&string); + if (message != NULL) + { + CuStringAppend(&string, message); + CuStringAppend(&string, ": "); + } + CuStringAppend(&string, "expected <"); + CuStringAppend(&string, expected); + CuStringAppend(&string, "> but was <"); + CuStringAppend(&string, actual); + CuStringAppend(&string, ">"); + CuFailInternal(tc, file, line, &string); +} + +void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, + int expected, int actual) +{ + char buf[STRING_MAX]; + if (expected == actual) return; + sprintf(buf, "expected <%d> but was <%d>", expected, actual); + CuFail_Line(tc, file, line, message, buf); +} + +void CuAssertLongIntEquals_LineMsg(CuTest *tc, const char *file, int line, const char *message, + long int expected, long int actual) +{ + char buf[STRING_MAX]; + if (expected == actual) return; + sprintf(buf, "expected <%ld> but was <%ld>", expected, actual); + CuFail_Line(tc, file, line, message, buf); +} + +void CuAssertDblEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, + double expected, double actual, double delta) +{ + char buf[STRING_MAX]; + if (fabs(expected - actual) <= delta) return; + sprintf(buf, "expected <%f> but was <%f>", expected, actual); + + CuFail_Line(tc, file, line, message, buf); +} + +void CuAssertPtrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, + const void* expected, const void* actual) +{ + char buf[STRING_MAX]; + if (expected == actual) return; + sprintf(buf, "expected pointer <0x%p> but was <0x%p>", expected, actual); + CuFail_Line(tc, file, line, message, buf); +} + + +/*-------------------------------------------------------------------------* + * CuSuite + *-------------------------------------------------------------------------*/ + +void CuSuiteInit(CuSuite* testSuite) +{ + testSuite->count = 0; + testSuite->failCount = 0; + memset(testSuite->list, 0, sizeof(testSuite->list)); +} + +CuSuite* CuSuiteNew(void) +{ + CuSuite* testSuite = CU_ALLOC(CuSuite); + CuSuiteInit(testSuite); + return testSuite; +} + +void CuSuiteDelete(CuSuite *testSuite) +{ + unsigned int n; + for (n=0; n < MAX_TEST_CASES; n++) + { + if (testSuite->list[n]) + { + CuTestDelete(testSuite->list[n]); + } + } + free(testSuite); + +} + +void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase) +{ + assert(testSuite->count < MAX_TEST_CASES); + testSuite->list[testSuite->count] = testCase; + testSuite->count++; +} + +void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2) +{ + int i; + for (i = 0 ; i < testSuite2->count ; ++i) + { + CuTest* testCase = testSuite2->list[i]; + CuSuiteAdd(testSuite, testCase); + } +} + +void CuSuiteRun(CuSuite* testSuite) +{ + int i; + for (i = 0 ; i < testSuite->count ; ++i) + { + CuTest* testCase = testSuite->list[i]; + CuTestRun(testCase); + if (testCase->failed) { testSuite->failCount += 1; } + } +} + +void CuSuiteSummary(CuSuite* testSuite, CuString* summary) +{ + int i; + for (i = 0 ; i < testSuite->count ; ++i) + { + CuTest* testCase = testSuite->list[i]; + CuStringAppend(summary, testCase->failed ? "F" : "."); + } + CuStringAppend(summary, "\n\n"); +} + +void CuSuiteDetails(CuSuite* testSuite, CuString* details) +{ + int i; + int failCount = 0; + + if (testSuite->failCount == 0) + { + int passCount = testSuite->count - testSuite->failCount; + const char* testWord = passCount == 1 ? "test" : "tests"; + CuStringAppendFormat(details, "OK (%d %s)\n", passCount, testWord); + } + else + { + if (testSuite->failCount == 1) + CuStringAppend(details, "There was 1 failure:\n"); + else + CuStringAppendFormat(details, "There were %d failures:\n", testSuite->failCount); + + for (i = 0 ; i < testSuite->count ; ++i) + { + CuTest* testCase = testSuite->list[i]; + if (testCase->failed) + { + failCount++; + CuStringAppendFormat(details, "%d) %s: %s\n", + failCount, testCase->name, testCase->message); + } + } + CuStringAppend(details, "\n!!!FAILURES!!!\n"); + + CuStringAppendFormat(details, "Runs: %d ", testSuite->count); + CuStringAppendFormat(details, "Passes: %d ", testSuite->count - testSuite->failCount); + CuStringAppendFormat(details, "Fails: %d\n", testSuite->failCount); + } +} diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/CuTest.h b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/CuTest.h new file mode 100644 index 0000000..0f58592 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/CuTest.h @@ -0,0 +1,121 @@ +#ifndef CU_TEST_H +#define CU_TEST_H + +#include +#include + +#define CUTEST_VERSION "CuTest 1.5" + +/* CuString */ + +char* CuStrAlloc(int size); +char* CuStrCopy(const char* old); + +#define CU_ALLOC(TYPE) ((TYPE*) malloc(sizeof(TYPE))) + +#define HUGE_STRING_LEN 8192 +#define STRING_MAX 256 +#define STRING_INC 256 + +typedef struct +{ + int length; + int size; + char* buffer; +} CuString; + +void CuStringInit(CuString* str); +CuString* CuStringNew(void); +void CuStringRead(CuString* str, const char* path); +void CuStringAppend(CuString* str, const char* text); +void CuStringAppendChar(CuString* str, char ch); +void CuStringAppendFormat(CuString* str, const char* format, ...); +void CuStringInsert(CuString* str, const char* text, int pos); +void CuStringResize(CuString* str, int newSize); +void CuStringDelete(CuString* str); + +/* CuTest */ + +typedef struct CuTest CuTest; + +typedef void (*TestFunction)(CuTest *); + +struct CuTest +{ + char* name; + TestFunction function; + int failed; + int ran; + const char* message; + jmp_buf *jumpBuf; +}; + +void CuTestInit(CuTest* t, const char* name, TestFunction function); +CuTest* CuTestNew(const char* name, TestFunction function); +void CuTestRun(CuTest* tc); +void CuTestDelete(CuTest *t); + +/* Internal versions of assert functions -- use the public versions */ +void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message); +void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition); +void CuAssertStrEquals_LineMsg(CuTest* tc, + const char* file, int line, const char* message, + const char* expected, const char* actual); +void CuAssertIntEquals_LineMsg(CuTest* tc, + const char* file, int line, const char* message, + int expected, int actual); +void CuAssertLongIntEquals_LineMsg(CuTest *tc, + const char *file, int line, const char *message, + long int expected, long int actual); +void CuAssertDblEquals_LineMsg(CuTest* tc, + const char* file, int line, const char* message, + double expected, double actual, double delta); +void CuAssertPtrEquals_LineMsg(CuTest* tc, + const char* file, int line, const char* message, + const void* expected, const void* actual); + +/* public assert functions */ + +#define CuFail(tc, ms) CuFail_Line( (tc), __FILE__, __LINE__, NULL, (ms)) +#define CuAssert(tc, ms, cond) CuAssert_Line((tc), __FILE__, __LINE__, (ms), (cond)) +#define CuAssertTrue(tc, cond) CuAssert_Line((tc), __FILE__, __LINE__, "assert failed", (cond)) + +#define CuAssertStrEquals(tc,ex,ac) CuAssertStrEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) +#define CuAssertStrEquals_Msg(tc,ms,ex,ac) CuAssertStrEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) +#define CuAssertIntEquals(tc,ex,ac) CuAssertIntEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) +#define CuAssertIntEquals_Msg(tc,ms,ex,ac) CuAssertIntEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) +#define CuAssertLongIntEquals(tc,ex,ac) CuAssertLongIntEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) +#define CuAssertLongIntEquals_Msg(tc,ms,ex,ac) CuAssertLongIntEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) +#define CuAssertDblEquals(tc,ex,ac,dl) CuAssertDblEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac),(dl)) +#define CuAssertDblEquals_Msg(tc,ms,ex,ac,dl) CuAssertDblEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac),(dl)) +#define CuAssertPtrEquals(tc,ex,ac) CuAssertPtrEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) +#define CuAssertPtrEquals_Msg(tc,ms,ex,ac) CuAssertPtrEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) + +#define CuAssertPtrNotNull(tc,p) CuAssert_Line((tc),__FILE__,__LINE__,"null pointer unexpected",(p != NULL)) +#define CuAssertPtrNotNullMsg(tc,msg,p) CuAssert_Line((tc),__FILE__,__LINE__,(msg),(p != NULL)) + +/* CuSuite */ + +#define MAX_TEST_CASES 1024 + +#define SUITE_ADD_TEST(SUITE,TEST) CuSuiteAdd(SUITE, CuTestNew(#TEST, TEST)) + +typedef struct +{ + int count; + CuTest* list[MAX_TEST_CASES]; + int failCount; + +} CuSuite; + + +void CuSuiteInit(CuSuite* testSuite); +CuSuite* CuSuiteNew(void); +void CuSuiteDelete(CuSuite *testSuite); +void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase); +void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2); +void CuSuiteRun(CuSuite* testSuite); +void CuSuiteSummary(CuSuite* testSuite, CuString* summary); +void CuSuiteDetails(CuSuite* testSuite, CuString* details); + +#endif /* CU_TEST_H */ diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/CuTest_license.txt b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/CuTest_license.txt new file mode 100644 index 0000000..fd81689 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/CuTest_license.txt @@ -0,0 +1,38 @@ +NOTE + +The license is based on the zlib/libpng license. For more details see +http://www.opensource.org/licenses/zlib-license.html. The intent of the +license is to: + +- keep the license as simple as possible +- encourage the use of CuTest in both free and commercial applications + and libraries +- keep the source code together +- give credit to the CuTest contributors for their work + +If you ship CuTest in source form with your source distribution, the +following license document must be included with it in unaltered form. +If you find CuTest useful we would like to hear about it. + +LICENSE + +Copyright (c) 2003 Asim Jalis + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software in +a product, an acknowledgment in the product documentation would be +appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not +be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/Makefile b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/Makefile new file mode 100644 index 0000000..15a8d26 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/Makefile @@ -0,0 +1,35 @@ +CC ?= gcc + +ifndef V +QUIET_CC = @echo "CC $@"; +QUIET_MAKE_TESTS = @echo "GN Alltests.c"; +endif + +DEPS = $(shell ls ../src/*.[ch]) + +SRC = $(shell ls *.c | sed 's/AllTests.c//') +OBJ = $(SRC:.c=.o) + +INCLUDE = -I../src +CFLAGS += -pipe -ansi -pedantic -Wall -Wextra -g +LDFLAGS += + +all: check + +check: testrun + @./testrun + +testrun: AllTests.o $(OBJ) + $(QUIET_CC)$(CC) -o $@ AllTests.o $(OBJ) $(LDFLAGS) + +AllTests.o: $(OBJ) + $(QUIET_MAKE_TESTS)./make-tests.sh > AllTests.c + $(QUIET_CC)$(CC) -c -o AllTests.o AllTests.c $(CFLAGS) $(INCLUDE) + +%.o: %.c $(DEPS) + $(QUIET_CC)$(CC) -c -o $@ $< $(CFLAGS) $(INCLUDE) + +clean veryclean: + rm -rf AllTests.c + rm -rf $(OBJ) AllTests.o + rm -rf testrun diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/make-tests.sh b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/make-tests.sh new file mode 100644 index 0000000..f2a3f2a --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/make-tests.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash + +# Auto generate single AllTests file for CuTest. +# Searches through all *.c files in the current directory. +# Prints to stdout. +# Author: Asim Jalis +# Date: 01/08/2003 + +if test $# -eq 0 ; then FILES=*.c ; else FILES=$* ; fi + +echo ' + +/* This is auto-generated code. Edit at your own peril. */ +#include +#include + +#include "CuTest.h" + +' + +cat $FILES | grep '^void Test' | + sed -e 's/(.*$//' \ + -e 's/$/(CuTest*);/' \ + -e 's/^/extern /' + +echo \ +' + +void RunAllTests(void) +{ + CuString *output = CuStringNew(); + CuSuite* suite = CuSuiteNew(); + +' +cat $FILES | grep '^void Test' | + sed -e 's/^void //' \ + -e 's/(.*$//' \ + -e 's/^/ SUITE_ADD_TEST(suite, /' \ + -e 's/$/);/' + +echo \ +' + CuSuiteRun(suite); + CuSuiteSummary(suite, output); + CuSuiteDetails(suite, output); + printf("%s\n", output->buffer); + CuStringDelete(output); + CuSuiteDelete(suite); +} + +int main(void) +{ + RunAllTests(); + return 0; +} +' diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/ressources/bad_ini/ends_well.ini b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/ressources/bad_ini/ends_well.ini new file mode 100644 index 0000000..3f920c7 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/ressources/bad_ini/ends_well.ini @@ -0,0 +1,6 @@ +# +# This dict contains an error but ends up with a correct entry +# +[section] +error is here +a = b diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/ressources/bad_ini/twisted-errors.ini b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/ressources/bad_ini/twisted-errors.ini new file mode 100644 index 0000000..4dc3bbe --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/ressources/bad_ini/twisted-errors.ini @@ -0,0 +1,9 @@ +# +# All of these should trigger syntax errors +# +[section] +hello +world +hello \ +world +a + b ; diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/ressources/bad_ini/twisted-ofkey.ini b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/ressources/bad_ini/twisted-ofkey.ini new file mode 100644 index 0000000..4f2e72e --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/ressources/bad_ini/twisted-ofkey.ini @@ -0,0 +1,66 @@ +# Stress testing buffers for overflows +[long] +# Shitload key size +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=1 + diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/ressources/bad_ini/twisted-ofval.ini b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/ressources/bad_ini/twisted-ofval.ini new file mode 100644 index 0000000..2a3cedf --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/ressources/bad_ini/twisted-ofval.ini @@ -0,0 +1,56 @@ +# Shitload data size +[long] +a=\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\ +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890; + diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/ressources/good_ini/empty.ini b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/ressources/good_ini/empty.ini new file mode 100644 index 0000000..e69de29 diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/ressources/good_ini/spaced.ini b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/ressources/good_ini/spaced.ini new file mode 100644 index 0000000..8e78e3b --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/ressources/good_ini/spaced.ini @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/ressources/good_ini/spaced2.ini b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/ressources/good_ini/spaced2.ini new file mode 100644 index 0000000..2acbd74 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/ressources/good_ini/spaced2.ini @@ -0,0 +1,20 @@ + +# spaced2.ini + +[blanks] + + + + + + + + + + + +a=1 +b=1; +c=1; comment +d=1# comment + \ No newline at end of file diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/ressources/good_ini/twisted.ini b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/ressources/good_ini/twisted.ini new file mode 100644 index 0000000..86e549f --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/ressources/good_ini/twisted.ini @@ -0,0 +1,131 @@ +# +# Twisted.ini +# This file is meant for regression tests + +# Different blank settings around the equal sign +[blanks] +a=1 +b=1; +c=1; comment +d=1# comment + +e =1 +f =1; +g =1; comment +h =1# comment + +i= 1 +j= 1; +k= 1; comment +l= 1# comment + +m = 1 +n = 1; +o = 1; comment +p = 1# comment + +q=1 ; +r=1 ; comment +s=1 ;comment +t=1 #comment + +# Empty values +[empty] +a = '' +b = "" + +c = '' ; +d = "" ; + +e = '' ; comment +f = "" ; comment + +g = +h = ; +i = ; comment +j = # comment + +k= +l=; +m=;comment +n=# + +# Peculiar values +[peculiar] +a=';'; +b='#'# +c=';';comment +d='#'#comment +e=\; +f=\# +g=\;comment +h=\#comment +i=;; +j=## +k=;;;;;;;;;; +l=########## + +# Quotes +[quotes] +s1=' +s2='' +s3=''' +s4='''' + +d1=" +d2="" +d3=""" +d4="""" + +m1='"' +m2="'" + +h1=hello'world +h2='hello'world +h3='hello'world' + +h4=hello"world +h5="hello"world +h6="hello"world" + +# Section names +[a] +[ b] +[c ] +[ d ] +[ begin end ] +[ open[ ] + +# Multi-line inputs +[multi] +a = begin\ +end +b = begin \ +end +c = begin \ + end +d = 1\ +2\ +3\ +4 +e = 1 \ + 2 \ + 3 \ + 4 +f = 1 ; \ +hidden = because of the preceding backslash multi-lining the comment ; +visible = 1 +g = 1 #\ +and now this comment is hidden too \ +and this one too +h = 1 +multi \ +line \ +key = 1 +multi \ +line \ +key = \ +multi \ +line \ +value ; +# end of file diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/test_dictionary.c b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/test_dictionary.c new file mode 100644 index 0000000..f89f1c1 --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/test_dictionary.c @@ -0,0 +1,237 @@ +#include +#include + +#include "CuTest.h" + +/* We need to directly insert the .c file in order to test the */ +/* static functions as well */ +#include "dictionary.c" + +void Test_xstrdup(CuTest *tc) +{ + size_t i; + char *dup_str; + const char *strings[] = { + "", + "test", + " " + }; + char *string_very_long; + + /* NULL test */ + CuAssertPtrEquals(tc, NULL, xstrdup(NULL)); + + for (i = 0 ; i < sizeof(strings) / sizeof(char *) ; ++i) { + dup_str = xstrdup(strings[i]); + CuAssertStrEquals(tc, strings[i], dup_str); + free(dup_str); + } + + /* test a overflowing string */ + string_very_long = (char*) malloc(10 * 1024); + memset(string_very_long, '#', 10 * 1024); + string_very_long[10 * 1024 - 1] = '\0'; + dup_str = xstrdup(string_very_long); + CuAssertStrEquals(tc, string_very_long, dup_str); + + free(string_very_long); + free(dup_str); +} + +void Test_dictionary_grow(CuTest *tc) +{ + unsigned i; + dictionary *dic; + + dic = dictionary_new(DICTMINSZ); + CuAssertPtrNotNull(tc, dic); + CuAssertIntEquals(tc, 0, dic->n); + CuAssertIntEquals(tc, DICTMINSZ, dic->size); + + for (i = 1 ; i < 10 ; ++i) { + CuAssertIntEquals(tc, 0, dictionary_grow(dic)); + CuAssertIntEquals(tc, 0, dic->n); + CuAssertIntEquals(tc, (1 << i) * DICTMINSZ, dic->size); + } +} + +void Test_dictionary_hash(CuTest *tc) +{ + /* NULL test */ + CuAssertIntEquals(tc, 0, dictionary_hash(NULL)); +} + +void Test_dictionary_growing(CuTest *tc) +{ + int i, j; + char sec_name[32]; + char key_name[64]; + dictionary *dic; + + dic = dictionary_new(DICTMINSZ); + CuAssertPtrNotNull(tc, dic); + CuAssertIntEquals(tc, 0, dic->n); + + /* Makes the dictionary grow */ + for (i = 1 ; i < 101; ++i) { + sprintf(sec_name, "sec%d", i); + CuAssertIntEquals(tc, 0, dictionary_set(dic, sec_name, "")); + for (j = 1 ; j < 11; ++j) { + sprintf(key_name, "%s:key%d", sec_name, j); + CuAssertIntEquals(tc, 0, dictionary_set(dic, key_name, "dummy_value")); + CuAssertIntEquals(tc, i + (i - 1) * 10 + j, dic->n); + } + } + + /* Shrink the dictionary */ + for (i = 100 ; i > 0; --i) { + sprintf(sec_name, "sec%d", i); + for (j = 10 ; j > 0; --j) { + sprintf(key_name, "%s:key%d", sec_name, j); + dictionary_unset(dic, key_name); + } + dictionary_unset(dic, sec_name); + CuAssertIntEquals(tc, (i - 1) * (11), dic->n); + } + + dictionary_del(dic); +} + +static char *get_dump(dictionary *d) +{ + FILE *fd; + char *dump_buff; + int dump_size; + + /* Dump the dictionary in temporary file */ + fd = tmpfile(); + if (fd == NULL) + return NULL; + dictionary_dump(d, fd); + + /* Retrieve the dump file */ + dump_size = ftell(fd); + if (dump_size == -1) { + fclose(fd); + return NULL; + } + rewind(fd); + + dump_buff = (char*) calloc(1, dump_size + 1); + if (dump_buff == NULL) { + fclose(fd); + return NULL; + } + if (fread(dump_buff, 1, dump_size, fd) != (size_t)dump_size) { + fclose(fd); + return NULL; + } + + fclose(fd); + return dump_buff; +} + +void Test_dictionary_unset(CuTest *tc) +{ + int i, j; + char sec_name[32]; + char key_name[64]; + dictionary *dic1; + dictionary *dic2; + char *dic1_dump; + char *dic2_dump; + + /* try dummy unsets */ + dictionary_unset(NULL, NULL); + dictionary_unset(NULL, key_name); + + /* Generate two similar dictionaries */ + dic1 = dictionary_new(DICTMINSZ); + CuAssertPtrNotNull(tc, dic1); + for (i = 1 ; i < 10; ++i) { + sprintf(sec_name, "sec%d", i); + dictionary_set(dic1, sec_name, ""); + for (j = 1 ; j < 10; ++j) { + sprintf(key_name, "%s:key%d", sec_name, j); + dictionary_set(dic1, key_name, "dummy_value"); + } + } + dic2 = dictionary_new(DICTMINSZ); + CuAssertPtrNotNull(tc, dic2); + for (i = 1 ; i < 10; ++i) { + sprintf(sec_name, "sec%d", i); + dictionary_set(dic2, sec_name, ""); + for (j = 1 ; j < 10; ++j) { + sprintf(key_name, "%s:key%d", sec_name, j); + dictionary_set(dic2, key_name, "dummy_value"); + } + } + + /* Make sure the dictionaries are the same */ + dic1_dump = get_dump(dic1); + dic2_dump = get_dump(dic2); + CuAssertStrEquals(tc, dic1_dump, dic2_dump); + free(dic1_dump); + free(dic2_dump); + + /* Those tests should not change the dictionary */ + dictionary_unset(dic2, NULL); + dictionary_unset(dic2, "bad_key"); + + /* dic1 and dic2 must still be the same */ + dic1_dump = get_dump(dic1); + dic2_dump = get_dump(dic2); + CuAssertStrEquals(tc, dic1_dump, dic2_dump); + free(dic1_dump); + free(dic2_dump); +} + +void Test_dictionary_dump(CuTest *tc) +{ + int i, j; + char sec_name[32]; + char key_name[64]; + dictionary *dic; + char *dump_buff; + const char dump_real[] = "\ + sec1\t[]\n\ + sec1:key1\t[dummy_value]\n\ + sec1:key2\t[dummy_value]\n\ + sec1:key3\t[dummy_value]\n\ + sec1:key4\t[dummy_value]\n\ + sec2\t[]\n\ + sec2:key1\t[dummy_value]\n\ + sec2:key2\t[dummy_value]\n\ + sec2:key3\t[dummy_value]\n\ + sec2:key4\t[dummy_value]\n\ +"; + + dic = dictionary_new(DICTMINSZ); + CuAssertPtrNotNull(tc, dic); + + /* Try dummy values */ + dictionary_dump(NULL, NULL); + dictionary_dump(dic, NULL); + + /* Try with empty dictionary first */ + dump_buff = get_dump(dic); + CuAssertStrEquals(tc, "empty dictionary\n", dump_buff); + free(dump_buff); + + /* Populate the dictionary */ + for (i = 1 ; i < 3; ++i) { + sprintf(sec_name, "sec%d", i); + dictionary_set(dic, sec_name, ""); + for (j = 1 ; j < 5; ++j) { + sprintf(key_name, "%s:key%d", sec_name, j); + dictionary_set(dic, key_name, "dummy_value"); + } + } + + /* Check the dump file */ + dump_buff = get_dump(dic); + CuAssertStrEquals(tc, dump_real, dump_buff); + free(dump_buff); + + dictionary_del(dic); +} diff --git a/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/test_iniparser.c b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/test_iniparser.c new file mode 100644 index 0000000..b7cd5fc --- /dev/null +++ b/src/device/soc/hisilicon/hi3516dv300/sdk_linux/sample/taurus/smart_vendor_ai/third_party/src/iniparser/test/test_iniparser.c @@ -0,0 +1,698 @@ +#include +#include +#include +#include +#include +#include + +#include "CuTest.h" +#include "dictionary.h" + +/* We need to directly insert the .c file in order to test the */ +/* static functions as well */ +#include "iniparser.c" + +#define GOOD_INI_PATH "ressources/good_ini" +#define BAD_INI_PATH "ressources/bad_ini" + + +/* Tool function to create and populate a generic non-empty dictionary */ +static dictionary * generate_dictionary(unsigned sections, unsigned entries_per_section) +{ + unsigned i, j ; + dictionary * dic; + char sec_name[32]; + char key_name[64]; + char key_value[32]; + + dic = dictionary_new(sections + sections * entries_per_section); + if (dic == NULL) + return NULL; + + /* Insert the sections */ + for (i = 0; i < sections; ++i) { + sprintf(sec_name, "sec%d", i); + dictionary_set(dic, sec_name, ""); + for (j = 0; j < entries_per_section; ++j) { + /* Populate the section with the entries */ + sprintf(key_name, "%s:key%d", sec_name, j); + sprintf(key_value, "value-%d/%d", i, j); + dictionary_set(dic, key_name, key_value); + } + } + + return dic; +} + +void Test_iniparser_strlwc(CuTest *tc) +{ + char out_buffer[128]; + + /* NULL ptr as input */ + CuAssertPtrEquals(tc, NULL, strlwc(NULL, NULL, 0)); + CuAssertPtrEquals(tc, NULL, strlwc(NULL, out_buffer, sizeof (out_buffer))); + CuAssertPtrEquals(tc, NULL, strlwc("", NULL, sizeof (out_buffer))); + CuAssertPtrEquals(tc, NULL, strlwc("", out_buffer, 0)); + CuAssertPtrEquals(tc, NULL, strlwc(NULL, NULL, 0)); + + /* empty string */ + CuAssertStrEquals(tc, "", strlwc("", out_buffer, sizeof (out_buffer))); + + CuAssertStrEquals(tc, " ", strlwc(" ", out_buffer, sizeof (out_buffer))); + CuAssertStrEquals(tc, "test", strlwc("test", out_buffer, sizeof (out_buffer))); + CuAssertStrEquals(tc, "test", strlwc("TEST", out_buffer, sizeof (out_buffer))); + CuAssertStrEquals(tc, "test", strlwc("TeSt", out_buffer, sizeof (out_buffer))); + CuAssertStrEquals(tc, "test test", + strlwc("TEST TEST", out_buffer, sizeof (out_buffer))); + CuAssertStrEquals(tc, "very long string !!!!!!!", + strlwc("very long string !!!!!!!", out_buffer, sizeof (out_buffer))); + CuAssertStrEquals(tc, "cutted string", strlwc("cutted string<---here", out_buffer, 14)); + + /* test using same buffer as input and output */ + strcpy(out_buffer, "OVERWRITE ME !"); + CuAssertPtrNotNull(tc, strlwc(out_buffer, out_buffer, sizeof(out_buffer))); + CuAssertStrEquals(tc, "overwrite me !", out_buffer); +} + +void Test_iniparser_strstrip(CuTest *tc) +{ + /* First element in the array is the expected stripping result */ + const char *strings_empty[] = { + "", + " ", + "\n\n\n\n", + "\t\t\t\t", + "\n \t\n\t\n " + }; + const char *strings_test[] = { + "test", + "test ", + "test ", + " test", + " test ", + "\ttest\t", + "\ttest\n" + + }; + const char *test_with_spaces = "I am a test with\tspaces."; + char stripped[ASCIILINESZ+1]; + char error_msg[1060]; + unsigned i; + + /* NULL ptr as input */ + strstrip(NULL); + + /* empty string */ + for (i = 0 ; i < sizeof (strings_empty) / sizeof (char *) ; ++i) { + strcpy(stripped, strings_empty[i]); + strstrip(stripped); + sprintf(error_msg, "Bad stripping : strstrip(\"%s\") ==> \"%s\"", + strings_empty[i], stripped); + CuAssertStrEquals_Msg(tc, error_msg, stripped, strings_empty[0]); + } + + /* test string */ + for (i = 0 ; i < sizeof (strings_test) / sizeof (char *) ; ++i) { + strcpy(stripped, strings_test[i]); + strstrip(stripped); + sprintf(error_msg, "Bad stripping : strstrip(\"%s\") ==> \"%s\"", + strings_test[i], stripped); + CuAssertStrEquals_Msg(tc, error_msg, strings_test[0], stripped); + } + strcpy(stripped, "."); + strstrip(stripped); + CuAssertStrEquals(tc, ".", stripped); + + /* string containing spaces */ + strcpy(stripped, test_with_spaces); + strstrip(stripped); + CuAssertStrEquals(tc, test_with_spaces, stripped); +} + +void Test_iniparser_getnsec(CuTest *tc) +{ + int i; + char sec_name[32]; + dictionary *dic; + + /* NULL test */ + CuAssertIntEquals(tc, -1, iniparser_getnsec(NULL)); + + /* Empty dictionary */ + dic = dictionary_new(10); + CuAssertIntEquals(tc, 0, iniparser_getnsec(dic)); + dictionary_del(dic); + + /* Regular dictionary */ + dic = generate_dictionary(512, 0); + CuAssertIntEquals(tc, 512, iniparser_getnsec(dic)); + + /* Check after removing sections */ + for (i = 1; i < 512; ++i) { + sprintf(sec_name, "sec%d", i); + dictionary_unset(dic, sec_name); + CuAssertIntEquals(tc, 512 - i, iniparser_getnsec(dic)); + } + dictionary_del(dic); + + /* Mix sections and regular keys */ + dic = generate_dictionary(10, 512); + CuAssertIntEquals(tc, 10, iniparser_getnsec(dic)); + dictionary_del(dic); +} + +void Test_iniparser_getsecname(CuTest *tc) +{ + unsigned i; + char sec_name[32]; + dictionary *dic; + /* NULL test */ + CuAssertTrue(tc, iniparser_getsecname(NULL, 0) == NULL); + + /* Empty dictionary */ + dic = dictionary_new(10); + CuAssertPtrEquals(tc, NULL, iniparser_getsecname(dic, 0)); + dictionary_del(dic); + + /* Sections without entries dictionary */ + dic = generate_dictionary(100, 0); + for (i = 0; i < 100; ++i) { + sprintf(sec_name, "sec%d", i); + CuAssertStrEquals(tc, sec_name, iniparser_getsecname(dic, i)); + } + dictionary_del(dic); + + /* Generic dictionary */ + dic = generate_dictionary(10, 100); + for (i = 0; i < 10; ++i) { + sprintf(sec_name, "sec%d", i); + CuAssertStrEquals(tc, sec_name, iniparser_getsecname(dic, i)); + } + dictionary_del(dic); +} + +void Test_iniparser_getseckeys(CuTest *tc) +{ + unsigned i; + char key_name[64]; + dictionary *dic; + int nkeys; + const char * keys[10]; /* At most 10 elements per section */ + /* NULL test */ + CuAssertPtrEquals(tc, NULL, iniparser_getseckeys(NULL, NULL, NULL)); + CuAssertPtrEquals(tc, NULL, iniparser_getseckeys(NULL, "dummy", NULL)); + CuAssertPtrEquals(tc, NULL, iniparser_getseckeys(NULL, "dummy", keys)); + + /* Empty dictionary */ + dic = dictionary_new(10); + CuAssertPtrEquals(tc, NULL, iniparser_getseckeys(dic, NULL, keys)); + CuAssertPtrEquals(tc, NULL, iniparser_getseckeys(dic, "dummy", keys)); + dictionary_del(dic); + + /* Generic dictionary */ + + dic = generate_dictionary(100, 10); + CuAssertPtrEquals(tc, NULL, iniparser_getseckeys(dic, NULL, keys)); + CuAssertPtrEquals(tc, NULL, iniparser_getseckeys(dic, "dummy", keys)); + CuAssertPtrEquals(tc, NULL, iniparser_getseckeys(dic, "sec0", NULL)); + nkeys = iniparser_getsecnkeys(dic, "sec42"); + CuAssertIntEquals(tc, nkeys, 10); + CuAssertPtrEquals(tc, keys, iniparser_getseckeys(dic, "sec42", keys)); + for (i = 0; i < 10; ++i) { + sprintf(key_name, "sec42:key%d", i); + CuAssertStrEquals(tc, key_name, keys[i]); + } + + /* Remove some keys to make the dictionary more real */ + dictionary_unset(dic, "sec42"); + dictionary_unset(dic, "sec99:key9"); + dictionary_unset(dic, "sec0:key0"); + dictionary_unset(dic, "sec0:key1"); + dictionary_unset(dic, "sec0:key2"); + + CuAssertPtrEquals(tc, NULL, iniparser_getseckeys(dic, "sec42", keys)); + nkeys = iniparser_getsecnkeys(dic, "Sec99"); + CuAssertIntEquals(tc, nkeys, 9); + CuAssertPtrEquals(tc, keys, iniparser_getseckeys(dic, "Sec99", keys)); + for (i = 0; i < 9; ++i) { + sprintf(key_name, "sec99:key%d", i); + CuAssertStrEquals(tc, key_name, keys[i]); + } + + nkeys = iniparser_getsecnkeys(dic, "sec0"); + CuAssertIntEquals(tc, nkeys, 7); + CuAssertPtrEquals(tc, keys, iniparser_getseckeys(dic, "sec0", keys)); + for (i = 0; i < 7; ++i) { + sprintf(key_name, "sec0:key%d", i + 3); + CuAssertStrEquals(tc, key_name, keys[i]); + } + + dictionary_del(dic); +} + +void Test_iniparser_getstring(CuTest *tc) +{ + dictionary *dic; + /* NULL test */ + CuAssertPtrEquals(tc, NULL, iniparser_getstring(NULL, NULL, NULL)); + CuAssertPtrEquals(tc, NULL, iniparser_getstring(NULL, "dummy", NULL)); + + /* Check the def return element */ + dic = dictionary_new(10); + CuAssertPtrEquals(tc, NULL, iniparser_getstring(dic, "dummy", NULL)); + CuAssertStrEquals(tc, "def", iniparser_getstring(dic, NULL, "def")); + CuAssertStrEquals(tc, "def", iniparser_getstring(dic, "dummy", "def")); + dictionary_del(dic); + + /* Generic dictionary */ + dic = generate_dictionary(100, 10); + CuAssertStrEquals(tc, "value-0/0", + iniparser_getstring(dic, "sec0:key0", NULL)); + CuAssertStrEquals(tc, "value-42/5", + iniparser_getstring(dic, "sec42:key5", NULL)); + CuAssertStrEquals(tc, "value-99/9", + iniparser_getstring(dic, "sec99:key9", NULL)); + dictionary_del(dic); +} + +void Test_iniparser_getint(CuTest *tc) +{ + unsigned i; + char key_name[64]; + dictionary *dic; + const struct { int num; const char *value; } good_val[] = { + { 0, "0" }, + { 1, "1" }, + { -1, "-1" }, + { 1000, "1000" }, + { 077, "077" }, + { -01000, "-01000" }, + { 0xFFFF, "0xFFFF" }, + { -0xFFFF, "-0xFFFF" }, + { 0x4242, "0x4242" }, + { 0, NULL} /* must be last */ + }; + const char *bad_val[] = { + "", + "notanumber", + "0x", + "k2000", + " ", + "0xG1" + }; + /* NULL test */ + CuAssertIntEquals(tc, -42, iniparser_getint(NULL, NULL, -42)); + CuAssertIntEquals(tc, -42, iniparser_getint(NULL, "dummy", -42)); + + /* Check the def return element */ + dic = dictionary_new(10); + CuAssertIntEquals(tc, 42, iniparser_getint(dic, "dummy", 42)); + CuAssertIntEquals(tc, 0xFFFF, iniparser_getint(dic, NULL, 0xFFFF)); + CuAssertIntEquals(tc, -0xFFFF, iniparser_getint(dic, "dummy", -0xFFFF)); + dictionary_del(dic); + + /* Generic dictionary */ + dic = dictionary_new(10); + for (i = 0; good_val[i].value != NULL; ++i) { + sprintf(key_name, "int:value%d", i); + dictionary_set(dic, key_name, good_val[i].value); + } + for (i = 0; good_val[i].value != NULL; ++i) { + sprintf(key_name, "int:value%d", i); + CuAssertIntEquals(tc, good_val[i].num, + iniparser_getint(dic, key_name, 0)); + } + dictionary_del(dic); + + /* Test bad names */ + dic = dictionary_new(10); + for (i = 0; i < sizeof (bad_val) / sizeof (char *); ++i) { + sprintf(key_name, "int:bad%d", i); + dictionary_set(dic, key_name, bad_val[i]); + } + for (i = 0; i < sizeof (bad_val) / sizeof (char *); ++i) { + sprintf(key_name, "int:bad%d", i); + CuAssertIntEquals(tc, 0, + iniparser_getint(dic, key_name, 0)); + } + dictionary_del(dic); +} + +void Test_iniparser_getlongint(CuTest *tc) +{ + unsigned i; + char key_name[64]; + dictionary *dic; + const struct { long int num; const char *value; } good_val[] = { + { 0, "0" }, + { 1, "1" }, + { -1, "-1" }, + { 1000, "1000" }, + { 077, "077" }, + { -01000, "-01000" }, + { 0x7FFFFFFFFFFFFFFF, "0x7FFFFFFFFFFFFFFF" }, + { -0x7FFFFFFFFFFFFFFF, "-0x7FFFFFFFFFFFFFFF" }, + { 0x4242, "0x4242" }, + { 0, NULL} /* must be last */ + }; + const char *bad_val[] = { + "", + "notanumber", + "0x", + "k2000", + " ", + "0xG1" + }; + /* NULL test */ + CuAssertLongIntEquals(tc, -42, iniparser_getlongint(NULL, NULL, -42)); + CuAssertLongIntEquals(tc, -42, iniparser_getlongint(NULL, "dummy", -42)); + + /* Check the def return element */ + dic = dictionary_new(10); + CuAssertLongIntEquals(tc, 42, iniparser_getlongint(dic, "dummy", 42)); + CuAssertLongIntEquals(tc, 0x7FFFFFFFFFFFFFFF, iniparser_getlongint(dic, NULL, 0x7FFFFFFFFFFFFFFF)); + CuAssertLongIntEquals(tc, -0x7FFFFFFFFFFFFFFF, iniparser_getlongint(dic, "dummy", -0x7FFFFFFFFFFFFFFF)); + dictionary_del(dic); + + /* Generic dictionary */ + dic = dictionary_new(10); + for (i = 0; good_val[i].value != NULL; ++i) { + sprintf(key_name, "longint:value%d", i); + dictionary_set(dic, key_name, good_val[i].value); + } + for (i = 0; good_val[i].value != NULL; ++i) { + sprintf(key_name, "longint:value%d", i); + CuAssertLongIntEquals(tc, good_val[i].num, + iniparser_getlongint(dic, key_name, 0)); + } + dictionary_del(dic); + + /* Test bad names */ + dic = dictionary_new(10); + for (i = 0; i < sizeof (bad_val) / sizeof (char *); ++i) { + sprintf(key_name, "longint:bad%d", i); + dictionary_set(dic, key_name, bad_val[i]); + } + for (i = 0; i < sizeof (bad_val) / sizeof (char *); ++i) { + sprintf(key_name, "longint:bad%d", i); + CuAssertLongIntEquals(tc, 0, + iniparser_getlongint(dic, key_name, 0)); + } + dictionary_del(dic); +} + +void Test_iniparser_getdouble(CuTest *tc) +{ + dictionary *dic; + + /* NULL test */ + CuAssertDblEquals(tc, -42, iniparser_getdouble(NULL, NULL, -42), 0); + CuAssertDblEquals(tc, 4.2, iniparser_getdouble(NULL, "dummy", 4.2), 0); + + /* Check the def return element */ + dic = dictionary_new(10); + CuAssertDblEquals(tc, 3.1415, iniparser_getdouble(dic, "dummy", 3.1415), 0); + CuAssertDblEquals(tc, 0xFFFFFFFF, iniparser_getdouble(dic, NULL, 0xFFFFFFFF), 0); + CuAssertDblEquals(tc, -0xFFFFFFFF, iniparser_getdouble(dic, "dummy", -0xFFFFFFFF), 0); + + /* Insert some values */ + dictionary_set(dic, "double", ""); + dictionary_set(dic, "double:good0", "0"); + dictionary_set(dic, "double:good1", "-0"); + dictionary_set(dic, "double:good2", "1.0"); + dictionary_set(dic, "double:good3", "3.1415"); + dictionary_set(dic, "double:good4", "6.6655957"); + dictionary_set(dic, "double:good5", "-123456789.123456789"); + + /* Add dummy stuff too */ + dictionary_set(dic, "double:bad0", "foo"); + + /* Get back the values */ + CuAssertDblEquals(tc, 0, iniparser_getdouble(dic, "double:good0", 0xFF), 0); + CuAssertDblEquals(tc, 0, iniparser_getdouble(dic, "double:good1", 0xFF), 0); + CuAssertDblEquals(tc, 1.0, iniparser_getdouble(dic, "double:good2", 0xFF), 0); + CuAssertDblEquals(tc, 3.1415, iniparser_getdouble(dic, "double:good3", 0xFF), 0); + CuAssertDblEquals(tc, 6.6655957, iniparser_getdouble(dic, "double:good4", 0xFF), 0); + CuAssertDblEquals(tc, -123456789.123456789, + iniparser_getdouble(dic, "double:good5", 0xFF), 0); + + CuAssertDblEquals(tc, 0, iniparser_getdouble(dic, "double:bad0", 42.42), 0); + + dictionary_del(dic); +} + +void Test_iniparser_getboolean(CuTest *tc) +{ + unsigned i; + char key_name[64]; + + dictionary *dic; + const char *token_true[] = { + "1", + "true", + "t", + "TRUE", + "T", + "yes", + "y", + "YES" + "Y", + NULL + }; + const char *token_false[] = { + "0", + "false", + "f", + "FALSE", + "F", + "no", + "n", + "NO", + "N", + NULL + }; + + /* NULL test */ + CuAssertIntEquals(tc, 1, iniparser_getboolean(NULL, NULL, 1)); + CuAssertIntEquals(tc, 1, iniparser_getboolean(NULL, "dummy", 1)); + + /* Check the def return element */ + dic = dictionary_new(10); + CuAssertIntEquals(tc, 1, iniparser_getboolean(dic, "dummy", 1)); + CuAssertIntEquals(tc, 0, iniparser_getboolean(dic, NULL, 0)); + CuAssertIntEquals(tc, 1, iniparser_getboolean(dic, "dummy", 1)); + + for (i = 0; token_true[i] != NULL; ++i) { + sprintf(key_name, "bool:true%d", i); + iniparser_set(dic, key_name, token_true[i]); + } + for (i = 0; token_false[i] != NULL; ++i) { + sprintf(key_name, "bool:false%d", i); + iniparser_set(dic, key_name, token_false[i]); + } + + for (i = 0; token_true[i] != NULL; ++i) { + sprintf(key_name, "bool:true%d", i); + CuAssertIntEquals(tc, 1, iniparser_getboolean(dic, key_name, 0)); + } + for (i = 0; token_false[i] != NULL; ++i) { + sprintf(key_name, "bool:false%d", i); + CuAssertIntEquals(tc, 0, iniparser_getboolean(dic, key_name, 1)); + } + + /* Test bad boolean */ + iniparser_set(dic, "bool:bad0", ""); + iniparser_set(dic, "bool:bad1", "m'kay"); + iniparser_set(dic, "bool:bad2", "42"); + iniparser_set(dic, "bool:bad3", "_true"); + CuAssertIntEquals(tc, 0xFF, iniparser_getboolean(dic, "bool:bad0", 0xFF)); + CuAssertIntEquals(tc, 0xFF, iniparser_getboolean(dic, "bool:bad1", 0xFF)); + CuAssertIntEquals(tc, 0xFF, iniparser_getboolean(dic, "bool:bad2", 0xFF)); + CuAssertIntEquals(tc, 0xFF, iniparser_getboolean(dic, "bool:bad3", 0xFF)); + + dictionary_del(dic); +} + +void Test_iniparser_line(CuTest *tc) +{ + char section [ASCIILINESZ+1] ; + char key [ASCIILINESZ+1] ; + char val [ASCIILINESZ+1] ; + + /* Test empty line */ + CuAssertIntEquals(tc, LINE_EMPTY, iniparser_line("", section, key, val)); + CuAssertIntEquals(tc, LINE_EMPTY, iniparser_line(" ", section, key, val)); + CuAssertIntEquals(tc, LINE_EMPTY, iniparser_line("\t", section, key, val)); + + /* Test valid syntax */ + CuAssertIntEquals(tc, LINE_SECTION, iniparser_line("[s]", section, key, val)); + CuAssertStrEquals(tc, "s", section); + + CuAssertIntEquals(tc, LINE_SECTION, iniparser_line("[ section ]", section, key, val)); + CuAssertStrEquals(tc, "section", section); + + CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("k=1", section, key, val)); + CuAssertStrEquals(tc, "k", key); + CuAssertStrEquals(tc, "1", val); + + CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("key = 0x42", section, key, val)); + CuAssertStrEquals(tc, "key", key); + CuAssertStrEquals(tc, "0x42", val); + + CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("key= value with spaces", section, key, val)); + CuAssertStrEquals(tc, "key", key); + CuAssertStrEquals(tc, "value with spaces", val); + + CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("k =_!<>''", section, key, val)); + CuAssertStrEquals(tc, "k", key); + CuAssertStrEquals(tc, "_!<>''", val); + + CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("empty_value =", section, key, val)); + CuAssertStrEquals(tc, "empty_value", key); + CuAssertStrEquals(tc, "", val); + + CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("empty_value = \t\n", section, key, val)); + CuAssertStrEquals(tc, "empty_value", key); + CuAssertStrEquals(tc, "", val); + + CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("key =\tval # comment", section, key, val)); + CuAssertStrEquals(tc, "key", key); + CuAssertStrEquals(tc, "val", val); + + CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("key \n\n = \n val", section, key, val)); + CuAssertStrEquals(tc, "key", key); + CuAssertStrEquals(tc, "val", val); + + CuAssertIntEquals(tc, LINE_COMMENT, iniparser_line(";comment", section, key, val)); + CuAssertIntEquals(tc, LINE_COMMENT, iniparser_line(" # comment", section, key, val)); + + CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("key = \" do_not_strip \"", section, key, val)); + CuAssertStrEquals(tc, "key", key); + CuAssertStrEquals(tc, " do_not_strip ", val); + + CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("key = ' '", section, key, val)); + CuAssertStrEquals(tc, "key", key); + CuAssertStrEquals(tc, " ", val); + + CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("key = \"\"", section, key, val)); + CuAssertStrEquals(tc, "key", key); + CuAssertStrEquals(tc, "", val); + + CuAssertIntEquals(tc, LINE_VALUE, iniparser_line("key = ''", section, key, val)); + CuAssertStrEquals(tc, "key", key); + CuAssertStrEquals(tc, "", val); + + /* Test syntax error */ + CuAssertIntEquals(tc, LINE_ERROR, iniparser_line("empty_value", section, key, val)); + CuAssertIntEquals(tc, LINE_ERROR, iniparser_line("not finished\\", section, key, val)); + CuAssertIntEquals(tc, LINE_ERROR, iniparser_line("0x42 / 0b101010", section, key, val)); + +} + +void Test_iniparser_load(CuTest *tc) +{ + DIR *dir; + struct dirent *curr; + struct stat curr_stat; + dictionary *dic; + char ini_path[276]; + + /* Dummy tests */ + dic = iniparser_load("/you/shall/not/path"); + CuAssertPtrEquals(tc, NULL, dic); + + /* Test all the good .ini files */ + dir = opendir(GOOD_INI_PATH); + CuAssertPtrNotNullMsg(tc, "Cannot open good .ini conf directory", dir); + for (curr = readdir(dir); curr != NULL; curr = readdir(dir)) { + sprintf(ini_path, "%s/%s", GOOD_INI_PATH, curr->d_name); + stat(ini_path, &curr_stat); + if (S_ISREG(curr_stat.st_mode)) { + dic = iniparser_load(ini_path); + CuAssertPtrNotNullMsg(tc, ini_path, dic); + dictionary_del(dic); + } + } + closedir(dir); + + /* Test all the bad .ini files */ + dir = opendir(BAD_INI_PATH); + CuAssertPtrNotNullMsg(tc, "Cannot open bad .ini conf directory", dir); + for (curr = readdir(dir); curr != NULL; curr = readdir(dir)) { + sprintf(ini_path, "%s/%s", BAD_INI_PATH, curr->d_name); + stat(ini_path, &curr_stat); + if (S_ISREG(curr_stat.st_mode)) { + dic = iniparser_load(ini_path); + CuAssertPtrEquals_Msg(tc, ini_path, NULL, dic); + dictionary_del(dic); + } + } + closedir(dir); +} + +void Test_dictionary_wrapper(CuTest *tc) +{ + dictionary *dic; + + dic = dictionary_new(10); + + CuAssertIntEquals(tc, -1, iniparser_set(dic, NULL, NULL)); + CuAssertIntEquals(tc, -1, iniparser_set(NULL, "section", "value")); + + CuAssertIntEquals(tc, 0, iniparser_set(dic, "section", NULL)); + CuAssertIntEquals(tc, 0, iniparser_set(dic, "section:key", "value")); + + CuAssertStrEquals(tc, "value", iniparser_getstring(dic, "section:key", NULL)); + /* reset the key's value*/ + CuAssertIntEquals(tc, 0, iniparser_set(dic, "section:key", NULL)); + CuAssertStrEquals(tc, NULL, iniparser_getstring(dic, "section:key", "dummy")); + CuAssertIntEquals(tc, 0, iniparser_set(dic, "section:key", "value")); + CuAssertStrEquals(tc, "value", iniparser_getstring(dic, "section:key", NULL)); + + iniparser_unset(dic, "section:key"); + CuAssertStrEquals(tc, "dummy", iniparser_getstring(dic, "section:key", "dummy")); + CuAssertStrEquals(tc, NULL, iniparser_getstring(dic, "section", "dummy")); + + CuAssertIntEquals(tc, 0, iniparser_set(dic, "section:key", NULL)); + CuAssertIntEquals(tc, 0, iniparser_set(dic, "section:key1", NULL)); + CuAssertIntEquals(tc, 0, iniparser_set(dic, "section:key2", NULL)); + + iniparser_unset(dic, "section"); + CuAssertStrEquals(tc, NULL, iniparser_getstring(dic, "section", NULL)); + + iniparser_freedict(dic); +} + +static char _last_error[1024]; +static int _error_callback(const char *format, ...) +{ + int ret; + va_list argptr; + va_start(argptr, format); + ret = vsprintf(_last_error, format, argptr); + va_end(argptr); + return ret; + +} + +void Test_iniparser_error_callback(CuTest *tc) +{ + dictionary *dic; + + /* Specify our custom error_callback */ + iniparser_set_error_callback(_error_callback); + + /* Trigger an error and check it was written on the right output */ + dic = iniparser_load("/path/to/nowhere.ini"); + CuAssertPtrEquals(tc, NULL, dic); + CuAssertStrEquals(tc, "iniparser: cannot open /path/to/nowhere.ini\n", _last_error); + + /* Reset erro_callback */ + _last_error[0] = '\0'; + iniparser_set_error_callback(NULL); + + /* Make sure custom callback is no more called */ + dic = iniparser_load("/path/to/nowhere.ini"); + CuAssertPtrEquals(tc, NULL, dic); + CuAssertStrEquals(tc, "", _last_error); +} diff --git a/src/dl/NOTICE b/src/dl/NOTICE new file mode 100644 index 0000000..14c6077 --- /dev/null +++ b/src/dl/NOTICE @@ -0,0 +1,6 @@ +Deep Learning Models for SMART VENDING MACHINE 3516-VISION CLIENT +Copyright 2022 Sidi Liang, YiLiu and Yicong Liu. + +This product includes gesture classification models developed by Sidi Liang, Yi Liu and Yicong Liu, released under Apache 2.0 license. + +This product includes a hand detection model (hand_detect.wk) developed by HiSilicon (Shanghai) Technologies CO., LIMITED, distributed under Apache 2.0 license. diff --git a/src/dl/extract_val_test.sh b/src/dl/extract_val_test.sh new file mode 100644 index 0000000..ce6b844 --- /dev/null +++ b/src/dl/extract_val_test.sh @@ -0,0 +1,21 @@ +i=1 +dir='15_empty' +mkdir ../val/$dir/ +mkdir ../test/$dir/ +while ((i <= 400)) +do + file=`/bin/ls -1 "$dir" | sort --random-sort | head -1` + path=`greadlink --canonicalize "$dir/$file"` # Converts to full path + echo "The randomly-selected file for val is: $path" + mv $path ../val/$dir/$file + ((i++)) +done +i=1 +while ((i <= 400)) +do + file=`/bin/ls -1 "$dir" | sort --random-sort | head -1` + path=`greadlink --canonicalize "$dir/$file"` # Converts to full path + echo "The randomly-selected file for test is: $path" + mv $path ../test/$dir/$file + ((i++)) +done diff --git a/src/dl/gesture_classification_v5.wk b/src/dl/gesture_classification_v5.wk new file mode 100644 index 0000000..616c65a Binary files /dev/null and b/src/dl/gesture_classification_v5.wk differ diff --git a/src/dl/gesture_classification_v6.pth b/src/dl/gesture_classification_v6.pth new file mode 100644 index 0000000..0c73388 Binary files /dev/null and b/src/dl/gesture_classification_v6.pth differ diff --git a/src/dl/gesture_classification_v6.wk b/src/dl/gesture_classification_v6.wk new file mode 100644 index 0000000..f4859d7 Binary files /dev/null and b/src/dl/gesture_classification_v6.wk differ diff --git a/src/dl/hand_detect.wk b/src/dl/hand_detect.wk new file mode 100644 index 0000000..cc476e7 Binary files /dev/null and b/src/dl/hand_detect.wk differ diff --git a/src/img/img1.png b/src/img/img1.png new file mode 100644 index 0000000..88b76df Binary files /dev/null and b/src/img/img1.png differ diff --git a/src/img/img10.png b/src/img/img10.png new file mode 100644 index 0000000..c9e4351 Binary files /dev/null and b/src/img/img10.png differ diff --git a/src/img/img11.png b/src/img/img11.png new file mode 100644 index 0000000..4212711 Binary files /dev/null and b/src/img/img11.png differ diff --git a/src/img/img12.png b/src/img/img12.png new file mode 100644 index 0000000..82f9fc0 Binary files /dev/null and b/src/img/img12.png differ diff --git a/src/img/img13.png b/src/img/img13.png new file mode 100644 index 0000000..ed3a839 Binary files /dev/null and b/src/img/img13.png differ diff --git a/src/img/img14.png b/src/img/img14.png new file mode 100644 index 0000000..5ea697d Binary files /dev/null and b/src/img/img14.png differ diff --git a/src/img/img15.png b/src/img/img15.png new file mode 100644 index 0000000..214b1fb Binary files /dev/null and b/src/img/img15.png differ diff --git a/src/img/img16.png b/src/img/img16.png new file mode 100644 index 0000000..c82de00 Binary files /dev/null and b/src/img/img16.png differ diff --git a/src/img/img17.png b/src/img/img17.png new file mode 100644 index 0000000..263e73f Binary files /dev/null and b/src/img/img17.png differ diff --git a/src/img/img18.png b/src/img/img18.png new file mode 100644 index 0000000..39b9fbe Binary files /dev/null and b/src/img/img18.png differ diff --git a/src/img/img19.png b/src/img/img19.png new file mode 100644 index 0000000..c147aaf Binary files /dev/null and b/src/img/img19.png differ diff --git a/src/img/img2.png b/src/img/img2.png new file mode 100644 index 0000000..e1a9ea6 Binary files /dev/null and b/src/img/img2.png differ diff --git a/src/img/img20.png b/src/img/img20.png new file mode 100644 index 0000000..747917f Binary files /dev/null and b/src/img/img20.png differ diff --git a/src/img/img21.png b/src/img/img21.png new file mode 100644 index 0000000..bdd99e5 Binary files /dev/null and b/src/img/img21.png differ diff --git a/src/img/img21_1.png b/src/img/img21_1.png new file mode 100644 index 0000000..6042fb3 Binary files /dev/null and b/src/img/img21_1.png differ diff --git a/src/img/img3.png b/src/img/img3.png new file mode 100644 index 0000000..871cfbf Binary files /dev/null and b/src/img/img3.png differ diff --git a/src/img/img4.png b/src/img/img4.png new file mode 100644 index 0000000..33a9fe4 Binary files /dev/null and b/src/img/img4.png differ diff --git a/src/img/img5.png b/src/img/img5.png new file mode 100644 index 0000000..6e8e3d6 Binary files /dev/null and b/src/img/img5.png differ diff --git a/src/img/img6.png b/src/img/img6.png new file mode 100644 index 0000000..aaf5a05 Binary files /dev/null and b/src/img/img6.png differ diff --git a/src/img/img7.png b/src/img/img7.png new file mode 100644 index 0000000..eeeefc7 Binary files /dev/null and b/src/img/img7.png differ diff --git a/src/img/img8.png b/src/img/img8.png new file mode 100644 index 0000000..b6d98d1 Binary files /dev/null and b/src/img/img8.png differ diff --git a/src/management_miniprogram/.cloudbase/container/debug.json b/src/management_miniprogram/.cloudbase/container/debug.json new file mode 100644 index 0000000..79ca5f4 --- /dev/null +++ b/src/management_miniprogram/.cloudbase/container/debug.json @@ -0,0 +1 @@ +{"containers":[]} \ No newline at end of file diff --git a/src/management_miniprogram/.eslintrc.js b/src/management_miniprogram/.eslintrc.js new file mode 100644 index 0000000..115cc02 --- /dev/null +++ b/src/management_miniprogram/.eslintrc.js @@ -0,0 +1,31 @@ +/* + * Eslint config file + * Documentation: https://eslint.org/docs/user-guide/configuring/ + * Install the Eslint extension before using this feature. + */ +module.exports = { + env: { + es6: true, + browser: true, + node: true, + }, + ecmaFeatures: { + modules: true, + }, + parserOptions: { + ecmaVersion: 2018, + sourceType: 'module', + }, + globals: { + wx: true, + App: true, + Page: true, + getCurrentPages: true, + getApp: true, + Component: true, + requirePlugin: true, + requireMiniProgram: true, + }, + // extends: 'eslint:recommended', + rules: {}, +} diff --git a/src/management_miniprogram/.gitignore b/src/management_miniprogram/.gitignore new file mode 100644 index 0000000..14ea590 --- /dev/null +++ b/src/management_miniprogram/.gitignore @@ -0,0 +1,14 @@ +# Windows +[Dd]esktop.ini +Thumbs.db +$RECYCLE.BIN/ + +# macOS +.DS_Store +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes + +# Node.js +node_modules/ diff --git a/src/management_miniprogram/README.md b/src/management_miniprogram/README.md new file mode 100644 index 0000000..5eff97f --- /dev/null +++ b/src/management_miniprogram/README.md @@ -0,0 +1,7 @@ +# MQTT Client Wechat miniprogram + +## 使用 + +克隆或下载该仓库,使用微信小程序导入 `mqtt-client-wechat-miniprogram` 文件夹即可使用 + +![mqtt](./mqtt.png) diff --git a/src/management_miniprogram/app.js b/src/management_miniprogram/app.js new file mode 100644 index 0000000..4af33be --- /dev/null +++ b/src/management_miniprogram/app.js @@ -0,0 +1,2 @@ +// app.js +App({}) diff --git a/src/management_miniprogram/app.json b/src/management_miniprogram/app.json new file mode 100644 index 0000000..0e28706 --- /dev/null +++ b/src/management_miniprogram/app.json @@ -0,0 +1,14 @@ +{ + "pages": [ + "pages/index/index", + "pages/logs/logs" + ], + "window": { + "backgroundTextStyle": "light", + "navigationBarBackgroundColor": "#fff", + "navigationBarTitleText": "产品管理中心(未连接)", + "navigationBarTextStyle": "black" + }, + "style": "v2", + "sitemapLocation": "sitemap.json" +} \ No newline at end of file diff --git a/src/management_miniprogram/app.wxss b/src/management_miniprogram/app.wxss new file mode 100644 index 0000000..4684d3c --- /dev/null +++ b/src/management_miniprogram/app.wxss @@ -0,0 +1,7 @@ +/**app.wxss**/ +.container { + padding: 48rpx; +} +page{ + font-family: "PingFangSC-Thin" +} diff --git a/src/management_miniprogram/pages/index/index.js b/src/management_miniprogram/pages/index/index.js new file mode 100644 index 0000000..741e254 --- /dev/null +++ b/src/management_miniprogram/pages/index/index.js @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2022 Yicong Liu and Sidi Liang. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import mqtt from '../../utils/mqtt.min.js' + +Page({ + data: { + client: null, + conenctBtnText: '连接', + host: 'YT32IOSCAL.ap-guangzhou.iothub.tencentdevices.com:443', + pubTopic: '$shadow/operation/YT32IOSCAL/miniprogram', + receivedMsg: '', + received: '', + version: 38, + name1: '创口贴', + price1: 9.9, + remain_num1: 3, + name2: '口罩', + price2: 1, + remain_num2: 3, + name3: '棉签', + price3: 6.9, + remain_num3: 3, + name4: '口罩', + price4: 1, + remain_num4: 3, + mqttOptions: { + username: 'YT32IOSCALminiprogram;12010126;72bb5;1666022400', + password: '03f6c586126cbc084d0f5b37fd0005f6a062c942c25fc9123e5a4a171044ceac;hmacsha256', + reconnectPeriod: 1000, + connectTimeout: 30 * 1000 + } + }, + + requestData: function () { + var requestMsg = { + 'type': 'get', + 'clientToken': 'clientToken' + } + this.data.client.publish(this.data.pubTopic, JSON.stringify(requestMsg)) + }, + _nameEdit1: function (event) { + this.setData({ + name1: event.detail.value + }) + this.publish() + }, + _priceEdit1: function (event) { + this.setData({ + price1: event.detail.value + }) + this.publish() + }, + _remainingNumEdit1: function (event) { + this.setData({ + remain_num1: event.detail.value + }) + this.publish() + }, + + _nameEdit2: function (event) { + this.setData({ + name2: event.detail.value + }) + this.publish() + }, + _priceEdit2: function (event) { + this.setData({ + price2: event.detail.value + }) + this.publish() + }, + _remainingNumEdit2: function (event) { + this.setData({ + remain_num2: event.detail.value + }) + this.publish() + }, + + _nameEdit3: function (event) { + this.setData({ + name3: event.detail.value + }) + this.publish() + }, + _priceEdit3: function (event) { + this.setData({ + price3: event.detail.value + }) + this.publish() + }, + _remainingNumEdit3: function (event) { + this.setData({ + remain_num3: event.detail.value + }) + this.publish() + }, + + _nameEdit4: function (event) { + this.setData({ + name4: event.detail.value + }) + this.publish() + }, + _priceEdit4: function (event) { + this.setData({ + price4: event.detail.value + }) + this.publish() + }, + _remainingNumEdit4: function (event) { + this.setData({ + remain_num4: event.detail.value + }) + this.publish() + }, + + setValue (key, value) { + this.setData({ + [key]: value + }) + }, + + setHost (e) { + this.setValue('host', e.detail.value) + }, + setSubTopic (e) { + this.setValue('subTopic', e.detail.value) + }, + setPubTopic (e) { + this.setValue('pubTopic', e.detail.value) + }, + setPubMsg (e) { + this.setValue('pubMsg', e.detail.value) + }, + setRecMsg (msg) { + this.setValue('receivedMsg', msg) + }, + + connect () { + try { + wx.setNavigationBarTitle({ + title: '产品管理中心(连接中...)' + }) + const clientId = new Date().getTime() + this.data.client = mqtt.connect(`wxs://${this.data.host}/mqtt`, { + ...this.data.mqttOptions, + clientId + }) + + this.data.client.on('connect', () => { + wx.setNavigationBarTitle({ + title: '产品管理中心' + }) + + this.data.client.on('message', (topic, payload) => { + const currMsg = this.data.receivedMsg ? `
${payload}` : payload + + this.setValue('receivedMsg', this.data.receivedMsg.concat(currMsg)) + this.data.version = JSON.parse(this.data.receivedMsg).payload.version + console.log(this.data.version) + this.data.receivedMsg = '' + }) + + this.data.client.on('error', (error) => { + wx.setNavigationBarTitle({ + title: '产品管理中心(连接错误)' + }) + console.log('onError', error) + }) + + this.data.client.on('reconnect', () => { + wx.setNavigationBarTitle({ + title: '产品管理中心(重连中...)' + }) + console.log('reconnecting...') + }) + + this.data.client.on('offline', () => { + wx.setNavigationBarTitle({ + title: '产品管理中心(未连接)' + }) + console.log('onOffline') + }) + }) + } catch (error) { + wx.setNavigationBarTitle({ + title: '产品管理中心(连接错误)' + }) + console.log('mqtt.connect error', error) + } + }, + + subscribe () { + if (this.data.client) { + return + } + }, + + unsubscribe () { + if (this.data.client) { + this.data.client.unsubscribe(this.data.subTopic) + return + } + }, + + deal () // 需要根据通信协议更改的地方 + { + return { + type: 'update', + state: { + reported: { + product_info: [{ + slot_num: '1', + product_price: this.data.price1, + remaining_num: this.data.remain_num1, + product_name: this.data.name1 + }, { + slot_num: '2', + product_price: this.data.price2, + remaining_num: this.data.remain_num2, + product_name: this.data.name2 + }, { + slot_num: 3, + product_price: this.data.price3, + remaining_num: this.data.remain_num3, + product_name: this.data.name3 + }, { + slot_num: 4, + product_price: this.data.price4, + remaining_num: this.data.remain_num4, + product_name: this.data.name4 + }] + } + }, + version: this.data.version, + clientToken: '' + } + }, + + publish () { + if (this.data.client) { + this.data.client.publish(this.data.pubTopic, JSON.stringify(this.deal())) + this.data.version++ + console.log(JSON.stringify(this.deal())) + return + } + }, + + onLoad: function () { + this.connect() + this.subscribe() + } +}) diff --git a/src/management_miniprogram/pages/index/index.json b/src/management_miniprogram/pages/index/index.json new file mode 100644 index 0000000..a97367d --- /dev/null +++ b/src/management_miniprogram/pages/index/index.json @@ -0,0 +1,3 @@ +{ + "usingComponents": {} +} diff --git a/src/management_miniprogram/pages/index/index.wxml b/src/management_miniprogram/pages/index/index.wxml new file mode 100644 index 0000000..85db83f --- /dev/null +++ b/src/management_miniprogram/pages/index/index.wxml @@ -0,0 +1,49 @@ + + + + + 货道: 1 + 产品名称 + + 产品价格 + + 剩余数量 + + + \n + + + + 货道: 2 + 产品名称 + + 产品价格 + + 剩余数量 + + \n + + + + + 货道: 3 + 产品名称 + + 产品价格 + + 剩余数量 + + + + + + 货道: 4 + 产品名称 + + 产品价格 + + 剩余数量 + + + + \ No newline at end of file diff --git a/src/management_miniprogram/pages/index/index.wxss b/src/management_miniprogram/pages/index/index.wxss new file mode 100644 index 0000000..f3e3414 --- /dev/null +++ b/src/management_miniprogram/pages/index/index.wxss @@ -0,0 +1,43 @@ +.cps2{ + display: flex; + flex-wrap: wrap; + justify-content: center; +} +.cp-item1{ + width: 50%; + display: flex; + align-items:center; + flex-direction: column; + font-size:30rpx; +} +.cp-image2{ + width: 300rpx; + height: 280rpx; +} +.cp-item2 text{ + font-size: 30rpx; + width: 100%; + text-align:center; + margin-left:20rpx; +} +.text1{ + height: 45rpx; + font-weight: 600; +} +.text3{ + height: 60rpx; + font-weight: 900; +} +.text4{ + font-weight: 900; +} +.container{ + min-height: 100vh; + background-color: rgb(255, 255, 255); +} + +.text2{ + height: 40rpx; + font-weight: 600; + color: rgb(38, 0, 255); +} \ No newline at end of file diff --git a/src/management_miniprogram/pages/logs/logs.js b/src/management_miniprogram/pages/logs/logs.js new file mode 100644 index 0000000..26e868a --- /dev/null +++ b/src/management_miniprogram/pages/logs/logs.js @@ -0,0 +1,66 @@ +// pages/logs/logs.js +Page({ + + /** + * 页面的初始数据 + */ + data: { + + }, + + /** + * 生命周期函数--监听页面加载 + */ + onLoad(options) { + + }, + + /** + * 生命周期函数--监听页面初次渲染完成 + */ + onReady() { + + }, + + /** + * 生命周期函数--监听页面显示 + */ + onShow() { + + }, + + /** + * 生命周期函数--监听页面隐藏 + */ + onHide() { + + }, + + /** + * 生命周期函数--监听页面卸载 + */ + onUnload() { + + }, + + /** + * 页面相关事件处理函数--监听用户下拉动作 + */ + onPullDownRefresh() { + + }, + + /** + * 页面上拉触底事件的处理函数 + */ + onReachBottom() { + + }, + + /** + * 用户点击右上角分享 + */ + onShareAppMessage() { + + } +}) \ No newline at end of file diff --git a/src/management_miniprogram/pages/logs/logs.wxml b/src/management_miniprogram/pages/logs/logs.wxml new file mode 100644 index 0000000..c49f50c --- /dev/null +++ b/src/management_miniprogram/pages/logs/logs.wxml @@ -0,0 +1,2 @@ + +pages/logs/logs.wxml diff --git a/src/management_miniprogram/project.config.json b/src/management_miniprogram/project.config.json new file mode 100644 index 0000000..e96edea --- /dev/null +++ b/src/management_miniprogram/project.config.json @@ -0,0 +1,53 @@ +{ + "description": "项目配置文件,详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html", + "setting": { + "bundle": false, + "userConfirmedBundleSwitch": false, + "urlCheck": true, + "scopeDataCheck": false, + "coverView": true, + "es6": false, + "postcss": true, + "compileHotReLoad": true, + "lazyloadPlaceholderEnable": false, + "preloadBackgroundData": false, + "minified": true, + "autoAudits": false, + "newFeature": false, + "uglifyFileName": false, + "uploadWithSourceMap": true, + "useIsolateContext": true, + "nodeModules": false, + "enhance": true, + "useMultiFrameRuntime": true, + "showShadowRootInWxmlPanel": true, + "packNpmManually": false, + "enableEngineNative": false, + "packNpmRelationList": [], + "minifyWXSS": true, + "showES6CompileOption": false, + "minifyWXML": true, + "useStaticServer": true, + "checkInvalidKey": true, + "babelSetting": { + "ignore": [], + "disablePlugins": [], + "outputPath": "" + }, + "disableUseStrict": false, + "useCompilerPlugins": false, + "ignoreUploadUnusedFiles": true + }, + "compileType": "miniprogram", + "condition": {}, + "editorSetting": { + "tabIndent": "insertSpaces", + "tabSize": 4 + }, + "libVersion": "2.25.0", + "packOptions": { + "ignore": [], + "include": [] + }, + "appid": "wxf365d4705f673e24" +} \ No newline at end of file diff --git a/src/management_miniprogram/project.private.config.json b/src/management_miniprogram/project.private.config.json new file mode 100644 index 0000000..713a7b7 --- /dev/null +++ b/src/management_miniprogram/project.private.config.json @@ -0,0 +1,8 @@ +{ + "projectname": "management", + "setting": { + "compileHotReLoad": true, + "urlCheck": true + }, + "description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html" +} \ No newline at end of file diff --git a/src/management_miniprogram/sitemap.json b/src/management_miniprogram/sitemap.json new file mode 100644 index 0000000..27b2b26 --- /dev/null +++ b/src/management_miniprogram/sitemap.json @@ -0,0 +1,7 @@ +{ + "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html", + "rules": [{ + "action": "allow", + "page": "*" + }] +} \ No newline at end of file diff --git a/src/management_miniprogram/utils/mqtt.min.js b/src/management_miniprogram/utils/mqtt.min.js new file mode 100644 index 0000000..ed91d92 --- /dev/null +++ b/src/management_miniprogram/utils/mqtt.min.js @@ -0,0 +1 @@ +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).mqtt=e()}}(function(){return function(){return function e(t,r,n){function i(s,a){if(!r[s]){if(!t[s]){var c="function"==typeof require&&require;if(!a&&c)return c(s,!0);if(o)return o(s,!0);var u=new Error("Cannot find module '"+s+"'");throw u.code="MODULE_NOT_FOUND",u}var l=r[s]={exports:{}};t[s][0].call(l.exports,function(e){return i(t[s][1][e]||e)},l,l.exports,e,t,r,n)}return r[s].exports}for(var o="function"==typeof require&&require,s=0;sthis.emit("error",new Error("Packet has no Authentication Method"))),this;if(this.options.properties.authenticationMethod&&this.options.authPacket&&"object"==typeof this.options.authPacket)y(this,f({cmd:"auth",reasonCode:0},this.options.authPacket))}this.stream.setMaxListeners(1e3),clearTimeout(this.connackTimer),this.connackTimer=setTimeout(function(){p("!!connectTimeout hit!! Calling _cleanUp with force `true`"),t._cleanUp(!0)},this.options.connectTimeout)},w.prototype._handlePacket=function(e,t){var r=this.options;if(5===r.protocolVersion&&r.properties&&r.properties.maximumPacketSize&&r.properties.maximumPacketSizeo.properties.topicAliasMaximum||!o.properties.topicAliasMaximum&&r.properties.topicAlias))&&delete i.properties.topicAlias),p("publish :: qos",r.qos),r.qos){case 1:case 2:this.outgoing[i.messageId]={volatile:!1,cb:n||v},this._storeProcessing?(p("_storeProcessing enabled"),this._packetIdsDuringStoreProcessing[i.messageId]=!1,this._storePacket(i,void 0,r.cbStorePut)):(p("MqttClient:publish: packet cmd: %s",i.cmd),this._sendPacket(i,void 0,r.cbStorePut));break;default:this._storeProcessing?(p("_storeProcessing enabled"),this._storePacket(i,n,r.cbStorePut)):(p("MqttClient:publish: packet cmd: %s",i.cmd),this._sendPacket(i,n,r.cbStorePut))}return this},w.prototype.subscribe=function(){for(var e,t=new Array(arguments.length),r=0;r0){var t={qos:e.qos};5===h&&(t.nl=e.nl||!1,t.rap=e.rap||!1,t.rh=e.rh||0,t.properties=e.properties),u._resubscribeTopics[e.topic]=t,b.push(e.topic)}}),u.messageIdToTopic[e.messageId]=b}return this.outgoing[e.messageId]={volatile:!0,cb:function(e,t){if(!e)for(var r=t.granted,n=0;n{p("end :: finish :: calling process.nextTick on closeStores"),h(function(){p("end :: closeStores: closing incoming and outgoing stores"),n.disconnected=!0,n.incomingStore.close(function(e){n.outgoingStore.close(function(t){if(p("end :: closeStores: emitting end"),n.emit("end"),r){let n=e||t;p("end :: closeStores: invoking callback with args"),r(n)}})}),n._deferredReconnect&&n._deferredReconnect()}.bind(n))},t)}return p("end :: (%s)",this.options.clientId),null!=e&&"boolean"==typeof e||(r=t||v,t=e,e=!1,"object"!=typeof t&&(r=t,t=null,"function"!=typeof r&&(r=v))),"object"!=typeof t&&(r=t,t=null),p("end :: cb? %s",!!r),r=r||v,this.disconnecting?(r(),this):(this._clearReconnect(),this.disconnecting=!0,!e&&Object.keys(this.outgoing).length>0?(p("end :: (%s) :: calling finish in 10ms once outgoing is empty",n.options.clientId),this.once("outgoingEmpty",setTimeout.bind(null,i,10))):(p("end :: (%s) :: immediately calling finish",n.options.clientId),i()),this)},w.prototype.removeOutgoingMessage=function(e){var t=this.outgoing[e]?this.outgoing[e].cb:null;return delete this.outgoing[e],this.outgoingStore.del({messageId:e},function(){t(new Error("Message removed"))}),this},w.prototype.reconnect=function(e){p("client reconnect");var t=this,r=function(){e?(t.options.incomingStore=e.incomingStore,t.options.outgoingStore=e.outgoingStore):(t.options.incomingStore=null,t.options.outgoingStore=null),t.incomingStore=t.options.incomingStore||new o,t.outgoingStore=t.options.outgoingStore||new o,t.disconnecting=!1,t.disconnected=!1,t._deferredReconnect=null,t._reconnect()};return this.disconnecting&&!this.disconnected?this._deferredReconnect=r:r(),this},w.prototype._reconnect=function(){p("_reconnect: emitting reconnect to client"),this.emit("reconnect"),p("_reconnect: calling _setupStream"),this._setupStream()},w.prototype._setupReconnect=function(){var e=this;!e.disconnecting&&!e.reconnectTimer&&e.options.reconnectPeriod>0?(this.reconnecting||(p("_setupReconnect :: emit `offline` state"),this.emit("offline"),p("_setupReconnect :: set `reconnecting` to `true`"),this.reconnecting=!0),p("_setupReconnect :: setting reconnectTimer for %d ms",e.options.reconnectPeriod),e.reconnectTimer=setInterval(function(){p("reconnectTimer :: reconnect triggered!"),e._reconnect()},e.options.reconnectPeriod)):p("_setupReconnect :: doing nothing...")},w.prototype._clearReconnect=function(){p("_clearReconnect : clearing reconnect timer"),this.reconnectTimer&&(clearInterval(this.reconnectTimer),this.reconnectTimer=null)},w.prototype._cleanUp=function(e,t){var r,n=arguments[2];if(t&&(p("_cleanUp :: done callback provided for on stream close"),this.stream.on("close",t)),p("_cleanUp :: forced? %s",e),e)0===this.options.reconnectPeriod&&this.options.clean&&(r=this.outgoing)&&(p("flush: queue exists? %b",!!r),Object.keys(r).forEach(function(e){"function"==typeof r[e].cb&&(r[e].cb(new Error("Connection closed")),delete r[e])})),p("_cleanUp :: (%s) :: destroying stream",this.options.clientId),this.stream.destroy();else{var i=f({cmd:"disconnect"},n);p("_cleanUp :: (%s) :: call _sendPacket with disconnect packet",this.options.clientId),this._sendPacket(i,d.bind(null,this.stream.end.bind(this.stream)))}this.disconnecting||(p("_cleanUp :: client not disconnecting. Clearing and resetting reconnect."),this._clearReconnect(),this._setupReconnect()),null!==this.pingTimer&&(p("_cleanUp :: clearing pingTimer"),this.pingTimer.clear(),this.pingTimer=null),t&&!this.connected&&(p("_cleanUp :: (%s) :: removing stream `done` callback `close` listener",this.options.clientId),this.stream.removeListener("close",t),t())},w.prototype._sendPacket=function(e,t,r){if(p("_sendPacket :: (%s) :: start",this.options.clientId),r=r||v,!this.connected)return p("_sendPacket :: client not connected. Storing packet offline."),void this._storePacket(e,t,r);switch(this._shiftPingInterval(),e.cmd){case"publish":break;case"pubrel":return void _(this,e,t,r);default:return void y(this,e,t)}switch(e.qos){case 2:case 1:_(this,e,t,r);break;case 0:default:y(this,e,t)}p("_sendPacket :: (%s) :: end",this.options.clientId)},w.prototype._storePacket=function(e,t,r){p("_storePacket :: packet: %o",e),p("_storePacket :: cb? %s",!!t),r=r||v,0===(e.qos||0)&&this.queueQoSZero||"publish"!==e.cmd?this.queue.push({packet:e,cb:t}):e.qos>0?(t=this.outgoing[e.messageId]?this.outgoing[e.messageId].cb:null,this.outgoingStore.put(e,function(e){if(e)return t&&t(e);r()})):t&&t(new Error("No connection to broker"))},w.prototype._setupPingTimer=function(){p("_setupPingTimer :: keepalive %d (seconds)",this.options.keepalive);var e=this;!this.pingTimer&&this.options.keepalive&&(this.pingResp=!0,this.pingTimer=u(function(){e._checkPing()},1e3*this.options.keepalive))},w.prototype._shiftPingInterval=function(){this.pingTimer&&this.options.keepalive&&this.options.reschedulePings&&this.pingTimer.reschedule(1e3*this.options.keepalive)},w.prototype._checkPing=function(){p("_checkPing :: checking ping..."),this.pingResp?(p("_checkPing :: ping response received. Clearing flag and sending `pingreq`"),this.pingResp=!1,this._sendPacket({cmd:"pingreq"})):(p("_checkPing :: calling _cleanUp with force true"),this._cleanUp(!0))},w.prototype._handlePingresp=function(){this.pingResp=!0},w.prototype._handleConnack=function(e){p("_handleConnack");var t=this.options,r=5===t.protocolVersion?e.reasonCode:e.returnCode;if(clearTimeout(this.connackTimer),e.properties&&(e.properties.topicAliasMaximum&&(t.properties||(t.properties={}),t.properties.topicAliasMaximum=e.properties.topicAliasMaximum),e.properties.serverKeepAlive&&t.keepalive&&(t.keepalive=e.properties.serverKeepAlive,this._shiftPingInterval()),e.properties.maximumPacketSize&&(t.properties||(t.properties={}),t.properties.maximumPacketSize=e.properties.maximumPacketSize)),0===r)this.reconnecting=!1,this._onConnect(e);else if(r>0){var n=new Error("Connection refused: "+m[r]);n.code=r,this.emit("error",n)}},w.prototype._handlePublish=function(e,t){p("_handlePublish: packet %o",e),t=void 0!==t?t:v;var r=e.topic.toString(),n=e.payload,i=e.qos,o=e.messageId,s=this,a=this.options,c=[0,16,128,131,135,144,145,151,153];switch(p("_handlePublish: qos %d",i),i){case 2:a.customHandleAcks(r,n,e,function(r,n){return r instanceof Error||(n=r,r=null),r?s.emit("error",r):-1===c.indexOf(n)?s.emit("error",new Error("Wrong reason code for pubrec")):void(n?s._sendPacket({cmd:"pubrec",messageId:o,reasonCode:n},t):s.incomingStore.put(e,function(){s._sendPacket({cmd:"pubrec",messageId:o},t)}))});break;case 1:a.customHandleAcks(r,n,e,function(i,a){return i instanceof Error||(a=i,i=null),i?s.emit("error",i):-1===c.indexOf(a)?s.emit("error",new Error("Wrong reason code for puback")):(a||s.emit("message",r,n,e),void s.handleMessage(e,function(e){if(e)return t&&t(e);s._sendPacket({cmd:"puback",messageId:o,reasonCode:a},t)}))});break;case 0:this.emit("message",r,n,e),this.handleMessage(e,t);break;default:p("_handlePublish: unknown QoS. Doing nothing.")}},w.prototype.handleMessage=function(e,t){t()},w.prototype._handleAck=function(e){var t,r=e.messageId,n=e.cmd,i=null,o=this.outgoing[r]?this.outgoing[r].cb:null,s=this;if(o){switch(p("_handleAck :: packet type",n),n){case"pubcomp":case"puback":var a=e.reasonCode;a&&a>0&&16!==a&&((t=new Error("Publish error: "+m[a])).code=a,o(t,e)),delete this.outgoing[r],this.outgoingStore.del(e,o);break;case"pubrec":i={cmd:"pubrel",qos:2,messageId:r};var c=e.reasonCode;c&&c>0&&16!==c?((t=new Error("Publish error: "+m[c])).code=c,o(t,e)):this._sendPacket(i);break;case"suback":delete this.outgoing[r];for(var u=0;u0)if(this.options.resubscribe)if(5===this.options.protocolVersion){p("_resubscribe: protocolVersion 5");for(var r=0;rn&&setTimeout(e,u,t,r,i),l&&"string"==typeof t&&(t=s.from(t,"utf8"));try{h.send(t)}catch(e){return i(e)}i()},function(e){h.close(),e()});t.objectMode||(d._writev=v),d.on("close",()=>{h.close()});const g=void 0===h.addEventListener;function b(){r.setReadable(d),r.setWritable(d),r.emit("connect")}function m(){r.end(),r.destroy()}function y(e){r.destroy(e)}function _(e){let t=e.data;t=t instanceof ArrayBuffer?s.from(t):s.from(t,"utf8"),d.push(t)}function v(e,t){const r=new Array(e.length);for(let t=0;t0?s-4:s;for(r=0;r>16&255,c[l++]=t>>8&255,c[l++]=255&t;2===a&&(t=i[e.charCodeAt(r)]<<2|i[e.charCodeAt(r+1)]>>4,c[l++]=255&t);1===a&&(t=i[e.charCodeAt(r)]<<10|i[e.charCodeAt(r+1)]<<4|i[e.charCodeAt(r+2)]>>2,c[l++]=t>>8&255,c[l++]=255&t);return c},r.fromByteArray=function(e){for(var t,r=e.length,i=r%3,o=[],s=0,a=r-i;sa?a:s+16383));1===i?(t=e[r-1],o.push(n[t>>2]+n[t<<4&63]+"==")):2===i&&(t=(e[r-2]<<8)+e[r-1],o.push(n[t>>10]+n[t>>4&63]+n[t<<2&63]+"="));return o.join("")};for(var n=[],i=[],o="undefined"!=typeof Uint8Array?Uint8Array:Array,s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",a=0,c=s.length;a0)throw new Error("Invalid string. Length must be a multiple of 4");var r=e.indexOf("=");return-1===r&&(r=t),[r,r===t?0:4-r%4]}function l(e,t,r){for(var i,o,s=[],a=t;a>18&63]+n[o>>12&63]+n[o>>6&63]+n[63&o]);return s.join("")}i["-".charCodeAt(0)]=62,i["_".charCodeAt(0)]=63},{}],11:[function(e,t,r){var n=e("readable-stream/duplex"),i=e("util"),o=e("safe-buffer").Buffer;function s(e){if(!(this instanceof s))return new s(e);if(this._bufs=[],this.length=0,"function"==typeof e){this._callback=e;var t=function(e){this._callback&&(this._callback(e),this._callback=null)}.bind(this);this.on("pipe",function(e){e.on("error",t)}),this.on("unpipe",function(e){e.removeListener("error",t)})}else this.append(e);n.call(this)}i.inherits(s,n),s.prototype._offset=function(e){var t,r=0,n=0;if(0===e)return[0,0];for(;nthis.length)&&(n=this.length),r>=this.length)return e||o.alloc(0);if(n<=0)return e||o.alloc(0);var i,s,a=!!e,c=this._offset(r),u=n-r,l=u,f=a&&t||0,p=c[1];if(0===r&&n==this.length){if(!a)return 1===this._bufs.length?this._bufs[0]:o.concat(this._bufs,this.length);for(s=0;s(i=this._bufs[s].length-p))){this._bufs[s].copy(e,f,p,p+l);break}this._bufs[s].copy(e,f,p),f+=i,l-=i,p&&(p=0)}return e},s.prototype.shallowSlice=function(e,t){e=e||0,t=t||this.length,e<0&&(e+=this.length),t<0&&(t+=this.length);var r=this._offset(e),n=this._offset(t),i=this._bufs.slice(r[0],n[0]+1);return 0==n[1]?i.pop():i[i.length-1]=i[i.length-1].slice(0,n[1]),0!=r[1]&&(i[0]=i[0].slice(r[1])),new s(i)},s.prototype.toString=function(e,t,r){return this.slice(t,r).toString(e)},s.prototype.consume=function(e){for(;this._bufs.length;){if(!(e>=this._bufs[0].length)){this._bufs[0]=this._bufs[0].slice(e),this.length-=e;break}e-=this._bufs[0].length,this.length-=this._bufs[0].length,this._bufs.shift()}return this},s.prototype.duplicate=function(){for(var e=0,t=new s;eo)throw new RangeError('The value "'+e+'" is invalid for option "size"');var r=new Uint8Array(e);return r.__proto__=t.prototype,r}function t(e,t,r){if("number"==typeof e){if("string"==typeof t)throw new TypeError('The "string" argument must be of type string. Received type number');return u(e)}return a(e,t,r)}function a(e,r,n){if("string"==typeof e)return function(e,r){"string"==typeof r&&""!==r||(r="utf8");if(!t.isEncoding(r))throw new TypeError("Unknown encoding: "+r);var n=0|p(e,r),i=s(n),o=i.write(e,r);o!==n&&(i=i.slice(0,o));return i}(e,r);if(ArrayBuffer.isView(e))return l(e);if(null==e)throw TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof e);if(q(e,ArrayBuffer)||e&&q(e.buffer,ArrayBuffer))return function(e,r,n){if(r<0||e.byteLength=o)throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+o.toString(16)+" bytes");return 0|e}function p(e,r){if(t.isBuffer(e))return e.length;if(ArrayBuffer.isView(e)||q(e,ArrayBuffer))return e.byteLength;if("string"!=typeof e)throw new TypeError('The "string" argument must be one of type string, Buffer, or ArrayBuffer. Received type '+typeof e);var n=e.length,i=arguments.length>2&&!0===arguments[2];if(!i&&0===n)return 0;for(var o=!1;;)switch(r){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":return N(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return U(e).length;default:if(o)return i?-1:N(e).length;r=(""+r).toLowerCase(),o=!0}}function h(e,t,r){var n=e[t];e[t]=e[r],e[r]=n}function d(e,r,n,i,o){if(0===e.length)return-1;if("string"==typeof n?(i=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),F(n=+n)&&(n=o?0:e.length-1),n<0&&(n=e.length+n),n>=e.length){if(o)return-1;n=e.length-1}else if(n<0){if(!o)return-1;n=0}if("string"==typeof r&&(r=t.from(r,i)),t.isBuffer(r))return 0===r.length?-1:g(e,r,n,i,o);if("number"==typeof r)return r&=255,"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(e,r,n):Uint8Array.prototype.lastIndexOf.call(e,r,n):g(e,[r],n,i,o);throw new TypeError("val must be string, number or Buffer")}function g(e,t,r,n,i){var o,s=1,a=e.length,c=t.length;if(void 0!==n&&("ucs2"===(n=String(n).toLowerCase())||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(e.length<2||t.length<2)return-1;s=2,a/=2,c/=2,r/=2}function u(e,t){return 1===s?e[t]:e.readUInt16BE(t*s)}if(i){var l=-1;for(o=r;oa&&(r=a-c),o=r;o>=0;o--){for(var f=!0,p=0;pi&&(n=i):n=i;var o=t.length;n>o/2&&(n=o/2);for(var s=0;s>8,i=r%256,o.push(i),o.push(n);return o}(t,e.length-r),e,r,n)}function S(e,t,r){return 0===t&&r===e.length?n.fromByteArray(e):n.fromByteArray(e.slice(t,r))}function k(e,t,r){r=Math.min(e.length,r);for(var n=[],i=t;i239?4:u>223?3:u>191?2:1;if(i+f<=r)switch(f){case 1:u<128&&(l=u);break;case 2:128==(192&(o=e[i+1]))&&(c=(31&u)<<6|63&o)>127&&(l=c);break;case 3:o=e[i+1],s=e[i+2],128==(192&o)&&128==(192&s)&&(c=(15&u)<<12|(63&o)<<6|63&s)>2047&&(c<55296||c>57343)&&(l=c);break;case 4:o=e[i+1],s=e[i+2],a=e[i+3],128==(192&o)&&128==(192&s)&&128==(192&a)&&(c=(15&u)<<18|(63&o)<<12|(63&s)<<6|63&a)>65535&&c<1114112&&(l=c)}null===l?(l=65533,f=1):l>65535&&(l-=65536,n.push(l>>>10&1023|55296),l=56320|1023&l),n.push(l),i+=f}return function(e){var t=e.length;if(t<=x)return String.fromCharCode.apply(String,e);var r="",n=0;for(;nthis.length)return"";if((void 0===r||r>this.length)&&(r=this.length),r<=0)return"";if((r>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return C(this,t,r);case"utf8":case"utf-8":return k(this,t,r);case"ascii":return E(this,t,r);case"latin1":case"binary":return I(this,t,r);case"base64":return S(this,t,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return O(this,t,r);default:if(n)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),n=!0}}.apply(this,arguments)},t.prototype.toLocaleString=t.prototype.toString,t.prototype.equals=function(e){if(!t.isBuffer(e))throw new TypeError("Argument must be a Buffer");return this===e||0===t.compare(this,e)},t.prototype.inspect=function(){var e="",t=r.INSPECT_MAX_BYTES;return e=this.toString("hex",0,t).replace(/(.{2})/g,"$1 ").trim(),this.length>t&&(e+=" ... "),""},t.prototype.compare=function(e,r,n,i,o){if(q(e,Uint8Array)&&(e=t.from(e,e.offset,e.byteLength)),!t.isBuffer(e))throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. Received type '+typeof e);if(void 0===r&&(r=0),void 0===n&&(n=e?e.length:0),void 0===i&&(i=0),void 0===o&&(o=this.length),r<0||n>e.length||i<0||o>this.length)throw new RangeError("out of range index");if(i>=o&&r>=n)return 0;if(i>=o)return-1;if(r>=n)return 1;if(r>>>=0,n>>>=0,i>>>=0,o>>>=0,this===e)return 0;for(var s=o-i,a=n-r,c=Math.min(s,a),u=this.slice(i,o),l=e.slice(r,n),f=0;f>>=0,isFinite(r)?(r>>>=0,void 0===n&&(n="utf8")):(n=r,r=void 0)}var i=this.length-t;if((void 0===r||r>i)&&(r=i),e.length>0&&(r<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");n||(n="utf8");for(var o=!1;;)switch(n){case"hex":return b(this,e,t,r);case"utf8":case"utf-8":return m(this,e,t,r);case"ascii":return y(this,e,t,r);case"latin1":case"binary":return _(this,e,t,r);case"base64":return v(this,e,t,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return w(this,e,t,r);default:if(o)throw new TypeError("Unknown encoding: "+n);n=(""+n).toLowerCase(),o=!0}},t.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var x=4096;function E(e,t,r){var n="";r=Math.min(e.length,r);for(var i=t;in)&&(r=n);for(var i="",o=t;or)throw new RangeError("Trying to access beyond buffer length")}function A(e,r,n,i,o,s){if(!t.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(r>o||re.length)throw new RangeError("Index out of range")}function T(e,t,r,n,i,o){if(r+n>e.length)throw new RangeError("Index out of range");if(r<0)throw new RangeError("Index out of range")}function P(e,t,r,n,o){return t=+t,r>>>=0,o||T(e,0,r,4),i.write(e,t,r,n,23,4),r+4}function M(e,t,r,n,o){return t=+t,r>>>=0,o||T(e,0,r,8),i.write(e,t,r,n,52,8),r+8}t.prototype.slice=function(e,r){var n=this.length;e=~~e,r=void 0===r?n:~~r,e<0?(e+=n)<0&&(e=0):e>n&&(e=n),r<0?(r+=n)<0&&(r=0):r>n&&(r=n),r>>=0,t>>>=0,r||j(e,t,this.length);for(var n=this[e],i=1,o=0;++o>>=0,t>>>=0,r||j(e,t,this.length);for(var n=this[e+--t],i=1;t>0&&(i*=256);)n+=this[e+--t]*i;return n},t.prototype.readUInt8=function(e,t){return e>>>=0,t||j(e,1,this.length),this[e]},t.prototype.readUInt16LE=function(e,t){return e>>>=0,t||j(e,2,this.length),this[e]|this[e+1]<<8},t.prototype.readUInt16BE=function(e,t){return e>>>=0,t||j(e,2,this.length),this[e]<<8|this[e+1]},t.prototype.readUInt32LE=function(e,t){return e>>>=0,t||j(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},t.prototype.readUInt32BE=function(e,t){return e>>>=0,t||j(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},t.prototype.readIntLE=function(e,t,r){e>>>=0,t>>>=0,r||j(e,t,this.length);for(var n=this[e],i=1,o=0;++o=(i*=128)&&(n-=Math.pow(2,8*t)),n},t.prototype.readIntBE=function(e,t,r){e>>>=0,t>>>=0,r||j(e,t,this.length);for(var n=t,i=1,o=this[e+--n];n>0&&(i*=256);)o+=this[e+--n]*i;return o>=(i*=128)&&(o-=Math.pow(2,8*t)),o},t.prototype.readInt8=function(e,t){return e>>>=0,t||j(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},t.prototype.readInt16LE=function(e,t){e>>>=0,t||j(e,2,this.length);var r=this[e]|this[e+1]<<8;return 32768&r?4294901760|r:r},t.prototype.readInt16BE=function(e,t){e>>>=0,t||j(e,2,this.length);var r=this[e+1]|this[e]<<8;return 32768&r?4294901760|r:r},t.prototype.readInt32LE=function(e,t){return e>>>=0,t||j(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},t.prototype.readInt32BE=function(e,t){return e>>>=0,t||j(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},t.prototype.readFloatLE=function(e,t){return e>>>=0,t||j(e,4,this.length),i.read(this,e,!0,23,4)},t.prototype.readFloatBE=function(e,t){return e>>>=0,t||j(e,4,this.length),i.read(this,e,!1,23,4)},t.prototype.readDoubleLE=function(e,t){return e>>>=0,t||j(e,8,this.length),i.read(this,e,!0,52,8)},t.prototype.readDoubleBE=function(e,t){return e>>>=0,t||j(e,8,this.length),i.read(this,e,!1,52,8)},t.prototype.writeUIntLE=function(e,t,r,n){(e=+e,t>>>=0,r>>>=0,n)||A(this,e,t,r,Math.pow(2,8*r)-1,0);var i=1,o=0;for(this[t]=255&e;++o>>=0,r>>>=0,n)||A(this,e,t,r,Math.pow(2,8*r)-1,0);var i=r-1,o=1;for(this[t+i]=255&e;--i>=0&&(o*=256);)this[t+i]=e/o&255;return t+r},t.prototype.writeUInt8=function(e,t,r){return e=+e,t>>>=0,r||A(this,e,t,1,255,0),this[t]=255&e,t+1},t.prototype.writeUInt16LE=function(e,t,r){return e=+e,t>>>=0,r||A(this,e,t,2,65535,0),this[t]=255&e,this[t+1]=e>>>8,t+2},t.prototype.writeUInt16BE=function(e,t,r){return e=+e,t>>>=0,r||A(this,e,t,2,65535,0),this[t]=e>>>8,this[t+1]=255&e,t+2},t.prototype.writeUInt32LE=function(e,t,r){return e=+e,t>>>=0,r||A(this,e,t,4,4294967295,0),this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e,t+4},t.prototype.writeUInt32BE=function(e,t,r){return e=+e,t>>>=0,r||A(this,e,t,4,4294967295,0),this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e,t+4},t.prototype.writeIntLE=function(e,t,r,n){if(e=+e,t>>>=0,!n){var i=Math.pow(2,8*r-1);A(this,e,t,r,i-1,-i)}var o=0,s=1,a=0;for(this[t]=255&e;++o>0)-a&255;return t+r},t.prototype.writeIntBE=function(e,t,r,n){if(e=+e,t>>>=0,!n){var i=Math.pow(2,8*r-1);A(this,e,t,r,i-1,-i)}var o=r-1,s=1,a=0;for(this[t+o]=255&e;--o>=0&&(s*=256);)e<0&&0===a&&0!==this[t+o+1]&&(a=1),this[t+o]=(e/s>>0)-a&255;return t+r},t.prototype.writeInt8=function(e,t,r){return e=+e,t>>>=0,r||A(this,e,t,1,127,-128),e<0&&(e=255+e+1),this[t]=255&e,t+1},t.prototype.writeInt16LE=function(e,t,r){return e=+e,t>>>=0,r||A(this,e,t,2,32767,-32768),this[t]=255&e,this[t+1]=e>>>8,t+2},t.prototype.writeInt16BE=function(e,t,r){return e=+e,t>>>=0,r||A(this,e,t,2,32767,-32768),this[t]=e>>>8,this[t+1]=255&e,t+2},t.prototype.writeInt32LE=function(e,t,r){return e=+e,t>>>=0,r||A(this,e,t,4,2147483647,-2147483648),this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24,t+4},t.prototype.writeInt32BE=function(e,t,r){return e=+e,t>>>=0,r||A(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e,t+4},t.prototype.writeFloatLE=function(e,t,r){return P(this,e,t,!0,r)},t.prototype.writeFloatBE=function(e,t,r){return P(this,e,t,!1,r)},t.prototype.writeDoubleLE=function(e,t,r){return M(this,e,t,!0,r)},t.prototype.writeDoubleBE=function(e,t,r){return M(this,e,t,!1,r)},t.prototype.copy=function(e,r,n,i){if(!t.isBuffer(e))throw new TypeError("argument should be a Buffer");if(n||(n=0),i||0===i||(i=this.length),r>=e.length&&(r=e.length),r||(r=0),i>0&&i=this.length)throw new RangeError("Index out of range");if(i<0)throw new RangeError("sourceEnd out of bounds");i>this.length&&(i=this.length),e.length-r=0;--s)e[s+r]=this[s+n];else Uint8Array.prototype.set.call(e,this.subarray(n,i),r);return o},t.prototype.fill=function(e,r,n,i){if("string"==typeof e){if("string"==typeof r?(i=r,r=0,n=this.length):"string"==typeof n&&(i=n,n=this.length),void 0!==i&&"string"!=typeof i)throw new TypeError("encoding must be a string");if("string"==typeof i&&!t.isEncoding(i))throw new TypeError("Unknown encoding: "+i);if(1===e.length){var o=e.charCodeAt(0);("utf8"===i&&o<128||"latin1"===i)&&(e=o)}}else"number"==typeof e&&(e&=255);if(r<0||this.length>>=0,n=void 0===n?this.length:n>>>0,e||(e=0),"number"==typeof e)for(s=r;s55295&&r<57344){if(!i){if(r>56319){(t-=3)>-1&&o.push(239,191,189);continue}if(s+1===n){(t-=3)>-1&&o.push(239,191,189);continue}i=r;continue}if(r<56320){(t-=3)>-1&&o.push(239,191,189),i=r;continue}r=65536+(i-55296<<10|r-56320)}else i&&(t-=3)>-1&&o.push(239,191,189);if(i=null,r<128){if((t-=1)<0)break;o.push(r)}else if(r<2048){if((t-=2)<0)break;o.push(r>>6|192,63&r|128)}else if(r<65536){if((t-=3)<0)break;o.push(r>>12|224,r>>6&63|128,63&r|128)}else{if(!(r<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;o.push(r>>18|240,r>>12&63|128,r>>6&63|128,63&r|128)}}return o}function U(e){return n.toByteArray(function(e){if((e=(e=e.split("=")[0]).trim().replace(B,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function L(e,t,r,n){for(var i=0;i=t.length||i>=e.length);++i)t[i+r]=e[i];return i}function q(e,t){return e instanceof t||null!=e&&null!=e.constructor&&null!=e.constructor.name&&e.constructor.name===t.name}function F(e){return e!=e}}).call(this,e("buffer").Buffer)},{"base64-js":10,buffer:13,ieee754:87}],14:[function(e,t,r){(function(e){function t(e){return Object.prototype.toString.call(e)}r.isArray=function(e){return Array.isArray?Array.isArray(e):"[object Array]"===t(e)},r.isBoolean=function(e){return"boolean"==typeof e},r.isNull=function(e){return null===e},r.isNullOrUndefined=function(e){return null==e},r.isNumber=function(e){return"number"==typeof e},r.isString=function(e){return"string"==typeof e},r.isSymbol=function(e){return"symbol"==typeof e},r.isUndefined=function(e){return void 0===e},r.isRegExp=function(e){return"[object RegExp]"===t(e)},r.isObject=function(e){return"object"==typeof e&&null!==e},r.isDate=function(e){return"[object Date]"===t(e)},r.isError=function(e){return"[object Error]"===t(e)||e instanceof Error},r.isFunction=function(e){return"function"==typeof e},r.isPrimitive=function(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||void 0===e},r.isBuffer=e.isBuffer}).call(this,{isBuffer:e("../../is-buffer/index.js")})},{"../../is-buffer/index.js":89}],15:[function(e,t,r){"use strict";var n,i=e("type/value/is"),o=e("type/value/ensure"),s=e("type/plain-function/ensure"),a=e("es5-ext/object/copy"),c=e("es5-ext/object/normalize-options"),u=e("es5-ext/object/map"),l=Function.prototype.bind,f=Object.defineProperty,p=Object.prototype.hasOwnProperty;n=function(e,t,r){var n,i=o(t)&&s(t.value);return delete(n=a(t)).writable,delete n.value,n.get=function(){return!r.overwriteDefinition&&p.call(this,e)?i:(t.value=l.call(i,r.resolveContext?r.resolveContext(this):this),f(this,e,t),this[e])},n},t.exports=function(e){var t=c(arguments[1]);return i(t.resolveContext)&&s(t.resolveContext),u(e,function(e,r){return n(r,e,t)})}},{"es5-ext/object/copy":41,"es5-ext/object/map":49,"es5-ext/object/normalize-options":50,"type/plain-function/ensure":126,"type/value/ensure":130,"type/value/is":131}],16:[function(e,t,r){"use strict";var n=e("type/value/is"),i=e("type/plain-function/is"),o=e("es5-ext/object/assign"),s=e("es5-ext/object/normalize-options"),a=e("es5-ext/string/#/contains");(t.exports=function(e,t){var r,i,c,u,l;return arguments.length<2||"string"!=typeof e?(u=t,t=e,e=null):u=arguments[2],n(e)?(r=a.call(e,"c"),i=a.call(e,"e"),c=a.call(e,"w")):(r=c=!0,i=!1),l={value:t,configurable:r,enumerable:i,writable:c},u?o(s(u),l):l}).gs=function(e,t,r){var c,u,l,f;return"string"!=typeof e?(l=r,r=t,t=e,e=null):l=arguments[3],n(t)?i(t)?n(r)?i(r)||(l=r,r=void 0):r=void 0:(l=t,t=r=void 0):t=void 0,n(e)?(c=a.call(e,"c"),u=a.call(e,"e")):(c=!0,u=!1),f={get:t,set:r,configurable:c,enumerable:u},l?o(s(l),f):f}},{"es5-ext/object/assign":38,"es5-ext/object/normalize-options":50,"es5-ext/string/#/contains":57,"type/plain-function/is":127,"type/value/is":131}],17:[function(e,t,r){(function(n){r.log=function(...e){return"object"==typeof console&&console.log&&console.log(...e)},r.formatArgs=function(e){if(e[0]=(this.useColors?"%c":"")+this.namespace+(this.useColors?" %c":" ")+e[0]+(this.useColors?"%c ":" ")+"+"+t.exports.humanize(this.diff),!this.useColors)return;const r="color: "+this.color;e.splice(1,0,r,"color: inherit");let n=0,i=0;e[0].replace(/%[a-zA-Z%]/g,e=>{"%%"!==e&&"%c"===e&&(i=++n)}),e.splice(i,0,r)},r.save=function(e){try{e?r.storage.setItem("debug",e):r.storage.removeItem("debug")}catch(e){}},r.load=function(){let e;try{e=r.storage.getItem("debug")}catch(e){}!e&&void 0!==n&&"env"in n&&(e=n.env.DEBUG);return e},r.useColors=function(){if("undefined"!=typeof window&&window.process&&("renderer"===window.process.type||window.process.__nwjs))return!0;if("undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/))return!1;return"undefined"!=typeof document&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||"undefined"!=typeof window&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||"undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)&&parseInt(RegExp.$1,10)>=31||"undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)},r.storage=function(){try{return localStorage}catch(e){}}(),r.colors=["#0000CC","#0000FF","#0033CC","#0033FF","#0066CC","#0066FF","#0099CC","#0099FF","#00CC00","#00CC33","#00CC66","#00CC99","#00CCCC","#00CCFF","#3300CC","#3300FF","#3333CC","#3333FF","#3366CC","#3366FF","#3399CC","#3399FF","#33CC00","#33CC33","#33CC66","#33CC99","#33CCCC","#33CCFF","#6600CC","#6600FF","#6633CC","#6633FF","#66CC00","#66CC33","#9900CC","#9900FF","#9933CC","#9933FF","#99CC00","#99CC33","#CC0000","#CC0033","#CC0066","#CC0099","#CC00CC","#CC00FF","#CC3300","#CC3333","#CC3366","#CC3399","#CC33CC","#CC33FF","#CC6600","#CC6633","#CC9900","#CC9933","#CCCC00","#CCCC33","#FF0000","#FF0033","#FF0066","#FF0099","#FF00CC","#FF00FF","#FF3300","#FF3333","#FF3366","#FF3399","#FF33CC","#FF33FF","#FF6600","#FF6633","#FF9900","#FF9933","#FFCC00","#FFCC33"],t.exports=e("./common")(r);const{formatters:i}=t.exports;i.j=function(e){try{return JSON.stringify(e)}catch(e){return"[UnexpectedJSONParseError]: "+e.message}}}).call(this,e("_process"))},{"./common":18,_process:101}],18:[function(e,t,r){t.exports=function(t){function r(e){let t=0;for(let r=0;r{if("%%"===t)return t;a++;const o=n.formatters[i];if("function"==typeof o){const n=e[a];t=o.call(r,n),e.splice(a,1),a--}return t}),n.formatArgs.call(r,e),(r.log||n.log).apply(r,e)}return s.namespace=e,s.enabled=n.enabled(e),s.useColors=n.useColors(),s.color=r(e),s.destroy=i,s.extend=o,"function"==typeof n.init&&n.init(s),n.instances.push(s),s}function i(){const e=n.instances.indexOf(this);return-1!==e&&(n.instances.splice(e,1),!0)}function o(e,t){const r=n(this.namespace+(void 0===t?":":t)+e);return r.log=this.log,r}function s(e){return e.toString().substring(2,e.toString().length-2).replace(/\.\*\?$/,"*")}return n.debug=n,n.default=n,n.coerce=function(e){return e instanceof Error?e.stack||e.message:e},n.disable=function(){const e=[...n.names.map(s),...n.skips.map(s).map(e=>"-"+e)].join(",");return n.enable(""),e},n.enable=function(e){let t;n.save(e),n.names=[],n.skips=[];const r=("string"==typeof e?e:"").split(/[\s,]+/),i=r.length;for(t=0;t{n[e]=t[e]}),n.instances=[],n.names=[],n.skips=[],n.formatters={},n.selectColor=r,n.enable(n.load()),n}},{ms:98}],19:[function(e,t,r){(function(r,n){var i=e("readable-stream"),o=e("end-of-stream"),s=e("inherits"),a=e("stream-shift"),c=n.from&&n.from!==Uint8Array.from?n.from([0]):new n([0]),u=function(e,t){e._corked?e.once("uncork",t):t()},l=function(e,t){return function(r){r?function(e,t){e._autoDestroy&&e.destroy(t)}(e,"premature close"===r.message?null:r):t&&!e._ended&&e.end()}},f=function(e,t,r){if(!(this instanceof f))return new f(e,t,r);i.Duplex.call(this,r),this._writable=null,this._readable=null,this._readable2=null,this._autoDestroy=!r||!1!==r.autoDestroy,this._forwardDestroy=!r||!1!==r.destroy,this._forwardEnd=!r||!1!==r.end,this._corked=1,this._ondrain=null,this._drained=!1,this._forwarding=!1,this._unwrite=null,this._unread=null,this._ended=!1,this.destroyed=!1,e&&this.setWritable(e),t&&this.setReadable(t)};s(f,i.Duplex),f.obj=function(e,t,r){return r||(r={}),r.objectMode=!0,r.highWaterMark=16,new f(e,t,r)},f.prototype.cork=function(){1==++this._corked&&this.emit("cork")},f.prototype.uncork=function(){this._corked&&0==--this._corked&&this.emit("uncork")},f.prototype.setWritable=function(e){if(this._unwrite&&this._unwrite(),this.destroyed)e&&e.destroy&&e.destroy();else if(null!==e&&!1!==e){var t=this,n=o(e,{writable:!0,readable:!1},l(this,this._forwardEnd)),i=function(){var e=t._ondrain;t._ondrain=null,e&&e()};this._unwrite&&r.nextTick(i),this._writable=e,this._writable.on("drain",i),this._unwrite=function(){t._writable.removeListener("drain",i),n()},this.uncork()}else this.end()},f.prototype.setReadable=function(e){if(this._unread&&this._unread(),this.destroyed)e&&e.destroy&&e.destroy();else{if(null===e||!1===e)return this.push(null),void this.resume();var t,r=this,n=o(e,{writable:!1,readable:!0},l(this)),s=function(){r._forward()},a=function(){r.push(null)};this._drained=!0,this._readable=e,this._readable2=e._readableState?e:(t=e,new i.Readable({objectMode:!0,highWaterMark:16}).wrap(t)),this._readable2.on("readable",s),this._readable2.on("end",a),this._unread=function(){r._readable2.removeListener("readable",s),r._readable2.removeListener("end",a),n()},this._forward()}},f.prototype._read=function(){this._drained=!0,this._forward()},f.prototype._forward=function(){if(!this._forwarding&&this._readable2&&this._drained){var e;for(this._forwarding=!0;this._drained&&null!==(e=a(this._readable2));)this.destroyed||(this._drained=this.push(e));this._forwarding=!1}},f.prototype.destroy=function(e){if(!this.destroyed){this.destroyed=!0;var t=this;r.nextTick(function(){t._destroy(e)})}},f.prototype._destroy=function(e){if(e){var t=this._ondrain;this._ondrain=null,t?t(e):this.emit("error",e)}this._forwardDestroy&&(this._readable&&this._readable.destroy&&this._readable.destroy(),this._writable&&this._writable.destroy&&this._writable.destroy()),this.emit("close")},f.prototype._write=function(e,t,r){return this.destroyed?r():this._corked?u(this,this._write.bind(this,e,t,r)):e===c?this._finish(r):this._writable?void(!1===this._writable.write(e)?this._ondrain=r:r()):r()},f.prototype._finish=function(e){var t=this;this.emit("preend"),u(this,function(){var r,n;r=t._forwardEnd&&t._writable,n=function(){!1===t._writableState.prefinished&&(t._writableState.prefinished=!0),t.emit("prefinish"),u(t,e)},r?r._writableState&&r._writableState.finished?n():r._writableState?r.end(n):(r.end(),n()):n()})},f.prototype.end=function(e,t,r){return"function"==typeof e?this.end(null,null,e):"function"==typeof t?this.end(e,null,t):(this._ended=!0,e&&this.write(e),this._writableState.ending||this.write(c),i.Writable.prototype.end.call(this,r))},t.exports=f}).call(this,e("_process"),e("buffer").Buffer)},{_process:101,buffer:13,"end-of-stream":20,inherits:88,"readable-stream":115,"stream-shift":118}],20:[function(e,t,r){(function(r){var n=e("once"),i=function(){},o=function(e,t,s){if("function"==typeof t)return o(e,null,t);t||(t={}),s=n(s||i);var a=e._writableState,c=e._readableState,u=t.readable||!1!==t.readable&&e.readable,l=t.writable||!1!==t.writable&&e.writable,f=!1,p=function(){e.writable||h()},h=function(){l=!1,u||s.call(e)},d=function(){u=!1,l||s.call(e)},g=function(t){s.call(e,t?new Error("exited with error code: "+t):null)},b=function(t){s.call(e,t)},m=function(){r.nextTick(y)},y=function(){if(!f)return(!u||c&&c.ended&&!c.destroyed)&&(!l||a&&a.ended&&!a.destroyed)?void 0:s.call(e,new Error("premature close"))},_=function(){e.req.on("finish",h)};return!function(e){return e.setHeader&&"function"==typeof e.abort}(e)?l&&!a&&(e.on("end",p),e.on("close",p)):(e.on("complete",h),e.on("abort",m),e.req?_():e.on("request",_)),function(e){return e.stdio&&Array.isArray(e.stdio)&&3===e.stdio.length}(e)&&e.on("exit",g),e.on("end",d),e.on("finish",h),!1!==t.error&&e.on("error",b),e.on("close",m),function(){f=!0,e.removeListener("complete",h),e.removeListener("abort",m),e.removeListener("request",_),e.req&&e.req.removeListener("finish",h),e.removeListener("end",p),e.removeListener("close",p),e.removeListener("finish",h),e.removeListener("exit",g),e.removeListener("end",d),e.removeListener("error",b),e.removeListener("close",m)}};t.exports=o}).call(this,e("_process"))},{_process:101,once:99}],21:[function(e,t,r){"use strict";var n=e("../../object/valid-value");t.exports=function(){return n(this).length=0,this}},{"../../object/valid-value":56}],22:[function(e,t,r){"use strict";var n=e("../../number/is-nan"),i=e("../../number/to-pos-integer"),o=e("../../object/valid-value"),s=Array.prototype.indexOf,a=Object.prototype.hasOwnProperty,c=Math.abs,u=Math.floor;t.exports=function(e){var t,r,l,f;if(!n(e))return s.apply(this,arguments);for(r=i(o(this).length),l=arguments[1],t=l=isNaN(l)?0:l>=0?u(l):i(this.length)-u(c(l));t=55296&&y<=56319&&(S+=e[++r]),S=k?p.call(k,x,S,g):S,t?(h.value=S,d(b,g,h)):b[g]=S,++g;m=g}if(void 0===m)for(m=s(e.length),t&&(b=new t(m)),r=0;r0?1:-1}},{}],32:[function(e,t,r){"use strict";t.exports=e("./is-implemented")()?Number.isNaN:e("./shim")},{"./is-implemented":33,"./shim":34}],33:[function(e,t,r){"use strict";t.exports=function(){var e=Number.isNaN;return"function"==typeof e&&(!e({})&&e(NaN)&&!e(34))}},{}],34:[function(e,t,r){"use strict";t.exports=function(e){return e!=e}},{}],35:[function(e,t,r){"use strict";var n=e("../math/sign"),i=Math.abs,o=Math.floor;t.exports=function(e){return isNaN(e)?0:0!==(e=Number(e))&&isFinite(e)?n(e)*o(i(e)):e}},{"../math/sign":29}],36:[function(e,t,r){"use strict";var n=e("./to-integer"),i=Math.max;t.exports=function(e){return i(0,n(e))}},{"./to-integer":35}],37:[function(e,t,r){"use strict";var n=e("./valid-callable"),i=e("./valid-value"),o=Function.prototype.bind,s=Function.prototype.call,a=Object.keys,c=Object.prototype.propertyIsEnumerable;t.exports=function(e,t){return function(r,u){var l,f=arguments[2],p=arguments[3];return r=Object(i(r)),n(u),l=a(r),p&&l.sort("function"==typeof p?o.call(p,r):void 0),"function"!=typeof e&&(e=l[e]),s.call(e,l,function(e,n){return c.call(r,e)?s.call(u,f,r[e],e,r,n):t})}}},{"./valid-callable":55,"./valid-value":56}],38:[function(e,t,r){"use strict";t.exports=e("./is-implemented")()?Object.assign:e("./shim")},{"./is-implemented":39,"./shim":40}],39:[function(e,t,r){"use strict";t.exports=function(){var e,t=Object.assign;return"function"==typeof t&&(t(e={foo:"raz"},{bar:"dwa"},{trzy:"trzy"}),e.foo+e.bar+e.trzy==="razdwatrzy")}},{}],40:[function(e,t,r){"use strict";var n=e("../keys"),i=e("../valid-value"),o=Math.max;t.exports=function(e,t){var r,s,a,c=o(arguments.length,2);for(e=Object(i(e)),a=function(n){try{e[n]=t[n]}catch(e){r||(r=e)}},s=1;s-1}},{}],60:[function(e,t,r){"use strict";var n=Object.prototype.toString,i=n.call("");t.exports=function(e){return"string"==typeof e||e&&"object"==typeof e&&(e instanceof String||n.call(e)===i)||!1}},{}],61:[function(e,t,r){"use strict";var n,i=e("es5-ext/object/set-prototype-of"),o=e("es5-ext/string/#/contains"),s=e("d"),a=e("es6-symbol"),c=e("./"),u=Object.defineProperty;n=t.exports=function(e,t){if(!(this instanceof n))throw new TypeError("Constructor requires 'new'");c.call(this,e),t=t?o.call(t,"key+value")?"key+value":o.call(t,"key")?"key":"value":"value",u(this,"__kind__",s("",t))},i&&i(n,c),delete n.prototype.constructor,n.prototype=Object.create(c.prototype,{_resolve:s(function(e){return"value"===this.__kind__?this.__list__[e]:"key+value"===this.__kind__?[e,this.__list__[e]]:e})}),u(n.prototype,a.toStringTag,s("c","Array Iterator"))},{"./":64,d:16,"es5-ext/object/set-prototype-of":52,"es5-ext/string/#/contains":57,"es6-symbol":74}],62:[function(e,t,r){"use strict";var n=e("es5-ext/function/is-arguments"),i=e("es5-ext/object/valid-callable"),o=e("es5-ext/string/is-string"),s=e("./get"),a=Array.isArray,c=Function.prototype.call,u=Array.prototype.some;t.exports=function(e,t){var r,l,f,p,h,d,g,b,m=arguments[2];if(a(e)||n(e)?r="array":o(e)?r="string":e=s(e),i(t),f=function(){p=!0},"array"!==r)if("string"!==r)for(l=e.next();!l.done;){if(c.call(t,m,l.value,f),p)return;l=e.next()}else for(d=e.length,h=0;h=55296&&b<=56319&&(g+=e[++h]),c.call(t,m,g,f),!p);++h);else u.call(e,function(e){return c.call(t,m,e,f),p})}},{"./get":63,"es5-ext/function/is-arguments":26,"es5-ext/object/valid-callable":55,"es5-ext/string/is-string":60}],63:[function(e,t,r){"use strict";var n=e("es5-ext/function/is-arguments"),i=e("es5-ext/string/is-string"),o=e("./array"),s=e("./string"),a=e("./valid-iterable"),c=e("es6-symbol").iterator;t.exports=function(e){return"function"==typeof a(e)[c]?e[c]():n(e)?new o(e):i(e)?new s(e):new o(e)}},{"./array":61,"./string":66,"./valid-iterable":67,"es5-ext/function/is-arguments":26,"es5-ext/string/is-string":60,"es6-symbol":74}],64:[function(e,t,r){"use strict";var n,i=e("es5-ext/array/#/clear"),o=e("es5-ext/object/assign"),s=e("es5-ext/object/valid-callable"),a=e("es5-ext/object/valid-value"),c=e("d"),u=e("d/auto-bind"),l=e("es6-symbol"),f=Object.defineProperty,p=Object.defineProperties;t.exports=n=function(e,t){if(!(this instanceof n))throw new TypeError("Constructor requires 'new'");p(this,{__list__:c("w",a(e)),__context__:c("w",t),__nextIndex__:c("w",0)}),t&&(s(t.on),t.on("_add",this._onAdd),t.on("_delete",this._onDelete),t.on("_clear",this._onClear))},delete n.prototype.constructor,p(n.prototype,o({_next:c(function(){var e;if(this.__list__)return this.__redo__&&void 0!==(e=this.__redo__.shift())?e:this.__nextIndex__=this.__nextIndex__||(++this.__nextIndex__,this.__redo__?(this.__redo__.forEach(function(t,r){t>=e&&(this.__redo__[r]=++t)},this),this.__redo__.push(e)):f(this,"__redo__",c("c",[e])))}),_onDelete:c(function(e){var t;e>=this.__nextIndex__||(--this.__nextIndex__,this.__redo__&&(-1!==(t=this.__redo__.indexOf(e))&&this.__redo__.splice(t,1),this.__redo__.forEach(function(t,r){t>e&&(this.__redo__[r]=--t)},this)))}),_onClear:c(function(){this.__redo__&&i.call(this.__redo__),this.__nextIndex__=0})}))),f(n.prototype,l.iterator,c(function(){return this}))},{d:16,"d/auto-bind":15,"es5-ext/array/#/clear":21,"es5-ext/object/assign":38,"es5-ext/object/valid-callable":55,"es5-ext/object/valid-value":56,"es6-symbol":74}],65:[function(e,t,r){"use strict";var n=e("es5-ext/function/is-arguments"),i=e("es5-ext/object/is-value"),o=e("es5-ext/string/is-string"),s=e("es6-symbol").iterator,a=Array.isArray;t.exports=function(e){return!!i(e)&&(!!a(e)||(!!o(e)||(!!n(e)||"function"==typeof e[s])))}},{"es5-ext/function/is-arguments":26,"es5-ext/object/is-value":45,"es5-ext/string/is-string":60,"es6-symbol":74}],66:[function(e,t,r){"use strict";var n,i=e("es5-ext/object/set-prototype-of"),o=e("d"),s=e("es6-symbol"),a=e("./"),c=Object.defineProperty;n=t.exports=function(e){if(!(this instanceof n))throw new TypeError("Constructor requires 'new'");e=String(e),a.call(this,e),c(this,"__length__",o("",e.length))},i&&i(n,a),delete n.prototype.constructor,n.prototype=Object.create(a.prototype,{_next:o(function(){if(this.__list__)return this.__nextIndex__=55296&&t<=56319?r+this.__list__[this.__nextIndex__++]:r})}),c(n.prototype,s.toStringTag,o("c","String Iterator"))},{"./":64,d:16,"es5-ext/object/set-prototype-of":52,"es6-symbol":74}],67:[function(e,t,r){"use strict";var n=e("./is-iterable");t.exports=function(e){if(!n(e))throw new TypeError(e+" is not iterable");return e}},{"./is-iterable":65}],68:[function(e,t,r){"use strict";t.exports=e("./is-implemented")()?Map:e("./polyfill")},{"./is-implemented":69,"./polyfill":73}],69:[function(e,t,r){"use strict";t.exports=function(){var e,t;if("function"!=typeof Map)return!1;try{e=new Map([["raz","one"],["dwa","two"],["trzy","three"]])}catch(e){return!1}return"[object Map]"===String(e)&&(3===e.size&&("function"==typeof e.clear&&("function"==typeof e.delete&&("function"==typeof e.entries&&("function"==typeof e.forEach&&("function"==typeof e.get&&("function"==typeof e.has&&("function"==typeof e.keys&&("function"==typeof e.set&&("function"==typeof e.values&&(!1===(t=e.entries().next()).done&&(!!t.value&&("raz"===t.value[0]&&"one"===t.value[1])))))))))))))}},{}],70:[function(e,t,r){"use strict";t.exports="undefined"!=typeof Map&&"[object Map]"===Object.prototype.toString.call(new Map)},{}],71:[function(e,t,r){"use strict";t.exports=e("es5-ext/object/primitive-set")("key","value","key+value")},{"es5-ext/object/primitive-set":51}],72:[function(e,t,r){"use strict";var n,i=e("es5-ext/object/set-prototype-of"),o=e("d"),s=e("es6-iterator"),a=e("es6-symbol").toStringTag,c=e("./iterator-kinds"),u=Object.defineProperties,l=s.prototype._unBind;n=t.exports=function(e,t){if(!(this instanceof n))return new n(e,t);s.call(this,e.__mapKeysData__,e),t&&c[t]||(t="key+value"),u(this,{__kind__:o("",t),__values__:o("w",e.__mapValuesData__)})},i&&i(n,s),n.prototype=Object.create(s.prototype,{constructor:o(n),_resolve:o(function(e){return"value"===this.__kind__?this.__values__[e]:"key"===this.__kind__?this.__list__[e]:[this.__list__[e],this.__values__[e]]}),_unBind:o(function(){this.__values__=null,l.call(this)}),toString:o(function(){return"[object Map Iterator]"})}),Object.defineProperty(n.prototype,a,o("c","Map Iterator"))},{"./iterator-kinds":71,d:16,"es5-ext/object/set-prototype-of":52,"es6-iterator":64,"es6-symbol":74}],73:[function(e,t,r){"use strict";var n,i=e("es5-ext/array/#/clear"),o=e("es5-ext/array/#/e-index-of"),s=e("es5-ext/object/set-prototype-of"),a=e("es5-ext/object/valid-callable"),c=e("es5-ext/object/valid-value"),u=e("d"),l=e("event-emitter"),f=e("es6-symbol"),p=e("es6-iterator/valid-iterable"),h=e("es6-iterator/for-of"),d=e("./lib/iterator"),g=e("./is-native-implemented"),b=Function.prototype.call,m=Object.defineProperties,y=Object.getPrototypeOf;t.exports=n=function(){var e,t,r,i=arguments[0];if(!(this instanceof n))throw new TypeError("Constructor requires 'new'");return r=g&&s&&Map!==n?s(new Map,y(this)):this,null!=i&&p(i),m(r,{__mapKeysData__:u("c",e=[]),__mapValuesData__:u("c",t=[])}),i?(h(i,function(r){var n=c(r)[0];r=r[1],-1===o.call(e,n)&&(e.push(n),t.push(r))},r),r):r},g&&(s&&s(n,Map),n.prototype=Object.create(Map.prototype,{constructor:u(n)})),l(m(n.prototype,{clear:u(function(){this.__mapKeysData__.length&&(i.call(this.__mapKeysData__),i.call(this.__mapValuesData__),this.emit("_clear"))}),delete:u(function(e){var t=o.call(this.__mapKeysData__,e);return-1!==t&&(this.__mapKeysData__.splice(t,1),this.__mapValuesData__.splice(t,1),this.emit("_delete",t,e),!0)}),entries:u(function(){return new d(this,"key+value")}),forEach:u(function(e){var t,r,n=arguments[1];for(a(e),r=(t=this.entries())._next();void 0!==r;)b.call(e,n,this.__mapValuesData__[r],this.__mapKeysData__[r],this),r=t._next()}),get:u(function(e){var t=o.call(this.__mapKeysData__,e);if(-1!==t)return this.__mapValuesData__[t]}),has:u(function(e){return-1!==o.call(this.__mapKeysData__,e)}),keys:u(function(){return new d(this,"key")}),set:u(function(e,t){var r,n=o.call(this.__mapKeysData__,e);return-1===n&&(n=this.__mapKeysData__.push(e)-1,r=!0),this.__mapValuesData__[n]=t,r&&this.emit("_add",n,e),this}),size:u.gs(function(){return this.__mapKeysData__.length}),values:u(function(){return new d(this,"value")}),toString:u(function(){return"[object Map]"})})),Object.defineProperty(n.prototype,f.iterator,u(function(){return this.entries()})),Object.defineProperty(n.prototype,f.toStringTag,u("c","Map"))},{"./is-native-implemented":70,"./lib/iterator":72,d:16,"es5-ext/array/#/clear":21,"es5-ext/array/#/e-index-of":22,"es5-ext/object/set-prototype-of":52,"es5-ext/object/valid-callable":55,"es5-ext/object/valid-value":56,"es6-iterator/for-of":62,"es6-iterator/valid-iterable":67,"es6-symbol":74,"event-emitter":82}],74:[function(e,t,r){"use strict";t.exports=e("./is-implemented")()?e("ext/global-this").Symbol:e("./polyfill")},{"./is-implemented":75,"./polyfill":80,"ext/global-this":85}],75:[function(e,t,r){"use strict";var n=e("ext/global-this"),i={object:!0,symbol:!0};t.exports=function(){var e,t=n.Symbol;if("function"!=typeof t)return!1;e=t("test symbol");try{String(e)}catch(e){return!1}return!!i[typeof t.iterator]&&(!!i[typeof t.toPrimitive]&&!!i[typeof t.toStringTag])}},{"ext/global-this":85}],76:[function(e,t,r){"use strict";t.exports=function(e){return!!e&&("symbol"==typeof e||!!e.constructor&&("Symbol"===e.constructor.name&&"Symbol"===e[e.constructor.toStringTag]))}},{}],77:[function(e,t,r){"use strict";var n=e("d"),i=Object.create,o=Object.defineProperty,s=Object.prototype,a=i(null);t.exports=function(e){for(var t,r,i=0;a[e+(i||"")];)++i;return a[e+=i||""]=!0,o(s,t="@@"+e,n.gs(null,function(e){r||(r=!0,o(this,t,n(e)),r=!1)})),t}},{d:16}],78:[function(e,t,r){"use strict";var n=e("d"),i=e("ext/global-this").Symbol;t.exports=function(e){return Object.defineProperties(e,{hasInstance:n("",i&&i.hasInstance||e("hasInstance")),isConcatSpreadable:n("",i&&i.isConcatSpreadable||e("isConcatSpreadable")),iterator:n("",i&&i.iterator||e("iterator")),match:n("",i&&i.match||e("match")),replace:n("",i&&i.replace||e("replace")),search:n("",i&&i.search||e("search")),species:n("",i&&i.species||e("species")),split:n("",i&&i.split||e("split")),toPrimitive:n("",i&&i.toPrimitive||e("toPrimitive")),toStringTag:n("",i&&i.toStringTag||e("toStringTag")),unscopables:n("",i&&i.unscopables||e("unscopables"))})}},{d:16,"ext/global-this":85}],79:[function(e,t,r){"use strict";var n=e("d"),i=e("../../../validate-symbol"),o=Object.create(null);t.exports=function(e){return Object.defineProperties(e,{for:n(function(t){return o[t]?o[t]:o[t]=e(String(t))}),keyFor:n(function(e){var t;for(t in i(e),o)if(o[t]===e)return t})})}},{"../../../validate-symbol":81,d:16}],80:[function(e,t,r){"use strict";var n,i,o,s=e("d"),a=e("./validate-symbol"),c=e("ext/global-this").Symbol,u=e("./lib/private/generate-name"),l=e("./lib/private/setup/standard-symbols"),f=e("./lib/private/setup/symbol-registry"),p=Object.create,h=Object.defineProperties,d=Object.defineProperty;if("function"==typeof c)try{String(c()),o=!0}catch(e){}else c=null;i=function(e){if(this instanceof i)throw new TypeError("Symbol is not a constructor");return n(e)},t.exports=n=function e(t){var r;if(this instanceof e)throw new TypeError("Symbol is not a constructor");return o?c(t):(r=p(i.prototype),t=void 0===t?"":String(t),h(r,{__description__:s("",t),__name__:s("",u(t))}))},l(n),f(n),h(i.prototype,{constructor:s(n),toString:s("",function(){return this.__name__})}),h(n.prototype,{toString:s(function(){return"Symbol ("+a(this).__description__+")"}),valueOf:s(function(){return a(this)})}),d(n.prototype,n.toPrimitive,s("",function(){var e=a(this);return"symbol"==typeof e?e:e.toString()})),d(n.prototype,n.toStringTag,s("c","Symbol")),d(i.prototype,n.toStringTag,s("c",n.prototype[n.toStringTag])),d(i.prototype,n.toPrimitive,s("c",n.prototype[n.toPrimitive]))},{"./lib/private/generate-name":77,"./lib/private/setup/standard-symbols":78,"./lib/private/setup/symbol-registry":79,"./validate-symbol":81,d:16,"ext/global-this":85}],81:[function(e,t,r){"use strict";var n=e("./is-symbol");t.exports=function(e){if(!n(e))throw new TypeError(e+" is not a symbol");return e}},{"./is-symbol":76}],82:[function(e,t,r){"use strict";var n,i,o,s,a,c,u,l=e("d"),f=e("es5-ext/object/valid-callable"),p=Function.prototype.apply,h=Function.prototype.call,d=Object.create,g=Object.defineProperty,b=Object.defineProperties,m=Object.prototype.hasOwnProperty,y={configurable:!0,enumerable:!1,writable:!0};a={on:n=function(e,t){var r;return f(t),m.call(this,"__ee__")?r=this.__ee__:(r=y.value=d(null),g(this,"__ee__",y),y.value=null),r[e]?"object"==typeof r[e]?r[e].push(t):r[e]=[r[e],t]:r[e]=t,this},once:i=function(e,t){var r,i;return f(t),i=this,n.call(this,e,r=function(){o.call(i,e,r),p.call(t,this,arguments)}),r.__eeOnceListener__=t,this},off:o=function(e,t){var r,n,i,o;if(f(t),!m.call(this,"__ee__"))return this;if(!(r=this.__ee__)[e])return this;if("object"==typeof(n=r[e]))for(o=0;i=n[o];++o)i!==t&&i.__eeOnceListener__!==t||(2===n.length?r[e]=n[o?0:1]:n.splice(o,1));else n!==t&&n.__eeOnceListener__!==t||delete r[e];return this},emit:s=function(e){var t,r,n,i,o;if(m.call(this,"__ee__")&&(i=this.__ee__[e]))if("object"==typeof i){for(r=arguments.length,o=new Array(r-1),t=1;t0&&a.length>o){a.warned=!0;var c=new Error("Possible EventEmitter memory leak detected. "+a.length+' "'+String(t)+'" listeners added. Use emitter.setMaxListeners() to increase limit.');c.name="MaxListenersExceededWarning",c.emitter=e,c.type=t,c.count=a.length,"object"==typeof console&&console.warn&&console.warn("%s: %s",c.name,c.message)}}else a=s[t]=r,++e._eventsCount;return e}function p(){if(!this.fired)switch(this.target.removeListener(this.type,this.wrapFn),this.fired=!0,arguments.length){case 0:return this.listener.call(this.target);case 1:return this.listener.call(this.target,arguments[0]);case 2:return this.listener.call(this.target,arguments[0],arguments[1]);case 3:return this.listener.call(this.target,arguments[0],arguments[1],arguments[2]);default:for(var e=new Array(arguments.length),t=0;t1&&(t=arguments[1]),t instanceof Error)throw t;var c=new Error('Unhandled "error" event. ('+t+")");throw c.context=t,c}if(!(r=s[e]))return!1;var u="function"==typeof r;switch(n=arguments.length){case 1:!function(e,t,r){if(t)e.call(r);else for(var n=e.length,i=b(e,n),o=0;o=0;s--)if(r[s]===t||r[s].listener===t){a=r[s].listener,o=s;break}if(o<0)return this;0===o?r.shift():function(e,t){for(var r=t,n=r+1,i=e.length;n=0;o--)this.removeListener(e,t[o]);return this},s.prototype.listeners=function(e){return d(this,e,!0)},s.prototype.rawListeners=function(e){return d(this,e,!1)},s.listenerCount=function(e,t){return"function"==typeof e.listenerCount?e.listenerCount(t):g.call(e,t)},s.prototype.listenerCount=g,s.prototype.eventNames=function(){return this._eventsCount>0?Reflect.ownKeys(this._events):[]}},{}],84:[function(e,t,r){var n=function(){if("object"==typeof self&&self)return self;if("object"==typeof window&&window)return window;throw new Error("Unable to resolve global `this`")};t.exports=function(){if(this)return this;try{Object.defineProperty(Object.prototype,"__global__",{get:function(){return this},configurable:!0})}catch(e){return n()}try{return __global__||n()}finally{delete Object.prototype.__global__}}()},{}],85:[function(e,t,r){"use strict";t.exports=e("./is-implemented")()?globalThis:e("./implementation")},{"./implementation":84,"./is-implemented":86}],86:[function(e,t,r){"use strict";t.exports=function(){return"object"==typeof globalThis&&(!!globalThis&&globalThis.Array===Array)}},{}],87:[function(e,t,r){r.read=function(e,t,r,n,i){var o,s,a=8*i-n-1,c=(1<>1,l=-7,f=r?i-1:0,p=r?-1:1,h=e[t+f];for(f+=p,o=h&(1<<-l)-1,h>>=-l,l+=a;l>0;o=256*o+e[t+f],f+=p,l-=8);for(s=o&(1<<-l)-1,o>>=-l,l+=n;l>0;s=256*s+e[t+f],f+=p,l-=8);if(0===o)o=1-u;else{if(o===c)return s?NaN:1/0*(h?-1:1);s+=Math.pow(2,n),o-=u}return(h?-1:1)*s*Math.pow(2,o-n)},r.write=function(e,t,r,n,i,o){var s,a,c,u=8*o-i-1,l=(1<>1,p=23===i?Math.pow(2,-24)-Math.pow(2,-77):0,h=n?0:o-1,d=n?1:-1,g=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(a=isNaN(t)?1:0,s=l):(s=Math.floor(Math.log(t)/Math.LN2),t*(c=Math.pow(2,-s))<1&&(s--,c*=2),(t+=s+f>=1?p/c:p*Math.pow(2,1-f))*c>=2&&(s++,c/=2),s+f>=l?(a=0,s=l):s+f>=1?(a=(t*c-1)*Math.pow(2,i),s+=f):(a=t*Math.pow(2,f-1)*Math.pow(2,i),s=0));i>=8;e[r+h]=255&a,h+=d,a/=256,i-=8);for(s=s<0;e[r+h]=255&s,h+=d,s/=256,u-=8);e[r+h-d]|=128*g}},{}],88:[function(e,t,r){"function"==typeof Object.create?t.exports=function(e,t){t&&(e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}))}:t.exports=function(e,t){if(t){e.super_=t;var r=function(){};r.prototype=t.prototype,e.prototype=new r,e.prototype.constructor=e}}},{}],89:[function(e,t,r){function n(e){return!!e.constructor&&"function"==typeof e.constructor.isBuffer&&e.constructor.isBuffer(e)}t.exports=function(e){return null!=e&&(n(e)||function(e){return"function"==typeof e.readFloatLE&&"function"==typeof e.slice&&n(e.slice(0,0))}(e)||!!e._isBuffer)}},{}],90:[function(e,t,r){var n={}.toString;t.exports=Array.isArray||function(e){return"[object Array]"==n.call(e)}},{}],91:[function(e,t,r){"use strict";var n=e("safe-buffer").Buffer,i=t.exports;for(var o in i.types={0:"reserved",1:"connect",2:"connack",3:"publish",4:"puback",5:"pubrec",6:"pubrel",7:"pubcomp",8:"subscribe",9:"suback",10:"unsubscribe",11:"unsuback",12:"pingreq",13:"pingresp",14:"disconnect",15:"auth"},i.codes={},i.types){var s=i.types[o];i.codes[s]=o}for(var a in i.CMD_SHIFT=4,i.CMD_MASK=240,i.DUP_MASK=8,i.QOS_MASK=3,i.QOS_SHIFT=1,i.RETAIN_MASK=1,i.LENGTH_MASK=127,i.LENGTH_FIN_MASK=128,i.SESSIONPRESENT_MASK=1,i.SESSIONPRESENT_HEADER=n.from([i.SESSIONPRESENT_MASK]),i.CONNACK_HEADER=n.from([i.codes.connack<>8,0),t.writeUInt8(255&e,1),t}t.exports={cache:o,generateCache:function(){for(var e=0;e=0&&e<128?1:e>=128&&e<16384?2:e>=16384&&e<2097152?3:e>=2097152&&e<268435456?4:0}(e),o=n.allocUnsafe(i);do{t=e%128|0,(e=e/128|0)>0&&(t|=128),o.writeUInt8(t,r++)}while(e>0);return{data:o,length:i}},generate4ByteBuffer:function(e){var t=n.allocUnsafe(4);return t.writeUInt32BE(e,0),t}}},{"safe-buffer":117}],95:[function(e,t,r){t.exports=function(){this.cmd=null,this.retain=!1,this.qos=0,this.dup=!1,this.length=-1,this.topic=null,this.payload=null}},{}],96:[function(e,t,r){"use strict";var n=e("bl"),i=e("inherits"),o=e("events").EventEmitter,s=e("./packet"),a=e("./constants"),c=e("debug")("mqtt-packet:parser");function u(e){if(!(this instanceof u))return new u(e);this.settings=e||{},this._states=["_parseHeader","_parseLength","_parsePayload","_newPacket"],this._resetState()}i(u,o),u.prototype._resetState=function(){c("_resetState: resetting packet, error, _list, and _stateCounter"),this.packet=new s,this.error=null,this._list=n(),this._stateCounter=0},u.prototype.parse=function(e){for(this.error&&this._resetState(),this._list.append(e),c("parse: current state: %s",this._states[this._stateCounter]);(-1!==this.packet.length||this._list.length>0)&&this[this._states[this._stateCounter]]()&&!this.error;)this._stateCounter++,c("parse: state complete. _stateCounter is now: %d",this._stateCounter),c("parse: packet.length: %d, buffer list length: %d",this.packet.length,this._list.length),this._stateCounter>=this._states.length&&(this._stateCounter=0);return c("parse: exited while loop. packet: %d, buffer list length: %d",this.packet.length,this._list.length),this._list.length},u.prototype._parseHeader=function(){var e=this._list.readUInt8(0);return this.packet.cmd=a.types[e>>a.CMD_SHIFT],this.packet.retain=0!=(e&a.RETAIN_MASK),this.packet.qos=e>>a.QOS_SHIFT&a.QOS_MASK,this.packet.dup=0!=(e&a.DUP_MASK),c("_parseHeader: packet: %o",this.packet),this._list.consume(1),!0},u.prototype._parseLength=function(){var e=this._parseVarByteNum(!0);return e&&(this.packet.length=e.value,this._list.consume(e.bytes)),c("_parseLength %d",e.value),!!e},u.prototype._parsePayload=function(){c("_parsePayload: payload %O",this._list);var e=!1;if(0===this.packet.length||this._list.length>=this.packet.length){switch(this._pos=0,this.packet.cmd){case"connect":this._parseConnect();break;case"connack":this._parseConnack();break;case"publish":this._parsePublish();break;case"puback":case"pubrec":case"pubrel":case"pubcomp":this._parseConfirmation();break;case"subscribe":this._parseSubscribe();break;case"suback":this._parseSuback();break;case"unsubscribe":this._parseUnsubscribe();break;case"unsuback":this._parseUnsuback();break;case"pingreq":case"pingresp":break;case"disconnect":this._parseDisconnect();break;case"auth":this._parseAuth();break;default:this._emitError(new Error("Not supported"))}e=!0}return c("_parsePayload complete result: %s",e),e},u.prototype._parseConnect=function(){var e,t,r,n,i,o;c("_parseConnect");var s={},u=this.packet;if(null===(e=this._parseString()))return this._emitError(new Error("Cannot parse protocolId"));if("MQTT"!==e&&"MQIsdp"!==e)return this._emitError(new Error("Invalid protocolId"));if(u.protocolId=e,this._pos>=this._list.length)return this._emitError(new Error("Packet too short"));if(u.protocolVersion=this._list.readUInt8(this._pos),3!==u.protocolVersion&&4!==u.protocolVersion&&5!==u.protocolVersion)return this._emitError(new Error("Invalid protocol version"));if(this._pos++,this._pos>=this._list.length)return this._emitError(new Error("Packet too short"));if(s.username=this._list.readUInt8(this._pos)&a.USERNAME_MASK,s.password=this._list.readUInt8(this._pos)&a.PASSWORD_MASK,s.will=this._list.readUInt8(this._pos)&a.WILL_FLAG_MASK,s.will&&(u.will={},u.will.retain=0!=(this._list.readUInt8(this._pos)&a.WILL_RETAIN_MASK),u.will.qos=(this._list.readUInt8(this._pos)&a.WILL_QOS_MASK)>>a.WILL_QOS_SHIFT),u.clean=0!=(this._list.readUInt8(this._pos)&a.CLEAN_SESSION_MASK),this._pos++,u.keepalive=this._parseNum(),-1===u.keepalive)return this._emitError(new Error("Packet too short"));if(5===u.protocolVersion){var l=this._parseProperties();Object.getOwnPropertyNames(l).length&&(u.properties=l)}if(null===(t=this._parseString()))return this._emitError(new Error("Packet too short"));if(u.clientId=t,c("_parseConnect: packet.clientId: %s",u.clientId),s.will){if(5===u.protocolVersion){var f=this._parseProperties();Object.getOwnPropertyNames(f).length&&(u.will.properties=f)}if(null===(r=this._parseString()))return this._emitError(new Error("Cannot parse will topic"));if(u.will.topic=r,c("_parseConnect: packet.will.topic: %s",u.will.topic),null===(n=this._parseBuffer()))return this._emitError(new Error("Cannot parse will payload"));u.will.payload=n,c("_parseConnect: packet.will.paylaod: %s",u.will.payload)}if(s.username){if(null===(o=this._parseString()))return this._emitError(new Error("Cannot parse username"));u.username=o,c("_parseConnect: packet.username: %s",u.username)}if(s.password){if(null===(i=this._parseBuffer()))return this._emitError(new Error("Cannot parse password"));u.password=i}return this.settings=u,c("_parseConnect: complete"),u},u.prototype._parseConnack=function(){c("_parseConnack");var e=this.packet;if(this._list.length<2)return null;if(e.sessionPresent=!!(this._list.readUInt8(this._pos++)&a.SESSIONPRESENT_MASK),5===this.settings.protocolVersion?e.reasonCode=this._list.readUInt8(this._pos++):e.returnCode=this._list.readUInt8(this._pos++),-1===e.returnCode||-1===e.reasonCode)return this._emitError(new Error("Cannot parse return code"));if(5===this.settings.protocolVersion){var t=this._parseProperties();Object.getOwnPropertyNames(t).length&&(e.properties=t)}c("_parseConnack: complete")},u.prototype._parsePublish=function(){c("_parsePublish");var e=this.packet;if(e.topic=this._parseString(),null===e.topic)return this._emitError(new Error("Cannot parse topic"));if(!(e.qos>0)||this._parseMessageId()){if(5===this.settings.protocolVersion){var t=this._parseProperties();Object.getOwnPropertyNames(t).length&&(e.properties=t)}e.payload=this._list.slice(this._pos,e.length),c("_parsePublish: payload from buffer list: %o",e.payload)}},u.prototype._parseSubscribe=function(){c("_parseSubscribe");var e,t,r,n,i,o,s,u=this.packet;if(1!==u.qos)return this._emitError(new Error("Wrong subscribe header"));if(u.subscriptions=[],this._parseMessageId()){if(5===this.settings.protocolVersion){var l=this._parseProperties();Object.getOwnPropertyNames(l).length&&(u.properties=l)}for(;this._pos=u.length)return this._emitError(new Error("Malformed Subscribe Payload"));r=(t=this._parseByte())&a.SUBSCRIBE_OPTIONS_QOS_MASK,o=0!=(t>>a.SUBSCRIBE_OPTIONS_NL_SHIFT&a.SUBSCRIBE_OPTIONS_NL_MASK),i=0!=(t>>a.SUBSCRIBE_OPTIONS_RAP_SHIFT&a.SUBSCRIBE_OPTIONS_RAP_MASK),n=t>>a.SUBSCRIBE_OPTIONS_RH_SHIFT&a.SUBSCRIBE_OPTIONS_RH_MASK,s={topic:e,qos:r},5===this.settings.protocolVersion&&(s.nl=o,s.rap=i,s.rh=n),c("_parseSubscribe: push subscription `%s` to subscription",s),u.subscriptions.push(s)}}},u.prototype._parseSuback=function(){c("_parseSuback");var e=this.packet;if(this.packet.granted=[],this._parseMessageId()){if(5===this.settings.protocolVersion){var t=this._parseProperties();Object.getOwnPropertyNames(t).length&&(e.properties=t)}for(;this._pos2&&(e.reasonCode=this._parseByte(),c("_parseConfirmation: packet.reasonCode `%d`",e.reasonCode)),e.length>3)){var t=this._parseProperties();Object.getOwnPropertyNames(t).length&&(e.properties=t)}return!0},u.prototype._parseDisconnect=function(){var e=this.packet;if(c("_parseDisconnect"),5===this.settings.protocolVersion){e.reasonCode=this._parseByte();var t=this._parseProperties();Object.getOwnPropertyNames(t).length&&(e.properties=t)}return c("_parseDisconnect result: true"),!0},u.prototype._parseAuth=function(){c("_parseAuth");var e=this.packet;if(5!==this.settings.protocolVersion)return this._emitError(new Error("Not supported auth packet for this version MQTT"));e.reasonCode=this._parseByte();var t=this._parseProperties();return Object.getOwnPropertyNames(t).length&&(e.properties=t),c("_parseAuth: result: true"),!0},u.prototype._parseMessageId=function(){var e=this.packet;return e.messageId=this._parseNum(),null===e.messageId?(this._emitError(new Error("Cannot parse messageId")),!1):(c("_parseMessageId: packet.messageId %d",e.messageId),!0)},u.prototype._parseString=function(e){var t,r=this._parseNum(),n=r+this._pos;return-1===r||n>this._list.length||n>this.packet.length?null:(t=this._list.toString("utf8",this._pos,n),this._pos+=r,c("_parseString: result: %s",t),t)},u.prototype._parseStringPair=function(){return c("_parseStringPair"),{name:this._parseString(),value:this._parseString()}},u.prototype._parseBuffer=function(){var e,t=this._parseNum(),r=t+this._pos;return-1===t||r>this._list.length||r>this.packet.length?null:(e=this._list.slice(this._pos,r),this._pos+=t,c("_parseBuffer: result: %o",e),e)},u.prototype._parseNum=function(){if(this._list.length-this._pos<2)return-1;var e=this._list.readUInt16BE(this._pos);return this._pos+=2,c("_parseNum: result: %s",e),e},u.prototype._parse4ByteNum=function(){if(this._list.length-this._pos<4)return-1;var e=this._list.readUInt32BE(this._pos);return this._pos+=4,c("_parse4ByteNum: result: %s",e),e},u.prototype._parseVarByteNum=function(e){c("_parseVarByteNum");for(var t,r=0,n=1,i=0,o=!0,s=this._pos?this._pos:0;r<5&&(i+=n*((t=this._list.readUInt8(s+r++))&a.LENGTH_MASK),n*=128,0!=(t&a.LENGTH_FIN_MASK));)if(this._list.length<=r){o=!1;break}return s&&(this._pos+=r),c("_parseVarByteNum: result: %o",o=!!o&&(e?{bytes:r,value:i}:i)),o},u.prototype._parseByte=function(){var e=this._list.readUInt8(this._pos);return this._pos++,c("_parseByte: result: %o",e),e},u.prototype._parseByType=function(e){switch(c("_parseByType: type: %s",e),e){case"byte":return 0!==this._parseByte();case"int8":return this._parseByte();case"int16":return this._parseNum();case"int32":return this._parse4ByteNum();case"var":return this._parseVarByteNum();case"string":return this._parseString();case"pair":return this._parseStringPair();case"binary":return this._parseBuffer()}},u.prototype._parseProperties=function(){c("_parseProperties");for(var e=this._parseVarByteNum(),t=this._pos+e,r={};this._pos65535||l%1!=0)return t.emit("error",new Error("Invalid keepalive")),!1;b+=2;if(b+=1,5===a){var m=I(t,d);if(!m)return!1;b+=m.length}if(c){if("object"!=typeof c)return t.emit("error",new Error("Invalid will")),!1;if(!c.topic||"string"!=typeof c.topic)return t.emit("error",new Error("Invalid will topic")),!1;if(b+=i.byteLength(c.topic)+2,b+=2,c.payload){if(!(c.payload.length>=0))return t.emit("error",new Error("Invalid will payload")),!1;"string"==typeof c.payload?b+=i.byteLength(c.payload):b+=c.payload.length}var y={};if(5===a){if(!(y=I(t,c.properties)))return!1;b+=y.length}}var _=!1;if(null!=p){if(!T(p))return t.emit("error",new Error("Invalid username")),!1;_=!0,b+=i.byteLength(p)+2}if(null!=h){if(!_)return t.emit("error",new Error("Username is required to use password")),!1;if(!T(h))return t.emit("error",new Error("Invalid password")),!1;b+=A(h)+2}t.write(n.CONNECT_HEADER),v(t,b),E(t,s),t.write(4===a?n.VERSION4:5===a?n.VERSION5:n.VERSION3);var S=0;S|=null!=p?n.USERNAME_MASK:0,S|=null!=h?n.PASSWORD_MASK:0,S|=c&&c.retain?n.WILL_RETAIN_MASK:0,S|=c&&c.qos?c.qos<0&&g(t,h);null!=m&&m.write();return u("publish: payload: %o",p),t.write(p)}(e,t,r);case"puback":case"pubrec":case"pubrel":case"pubcomp":return function(e,t,r){var o=r?r.protocolVersion:4,s=e||{},a=s.cmd||"puback",c=s.messageId,u=s.dup&&"pubrel"===a?n.DUP_MASK:0,l=0,f=s.reasonCode,p=s.properties,h=5===o?3:2;"pubrel"===a&&(l=1);if("number"!=typeof c)return t.emit("error",new Error("Invalid messageId")),!1;var d=null;if(5===o&&"object"==typeof p){if(!(d=C(t,p,r,h)))return!1;h+=d.length}t.write(n.ACKS[a][l][u][0]),v(t,h),g(t,c),5===o&&t.write(i.from([f]));null!==d&&d.write();return!0}(e,t,r);case"subscribe":return function(e,t,r){u("subscribe: packet: ");var o=r?r.protocolVersion:4,s=e||{},a=s.dup?n.DUP_MASK:0,c=s.messageId,l=s.subscriptions,f=s.properties,p=0;if("number"!=typeof c)return t.emit("error",new Error("Invalid messageId")),!1;p+=2;var h=null;if(5===o){if(!(h=I(t,f)))return!1;p+=h.length}if("object"!=typeof l||!l.length)return t.emit("error",new Error("Invalid subscriptions")),!1;for(var d=0;d2)return t.emit("error",new Error("Invalid subscriptions - invalid Retain Handling")),!1}p+=i.byteLength(b)+2+1}u("subscribe: writing to stream: %o",n.SUBSCRIBE_HEADER),t.write(n.SUBSCRIBE_HEADER[1][a?1:0][0]),v(t,p),g(t,c),null!==h&&h.write();for(var k=!0,x=0;x255)return e.emit("error",new Error("Invalid "+t+": "+r)),!1;o+=2;break;case"binary":if(r&&null===r)return e.emit("error",new Error("Invalid "+t+": "+r)),!1;o+=1+i.byteLength(r)+2;break;case"int16":if("number"!=typeof r||r<0||r>65535)return e.emit("error",new Error("Invalid "+t+": "+r)),!1;o+=3;break;case"int32":if("number"!=typeof r||r<0||r>4294967295)return e.emit("error",new Error("Invalid "+t+": "+r)),!1;o+=5;break;case"var":if("number"!=typeof r||r<0||r>4294967295)return e.emit("error",new Error("Invalid "+t+": "+r)),!1;o+=1+h(r).length;break;case"string":if("string"!=typeof r)return e.emit("error",new Error("Invalid "+t+": "+r)),!1;o+=3+i.byteLength(r.toString());break;case"pair":if("object"!=typeof r)return e.emit("error",new Error("Invalid "+t+": "+r)),!1;o+=Object.getOwnPropertyNames(r).reduce(function(e,t){var n=r[t];return Array.isArray(n)?e+=n.reduce(function(e,r){return e+=3+i.byteLength(t.toString())+2+i.byteLength(r.toString())},0):e+=3+i.byteLength(t.toString())+2+i.byteLength(r[t].toString()),e},0);break;default:return e.emit("error",new Error("Invalid property "+t+": "+r)),!1}return o}if(t)for(var s in t){var a=0,c=0,u=t[s];if(Array.isArray(u))for(var l=0;lo;){var a=i.shift();if(!a||!t[a])return!1;delete t[a],s=I(e,t)}return s}function O(e,t,r){switch(n.propertiesTypes[t]){case"byte":e.write(i.from([n.properties[t]])),e.write(i.from([+r]));break;case"int8":e.write(i.from([n.properties[t]])),e.write(i.from([r]));break;case"binary":e.write(i.from([n.properties[t]])),E(e,r);break;case"int16":e.write(i.from([n.properties[t]])),g(e,r);break;case"int32":e.write(i.from([n.properties[t]])),function(e,t){var r=d(t);u("write4ByteNumber: %o",r),e.write(r)}(e,r);break;case"var":e.write(i.from([n.properties[t]])),v(e,r);break;case"string":e.write(i.from([n.properties[t]])),w(e,r);break;case"pair":Object.getOwnPropertyNames(r).forEach(function(o){var s=r[o];Array.isArray(s)?s.forEach(function(r){e.write(i.from([n.properties[t]])),S(e,o.toString(),r.toString())}):(e.write(i.from([n.properties[t]])),S(e,o.toString(),s.toString()))});break;default:return e.emit("error",new Error("Invalid property "+t+" value: "+r)),!1}}function j(e,t,r){for(var n in v(e,r),t)if(t.hasOwnProperty(n)&&null!==t[n]){var i=t[n];if(Array.isArray(i))for(var o=0;o=1.5*r;return Math.round(e/r)+" "+n+(i?"s":"")}t.exports=function(e,t){t=t||{};var r=typeof e;if("string"===r&&e.length>0)return function(e){if((e=String(e)).length>100)return;var t=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(e);if(!t)return;var r=parseFloat(t[1]);switch((t[2]||"ms").toLowerCase()){case"years":case"year":case"yrs":case"yr":case"y":return r*c;case"weeks":case"week":case"w":return r*a;case"days":case"day":case"d":return r*s;case"hours":case"hour":case"hrs":case"hr":case"h":return r*o;case"minutes":case"minute":case"mins":case"min":case"m":return r*i;case"seconds":case"second":case"secs":case"sec":case"s":return r*n;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return r;default:return}}(e);if("number"===r&&isFinite(e))return t.long?function(e){var t=Math.abs(e);if(t>=s)return u(e,t,s,"day");if(t>=o)return u(e,t,o,"hour");if(t>=i)return u(e,t,i,"minute");if(t>=n)return u(e,t,n,"second");return e+" ms"}(e):function(e){var t=Math.abs(e);if(t>=s)return Math.round(e/s)+"d";if(t>=o)return Math.round(e/o)+"h";if(t>=i)return Math.round(e/i)+"m";if(t>=n)return Math.round(e/n)+"s";return e+"ms"}(e);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(e))}},{}],99:[function(e,t,r){var n=e("wrappy");function i(e){var t=function(){return t.called?t.value:(t.called=!0,t.value=e.apply(this,arguments))};return t.called=!1,t}function o(e){var t=function(){if(t.called)throw new Error(t.onceError);return t.called=!0,t.value=e.apply(this,arguments)},r=e.name||"Function wrapped with `once`";return t.onceError=r+" shouldn't be called more than once",t.called=!1,t}t.exports=n(i),t.exports.strict=n(o),i.proto=i(function(){Object.defineProperty(Function.prototype,"once",{value:function(){return i(this)},configurable:!0}),Object.defineProperty(Function.prototype,"onceStrict",{value:function(){return o(this)},configurable:!0})})},{wrappy:138}],100:[function(e,t,r){(function(e){"use strict";void 0===e||!e.version||0===e.version.indexOf("v0.")||0===e.version.indexOf("v1.")&&0!==e.version.indexOf("v1.8.")?t.exports={nextTick:function(t,r,n,i){if("function"!=typeof t)throw new TypeError('"callback" argument must be a function');var o,s,a=arguments.length;switch(a){case 0:case 1:return e.nextTick(t);case 2:return e.nextTick(function(){t.call(null,r)});case 3:return e.nextTick(function(){t.call(null,r,n)});case 4:return e.nextTick(function(){t.call(null,r,n,i)});default:for(o=new Array(a-1),s=0;s1)for(var r=1;r= 0x80 (not a basic code point)","invalid-input":"Invalid input"},S=l-f,k=Math.floor,x=String.fromCharCode;function E(e){throw new RangeError(w[e])}function I(e,t){for(var r=e.length,n=[];r--;)n[r]=t(e[r]);return n}function C(e,t){var r=e.split("@"),n="";return r.length>1&&(n=r[0]+"@",e=r[1]),n+I((e=e.replace(v,".")).split("."),t).join(".")}function O(e){for(var t,r,n=[],i=0,o=e.length;i=55296&&t<=56319&&i65535&&(t+=x((e-=65536)>>>10&1023|55296),e=56320|1023&e),t+=x(e)}).join("")}function A(e,t){return e+22+75*(e<26)-((0!=t)<<5)}function T(e,t,r){var n=0;for(e=r?k(e/d):e>>1,e+=k(e/t);e>S*p>>1;n+=l)e=k(e/S);return k(n+(S+1)*e/(e+h))}function P(e){var t,r,n,i,o,s,a,c,h,d,y,_=[],v=e.length,w=0,S=b,x=g;for((r=e.lastIndexOf(m))<0&&(r=0),n=0;n=128&&E("not-basic"),_.push(e.charCodeAt(n));for(i=r>0?r+1:0;i=v&&E("invalid-input"),((c=(y=e.charCodeAt(i++))-48<10?y-22:y-65<26?y-65:y-97<26?y-97:l)>=l||c>k((u-w)/s))&&E("overflow"),w+=c*s,!(c<(h=a<=x?f:a>=x+p?p:a-x));a+=l)s>k(u/(d=l-h))&&E("overflow"),s*=d;x=T(w-o,t=_.length+1,0==o),k(w/t)>u-S&&E("overflow"),S+=k(w/t),w%=t,_.splice(w++,0,S)}return j(_)}function M(e){var t,r,n,i,o,s,a,c,h,d,y,_,v,w,S,I=[];for(_=(e=O(e)).length,t=b,r=0,o=g,s=0;s<_;++s)(y=e[s])<128&&I.push(x(y));for(n=i=I.length,i&&I.push(m);n<_;){for(a=u,s=0;s<_;++s)(y=e[s])>=t&&yk((u-r)/(v=n+1))&&E("overflow"),r+=(a-t)*v,t=a,s=0;s<_;++s)if((y=e[s])u&&E("overflow"),y==t){for(c=r,h=l;!(c<(d=h<=o?f:h>=o+p?p:h-o));h+=l)S=c-d,w=l-d,I.push(x(A(d+S%w,0))),c=k(S/w);I.push(x(A(c,0))),o=T(r,v,n==i),r=0,++n}++r,++t}return I.join("")}if(a={version:"1.4.1",ucs2:{decode:O,encode:j},decode:P,encode:M,toASCII:function(e){return C(e,function(e){return _.test(e)?"xn--"+M(e):e})},toUnicode:function(e){return C(e,function(e){return y.test(e)?P(e.slice(4).toLowerCase()):e})}},i&&o)if(t.exports==i)o.exports=a;else for(c in a)a.hasOwnProperty(c)&&(i[c]=a[c]);else n.punycode=a}(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],103:[function(e,t,r){"use strict";function n(e,t){return Object.prototype.hasOwnProperty.call(e,t)}t.exports=function(e,t,r,o){t=t||"&",r=r||"=";var s={};if("string"!=typeof e||0===e.length)return s;var a=/\+/g;e=e.split(t);var c=1e3;o&&"number"==typeof o.maxKeys&&(c=o.maxKeys);var u=e.length;c>0&&u>c&&(u=c);for(var l=0;l=0?(f=g.substr(0,b),p=g.substr(b+1)):(f=g,p=""),h=decodeURIComponent(f),d=decodeURIComponent(p),n(s,h)?i(s[h])?s[h].push(d):s[h]=[s[h],d]:s[h]=d}return s};var i=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)}},{}],104:[function(e,t,r){"use strict";var n=function(e){switch(typeof e){case"string":return e;case"boolean":return e?"true":"false";case"number":return isFinite(e)?e:"";default:return""}};t.exports=function(e,t,r,a){return t=t||"&",r=r||"=",null===e&&(e=void 0),"object"==typeof e?o(s(e),function(s){var a=encodeURIComponent(n(s))+r;return i(e[s])?o(e[s],function(e){return a+encodeURIComponent(n(e))}).join(t):a+encodeURIComponent(n(e[s]))}).join(t):a?encodeURIComponent(n(a))+r+encodeURIComponent(n(e)):""};var i=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)};function o(e,t){if(e.map)return e.map(t);for(var r=[],n=0;n0?("string"==typeof t||s.objectMode||Object.getPrototypeOf(t)===u.prototype||(t=function(e){return u.from(e)}(t)),n?s.endEmitted?e.emit("error",new Error("stream.unshift() after end event")):w(e,s,t,!0):s.ended?e.emit("error",new Error("stream.push() after EOF")):(s.reading=!1,s.decoder&&!r?(t=s.decoder.write(t),s.objectMode||0!==t.length?w(e,s,t,!1):I(e,s)):w(e,s,t,!1))):n||(s.reading=!1));return function(e){return!e.ended&&(e.needReadable||e.lengtht.highWaterMark&&(t.highWaterMark=function(e){return e>=S?e=S:(e--,e|=e>>>1,e|=e>>>2,e|=e>>>4,e|=e>>>8,e|=e>>>16,e++),e}(e)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0))}function x(e){var t=e._readableState;t.needReadable=!1,t.emittedReadable||(h("emitReadable",t.flowing),t.emittedReadable=!0,t.sync?i.nextTick(E,e):E(e))}function E(e){h("emit readable"),e.emit("readable"),A(e)}function I(e,t){t.readingMore||(t.readingMore=!0,i.nextTick(C,e,t))}function C(e,t){for(var r=t.length;!t.reading&&!t.flowing&&!t.ended&&t.length=t.length?(r=t.decoder?t.buffer.join(""):1===t.buffer.length?t.buffer.head.data:t.buffer.concat(t.length),t.buffer.clear()):r=function(e,t,r){var n;eo.length?o.length:e;if(s===o.length?i+=o:i+=o.slice(0,e),0===(e-=s)){s===o.length?(++n,r.next?t.head=r.next:t.head=t.tail=null):(t.head=r,r.data=o.slice(s));break}++n}return t.length-=n,i}(e,t):function(e,t){var r=u.allocUnsafe(e),n=t.head,i=1;n.data.copy(r),e-=n.data.length;for(;n=n.next;){var o=n.data,s=e>o.length?o.length:e;if(o.copy(r,r.length-e,0,s),0===(e-=s)){s===o.length?(++i,n.next?t.head=n.next:t.head=t.tail=null):(t.head=n,n.data=o.slice(s));break}++i}return t.length-=i,r}(e,t);return n}(e,t.buffer,t.decoder),r);var r}function P(e){var t=e._readableState;if(t.length>0)throw new Error('"endReadable()" called on non-empty stream');t.endEmitted||(t.ended=!0,i.nextTick(M,t,e))}function M(e,t){e.endEmitted||0!==e.length||(e.endEmitted=!0,t.readable=!1,t.emit("end"))}function B(e,t){for(var r=0,n=e.length;r=t.highWaterMark||t.ended))return h("read: emitReadable",t.length,t.ended),0===t.length&&t.ended?P(this):x(this),null;if(0===(e=k(e,t))&&t.ended)return 0===t.length&&P(this),null;var n,i=t.needReadable;return h("need readable",i),(0===t.length||t.length-e0?T(e,t):null)?(t.needReadable=!0,e=0):t.length-=e,0===t.length&&(t.ended||(t.needReadable=!0),r!==e&&t.ended&&P(this)),null!==n&&this.emit("data",n),n},_.prototype._read=function(e){this.emit("error",new Error("_read() is not implemented"))},_.prototype.pipe=function(e,t){var n=this,o=this._readableState;switch(o.pipesCount){case 0:o.pipes=e;break;case 1:o.pipes=[o.pipes,e];break;default:o.pipes.push(e)}o.pipesCount+=1,h("pipe count=%d opts=%j",o.pipesCount,t);var c=(!t||!1!==t.end)&&e!==r.stdout&&e!==r.stderr?l:_;function u(t,r){h("onunpipe"),t===n&&r&&!1===r.hasUnpiped&&(r.hasUnpiped=!0,h("cleanup"),e.removeListener("close",m),e.removeListener("finish",y),e.removeListener("drain",f),e.removeListener("error",b),e.removeListener("unpipe",u),n.removeListener("end",l),n.removeListener("end",_),n.removeListener("data",g),p=!0,!o.awaitDrain||e._writableState&&!e._writableState.needDrain||f())}function l(){h("onend"),e.end()}o.endEmitted?i.nextTick(c):n.once("end",c),e.on("unpipe",u);var f=function(e){return function(){var t=e._readableState;h("pipeOnDrain",t.awaitDrain),t.awaitDrain&&t.awaitDrain--,0===t.awaitDrain&&a(e,"data")&&(t.flowing=!0,A(e))}}(n);e.on("drain",f);var p=!1;var d=!1;function g(t){h("ondata"),d=!1,!1!==e.write(t)||d||((1===o.pipesCount&&o.pipes===e||o.pipesCount>1&&-1!==B(o.pipes,e))&&!p&&(h("false write response, pause",n._readableState.awaitDrain),n._readableState.awaitDrain++,d=!0),n.pause())}function b(t){h("onerror",t),_(),e.removeListener("error",b),0===a(e,"error")&&e.emit("error",t)}function m(){e.removeListener("finish",y),_()}function y(){h("onfinish"),e.removeListener("close",m),_()}function _(){h("unpipe"),n.unpipe(e)}return n.on("data",g),function(e,t,r){if("function"==typeof e.prependListener)return e.prependListener(t,r);e._events&&e._events[t]?s(e._events[t])?e._events[t].unshift(r):e._events[t]=[r,e._events[t]]:e.on(t,r)}(e,"error",b),e.once("close",m),e.once("finish",y),e.emit("pipe",n),o.flowing||(h("pipe resume"),n.resume()),e},_.prototype.unpipe=function(e){var t=this._readableState,r={hasUnpiped:!1};if(0===t.pipesCount)return this;if(1===t.pipesCount)return e&&e!==t.pipes?this:(e||(e=t.pipes),t.pipes=null,t.pipesCount=0,t.flowing=!1,e&&e.emit("unpipe",this,r),this);if(!e){var n=t.pipes,i=t.pipesCount;t.pipes=null,t.pipesCount=0,t.flowing=!1;for(var o=0;o-1?i:o.nextTick;y.WritableState=m;var u=Object.create(e("core-util-is"));u.inherits=e("inherits");var l={deprecate:e("util-deprecate")},f=e("./internal/streams/stream"),p=e("safe-buffer").Buffer,h=n.Uint8Array||function(){};var d,g=e("./internal/streams/destroy");function b(){}function m(t,r){a=a||e("./_stream_duplex"),t=t||{};var n=r instanceof a;this.objectMode=!!t.objectMode,n&&(this.objectMode=this.objectMode||!!t.writableObjectMode);var i=t.highWaterMark,u=t.writableHighWaterMark,l=this.objectMode?16:16384;this.highWaterMark=i||0===i?i:n&&(u||0===u)?u:l,this.highWaterMark=Math.floor(this.highWaterMark),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;var f=!1===t.decodeStrings;this.decodeStrings=!f,this.defaultEncoding=t.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(e){!function(e,t){var r=e._writableState,n=r.sync,i=r.writecb;if(function(e){e.writing=!1,e.writecb=null,e.length-=e.writelen,e.writelen=0}(r),t)!function(e,t,r,n,i){--t.pendingcb,r?(o.nextTick(i,n),o.nextTick(x,e,t),e._writableState.errorEmitted=!0,e.emit("error",n)):(i(n),e._writableState.errorEmitted=!0,e.emit("error",n),x(e,t))}(e,r,n,t,i);else{var s=S(r);s||r.corked||r.bufferProcessing||!r.bufferedRequest||w(e,r),n?c(v,e,r,s,i):v(e,r,s,i)}}(r,e)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.bufferedRequestCount=0,this.corkedRequestsFree=new s(this)}function y(t){if(a=a||e("./_stream_duplex"),!(d.call(y,this)||this instanceof a))return new y(t);this._writableState=new m(t,this),this.writable=!0,t&&("function"==typeof t.write&&(this._write=t.write),"function"==typeof t.writev&&(this._writev=t.writev),"function"==typeof t.destroy&&(this._destroy=t.destroy),"function"==typeof t.final&&(this._final=t.final)),f.call(this)}function _(e,t,r,n,i,o,s){t.writelen=n,t.writecb=s,t.writing=!0,t.sync=!0,r?e._writev(i,t.onwrite):e._write(i,o,t.onwrite),t.sync=!1}function v(e,t,r,n){r||function(e,t){0===t.length&&t.needDrain&&(t.needDrain=!1,e.emit("drain"))}(e,t),t.pendingcb--,n(),x(e,t)}function w(e,t){t.bufferProcessing=!0;var r=t.bufferedRequest;if(e._writev&&r&&r.next){var n=t.bufferedRequestCount,i=new Array(n),o=t.corkedRequestsFree;o.entry=r;for(var a=0,c=!0;r;)i[a]=r,r.isBuf||(c=!1),r=r.next,a+=1;i.allBuffers=c,_(e,t,!0,t.length,i,"",o.finish),t.pendingcb++,t.lastBufferedRequest=null,o.next?(t.corkedRequestsFree=o.next,o.next=null):t.corkedRequestsFree=new s(t),t.bufferedRequestCount=0}else{for(;r;){var u=r.chunk,l=r.encoding,f=r.callback;if(_(e,t,!1,t.objectMode?1:u.length,u,l,f),r=r.next,t.bufferedRequestCount--,t.writing)break}null===r&&(t.lastBufferedRequest=null)}t.bufferedRequest=r,t.bufferProcessing=!1}function S(e){return e.ending&&0===e.length&&null===e.bufferedRequest&&!e.finished&&!e.writing}function k(e,t){e._final(function(r){t.pendingcb--,r&&e.emit("error",r),t.prefinished=!0,e.emit("prefinish"),x(e,t)})}function x(e,t){var r=S(t);return r&&(!function(e,t){t.prefinished||t.finalCalled||("function"==typeof e._final?(t.pendingcb++,t.finalCalled=!0,o.nextTick(k,e,t)):(t.prefinished=!0,e.emit("prefinish")))}(e,t),0===t.pendingcb&&(t.finished=!0,e.emit("finish"))),r}u.inherits(y,f),m.prototype.getBuffer=function(){for(var e=this.bufferedRequest,t=[];e;)t.push(e),e=e.next;return t},function(){try{Object.defineProperty(m.prototype,"buffer",{get:l.deprecate(function(){return this.getBuffer()},"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.","DEP0003")})}catch(e){}}(),"function"==typeof Symbol&&Symbol.hasInstance&&"function"==typeof Function.prototype[Symbol.hasInstance]?(d=Function.prototype[Symbol.hasInstance],Object.defineProperty(y,Symbol.hasInstance,{value:function(e){return!!d.call(this,e)||this===y&&(e&&e._writableState instanceof m)}})):d=function(e){return e instanceof this},y.prototype.pipe=function(){this.emit("error",new Error("Cannot pipe, not readable"))},y.prototype.write=function(e,t,r){var n,i=this._writableState,s=!1,a=!i.objectMode&&(n=e,p.isBuffer(n)||n instanceof h);return a&&!p.isBuffer(e)&&(e=function(e){return p.from(e)}(e)),"function"==typeof t&&(r=t,t=null),a?t="buffer":t||(t=i.defaultEncoding),"function"!=typeof r&&(r=b),i.ended?function(e,t){var r=new Error("write after end");e.emit("error",r),o.nextTick(t,r)}(this,r):(a||function(e,t,r,n){var i=!0,s=!1;return null===r?s=new TypeError("May not write null values to stream"):"string"==typeof r||void 0===r||t.objectMode||(s=new TypeError("Invalid non-string/buffer chunk")),s&&(e.emit("error",s),o.nextTick(n,s),i=!1),i}(this,i,e,r))&&(i.pendingcb++,s=function(e,t,r,n,i,o){if(!r){var s=function(e,t,r){e.objectMode||!1===e.decodeStrings||"string"!=typeof t||(t=p.from(t,r));return t}(t,n,i);n!==s&&(r=!0,i="buffer",n=s)}var a=t.objectMode?1:n.length;t.length+=a;var c=t.length-1))throw new TypeError("Unknown encoding: "+e);return this._writableState.defaultEncoding=e,this},Object.defineProperty(y.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),y.prototype._write=function(e,t,r){r(new Error("_write() is not implemented"))},y.prototype._writev=null,y.prototype.end=function(e,t,r){var n=this._writableState;"function"==typeof e?(r=e,e=null,t=null):"function"==typeof t&&(r=t,t=null),null!==e&&void 0!==e&&this.write(e,t),n.corked&&(n.corked=1,this.uncork()),n.ending||n.finished||function(e,t,r){t.ending=!0,x(e,t),r&&(t.finished?o.nextTick(r):e.once("finish",r));t.ended=!0,e.writable=!1}(this,n,r)},Object.defineProperty(y.prototype,"destroyed",{get:function(){return void 0!==this._writableState&&this._writableState.destroyed},set:function(e){this._writableState&&(this._writableState.destroyed=e)}}),y.prototype.destroy=g.destroy,y.prototype._undestroy=g.undestroy,y.prototype._destroy=function(e,t){this.end(),t(e)}}).call(this,e("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},e("timers").setImmediate)},{"./_stream_duplex":107,"./internal/streams/destroy":113,"./internal/streams/stream":114,_process:101,"core-util-is":14,inherits:88,"process-nextick-args":100,"safe-buffer":117,timers:120,"util-deprecate":134}],112:[function(e,t,r){"use strict";var n=e("safe-buffer").Buffer,i=e("util");t.exports=function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.head=null,this.tail=null,this.length=0}return e.prototype.push=function(e){var t={data:e,next:null};this.length>0?this.tail.next=t:this.head=t,this.tail=t,++this.length},e.prototype.unshift=function(e){var t={data:e,next:this.head};0===this.length&&(this.tail=t),this.head=t,++this.length},e.prototype.shift=function(){if(0!==this.length){var e=this.head.data;return 1===this.length?this.head=this.tail=null:this.head=this.head.next,--this.length,e}},e.prototype.clear=function(){this.head=this.tail=null,this.length=0},e.prototype.join=function(e){if(0===this.length)return"";for(var t=this.head,r=""+t.data;t=t.next;)r+=e+t.data;return r},e.prototype.concat=function(e){if(0===this.length)return n.alloc(0);if(1===this.length)return this.head.data;for(var t,r,i,o=n.allocUnsafe(e>>>0),s=this.head,a=0;s;)t=s.data,r=o,i=a,t.copy(r,i),a+=s.data.length,s=s.next;return o},e}(),i&&i.inspect&&i.inspect.custom&&(t.exports.prototype[i.inspect.custom]=function(){var e=i.inspect({length:this.length});return this.constructor.name+" "+e})},{"safe-buffer":117,util:12}],113:[function(e,t,r){"use strict";var n=e("process-nextick-args");function i(e,t){e.emit("error",t)}t.exports={destroy:function(e,t){var r=this,o=this._readableState&&this._readableState.destroyed,s=this._writableState&&this._writableState.destroyed;return o||s?(t?t(e):!e||this._writableState&&this._writableState.errorEmitted||n.nextTick(i,this,e),this):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(e||null,function(e){!t&&e?(n.nextTick(i,r,e),r._writableState&&(r._writableState.errorEmitted=!0)):t&&t(e)}),this)},undestroy:function(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)}}},{"process-nextick-args":100}],114:[function(e,t,r){t.exports=e("events").EventEmitter},{events:83}],115:[function(e,t,r){(r=t.exports=e("./lib/_stream_readable.js")).Stream=r,r.Readable=r,r.Writable=e("./lib/_stream_writable.js"),r.Duplex=e("./lib/_stream_duplex.js"),r.Transform=e("./lib/_stream_transform.js"),r.PassThrough=e("./lib/_stream_passthrough.js")},{"./lib/_stream_duplex.js":107,"./lib/_stream_passthrough.js":108,"./lib/_stream_readable.js":109,"./lib/_stream_transform.js":110,"./lib/_stream_writable.js":111}],116:[function(e,t,r){"use strict";t.exports=function(){if("function"!=typeof arguments[0])throw new Error("callback needed");if("number"!=typeof arguments[1])throw new Error("interval needed");var e;if(arguments.length>0){e=new Array(arguments.length-2);for(var t=0;t>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function a(e){var t=this.lastTotal-this.lastNeed,r=function(e,t,r){if(128!=(192&t[0]))return e.lastNeed=0,"�";if(e.lastNeed>1&&t.length>1){if(128!=(192&t[1]))return e.lastNeed=1,"�";if(e.lastNeed>2&&t.length>2&&128!=(192&t[2]))return e.lastNeed=2,"�"}}(this,e);return void 0!==r?r:this.lastNeed<=e.length?(e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):(e.copy(this.lastChar,t,0,e.length),void(this.lastNeed-=e.length))}function c(e,t){if((e.length-t)%2==0){var r=e.toString("utf16le",t);if(r){var n=r.charCodeAt(r.length-1);if(n>=55296&&n<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],r.slice(0,-1)}return r}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString("utf16le",t,e.length-1)}function u(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var r=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,r)}return t}function l(e,t){var r=(e.length-t)%3;return 0===r?e.toString("base64",t):(this.lastNeed=3-r,this.lastTotal=3,1===r?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString("base64",t,e.length-r))}function f(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+this.lastChar.toString("base64",0,3-this.lastNeed):t}function p(e){return e.toString(this.encoding)}function h(e){return e&&e.length?this.write(e):""}r.StringDecoder=o,o.prototype.write=function(e){if(0===e.length)return"";var t,r;if(this.lastNeed){if(void 0===(t=this.fillLast(e)))return"";r=this.lastNeed,this.lastNeed=0}else r=0;return r=0)return i>0&&(e.lastNeed=i-1),i;if(--n=0)return i>0&&(e.lastNeed=i-2),i;if(--n=0)return i>0&&(2===i?i=0:e.lastNeed=i-3),i;return 0}(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=r;var n=e.length-(r-this.lastNeed);return e.copy(this.lastChar,0,n),e.toString("utf8",t,n)},o.prototype.fillLast=function(e){if(this.lastNeed<=e.length)return e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,e.length),this.lastNeed-=e.length}},{"safe-buffer":117}],120:[function(e,t,r){(function(t,n){var i=e("process/browser.js").nextTick,o=Function.prototype.apply,s=Array.prototype.slice,a={},c=0;function u(e,t){this._id=e,this._clearFn=t}r.setTimeout=function(){return new u(o.call(setTimeout,window,arguments),clearTimeout)},r.setInterval=function(){return new u(o.call(setInterval,window,arguments),clearInterval)},r.clearTimeout=r.clearInterval=function(e){e.close()},u.prototype.unref=u.prototype.ref=function(){},u.prototype.close=function(){this._clearFn.call(window,this._id)},r.enroll=function(e,t){clearTimeout(e._idleTimeoutId),e._idleTimeout=t},r.unenroll=function(e){clearTimeout(e._idleTimeoutId),e._idleTimeout=-1},r._unrefActive=r.active=function(e){clearTimeout(e._idleTimeoutId);var t=e._idleTimeout;t>=0&&(e._idleTimeoutId=setTimeout(function(){e._onTimeout&&e._onTimeout()},t))},r.setImmediate="function"==typeof t?t:function(e){var t=c++,n=!(arguments.length<2)&&s.call(arguments,1);return a[t]=!0,i(function(){a[t]&&(n?e.apply(null,n):e.call(null),r.clearImmediate(t))}),t},r.clearImmediate="function"==typeof n?n:function(e){delete a[e]}}).call(this,e("timers").setImmediate,e("timers").clearImmediate)},{"process/browser.js":101,timers:120}],121:[function(e,t,r){"use strict";var n=e("../prototype/is");t.exports=function(e){if("function"!=typeof e)return!1;if(!hasOwnProperty.call(e,"length"))return!1;try{if("number"!=typeof e.length)return!1;if("function"!=typeof e.call)return!1;if("function"!=typeof e.apply)return!1}catch(e){return!1}return!n(e)}},{"../prototype/is":128}],122:[function(e,t,r){"use strict";var n=e("../value/is"),i=e("../object/is"),o=e("../string/coerce"),s=e("./to-short-string"),a=function(e,t){return e.replace("%v",s(t))};t.exports=function(e,t,r){if(!i(r))throw new TypeError(a(t,e));if(!n(e)){if("default"in r)return r.default;if(r.isOptional)return null}var s=o(r.errorMessage);throw n(s)||(s=t),new TypeError(a(s,e))}},{"../object/is":125,"../string/coerce":129,"../value/is":131,"./to-short-string":124}],123:[function(e,t,r){"use strict";t.exports=function(e){try{return e.toString()}catch(t){try{return String(e)}catch(e){return null}}}},{}],124:[function(e,t,r){"use strict";var n=e("./safe-to-string"),i=/[\n\r\u2028\u2029]/g;t.exports=function(e){var t=n(e);return null===t?"":(t.length>100&&(t=t.slice(0,99)+"…"),t=t.replace(i,function(e){switch(e){case"\n":return"\\n";case"\r":return"\\r";case"\u2028":return"\\u2028";case"\u2029":return"\\u2029";default:throw new Error("Unexpected character")}}))}},{"./safe-to-string":123}],125:[function(e,t,r){"use strict";var n=e("../value/is"),i={object:!0,function:!0,undefined:!0};t.exports=function(e){return!!n(e)&&hasOwnProperty.call(i,typeof e)}},{"../value/is":131}],126:[function(e,t,r){"use strict";var n=e("../lib/resolve-exception"),i=e("./is");t.exports=function(e){return i(e)?e:n(e,"%v is not a plain function",arguments[1])}},{"../lib/resolve-exception":122,"./is":127}],127:[function(e,t,r){"use strict";var n=e("../function/is"),i=/^\s*class[\s{/}]/,o=Function.prototype.toString;t.exports=function(e){return!!n(e)&&!i.test(o.call(e))}},{"../function/is":121}],128:[function(e,t,r){"use strict";var n=e("../object/is");t.exports=function(e){if(!n(e))return!1;try{return!!e.constructor&&e.constructor.prototype===e}catch(e){return!1}}},{"../object/is":125}],129:[function(e,t,r){"use strict";var n=e("../value/is"),i=e("../object/is"),o=Object.prototype.toString;t.exports=function(e){if(!n(e))return null;if(i(e)){var t=e.toString;if("function"!=typeof t)return null;if(t===o)return null}try{return""+e}catch(e){return null}}},{"../object/is":125,"../value/is":131}],130:[function(e,t,r){"use strict";var n=e("../lib/resolve-exception"),i=e("./is");t.exports=function(e){return i(e)?e:n(e,"Cannot use %v",arguments[1])}},{"../lib/resolve-exception":122,"./is":131}],131:[function(e,t,r){"use strict";t.exports=function(e){return void 0!==e&&null!==e}},{}],132:[function(e,t,r){"use strict";var n=e("punycode"),i=e("./util");function o(){this.protocol=null,this.slashes=null,this.auth=null,this.host=null,this.port=null,this.hostname=null,this.hash=null,this.search=null,this.query=null,this.pathname=null,this.path=null,this.href=null}r.parse=_,r.resolve=function(e,t){return _(e,!1,!0).resolve(t)},r.resolveObject=function(e,t){return e?_(e,!1,!0).resolveObject(t):t},r.format=function(e){i.isString(e)&&(e=_(e));return e instanceof o?e.format():o.prototype.format.call(e)},r.Url=o;var s=/^([a-z0-9.+-]+:)/i,a=/:[0-9]*$/,c=/^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,u=["{","}","|","\\","^","`"].concat(["<",">",'"',"`"," ","\r","\n","\t"]),l=["'"].concat(u),f=["%","/","?",";","#"].concat(l),p=["/","?","#"],h=/^[+a-z0-9A-Z_-]{0,63}$/,d=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,g={javascript:!0,"javascript:":!0},b={javascript:!0,"javascript:":!0},m={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},y=e("querystring");function _(e,t,r){if(e&&i.isObject(e)&&e instanceof o)return e;var n=new o;return n.parse(e,t,r),n}o.prototype.parse=function(e,t,r){if(!i.isString(e))throw new TypeError("Parameter 'url' must be a string, not "+typeof e);var o=e.indexOf("?"),a=-1!==o&&o127?M+="x":M+=P[B];if(!M.match(h)){var N=A.slice(0,C),U=A.slice(C+1),L=P.match(d);L&&(N.push(L[1]),U.unshift(L[2])),U.length&&(_="/"+U.join(".")+_),this.hostname=N.join(".");break}}}this.hostname.length>255?this.hostname="":this.hostname=this.hostname.toLowerCase(),j||(this.hostname=n.toASCII(this.hostname));var q=this.port?":"+this.port:"",F=this.hostname||"";this.host=F+q,this.href+=this.host,j&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),"/"!==_[0]&&(_="/"+_))}if(!g[S])for(C=0,T=l.length;C0)&&r.host.split("@"))&&(r.auth=j.shift(),r.host=r.hostname=j.shift());return r.search=e.search,r.query=e.query,i.isNull(r.pathname)&&i.isNull(r.search)||(r.path=(r.pathname?r.pathname:"")+(r.search?r.search:"")),r.href=r.format(),r}if(!k.length)return r.pathname=null,r.search?r.path="/"+r.search:r.path=null,r.href=r.format(),r;for(var E=k.slice(-1)[0],I=(r.host||e.host||k.length>1)&&("."===E||".."===E)||""===E,C=0,O=k.length;O>=0;O--)"."===(E=k[O])?k.splice(O,1):".."===E?(k.splice(O,1),C++):C&&(k.splice(O,1),C--);if(!w&&!S)for(;C--;C)k.unshift("..");!w||""===k[0]||k[0]&&"/"===k[0].charAt(0)||k.unshift(""),I&&"/"!==k.join("/").substr(-1)&&k.push("");var j,A=""===k[0]||k[0]&&"/"===k[0].charAt(0);x&&(r.hostname=r.host=A?"":k.length?k.shift():"",(j=!!(r.host&&r.host.indexOf("@")>0)&&r.host.split("@"))&&(r.auth=j.shift(),r.host=r.hostname=j.shift()));return(w=w||r.host&&k.length)&&!A&&k.unshift(""),k.length?r.pathname=k.join("/"):(r.pathname=null,r.path=null),i.isNull(r.pathname)&&i.isNull(r.search)||(r.path=(r.pathname?r.pathname:"")+(r.search?r.search:"")),r.auth=e.auth||r.auth,r.slashes=r.slashes||e.slashes,r.href=r.format(),r},o.prototype.parseHost=function(){var e=this.host,t=a.exec(e);t&&(":"!==(t=t[0])&&(this.port=t.substr(1)),e=e.substr(0,e.length-t.length)),e&&(this.hostname=e)}},{"./util":133,punycode:102,querystring:105}],133:[function(e,t,r){"use strict";t.exports={isString:function(e){return"string"==typeof e},isObject:function(e){return"object"==typeof e&&null!==e},isNull:function(e){return null===e},isNullOrUndefined:function(e){return null==e}}},{}],134:[function(e,t,r){(function(e){function r(t){try{if(!e.localStorage)return!1}catch(e){return!1}var r=e.localStorage[t];return null!=r&&"true"===String(r).toLowerCase()}t.exports=function(e,t){if(r("noDeprecation"))return e;var n=!1;return function(){if(!n){if(r("throwDeprecation"))throw new Error(t);r("traceDeprecation")?console.trace(t):console.warn(t),n=!0}return e.apply(this,arguments)}}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],135:[function(e,t,r){"function"==typeof Object.create?t.exports=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:t.exports=function(e,t){e.super_=t;var r=function(){};r.prototype=t.prototype,e.prototype=new r,e.prototype.constructor=e}},{}],136:[function(e,t,r){t.exports=function(e){return e&&"object"==typeof e&&"function"==typeof e.copy&&"function"==typeof e.fill&&"function"==typeof e.readUInt8}},{}],137:[function(e,t,r){(function(t,n){var i=/%[sdj%]/g;r.format=function(e){if(!m(e)){for(var t=[],r=0;r=o)return e;switch(e){case"%s":return String(n[r++]);case"%d":return Number(n[r++]);case"%j":try{return JSON.stringify(n[r++])}catch(e){return"[Circular]"}default:return e}}),c=n[r];r=3&&(n.depth=arguments[2]),arguments.length>=4&&(n.colors=arguments[3]),d(t)?n.showHidden=t:t&&r._extend(n,t),y(n.showHidden)&&(n.showHidden=!1),y(n.depth)&&(n.depth=2),y(n.colors)&&(n.colors=!1),y(n.customInspect)&&(n.customInspect=!0),n.colors&&(n.stylize=c),l(n,e,n.depth)}function c(e,t){var r=a.styles[t];return r?"["+a.colors[r][0]+"m"+e+"["+a.colors[r][1]+"m":e}function u(e,t){return e}function l(e,t,n){if(e.customInspect&&t&&k(t.inspect)&&t.inspect!==r.inspect&&(!t.constructor||t.constructor.prototype!==t)){var i=t.inspect(n,e);return m(i)||(i=l(e,i,n)),i}var o=function(e,t){if(y(t))return e.stylize("undefined","undefined");if(m(t)){var r="'"+JSON.stringify(t).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return e.stylize(r,"string")}if(b(t))return e.stylize(""+t,"number");if(d(t))return e.stylize(""+t,"boolean");if(g(t))return e.stylize("null","null")}(e,t);if(o)return o;var s=Object.keys(t),a=function(e){var t={};return e.forEach(function(e,r){t[e]=!0}),t}(s);if(e.showHidden&&(s=Object.getOwnPropertyNames(t)),S(t)&&(s.indexOf("message")>=0||s.indexOf("description")>=0))return f(t);if(0===s.length){if(k(t)){var c=t.name?": "+t.name:"";return e.stylize("[Function"+c+"]","special")}if(_(t))return e.stylize(RegExp.prototype.toString.call(t),"regexp");if(w(t))return e.stylize(Date.prototype.toString.call(t),"date");if(S(t))return f(t)}var u,v="",x=!1,E=["{","}"];(h(t)&&(x=!0,E=["[","]"]),k(t))&&(v=" [Function"+(t.name?": "+t.name:"")+"]");return _(t)&&(v=" "+RegExp.prototype.toString.call(t)),w(t)&&(v=" "+Date.prototype.toUTCString.call(t)),S(t)&&(v=" "+f(t)),0!==s.length||x&&0!=t.length?n<0?_(t)?e.stylize(RegExp.prototype.toString.call(t),"regexp"):e.stylize("[Object]","special"):(e.seen.push(t),u=x?function(e,t,r,n,i){for(var o=[],s=0,a=t.length;s=0&&0,e+t.replace(/\u001b\[\d\d?m/g,"").length+1},0)>60)return r[0]+(""===t?"":t+"\n ")+" "+e.join(",\n ")+" "+r[1];return r[0]+t+" "+e.join(", ")+" "+r[1]}(u,v,E)):E[0]+v+E[1]}function f(e){return"["+Error.prototype.toString.call(e)+"]"}function p(e,t,r,n,i,o){var s,a,c;if((c=Object.getOwnPropertyDescriptor(t,i)||{value:t[i]}).get?a=c.set?e.stylize("[Getter/Setter]","special"):e.stylize("[Getter]","special"):c.set&&(a=e.stylize("[Setter]","special")),C(n,i)||(s="["+i+"]"),a||(e.seen.indexOf(c.value)<0?(a=g(r)?l(e,c.value,null):l(e,c.value,r-1)).indexOf("\n")>-1&&(a=o?a.split("\n").map(function(e){return" "+e}).join("\n").substr(2):"\n"+a.split("\n").map(function(e){return" "+e}).join("\n")):a=e.stylize("[Circular]","special")),y(s)){if(o&&i.match(/^\d+$/))return a;(s=JSON.stringify(""+i)).match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(s=s.substr(1,s.length-2),s=e.stylize(s,"name")):(s=s.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),s=e.stylize(s,"string"))}return s+": "+a}function h(e){return Array.isArray(e)}function d(e){return"boolean"==typeof e}function g(e){return null===e}function b(e){return"number"==typeof e}function m(e){return"string"==typeof e}function y(e){return void 0===e}function _(e){return v(e)&&"[object RegExp]"===x(e)}function v(e){return"object"==typeof e&&null!==e}function w(e){return v(e)&&"[object Date]"===x(e)}function S(e){return v(e)&&("[object Error]"===x(e)||e instanceof Error)}function k(e){return"function"==typeof e}function x(e){return Object.prototype.toString.call(e)}function E(e){return e<10?"0"+e.toString(10):e.toString(10)}r.debuglog=function(e){if(y(o)&&(o=t.env.NODE_DEBUG||""),e=e.toUpperCase(),!s[e])if(new RegExp("\\b"+e+"\\b","i").test(o)){var n=t.pid;s[e]=function(){var t=r.format.apply(r,arguments);console.error("%s %d: %s",e,n,t)}}else s[e]=function(){};return s[e]},r.inspect=a,a.colors={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},a.styles={special:"cyan",number:"yellow",boolean:"yellow",undefined:"grey",null:"bold",string:"green",date:"magenta",regexp:"red"},r.isArray=h,r.isBoolean=d,r.isNull=g,r.isNullOrUndefined=function(e){return null==e},r.isNumber=b,r.isString=m,r.isSymbol=function(e){return"symbol"==typeof e},r.isUndefined=y,r.isRegExp=_,r.isObject=v,r.isDate=w,r.isError=S,r.isFunction=k,r.isPrimitive=function(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||void 0===e},r.isBuffer=e("./support/isBuffer");var I=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function C(e,t){return Object.prototype.hasOwnProperty.call(e,t)}r.log=function(){var e,t;console.log("%s - %s",(e=new Date,t=[E(e.getHours()),E(e.getMinutes()),E(e.getSeconds())].join(":"),[e.getDate(),I[e.getMonth()],t].join(" ")),r.format.apply(r,arguments))},r.inherits=e("inherits"),r._extend=function(e,t){if(!t||!v(t))return e;for(var r=Object.keys(t),n=r.length;n--;)e[r[n]]=t[r[n]];return e}}).call(this,e("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./support/isBuffer":136,_process:101,inherits:135}],138:[function(e,t,r){t.exports=function e(t,r){if(t&&r)return e(t)(r);if("function"!=typeof t)throw new TypeError("need wrapper function");Object.keys(t).forEach(function(e){n[e]=t[e]});return n;function n(){for(var e=new Array(arguments.length),r=0;r { + const year = date.getFullYear() + const month = date.getMonth() + 1 + const day = date.getDate() + const hour = date.getHours() + const minute = date.getMinutes() + const second = date.getSeconds() + + return `${[year, month, day].map(formatNumber).join('/')} ${[hour, minute, second].map(formatNumber).join(':')}` +} + +const formatNumber = n => { + n = n.toString() + return n[1] ? n : `0${n}` +} + +module.exports = { + formatTime +} diff --git a/src/miniprogram_ui/.gitignore b/src/miniprogram_ui/.gitignore new file mode 100644 index 0000000..14ea590 --- /dev/null +++ b/src/miniprogram_ui/.gitignore @@ -0,0 +1,14 @@ +# Windows +[Dd]esktop.ini +Thumbs.db +$RECYCLE.BIN/ + +# macOS +.DS_Store +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes + +# Node.js +node_modules/ diff --git a/src/miniprogram_ui/app.js b/src/miniprogram_ui/app.js new file mode 100644 index 0000000..4af33be --- /dev/null +++ b/src/miniprogram_ui/app.js @@ -0,0 +1,2 @@ +// app.js +App({}) diff --git a/src/miniprogram_ui/app.json b/src/miniprogram_ui/app.json new file mode 100644 index 0000000..1e4ceeb --- /dev/null +++ b/src/miniprogram_ui/app.json @@ -0,0 +1,16 @@ +{ + "pages": [ + "pages/index/index", + "pages/face/face", + "pages/pay/pay", + "pages/logs/logs" + ], + "window": { + "backgroundTextStyle": "light", + "navigationBarBackgroundColor": "#fff", + "navigationBarTitleText": "商品选择", + "navigationBarTextStyle": "black" + }, + "style": "v2", + "sitemapLocation": "sitemap.json" +} \ No newline at end of file diff --git a/src/miniprogram_ui/app.wxss b/src/miniprogram_ui/app.wxss new file mode 100644 index 0000000..4684d3c --- /dev/null +++ b/src/miniprogram_ui/app.wxss @@ -0,0 +1,7 @@ +/**app.wxss**/ +.container { + padding: 48rpx; +} +page{ + font-family: "PingFangSC-Thin" +} diff --git a/src/miniprogram_ui/assets/payment_success_edited.mp3 b/src/miniprogram_ui/assets/payment_success_edited.mp3 new file mode 100644 index 0000000..281b5ea Binary files /dev/null and b/src/miniprogram_ui/assets/payment_success_edited.mp3 differ diff --git a/src/miniprogram_ui/image/face.png b/src/miniprogram_ui/image/face.png new file mode 100644 index 0000000..2c80cb7 Binary files /dev/null and b/src/miniprogram_ui/image/face.png differ diff --git a/src/miniprogram_ui/image/pay.png b/src/miniprogram_ui/image/pay.png new file mode 100644 index 0000000..9668a07 Binary files /dev/null and b/src/miniprogram_ui/image/pay.png differ diff --git a/src/miniprogram_ui/pages/face/face.js b/src/miniprogram_ui/pages/face/face.js new file mode 100644 index 0000000..3b6142c --- /dev/null +++ b/src/miniprogram_ui/pages/face/face.js @@ -0,0 +1,12 @@ + +Page({ + // 监听页面显示 + onShow: function () { + // 自动跳转到login + setTimeout(function () { + wx.navigateTo({ + url: '../pay/pay' + }) + }, 2000) + } +}) diff --git a/src/miniprogram_ui/pages/face/face.json b/src/miniprogram_ui/pages/face/face.json new file mode 100644 index 0000000..8835af0 --- /dev/null +++ b/src/miniprogram_ui/pages/face/face.json @@ -0,0 +1,3 @@ +{ + "usingComponents": {} +} \ No newline at end of file diff --git a/src/miniprogram_ui/pages/face/face.wxml b/src/miniprogram_ui/pages/face/face.wxml new file mode 100644 index 0000000..3dc2e5d --- /dev/null +++ b/src/miniprogram_ui/pages/face/face.wxml @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/miniprogram_ui/pages/face/face.wxss b/src/miniprogram_ui/pages/face/face.wxss new file mode 100644 index 0000000..139ea30 --- /dev/null +++ b/src/miniprogram_ui/pages/face/face.wxss @@ -0,0 +1,12 @@ + .image_{ + margin-top: 10%; + display:flex; + height: 100%; + justify-content: center; + align-items:center; + + } + .img{ + width:620rpx; + height:1100rpx; + } \ No newline at end of file diff --git a/src/miniprogram_ui/pages/index/index.js b/src/miniprogram_ui/pages/index/index.js new file mode 100644 index 0000000..17e2672 --- /dev/null +++ b/src/miniprogram_ui/pages/index/index.js @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2022 Yicong Liu and Sidi Liang. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import mqtt from '../../utils/mqtt.min.js' + +Page({ + data: { + client: null, + conenctBtnText: '连接', + host: 'YT32IOSCAL.ap-guangzhou.iothub.tencentdevices.com:443', + subTopic: 'YT32IOSCAL/UI/data', + syncTopic: 'YT32IOSCAL/UI/sync', + shadowTopic: '$shadow/operation/result/YT32IOSCAL/UI', + shadowReqTopic: '$shadow/operation/YT32IOSCAL/UI', + pubTopic: 'YT32IOSCAL/UI/event', + receivedMsg: '', + received: '', + paying: 0, + shadowMsg: '', + shadow: '', + shadowVersion: '', + lastReportedToShadowMsg: '', + name1: '口罩', + name2: '酒精棉片', + name3: '碘酒', + name4: '创可贴', + price1: 1, + price2: 9.9, + price3: 5.9, + price4: 9.9, + mqttOptions: { + username: 'YT32IOSCALUI;12010126;88a3d;1664208000', + password: + '2788c933085788d342950273e749b9c5f328221ef752a3392c0f590ec660e7c0;hmacsha256', + reconnectPeriod: 5000, + connectTimeout: 10 * 1000, + KeepAlive: 900 + } + }, + + setValue (key, value) { + this.setData({ + [key]: value + }) + }, + + setHost (e) { + this.setValue('host', e.detail.value) + }, + setSubTopic (e) { + this.setValue('subTopic', e.detail.value) + }, + setPubTopic (e) { + this.setValue('pubTopic', e.detail.value) + }, + setPubMsg (e) { + this.setValue('pubMsg', e.detail.value) + }, + setRecMsg (msg) { + this.setValue('receivedMsg', msg) + }, + + startDataUpdateTimer: function () { + var that = this + that.data.dataUpdateTimer = setInterval(function () { + that.sendDataRequest() + }, 1000) + }, + + sendDataRequest: function () { + var requestMsg = { + type: 'get', + clientToken: 'clientToken' + } + this.data.client.publish( + this.data.shadowReqTopic, + JSON.stringify(requestMsg) + ) + }, + + connect () { + try { + wx.setNavigationBarTitle({ + title: '商品选择(连接中...)' + }) + const clientId = new Date().getTime() + this.data.client = mqtt.connect(`wxs://${this.data.host}/mqtt`, { + ...this.data.mqttOptions, + clientId + }) + + this.data.client.on('connect', () => { + wx.setNavigationBarTitle({ + title: '商品选择' + }) + this.subscribe() + console.log('online') + }) + + this.data.client.on('message', (topic, payload) => { + if (topic === 'YT32IOSCAL/UI/data') { + const currMsg = this.data.receivedMsg ? `
${payload}` : payload + this.setValue('receivedMsg', this.data.receivedMsg.concat(currMsg)) + this.data.paying = 1 + wx.navigateTo({ + url: '../face/face' + }) + } + if (topic === '$shadow/operation/result/YT32IOSCAL/UI') { + console.log('receivedMessage') + const currMsg = this.data.shadowMsg ? `
${payload}` : payload + this.setValue('shadowMsg', this.data.shadowMsg.concat(currMsg)) + this.processShadowMessage() + this.data.shadowMsg = '' + } + if (topic === 'YT32IOSCAL/UI/sync') { + console.log('receivedMessage') + const currMsg = this.data.shadowMsg ? `
${payload}` : payload + this.setValue('shadowMsg', this.data.shadowMsg.concat(currMsg)) + this.processSyncMessage() + this.data.shadowMsg = '' + } + }) + + this.data.client.on('error', (error) => { + console.log('onError', error) + wx.setNavigationBarTitle({ + title: '商品选择(连接失败)' + }) + }) + + this.data.client.on('reconnect', () => { + console.log('reconnecting...') + wx.setNavigationBarTitle({ + title: '商品选择(重连中...)' + }) + }) + + this.data.client.on('offline', () => { + wx.setNavigationBarTitle({ + title: '商品选择(未连接)' + }) + console.log('Offline') + }) + } catch (error) { + this.setValue('conenctBtnText', '连接') + wx.setNavigationBarTitle({ + title: '商品选择(出现错误)' + }) + console.log('mqtt.connect error', error) + } + }, + + disconnect () { + this.data.client.end() + this.data.client = null + this.setValue('conenctBtnText', '连接') + wx.setNavigationBarTitle({ + title: '商品选择(未连接)' + }) + }, + + subscribe () { + if (this.data.client) { + this.data.client.subscribe(this.data.subTopic) + this.data.client.subscribe(this.data.shadowTopic) + this.data.client.subscribe(this.data.syncTopic) + console.log('subscribe success') + } + }, + + unsubscribe () { + if (this.data.client) { + this.data.client.unsubscribe(this.data.subTopic) + this.data.client.unsubscribe(this.data.shadowTopic) + this.data.client.unsubscribe(this.data.syncTopic) + } + }, + + processShadowMessage () { + const received = JSON.parse(this.data.shadowMsg) + // console.log(received) + if (received.type === 'get') { + this.data.name1 = + received.payload.state.reported.product_info[0].product_name + this.setData({ + name1: this.data.name1 + }) + this.data.name2 = + received.payload.state.reported.product_info[1].product_name + this.setData({ + name2: this.data.name2 + }) + this.data.name3 = + received.payload.state.reported.product_info[2].product_name + this.setData({ + name3: this.data.name3 + }) + this.data.name4 = + received.payload.state.reported.product_info[3].product_name + this.setData({ + name4: this.data.name4 + }) + this.data.price1 = + received.payload.state.reported.product_info[0].product_price + this.setData({ + price1: this.data.price1 + }) + this.data.price2 = + received.payload.state.reported.product_info[1].product_price + this.setData({ + price2: this.data.price2 + }) + this.data.price3 = + received.payload.state.reported.product_info[2].product_price + this.setData({ + price3: this.data.price3 + }) + this.data.price4 = + received.payload.state.reported.product_info[3].product_price + this.setData({ + price4: this.data.price4 + }) + } else if (received.type === 'update') { + console.log(received) + this.shadowVersion = received.payload.version + console.log('version updated to ') + console.log(this.shadowVersion) + if (received.result === 5005) { + this.reportToShadow(this.lastReportedToShadowMsg) + } + } + }, + + processSyncMessage () { + const received = JSON.parse(this.data.shadowMsg) + console.log(received) + this.data.name1 = received.state.reported.product_info[0].product_name + this.setData({ + name1: this.data.name1 + }) + this.data.name2 = received.state.reported.product_info[1].product_name + this.setData({ + name2: this.data.name2 + }) + this.data.name3 = received.state.reported.product_info[2].product_name + this.setData({ + name3: this.data.name3 + }) + this.data.name4 = received.state.reported.product_info[3].product_name + this.setData({ + name4: this.data.name4 + }) + this.data.price1 = received.state.reported.product_info[0].product_price + this.setData({ + price1: this.data.price1 + }) + this.data.price2 = received.state.reported.product_info[1].product_price + this.setData({ + price2: this.data.price2 + }) + this.data.price3 = received.state.reported.product_info[2].product_price + this.setData({ + price3: this.data.price3 + }) + this.data.price4 = received.state.reported.product_info[3].product_price + this.setData({ + price4: this.data.price4 + }) + this.reportToShadow(received.state.reported) + }, + + reportToShadow: function (msgObj) { + const reportMsg = { + type: 'update', + state: { + reported: { + ...msgObj + } + }, + version: this.shadowVersion, + clientToken: 'clientToken' + } + if (this.data.client) { + this.data.client.publish( + this.data.shadowReqTopic, + JSON.stringify(reportMsg) + ) + console.log(JSON.stringify(reportMsg)) + this.lastReportedToShadowMsg = msgObj + } + }, + + deal () { + const received = JSON.parse(this.data.receivedMsg) + if (received.slot_num === 1) { + return { + chosen_slot: 'slot_1' + } + } + if (received.slot_num === 2) { + return { + chosen_slot: 'slot_2' + } + } + if (received.slot_num === 3) { + return { + chosen_slot: 'slot_3' + } + } + if (received.slot_num === 4) { + return { + chosen_slot: 'slot_4' + } + } + }, + + publish () { + if (this.data.client) { + this.data.client.publish(this.data.pubTopic, JSON.stringify(this.deal())) + console.log(JSON.stringify(this.deal())) + // this.requestShadowData() + this.data.receivedMsg = '' + } + }, + + onShow: function () { + if (this.data.paying) { + this.publish() + this.data.paying = 0 + } + }, + onLoad: function () { + this.connect() + this.sendDataRequest() + this.startDataUpdateTimer() + } +}) diff --git a/src/miniprogram_ui/pages/index/index.json b/src/miniprogram_ui/pages/index/index.json new file mode 100644 index 0000000..a97367d --- /dev/null +++ b/src/miniprogram_ui/pages/index/index.json @@ -0,0 +1,3 @@ +{ + "usingComponents": {} +} diff --git a/src/miniprogram_ui/pages/index/index.wxml b/src/miniprogram_ui/pages/index/index.wxml new file mode 100644 index 0000000..49fb20d --- /dev/null +++ b/src/miniprogram_ui/pages/index/index.wxml @@ -0,0 +1,30 @@ + + + + + 1 + {{name1}} + ¥ {{price1}} + \n + + + + 2 + {{name2}} + ¥ {{price2}} + \n + + + + 3 + {{name3}} + ¥ {{price3}} + + + + 4 + {{name4}} + ¥ {{price4}} + + + \ No newline at end of file diff --git a/src/miniprogram_ui/pages/index/index.wxss b/src/miniprogram_ui/pages/index/index.wxss new file mode 100644 index 0000000..4e7f336 --- /dev/null +++ b/src/miniprogram_ui/pages/index/index.wxss @@ -0,0 +1,44 @@ +.cps2{ + display: flex; + flex-wrap: wrap; + justify-content: center; +} +.status{ + display: flex; + flex-wrap: wrap; + justify-content: left; +} +.cp-item1{ + width: 50%; + display: flex; + align-items:center; + flex-direction: column; + font-size:30rpx; +} +.cp-image2{ + width: 300rpx; + height: 280rpx; +} +.cp-item2 text{ + font-size: 30rpx; + width: 100%; + text-align:center; + margin-left:20rpx; +} +.text1{ + height: 55rpx; + font-weight: 900; +} +.text3{ + color:red; + height: 70rpx; + font-weight: 900; +} +.container{ + min-height: 100vh; + background-color: rgb(255, 255, 255); +} + +.text2{ + font-weight: 900; +} \ No newline at end of file diff --git a/src/miniprogram_ui/pages/logs/logs.js b/src/miniprogram_ui/pages/logs/logs.js new file mode 100644 index 0000000..26e868a --- /dev/null +++ b/src/miniprogram_ui/pages/logs/logs.js @@ -0,0 +1,66 @@ +// pages/logs/logs.js +Page({ + + /** + * 页面的初始数据 + */ + data: { + + }, + + /** + * 生命周期函数--监听页面加载 + */ + onLoad(options) { + + }, + + /** + * 生命周期函数--监听页面初次渲染完成 + */ + onReady() { + + }, + + /** + * 生命周期函数--监听页面显示 + */ + onShow() { + + }, + + /** + * 生命周期函数--监听页面隐藏 + */ + onHide() { + + }, + + /** + * 生命周期函数--监听页面卸载 + */ + onUnload() { + + }, + + /** + * 页面相关事件处理函数--监听用户下拉动作 + */ + onPullDownRefresh() { + + }, + + /** + * 页面上拉触底事件的处理函数 + */ + onReachBottom() { + + }, + + /** + * 用户点击右上角分享 + */ + onShareAppMessage() { + + } +}) \ No newline at end of file diff --git a/src/miniprogram_ui/pages/logs/logs.wxml b/src/miniprogram_ui/pages/logs/logs.wxml new file mode 100644 index 0000000..c49f50c --- /dev/null +++ b/src/miniprogram_ui/pages/logs/logs.wxml @@ -0,0 +1,2 @@ + +pages/logs/logs.wxml diff --git a/src/miniprogram_ui/pages/pay/pay.js b/src/miniprogram_ui/pages/pay/pay.js new file mode 100644 index 0000000..3372eac --- /dev/null +++ b/src/miniprogram_ui/pages/pay/pay.js @@ -0,0 +1,28 @@ + +Page({ + // 监听页面显示 + onShow: function () { + this.audioPlay() + // 自动跳转到login + setTimeout(function () { + // 页面跳转 + wx.navigateBack({ + delta: 2 + }) + }, 2000) + }, + audioPlay(){ + const successAudio = wx.createInnerAudioContext() + successAudio.src = 'https://cdn.fgprc.org.cn/vendor/payment_success_edited.mp3' + successAudio.obeyMuteSwitch = false + successAudio.play() + successAudio.onPlay(() => { + console.log('开始播放') + }) + successAudio.onError((res) => { + console.log(res.errMsg) + console.log(res.errCode) + }) + }, + +}) diff --git a/src/miniprogram_ui/pages/pay/pay.json b/src/miniprogram_ui/pages/pay/pay.json new file mode 100644 index 0000000..8835af0 --- /dev/null +++ b/src/miniprogram_ui/pages/pay/pay.json @@ -0,0 +1,3 @@ +{ + "usingComponents": {} +} \ No newline at end of file diff --git a/src/miniprogram_ui/pages/pay/pay.wxml b/src/miniprogram_ui/pages/pay/pay.wxml new file mode 100644 index 0000000..b345b59 --- /dev/null +++ b/src/miniprogram_ui/pages/pay/pay.wxml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/miniprogram_ui/pages/pay/pay.wxss b/src/miniprogram_ui/pages/pay/pay.wxss new file mode 100644 index 0000000..5e87baa --- /dev/null +++ b/src/miniprogram_ui/pages/pay/pay.wxss @@ -0,0 +1,14 @@ +page{ + height:80%; + } + .image_{ + display:flex; + height: 100%; + justify-content: center; + align-items:center; + + } + .img{ + width:460rpx; + height:400rpx; + } \ No newline at end of file diff --git a/src/miniprogram_ui/project.config.json b/src/miniprogram_ui/project.config.json new file mode 100644 index 0000000..f6f5a75 --- /dev/null +++ b/src/miniprogram_ui/project.config.json @@ -0,0 +1,53 @@ +{ + "description": "项目配置文件,详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html", + "setting": { + "bundle": false, + "userConfirmedBundleSwitch": false, + "urlCheck": true, + "scopeDataCheck": false, + "coverView": true, + "es6": false, + "postcss": true, + "compileHotReLoad": true, + "lazyloadPlaceholderEnable": false, + "preloadBackgroundData": false, + "minified": true, + "autoAudits": false, + "newFeature": false, + "uglifyFileName": false, + "uploadWithSourceMap": true, + "useIsolateContext": true, + "nodeModules": false, + "enhance": true, + "useMultiFrameRuntime": true, + "showShadowRootInWxmlPanel": true, + "packNpmManually": false, + "enableEngineNative": false, + "packNpmRelationList": [], + "minifyWXSS": true, + "showES6CompileOption": false, + "minifyWXML": true, + "useStaticServer": true, + "checkInvalidKey": true, + "babelSetting": { + "ignore": [], + "disablePlugins": [], + "outputPath": "" + }, + "disableUseStrict": false, + "useCompilerPlugins": false, + "ignoreUploadUnusedFiles": true + }, + "compileType": "miniprogram", + "condition": {}, + "editorSetting": { + "tabIndent": "insertSpaces", + "tabSize": 4 + }, + "libVersion": "2.25.1", + "packOptions": { + "ignore": [], + "include": [] + }, + "appid": "wx408e3aaf44bc0bd1" +} \ No newline at end of file diff --git a/src/miniprogram_ui/project.private.config.json b/src/miniprogram_ui/project.private.config.json new file mode 100644 index 0000000..7fd1067 --- /dev/null +++ b/src/miniprogram_ui/project.private.config.json @@ -0,0 +1,8 @@ +{ + "projectname": "miniprogram_ui", + "setting": { + "compileHotReLoad": true, + "urlCheck": true + }, + "description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html" +} \ No newline at end of file diff --git a/src/miniprogram_ui/sitemap.json b/src/miniprogram_ui/sitemap.json new file mode 100644 index 0000000..27b2b26 --- /dev/null +++ b/src/miniprogram_ui/sitemap.json @@ -0,0 +1,7 @@ +{ + "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html", + "rules": [{ + "action": "allow", + "page": "*" + }] +} \ No newline at end of file diff --git a/src/miniprogram_ui/utils/mqtt.min.js b/src/miniprogram_ui/utils/mqtt.min.js new file mode 100644 index 0000000..ed91d92 --- /dev/null +++ b/src/miniprogram_ui/utils/mqtt.min.js @@ -0,0 +1 @@ +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).mqtt=e()}}(function(){return function(){return function e(t,r,n){function i(s,a){if(!r[s]){if(!t[s]){var c="function"==typeof require&&require;if(!a&&c)return c(s,!0);if(o)return o(s,!0);var u=new Error("Cannot find module '"+s+"'");throw u.code="MODULE_NOT_FOUND",u}var l=r[s]={exports:{}};t[s][0].call(l.exports,function(e){return i(t[s][1][e]||e)},l,l.exports,e,t,r,n)}return r[s].exports}for(var o="function"==typeof require&&require,s=0;sthis.emit("error",new Error("Packet has no Authentication Method"))),this;if(this.options.properties.authenticationMethod&&this.options.authPacket&&"object"==typeof this.options.authPacket)y(this,f({cmd:"auth",reasonCode:0},this.options.authPacket))}this.stream.setMaxListeners(1e3),clearTimeout(this.connackTimer),this.connackTimer=setTimeout(function(){p("!!connectTimeout hit!! Calling _cleanUp with force `true`"),t._cleanUp(!0)},this.options.connectTimeout)},w.prototype._handlePacket=function(e,t){var r=this.options;if(5===r.protocolVersion&&r.properties&&r.properties.maximumPacketSize&&r.properties.maximumPacketSizeo.properties.topicAliasMaximum||!o.properties.topicAliasMaximum&&r.properties.topicAlias))&&delete i.properties.topicAlias),p("publish :: qos",r.qos),r.qos){case 1:case 2:this.outgoing[i.messageId]={volatile:!1,cb:n||v},this._storeProcessing?(p("_storeProcessing enabled"),this._packetIdsDuringStoreProcessing[i.messageId]=!1,this._storePacket(i,void 0,r.cbStorePut)):(p("MqttClient:publish: packet cmd: %s",i.cmd),this._sendPacket(i,void 0,r.cbStorePut));break;default:this._storeProcessing?(p("_storeProcessing enabled"),this._storePacket(i,n,r.cbStorePut)):(p("MqttClient:publish: packet cmd: %s",i.cmd),this._sendPacket(i,n,r.cbStorePut))}return this},w.prototype.subscribe=function(){for(var e,t=new Array(arguments.length),r=0;r0){var t={qos:e.qos};5===h&&(t.nl=e.nl||!1,t.rap=e.rap||!1,t.rh=e.rh||0,t.properties=e.properties),u._resubscribeTopics[e.topic]=t,b.push(e.topic)}}),u.messageIdToTopic[e.messageId]=b}return this.outgoing[e.messageId]={volatile:!0,cb:function(e,t){if(!e)for(var r=t.granted,n=0;n{p("end :: finish :: calling process.nextTick on closeStores"),h(function(){p("end :: closeStores: closing incoming and outgoing stores"),n.disconnected=!0,n.incomingStore.close(function(e){n.outgoingStore.close(function(t){if(p("end :: closeStores: emitting end"),n.emit("end"),r){let n=e||t;p("end :: closeStores: invoking callback with args"),r(n)}})}),n._deferredReconnect&&n._deferredReconnect()}.bind(n))},t)}return p("end :: (%s)",this.options.clientId),null!=e&&"boolean"==typeof e||(r=t||v,t=e,e=!1,"object"!=typeof t&&(r=t,t=null,"function"!=typeof r&&(r=v))),"object"!=typeof t&&(r=t,t=null),p("end :: cb? %s",!!r),r=r||v,this.disconnecting?(r(),this):(this._clearReconnect(),this.disconnecting=!0,!e&&Object.keys(this.outgoing).length>0?(p("end :: (%s) :: calling finish in 10ms once outgoing is empty",n.options.clientId),this.once("outgoingEmpty",setTimeout.bind(null,i,10))):(p("end :: (%s) :: immediately calling finish",n.options.clientId),i()),this)},w.prototype.removeOutgoingMessage=function(e){var t=this.outgoing[e]?this.outgoing[e].cb:null;return delete this.outgoing[e],this.outgoingStore.del({messageId:e},function(){t(new Error("Message removed"))}),this},w.prototype.reconnect=function(e){p("client reconnect");var t=this,r=function(){e?(t.options.incomingStore=e.incomingStore,t.options.outgoingStore=e.outgoingStore):(t.options.incomingStore=null,t.options.outgoingStore=null),t.incomingStore=t.options.incomingStore||new o,t.outgoingStore=t.options.outgoingStore||new o,t.disconnecting=!1,t.disconnected=!1,t._deferredReconnect=null,t._reconnect()};return this.disconnecting&&!this.disconnected?this._deferredReconnect=r:r(),this},w.prototype._reconnect=function(){p("_reconnect: emitting reconnect to client"),this.emit("reconnect"),p("_reconnect: calling _setupStream"),this._setupStream()},w.prototype._setupReconnect=function(){var e=this;!e.disconnecting&&!e.reconnectTimer&&e.options.reconnectPeriod>0?(this.reconnecting||(p("_setupReconnect :: emit `offline` state"),this.emit("offline"),p("_setupReconnect :: set `reconnecting` to `true`"),this.reconnecting=!0),p("_setupReconnect :: setting reconnectTimer for %d ms",e.options.reconnectPeriod),e.reconnectTimer=setInterval(function(){p("reconnectTimer :: reconnect triggered!"),e._reconnect()},e.options.reconnectPeriod)):p("_setupReconnect :: doing nothing...")},w.prototype._clearReconnect=function(){p("_clearReconnect : clearing reconnect timer"),this.reconnectTimer&&(clearInterval(this.reconnectTimer),this.reconnectTimer=null)},w.prototype._cleanUp=function(e,t){var r,n=arguments[2];if(t&&(p("_cleanUp :: done callback provided for on stream close"),this.stream.on("close",t)),p("_cleanUp :: forced? %s",e),e)0===this.options.reconnectPeriod&&this.options.clean&&(r=this.outgoing)&&(p("flush: queue exists? %b",!!r),Object.keys(r).forEach(function(e){"function"==typeof r[e].cb&&(r[e].cb(new Error("Connection closed")),delete r[e])})),p("_cleanUp :: (%s) :: destroying stream",this.options.clientId),this.stream.destroy();else{var i=f({cmd:"disconnect"},n);p("_cleanUp :: (%s) :: call _sendPacket with disconnect packet",this.options.clientId),this._sendPacket(i,d.bind(null,this.stream.end.bind(this.stream)))}this.disconnecting||(p("_cleanUp :: client not disconnecting. Clearing and resetting reconnect."),this._clearReconnect(),this._setupReconnect()),null!==this.pingTimer&&(p("_cleanUp :: clearing pingTimer"),this.pingTimer.clear(),this.pingTimer=null),t&&!this.connected&&(p("_cleanUp :: (%s) :: removing stream `done` callback `close` listener",this.options.clientId),this.stream.removeListener("close",t),t())},w.prototype._sendPacket=function(e,t,r){if(p("_sendPacket :: (%s) :: start",this.options.clientId),r=r||v,!this.connected)return p("_sendPacket :: client not connected. Storing packet offline."),void this._storePacket(e,t,r);switch(this._shiftPingInterval(),e.cmd){case"publish":break;case"pubrel":return void _(this,e,t,r);default:return void y(this,e,t)}switch(e.qos){case 2:case 1:_(this,e,t,r);break;case 0:default:y(this,e,t)}p("_sendPacket :: (%s) :: end",this.options.clientId)},w.prototype._storePacket=function(e,t,r){p("_storePacket :: packet: %o",e),p("_storePacket :: cb? %s",!!t),r=r||v,0===(e.qos||0)&&this.queueQoSZero||"publish"!==e.cmd?this.queue.push({packet:e,cb:t}):e.qos>0?(t=this.outgoing[e.messageId]?this.outgoing[e.messageId].cb:null,this.outgoingStore.put(e,function(e){if(e)return t&&t(e);r()})):t&&t(new Error("No connection to broker"))},w.prototype._setupPingTimer=function(){p("_setupPingTimer :: keepalive %d (seconds)",this.options.keepalive);var e=this;!this.pingTimer&&this.options.keepalive&&(this.pingResp=!0,this.pingTimer=u(function(){e._checkPing()},1e3*this.options.keepalive))},w.prototype._shiftPingInterval=function(){this.pingTimer&&this.options.keepalive&&this.options.reschedulePings&&this.pingTimer.reschedule(1e3*this.options.keepalive)},w.prototype._checkPing=function(){p("_checkPing :: checking ping..."),this.pingResp?(p("_checkPing :: ping response received. Clearing flag and sending `pingreq`"),this.pingResp=!1,this._sendPacket({cmd:"pingreq"})):(p("_checkPing :: calling _cleanUp with force true"),this._cleanUp(!0))},w.prototype._handlePingresp=function(){this.pingResp=!0},w.prototype._handleConnack=function(e){p("_handleConnack");var t=this.options,r=5===t.protocolVersion?e.reasonCode:e.returnCode;if(clearTimeout(this.connackTimer),e.properties&&(e.properties.topicAliasMaximum&&(t.properties||(t.properties={}),t.properties.topicAliasMaximum=e.properties.topicAliasMaximum),e.properties.serverKeepAlive&&t.keepalive&&(t.keepalive=e.properties.serverKeepAlive,this._shiftPingInterval()),e.properties.maximumPacketSize&&(t.properties||(t.properties={}),t.properties.maximumPacketSize=e.properties.maximumPacketSize)),0===r)this.reconnecting=!1,this._onConnect(e);else if(r>0){var n=new Error("Connection refused: "+m[r]);n.code=r,this.emit("error",n)}},w.prototype._handlePublish=function(e,t){p("_handlePublish: packet %o",e),t=void 0!==t?t:v;var r=e.topic.toString(),n=e.payload,i=e.qos,o=e.messageId,s=this,a=this.options,c=[0,16,128,131,135,144,145,151,153];switch(p("_handlePublish: qos %d",i),i){case 2:a.customHandleAcks(r,n,e,function(r,n){return r instanceof Error||(n=r,r=null),r?s.emit("error",r):-1===c.indexOf(n)?s.emit("error",new Error("Wrong reason code for pubrec")):void(n?s._sendPacket({cmd:"pubrec",messageId:o,reasonCode:n},t):s.incomingStore.put(e,function(){s._sendPacket({cmd:"pubrec",messageId:o},t)}))});break;case 1:a.customHandleAcks(r,n,e,function(i,a){return i instanceof Error||(a=i,i=null),i?s.emit("error",i):-1===c.indexOf(a)?s.emit("error",new Error("Wrong reason code for puback")):(a||s.emit("message",r,n,e),void s.handleMessage(e,function(e){if(e)return t&&t(e);s._sendPacket({cmd:"puback",messageId:o,reasonCode:a},t)}))});break;case 0:this.emit("message",r,n,e),this.handleMessage(e,t);break;default:p("_handlePublish: unknown QoS. Doing nothing.")}},w.prototype.handleMessage=function(e,t){t()},w.prototype._handleAck=function(e){var t,r=e.messageId,n=e.cmd,i=null,o=this.outgoing[r]?this.outgoing[r].cb:null,s=this;if(o){switch(p("_handleAck :: packet type",n),n){case"pubcomp":case"puback":var a=e.reasonCode;a&&a>0&&16!==a&&((t=new Error("Publish error: "+m[a])).code=a,o(t,e)),delete this.outgoing[r],this.outgoingStore.del(e,o);break;case"pubrec":i={cmd:"pubrel",qos:2,messageId:r};var c=e.reasonCode;c&&c>0&&16!==c?((t=new Error("Publish error: "+m[c])).code=c,o(t,e)):this._sendPacket(i);break;case"suback":delete this.outgoing[r];for(var u=0;u0)if(this.options.resubscribe)if(5===this.options.protocolVersion){p("_resubscribe: protocolVersion 5");for(var r=0;rn&&setTimeout(e,u,t,r,i),l&&"string"==typeof t&&(t=s.from(t,"utf8"));try{h.send(t)}catch(e){return i(e)}i()},function(e){h.close(),e()});t.objectMode||(d._writev=v),d.on("close",()=>{h.close()});const g=void 0===h.addEventListener;function b(){r.setReadable(d),r.setWritable(d),r.emit("connect")}function m(){r.end(),r.destroy()}function y(e){r.destroy(e)}function _(e){let t=e.data;t=t instanceof ArrayBuffer?s.from(t):s.from(t,"utf8"),d.push(t)}function v(e,t){const r=new Array(e.length);for(let t=0;t0?s-4:s;for(r=0;r>16&255,c[l++]=t>>8&255,c[l++]=255&t;2===a&&(t=i[e.charCodeAt(r)]<<2|i[e.charCodeAt(r+1)]>>4,c[l++]=255&t);1===a&&(t=i[e.charCodeAt(r)]<<10|i[e.charCodeAt(r+1)]<<4|i[e.charCodeAt(r+2)]>>2,c[l++]=t>>8&255,c[l++]=255&t);return c},r.fromByteArray=function(e){for(var t,r=e.length,i=r%3,o=[],s=0,a=r-i;sa?a:s+16383));1===i?(t=e[r-1],o.push(n[t>>2]+n[t<<4&63]+"==")):2===i&&(t=(e[r-2]<<8)+e[r-1],o.push(n[t>>10]+n[t>>4&63]+n[t<<2&63]+"="));return o.join("")};for(var n=[],i=[],o="undefined"!=typeof Uint8Array?Uint8Array:Array,s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",a=0,c=s.length;a0)throw new Error("Invalid string. Length must be a multiple of 4");var r=e.indexOf("=");return-1===r&&(r=t),[r,r===t?0:4-r%4]}function l(e,t,r){for(var i,o,s=[],a=t;a>18&63]+n[o>>12&63]+n[o>>6&63]+n[63&o]);return s.join("")}i["-".charCodeAt(0)]=62,i["_".charCodeAt(0)]=63},{}],11:[function(e,t,r){var n=e("readable-stream/duplex"),i=e("util"),o=e("safe-buffer").Buffer;function s(e){if(!(this instanceof s))return new s(e);if(this._bufs=[],this.length=0,"function"==typeof e){this._callback=e;var t=function(e){this._callback&&(this._callback(e),this._callback=null)}.bind(this);this.on("pipe",function(e){e.on("error",t)}),this.on("unpipe",function(e){e.removeListener("error",t)})}else this.append(e);n.call(this)}i.inherits(s,n),s.prototype._offset=function(e){var t,r=0,n=0;if(0===e)return[0,0];for(;nthis.length)&&(n=this.length),r>=this.length)return e||o.alloc(0);if(n<=0)return e||o.alloc(0);var i,s,a=!!e,c=this._offset(r),u=n-r,l=u,f=a&&t||0,p=c[1];if(0===r&&n==this.length){if(!a)return 1===this._bufs.length?this._bufs[0]:o.concat(this._bufs,this.length);for(s=0;s(i=this._bufs[s].length-p))){this._bufs[s].copy(e,f,p,p+l);break}this._bufs[s].copy(e,f,p),f+=i,l-=i,p&&(p=0)}return e},s.prototype.shallowSlice=function(e,t){e=e||0,t=t||this.length,e<0&&(e+=this.length),t<0&&(t+=this.length);var r=this._offset(e),n=this._offset(t),i=this._bufs.slice(r[0],n[0]+1);return 0==n[1]?i.pop():i[i.length-1]=i[i.length-1].slice(0,n[1]),0!=r[1]&&(i[0]=i[0].slice(r[1])),new s(i)},s.prototype.toString=function(e,t,r){return this.slice(t,r).toString(e)},s.prototype.consume=function(e){for(;this._bufs.length;){if(!(e>=this._bufs[0].length)){this._bufs[0]=this._bufs[0].slice(e),this.length-=e;break}e-=this._bufs[0].length,this.length-=this._bufs[0].length,this._bufs.shift()}return this},s.prototype.duplicate=function(){for(var e=0,t=new s;eo)throw new RangeError('The value "'+e+'" is invalid for option "size"');var r=new Uint8Array(e);return r.__proto__=t.prototype,r}function t(e,t,r){if("number"==typeof e){if("string"==typeof t)throw new TypeError('The "string" argument must be of type string. Received type number');return u(e)}return a(e,t,r)}function a(e,r,n){if("string"==typeof e)return function(e,r){"string"==typeof r&&""!==r||(r="utf8");if(!t.isEncoding(r))throw new TypeError("Unknown encoding: "+r);var n=0|p(e,r),i=s(n),o=i.write(e,r);o!==n&&(i=i.slice(0,o));return i}(e,r);if(ArrayBuffer.isView(e))return l(e);if(null==e)throw TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof e);if(q(e,ArrayBuffer)||e&&q(e.buffer,ArrayBuffer))return function(e,r,n){if(r<0||e.byteLength=o)throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+o.toString(16)+" bytes");return 0|e}function p(e,r){if(t.isBuffer(e))return e.length;if(ArrayBuffer.isView(e)||q(e,ArrayBuffer))return e.byteLength;if("string"!=typeof e)throw new TypeError('The "string" argument must be one of type string, Buffer, or ArrayBuffer. Received type '+typeof e);var n=e.length,i=arguments.length>2&&!0===arguments[2];if(!i&&0===n)return 0;for(var o=!1;;)switch(r){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":return N(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return U(e).length;default:if(o)return i?-1:N(e).length;r=(""+r).toLowerCase(),o=!0}}function h(e,t,r){var n=e[t];e[t]=e[r],e[r]=n}function d(e,r,n,i,o){if(0===e.length)return-1;if("string"==typeof n?(i=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),F(n=+n)&&(n=o?0:e.length-1),n<0&&(n=e.length+n),n>=e.length){if(o)return-1;n=e.length-1}else if(n<0){if(!o)return-1;n=0}if("string"==typeof r&&(r=t.from(r,i)),t.isBuffer(r))return 0===r.length?-1:g(e,r,n,i,o);if("number"==typeof r)return r&=255,"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(e,r,n):Uint8Array.prototype.lastIndexOf.call(e,r,n):g(e,[r],n,i,o);throw new TypeError("val must be string, number or Buffer")}function g(e,t,r,n,i){var o,s=1,a=e.length,c=t.length;if(void 0!==n&&("ucs2"===(n=String(n).toLowerCase())||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(e.length<2||t.length<2)return-1;s=2,a/=2,c/=2,r/=2}function u(e,t){return 1===s?e[t]:e.readUInt16BE(t*s)}if(i){var l=-1;for(o=r;oa&&(r=a-c),o=r;o>=0;o--){for(var f=!0,p=0;pi&&(n=i):n=i;var o=t.length;n>o/2&&(n=o/2);for(var s=0;s>8,i=r%256,o.push(i),o.push(n);return o}(t,e.length-r),e,r,n)}function S(e,t,r){return 0===t&&r===e.length?n.fromByteArray(e):n.fromByteArray(e.slice(t,r))}function k(e,t,r){r=Math.min(e.length,r);for(var n=[],i=t;i239?4:u>223?3:u>191?2:1;if(i+f<=r)switch(f){case 1:u<128&&(l=u);break;case 2:128==(192&(o=e[i+1]))&&(c=(31&u)<<6|63&o)>127&&(l=c);break;case 3:o=e[i+1],s=e[i+2],128==(192&o)&&128==(192&s)&&(c=(15&u)<<12|(63&o)<<6|63&s)>2047&&(c<55296||c>57343)&&(l=c);break;case 4:o=e[i+1],s=e[i+2],a=e[i+3],128==(192&o)&&128==(192&s)&&128==(192&a)&&(c=(15&u)<<18|(63&o)<<12|(63&s)<<6|63&a)>65535&&c<1114112&&(l=c)}null===l?(l=65533,f=1):l>65535&&(l-=65536,n.push(l>>>10&1023|55296),l=56320|1023&l),n.push(l),i+=f}return function(e){var t=e.length;if(t<=x)return String.fromCharCode.apply(String,e);var r="",n=0;for(;nthis.length)return"";if((void 0===r||r>this.length)&&(r=this.length),r<=0)return"";if((r>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return C(this,t,r);case"utf8":case"utf-8":return k(this,t,r);case"ascii":return E(this,t,r);case"latin1":case"binary":return I(this,t,r);case"base64":return S(this,t,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return O(this,t,r);default:if(n)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),n=!0}}.apply(this,arguments)},t.prototype.toLocaleString=t.prototype.toString,t.prototype.equals=function(e){if(!t.isBuffer(e))throw new TypeError("Argument must be a Buffer");return this===e||0===t.compare(this,e)},t.prototype.inspect=function(){var e="",t=r.INSPECT_MAX_BYTES;return e=this.toString("hex",0,t).replace(/(.{2})/g,"$1 ").trim(),this.length>t&&(e+=" ... "),""},t.prototype.compare=function(e,r,n,i,o){if(q(e,Uint8Array)&&(e=t.from(e,e.offset,e.byteLength)),!t.isBuffer(e))throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. Received type '+typeof e);if(void 0===r&&(r=0),void 0===n&&(n=e?e.length:0),void 0===i&&(i=0),void 0===o&&(o=this.length),r<0||n>e.length||i<0||o>this.length)throw new RangeError("out of range index");if(i>=o&&r>=n)return 0;if(i>=o)return-1;if(r>=n)return 1;if(r>>>=0,n>>>=0,i>>>=0,o>>>=0,this===e)return 0;for(var s=o-i,a=n-r,c=Math.min(s,a),u=this.slice(i,o),l=e.slice(r,n),f=0;f>>=0,isFinite(r)?(r>>>=0,void 0===n&&(n="utf8")):(n=r,r=void 0)}var i=this.length-t;if((void 0===r||r>i)&&(r=i),e.length>0&&(r<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");n||(n="utf8");for(var o=!1;;)switch(n){case"hex":return b(this,e,t,r);case"utf8":case"utf-8":return m(this,e,t,r);case"ascii":return y(this,e,t,r);case"latin1":case"binary":return _(this,e,t,r);case"base64":return v(this,e,t,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return w(this,e,t,r);default:if(o)throw new TypeError("Unknown encoding: "+n);n=(""+n).toLowerCase(),o=!0}},t.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var x=4096;function E(e,t,r){var n="";r=Math.min(e.length,r);for(var i=t;in)&&(r=n);for(var i="",o=t;or)throw new RangeError("Trying to access beyond buffer length")}function A(e,r,n,i,o,s){if(!t.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(r>o||re.length)throw new RangeError("Index out of range")}function T(e,t,r,n,i,o){if(r+n>e.length)throw new RangeError("Index out of range");if(r<0)throw new RangeError("Index out of range")}function P(e,t,r,n,o){return t=+t,r>>>=0,o||T(e,0,r,4),i.write(e,t,r,n,23,4),r+4}function M(e,t,r,n,o){return t=+t,r>>>=0,o||T(e,0,r,8),i.write(e,t,r,n,52,8),r+8}t.prototype.slice=function(e,r){var n=this.length;e=~~e,r=void 0===r?n:~~r,e<0?(e+=n)<0&&(e=0):e>n&&(e=n),r<0?(r+=n)<0&&(r=0):r>n&&(r=n),r>>=0,t>>>=0,r||j(e,t,this.length);for(var n=this[e],i=1,o=0;++o>>=0,t>>>=0,r||j(e,t,this.length);for(var n=this[e+--t],i=1;t>0&&(i*=256);)n+=this[e+--t]*i;return n},t.prototype.readUInt8=function(e,t){return e>>>=0,t||j(e,1,this.length),this[e]},t.prototype.readUInt16LE=function(e,t){return e>>>=0,t||j(e,2,this.length),this[e]|this[e+1]<<8},t.prototype.readUInt16BE=function(e,t){return e>>>=0,t||j(e,2,this.length),this[e]<<8|this[e+1]},t.prototype.readUInt32LE=function(e,t){return e>>>=0,t||j(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},t.prototype.readUInt32BE=function(e,t){return e>>>=0,t||j(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},t.prototype.readIntLE=function(e,t,r){e>>>=0,t>>>=0,r||j(e,t,this.length);for(var n=this[e],i=1,o=0;++o=(i*=128)&&(n-=Math.pow(2,8*t)),n},t.prototype.readIntBE=function(e,t,r){e>>>=0,t>>>=0,r||j(e,t,this.length);for(var n=t,i=1,o=this[e+--n];n>0&&(i*=256);)o+=this[e+--n]*i;return o>=(i*=128)&&(o-=Math.pow(2,8*t)),o},t.prototype.readInt8=function(e,t){return e>>>=0,t||j(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},t.prototype.readInt16LE=function(e,t){e>>>=0,t||j(e,2,this.length);var r=this[e]|this[e+1]<<8;return 32768&r?4294901760|r:r},t.prototype.readInt16BE=function(e,t){e>>>=0,t||j(e,2,this.length);var r=this[e+1]|this[e]<<8;return 32768&r?4294901760|r:r},t.prototype.readInt32LE=function(e,t){return e>>>=0,t||j(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},t.prototype.readInt32BE=function(e,t){return e>>>=0,t||j(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},t.prototype.readFloatLE=function(e,t){return e>>>=0,t||j(e,4,this.length),i.read(this,e,!0,23,4)},t.prototype.readFloatBE=function(e,t){return e>>>=0,t||j(e,4,this.length),i.read(this,e,!1,23,4)},t.prototype.readDoubleLE=function(e,t){return e>>>=0,t||j(e,8,this.length),i.read(this,e,!0,52,8)},t.prototype.readDoubleBE=function(e,t){return e>>>=0,t||j(e,8,this.length),i.read(this,e,!1,52,8)},t.prototype.writeUIntLE=function(e,t,r,n){(e=+e,t>>>=0,r>>>=0,n)||A(this,e,t,r,Math.pow(2,8*r)-1,0);var i=1,o=0;for(this[t]=255&e;++o>>=0,r>>>=0,n)||A(this,e,t,r,Math.pow(2,8*r)-1,0);var i=r-1,o=1;for(this[t+i]=255&e;--i>=0&&(o*=256);)this[t+i]=e/o&255;return t+r},t.prototype.writeUInt8=function(e,t,r){return e=+e,t>>>=0,r||A(this,e,t,1,255,0),this[t]=255&e,t+1},t.prototype.writeUInt16LE=function(e,t,r){return e=+e,t>>>=0,r||A(this,e,t,2,65535,0),this[t]=255&e,this[t+1]=e>>>8,t+2},t.prototype.writeUInt16BE=function(e,t,r){return e=+e,t>>>=0,r||A(this,e,t,2,65535,0),this[t]=e>>>8,this[t+1]=255&e,t+2},t.prototype.writeUInt32LE=function(e,t,r){return e=+e,t>>>=0,r||A(this,e,t,4,4294967295,0),this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e,t+4},t.prototype.writeUInt32BE=function(e,t,r){return e=+e,t>>>=0,r||A(this,e,t,4,4294967295,0),this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e,t+4},t.prototype.writeIntLE=function(e,t,r,n){if(e=+e,t>>>=0,!n){var i=Math.pow(2,8*r-1);A(this,e,t,r,i-1,-i)}var o=0,s=1,a=0;for(this[t]=255&e;++o>0)-a&255;return t+r},t.prototype.writeIntBE=function(e,t,r,n){if(e=+e,t>>>=0,!n){var i=Math.pow(2,8*r-1);A(this,e,t,r,i-1,-i)}var o=r-1,s=1,a=0;for(this[t+o]=255&e;--o>=0&&(s*=256);)e<0&&0===a&&0!==this[t+o+1]&&(a=1),this[t+o]=(e/s>>0)-a&255;return t+r},t.prototype.writeInt8=function(e,t,r){return e=+e,t>>>=0,r||A(this,e,t,1,127,-128),e<0&&(e=255+e+1),this[t]=255&e,t+1},t.prototype.writeInt16LE=function(e,t,r){return e=+e,t>>>=0,r||A(this,e,t,2,32767,-32768),this[t]=255&e,this[t+1]=e>>>8,t+2},t.prototype.writeInt16BE=function(e,t,r){return e=+e,t>>>=0,r||A(this,e,t,2,32767,-32768),this[t]=e>>>8,this[t+1]=255&e,t+2},t.prototype.writeInt32LE=function(e,t,r){return e=+e,t>>>=0,r||A(this,e,t,4,2147483647,-2147483648),this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24,t+4},t.prototype.writeInt32BE=function(e,t,r){return e=+e,t>>>=0,r||A(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e,t+4},t.prototype.writeFloatLE=function(e,t,r){return P(this,e,t,!0,r)},t.prototype.writeFloatBE=function(e,t,r){return P(this,e,t,!1,r)},t.prototype.writeDoubleLE=function(e,t,r){return M(this,e,t,!0,r)},t.prototype.writeDoubleBE=function(e,t,r){return M(this,e,t,!1,r)},t.prototype.copy=function(e,r,n,i){if(!t.isBuffer(e))throw new TypeError("argument should be a Buffer");if(n||(n=0),i||0===i||(i=this.length),r>=e.length&&(r=e.length),r||(r=0),i>0&&i=this.length)throw new RangeError("Index out of range");if(i<0)throw new RangeError("sourceEnd out of bounds");i>this.length&&(i=this.length),e.length-r=0;--s)e[s+r]=this[s+n];else Uint8Array.prototype.set.call(e,this.subarray(n,i),r);return o},t.prototype.fill=function(e,r,n,i){if("string"==typeof e){if("string"==typeof r?(i=r,r=0,n=this.length):"string"==typeof n&&(i=n,n=this.length),void 0!==i&&"string"!=typeof i)throw new TypeError("encoding must be a string");if("string"==typeof i&&!t.isEncoding(i))throw new TypeError("Unknown encoding: "+i);if(1===e.length){var o=e.charCodeAt(0);("utf8"===i&&o<128||"latin1"===i)&&(e=o)}}else"number"==typeof e&&(e&=255);if(r<0||this.length>>=0,n=void 0===n?this.length:n>>>0,e||(e=0),"number"==typeof e)for(s=r;s55295&&r<57344){if(!i){if(r>56319){(t-=3)>-1&&o.push(239,191,189);continue}if(s+1===n){(t-=3)>-1&&o.push(239,191,189);continue}i=r;continue}if(r<56320){(t-=3)>-1&&o.push(239,191,189),i=r;continue}r=65536+(i-55296<<10|r-56320)}else i&&(t-=3)>-1&&o.push(239,191,189);if(i=null,r<128){if((t-=1)<0)break;o.push(r)}else if(r<2048){if((t-=2)<0)break;o.push(r>>6|192,63&r|128)}else if(r<65536){if((t-=3)<0)break;o.push(r>>12|224,r>>6&63|128,63&r|128)}else{if(!(r<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;o.push(r>>18|240,r>>12&63|128,r>>6&63|128,63&r|128)}}return o}function U(e){return n.toByteArray(function(e){if((e=(e=e.split("=")[0]).trim().replace(B,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function L(e,t,r,n){for(var i=0;i=t.length||i>=e.length);++i)t[i+r]=e[i];return i}function q(e,t){return e instanceof t||null!=e&&null!=e.constructor&&null!=e.constructor.name&&e.constructor.name===t.name}function F(e){return e!=e}}).call(this,e("buffer").Buffer)},{"base64-js":10,buffer:13,ieee754:87}],14:[function(e,t,r){(function(e){function t(e){return Object.prototype.toString.call(e)}r.isArray=function(e){return Array.isArray?Array.isArray(e):"[object Array]"===t(e)},r.isBoolean=function(e){return"boolean"==typeof e},r.isNull=function(e){return null===e},r.isNullOrUndefined=function(e){return null==e},r.isNumber=function(e){return"number"==typeof e},r.isString=function(e){return"string"==typeof e},r.isSymbol=function(e){return"symbol"==typeof e},r.isUndefined=function(e){return void 0===e},r.isRegExp=function(e){return"[object RegExp]"===t(e)},r.isObject=function(e){return"object"==typeof e&&null!==e},r.isDate=function(e){return"[object Date]"===t(e)},r.isError=function(e){return"[object Error]"===t(e)||e instanceof Error},r.isFunction=function(e){return"function"==typeof e},r.isPrimitive=function(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||void 0===e},r.isBuffer=e.isBuffer}).call(this,{isBuffer:e("../../is-buffer/index.js")})},{"../../is-buffer/index.js":89}],15:[function(e,t,r){"use strict";var n,i=e("type/value/is"),o=e("type/value/ensure"),s=e("type/plain-function/ensure"),a=e("es5-ext/object/copy"),c=e("es5-ext/object/normalize-options"),u=e("es5-ext/object/map"),l=Function.prototype.bind,f=Object.defineProperty,p=Object.prototype.hasOwnProperty;n=function(e,t,r){var n,i=o(t)&&s(t.value);return delete(n=a(t)).writable,delete n.value,n.get=function(){return!r.overwriteDefinition&&p.call(this,e)?i:(t.value=l.call(i,r.resolveContext?r.resolveContext(this):this),f(this,e,t),this[e])},n},t.exports=function(e){var t=c(arguments[1]);return i(t.resolveContext)&&s(t.resolveContext),u(e,function(e,r){return n(r,e,t)})}},{"es5-ext/object/copy":41,"es5-ext/object/map":49,"es5-ext/object/normalize-options":50,"type/plain-function/ensure":126,"type/value/ensure":130,"type/value/is":131}],16:[function(e,t,r){"use strict";var n=e("type/value/is"),i=e("type/plain-function/is"),o=e("es5-ext/object/assign"),s=e("es5-ext/object/normalize-options"),a=e("es5-ext/string/#/contains");(t.exports=function(e,t){var r,i,c,u,l;return arguments.length<2||"string"!=typeof e?(u=t,t=e,e=null):u=arguments[2],n(e)?(r=a.call(e,"c"),i=a.call(e,"e"),c=a.call(e,"w")):(r=c=!0,i=!1),l={value:t,configurable:r,enumerable:i,writable:c},u?o(s(u),l):l}).gs=function(e,t,r){var c,u,l,f;return"string"!=typeof e?(l=r,r=t,t=e,e=null):l=arguments[3],n(t)?i(t)?n(r)?i(r)||(l=r,r=void 0):r=void 0:(l=t,t=r=void 0):t=void 0,n(e)?(c=a.call(e,"c"),u=a.call(e,"e")):(c=!0,u=!1),f={get:t,set:r,configurable:c,enumerable:u},l?o(s(l),f):f}},{"es5-ext/object/assign":38,"es5-ext/object/normalize-options":50,"es5-ext/string/#/contains":57,"type/plain-function/is":127,"type/value/is":131}],17:[function(e,t,r){(function(n){r.log=function(...e){return"object"==typeof console&&console.log&&console.log(...e)},r.formatArgs=function(e){if(e[0]=(this.useColors?"%c":"")+this.namespace+(this.useColors?" %c":" ")+e[0]+(this.useColors?"%c ":" ")+"+"+t.exports.humanize(this.diff),!this.useColors)return;const r="color: "+this.color;e.splice(1,0,r,"color: inherit");let n=0,i=0;e[0].replace(/%[a-zA-Z%]/g,e=>{"%%"!==e&&"%c"===e&&(i=++n)}),e.splice(i,0,r)},r.save=function(e){try{e?r.storage.setItem("debug",e):r.storage.removeItem("debug")}catch(e){}},r.load=function(){let e;try{e=r.storage.getItem("debug")}catch(e){}!e&&void 0!==n&&"env"in n&&(e=n.env.DEBUG);return e},r.useColors=function(){if("undefined"!=typeof window&&window.process&&("renderer"===window.process.type||window.process.__nwjs))return!0;if("undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/))return!1;return"undefined"!=typeof document&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||"undefined"!=typeof window&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||"undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)&&parseInt(RegExp.$1,10)>=31||"undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)},r.storage=function(){try{return localStorage}catch(e){}}(),r.colors=["#0000CC","#0000FF","#0033CC","#0033FF","#0066CC","#0066FF","#0099CC","#0099FF","#00CC00","#00CC33","#00CC66","#00CC99","#00CCCC","#00CCFF","#3300CC","#3300FF","#3333CC","#3333FF","#3366CC","#3366FF","#3399CC","#3399FF","#33CC00","#33CC33","#33CC66","#33CC99","#33CCCC","#33CCFF","#6600CC","#6600FF","#6633CC","#6633FF","#66CC00","#66CC33","#9900CC","#9900FF","#9933CC","#9933FF","#99CC00","#99CC33","#CC0000","#CC0033","#CC0066","#CC0099","#CC00CC","#CC00FF","#CC3300","#CC3333","#CC3366","#CC3399","#CC33CC","#CC33FF","#CC6600","#CC6633","#CC9900","#CC9933","#CCCC00","#CCCC33","#FF0000","#FF0033","#FF0066","#FF0099","#FF00CC","#FF00FF","#FF3300","#FF3333","#FF3366","#FF3399","#FF33CC","#FF33FF","#FF6600","#FF6633","#FF9900","#FF9933","#FFCC00","#FFCC33"],t.exports=e("./common")(r);const{formatters:i}=t.exports;i.j=function(e){try{return JSON.stringify(e)}catch(e){return"[UnexpectedJSONParseError]: "+e.message}}}).call(this,e("_process"))},{"./common":18,_process:101}],18:[function(e,t,r){t.exports=function(t){function r(e){let t=0;for(let r=0;r{if("%%"===t)return t;a++;const o=n.formatters[i];if("function"==typeof o){const n=e[a];t=o.call(r,n),e.splice(a,1),a--}return t}),n.formatArgs.call(r,e),(r.log||n.log).apply(r,e)}return s.namespace=e,s.enabled=n.enabled(e),s.useColors=n.useColors(),s.color=r(e),s.destroy=i,s.extend=o,"function"==typeof n.init&&n.init(s),n.instances.push(s),s}function i(){const e=n.instances.indexOf(this);return-1!==e&&(n.instances.splice(e,1),!0)}function o(e,t){const r=n(this.namespace+(void 0===t?":":t)+e);return r.log=this.log,r}function s(e){return e.toString().substring(2,e.toString().length-2).replace(/\.\*\?$/,"*")}return n.debug=n,n.default=n,n.coerce=function(e){return e instanceof Error?e.stack||e.message:e},n.disable=function(){const e=[...n.names.map(s),...n.skips.map(s).map(e=>"-"+e)].join(",");return n.enable(""),e},n.enable=function(e){let t;n.save(e),n.names=[],n.skips=[];const r=("string"==typeof e?e:"").split(/[\s,]+/),i=r.length;for(t=0;t{n[e]=t[e]}),n.instances=[],n.names=[],n.skips=[],n.formatters={},n.selectColor=r,n.enable(n.load()),n}},{ms:98}],19:[function(e,t,r){(function(r,n){var i=e("readable-stream"),o=e("end-of-stream"),s=e("inherits"),a=e("stream-shift"),c=n.from&&n.from!==Uint8Array.from?n.from([0]):new n([0]),u=function(e,t){e._corked?e.once("uncork",t):t()},l=function(e,t){return function(r){r?function(e,t){e._autoDestroy&&e.destroy(t)}(e,"premature close"===r.message?null:r):t&&!e._ended&&e.end()}},f=function(e,t,r){if(!(this instanceof f))return new f(e,t,r);i.Duplex.call(this,r),this._writable=null,this._readable=null,this._readable2=null,this._autoDestroy=!r||!1!==r.autoDestroy,this._forwardDestroy=!r||!1!==r.destroy,this._forwardEnd=!r||!1!==r.end,this._corked=1,this._ondrain=null,this._drained=!1,this._forwarding=!1,this._unwrite=null,this._unread=null,this._ended=!1,this.destroyed=!1,e&&this.setWritable(e),t&&this.setReadable(t)};s(f,i.Duplex),f.obj=function(e,t,r){return r||(r={}),r.objectMode=!0,r.highWaterMark=16,new f(e,t,r)},f.prototype.cork=function(){1==++this._corked&&this.emit("cork")},f.prototype.uncork=function(){this._corked&&0==--this._corked&&this.emit("uncork")},f.prototype.setWritable=function(e){if(this._unwrite&&this._unwrite(),this.destroyed)e&&e.destroy&&e.destroy();else if(null!==e&&!1!==e){var t=this,n=o(e,{writable:!0,readable:!1},l(this,this._forwardEnd)),i=function(){var e=t._ondrain;t._ondrain=null,e&&e()};this._unwrite&&r.nextTick(i),this._writable=e,this._writable.on("drain",i),this._unwrite=function(){t._writable.removeListener("drain",i),n()},this.uncork()}else this.end()},f.prototype.setReadable=function(e){if(this._unread&&this._unread(),this.destroyed)e&&e.destroy&&e.destroy();else{if(null===e||!1===e)return this.push(null),void this.resume();var t,r=this,n=o(e,{writable:!1,readable:!0},l(this)),s=function(){r._forward()},a=function(){r.push(null)};this._drained=!0,this._readable=e,this._readable2=e._readableState?e:(t=e,new i.Readable({objectMode:!0,highWaterMark:16}).wrap(t)),this._readable2.on("readable",s),this._readable2.on("end",a),this._unread=function(){r._readable2.removeListener("readable",s),r._readable2.removeListener("end",a),n()},this._forward()}},f.prototype._read=function(){this._drained=!0,this._forward()},f.prototype._forward=function(){if(!this._forwarding&&this._readable2&&this._drained){var e;for(this._forwarding=!0;this._drained&&null!==(e=a(this._readable2));)this.destroyed||(this._drained=this.push(e));this._forwarding=!1}},f.prototype.destroy=function(e){if(!this.destroyed){this.destroyed=!0;var t=this;r.nextTick(function(){t._destroy(e)})}},f.prototype._destroy=function(e){if(e){var t=this._ondrain;this._ondrain=null,t?t(e):this.emit("error",e)}this._forwardDestroy&&(this._readable&&this._readable.destroy&&this._readable.destroy(),this._writable&&this._writable.destroy&&this._writable.destroy()),this.emit("close")},f.prototype._write=function(e,t,r){return this.destroyed?r():this._corked?u(this,this._write.bind(this,e,t,r)):e===c?this._finish(r):this._writable?void(!1===this._writable.write(e)?this._ondrain=r:r()):r()},f.prototype._finish=function(e){var t=this;this.emit("preend"),u(this,function(){var r,n;r=t._forwardEnd&&t._writable,n=function(){!1===t._writableState.prefinished&&(t._writableState.prefinished=!0),t.emit("prefinish"),u(t,e)},r?r._writableState&&r._writableState.finished?n():r._writableState?r.end(n):(r.end(),n()):n()})},f.prototype.end=function(e,t,r){return"function"==typeof e?this.end(null,null,e):"function"==typeof t?this.end(e,null,t):(this._ended=!0,e&&this.write(e),this._writableState.ending||this.write(c),i.Writable.prototype.end.call(this,r))},t.exports=f}).call(this,e("_process"),e("buffer").Buffer)},{_process:101,buffer:13,"end-of-stream":20,inherits:88,"readable-stream":115,"stream-shift":118}],20:[function(e,t,r){(function(r){var n=e("once"),i=function(){},o=function(e,t,s){if("function"==typeof t)return o(e,null,t);t||(t={}),s=n(s||i);var a=e._writableState,c=e._readableState,u=t.readable||!1!==t.readable&&e.readable,l=t.writable||!1!==t.writable&&e.writable,f=!1,p=function(){e.writable||h()},h=function(){l=!1,u||s.call(e)},d=function(){u=!1,l||s.call(e)},g=function(t){s.call(e,t?new Error("exited with error code: "+t):null)},b=function(t){s.call(e,t)},m=function(){r.nextTick(y)},y=function(){if(!f)return(!u||c&&c.ended&&!c.destroyed)&&(!l||a&&a.ended&&!a.destroyed)?void 0:s.call(e,new Error("premature close"))},_=function(){e.req.on("finish",h)};return!function(e){return e.setHeader&&"function"==typeof e.abort}(e)?l&&!a&&(e.on("end",p),e.on("close",p)):(e.on("complete",h),e.on("abort",m),e.req?_():e.on("request",_)),function(e){return e.stdio&&Array.isArray(e.stdio)&&3===e.stdio.length}(e)&&e.on("exit",g),e.on("end",d),e.on("finish",h),!1!==t.error&&e.on("error",b),e.on("close",m),function(){f=!0,e.removeListener("complete",h),e.removeListener("abort",m),e.removeListener("request",_),e.req&&e.req.removeListener("finish",h),e.removeListener("end",p),e.removeListener("close",p),e.removeListener("finish",h),e.removeListener("exit",g),e.removeListener("end",d),e.removeListener("error",b),e.removeListener("close",m)}};t.exports=o}).call(this,e("_process"))},{_process:101,once:99}],21:[function(e,t,r){"use strict";var n=e("../../object/valid-value");t.exports=function(){return n(this).length=0,this}},{"../../object/valid-value":56}],22:[function(e,t,r){"use strict";var n=e("../../number/is-nan"),i=e("../../number/to-pos-integer"),o=e("../../object/valid-value"),s=Array.prototype.indexOf,a=Object.prototype.hasOwnProperty,c=Math.abs,u=Math.floor;t.exports=function(e){var t,r,l,f;if(!n(e))return s.apply(this,arguments);for(r=i(o(this).length),l=arguments[1],t=l=isNaN(l)?0:l>=0?u(l):i(this.length)-u(c(l));t=55296&&y<=56319&&(S+=e[++r]),S=k?p.call(k,x,S,g):S,t?(h.value=S,d(b,g,h)):b[g]=S,++g;m=g}if(void 0===m)for(m=s(e.length),t&&(b=new t(m)),r=0;r0?1:-1}},{}],32:[function(e,t,r){"use strict";t.exports=e("./is-implemented")()?Number.isNaN:e("./shim")},{"./is-implemented":33,"./shim":34}],33:[function(e,t,r){"use strict";t.exports=function(){var e=Number.isNaN;return"function"==typeof e&&(!e({})&&e(NaN)&&!e(34))}},{}],34:[function(e,t,r){"use strict";t.exports=function(e){return e!=e}},{}],35:[function(e,t,r){"use strict";var n=e("../math/sign"),i=Math.abs,o=Math.floor;t.exports=function(e){return isNaN(e)?0:0!==(e=Number(e))&&isFinite(e)?n(e)*o(i(e)):e}},{"../math/sign":29}],36:[function(e,t,r){"use strict";var n=e("./to-integer"),i=Math.max;t.exports=function(e){return i(0,n(e))}},{"./to-integer":35}],37:[function(e,t,r){"use strict";var n=e("./valid-callable"),i=e("./valid-value"),o=Function.prototype.bind,s=Function.prototype.call,a=Object.keys,c=Object.prototype.propertyIsEnumerable;t.exports=function(e,t){return function(r,u){var l,f=arguments[2],p=arguments[3];return r=Object(i(r)),n(u),l=a(r),p&&l.sort("function"==typeof p?o.call(p,r):void 0),"function"!=typeof e&&(e=l[e]),s.call(e,l,function(e,n){return c.call(r,e)?s.call(u,f,r[e],e,r,n):t})}}},{"./valid-callable":55,"./valid-value":56}],38:[function(e,t,r){"use strict";t.exports=e("./is-implemented")()?Object.assign:e("./shim")},{"./is-implemented":39,"./shim":40}],39:[function(e,t,r){"use strict";t.exports=function(){var e,t=Object.assign;return"function"==typeof t&&(t(e={foo:"raz"},{bar:"dwa"},{trzy:"trzy"}),e.foo+e.bar+e.trzy==="razdwatrzy")}},{}],40:[function(e,t,r){"use strict";var n=e("../keys"),i=e("../valid-value"),o=Math.max;t.exports=function(e,t){var r,s,a,c=o(arguments.length,2);for(e=Object(i(e)),a=function(n){try{e[n]=t[n]}catch(e){r||(r=e)}},s=1;s-1}},{}],60:[function(e,t,r){"use strict";var n=Object.prototype.toString,i=n.call("");t.exports=function(e){return"string"==typeof e||e&&"object"==typeof e&&(e instanceof String||n.call(e)===i)||!1}},{}],61:[function(e,t,r){"use strict";var n,i=e("es5-ext/object/set-prototype-of"),o=e("es5-ext/string/#/contains"),s=e("d"),a=e("es6-symbol"),c=e("./"),u=Object.defineProperty;n=t.exports=function(e,t){if(!(this instanceof n))throw new TypeError("Constructor requires 'new'");c.call(this,e),t=t?o.call(t,"key+value")?"key+value":o.call(t,"key")?"key":"value":"value",u(this,"__kind__",s("",t))},i&&i(n,c),delete n.prototype.constructor,n.prototype=Object.create(c.prototype,{_resolve:s(function(e){return"value"===this.__kind__?this.__list__[e]:"key+value"===this.__kind__?[e,this.__list__[e]]:e})}),u(n.prototype,a.toStringTag,s("c","Array Iterator"))},{"./":64,d:16,"es5-ext/object/set-prototype-of":52,"es5-ext/string/#/contains":57,"es6-symbol":74}],62:[function(e,t,r){"use strict";var n=e("es5-ext/function/is-arguments"),i=e("es5-ext/object/valid-callable"),o=e("es5-ext/string/is-string"),s=e("./get"),a=Array.isArray,c=Function.prototype.call,u=Array.prototype.some;t.exports=function(e,t){var r,l,f,p,h,d,g,b,m=arguments[2];if(a(e)||n(e)?r="array":o(e)?r="string":e=s(e),i(t),f=function(){p=!0},"array"!==r)if("string"!==r)for(l=e.next();!l.done;){if(c.call(t,m,l.value,f),p)return;l=e.next()}else for(d=e.length,h=0;h=55296&&b<=56319&&(g+=e[++h]),c.call(t,m,g,f),!p);++h);else u.call(e,function(e){return c.call(t,m,e,f),p})}},{"./get":63,"es5-ext/function/is-arguments":26,"es5-ext/object/valid-callable":55,"es5-ext/string/is-string":60}],63:[function(e,t,r){"use strict";var n=e("es5-ext/function/is-arguments"),i=e("es5-ext/string/is-string"),o=e("./array"),s=e("./string"),a=e("./valid-iterable"),c=e("es6-symbol").iterator;t.exports=function(e){return"function"==typeof a(e)[c]?e[c]():n(e)?new o(e):i(e)?new s(e):new o(e)}},{"./array":61,"./string":66,"./valid-iterable":67,"es5-ext/function/is-arguments":26,"es5-ext/string/is-string":60,"es6-symbol":74}],64:[function(e,t,r){"use strict";var n,i=e("es5-ext/array/#/clear"),o=e("es5-ext/object/assign"),s=e("es5-ext/object/valid-callable"),a=e("es5-ext/object/valid-value"),c=e("d"),u=e("d/auto-bind"),l=e("es6-symbol"),f=Object.defineProperty,p=Object.defineProperties;t.exports=n=function(e,t){if(!(this instanceof n))throw new TypeError("Constructor requires 'new'");p(this,{__list__:c("w",a(e)),__context__:c("w",t),__nextIndex__:c("w",0)}),t&&(s(t.on),t.on("_add",this._onAdd),t.on("_delete",this._onDelete),t.on("_clear",this._onClear))},delete n.prototype.constructor,p(n.prototype,o({_next:c(function(){var e;if(this.__list__)return this.__redo__&&void 0!==(e=this.__redo__.shift())?e:this.__nextIndex__=this.__nextIndex__||(++this.__nextIndex__,this.__redo__?(this.__redo__.forEach(function(t,r){t>=e&&(this.__redo__[r]=++t)},this),this.__redo__.push(e)):f(this,"__redo__",c("c",[e])))}),_onDelete:c(function(e){var t;e>=this.__nextIndex__||(--this.__nextIndex__,this.__redo__&&(-1!==(t=this.__redo__.indexOf(e))&&this.__redo__.splice(t,1),this.__redo__.forEach(function(t,r){t>e&&(this.__redo__[r]=--t)},this)))}),_onClear:c(function(){this.__redo__&&i.call(this.__redo__),this.__nextIndex__=0})}))),f(n.prototype,l.iterator,c(function(){return this}))},{d:16,"d/auto-bind":15,"es5-ext/array/#/clear":21,"es5-ext/object/assign":38,"es5-ext/object/valid-callable":55,"es5-ext/object/valid-value":56,"es6-symbol":74}],65:[function(e,t,r){"use strict";var n=e("es5-ext/function/is-arguments"),i=e("es5-ext/object/is-value"),o=e("es5-ext/string/is-string"),s=e("es6-symbol").iterator,a=Array.isArray;t.exports=function(e){return!!i(e)&&(!!a(e)||(!!o(e)||(!!n(e)||"function"==typeof e[s])))}},{"es5-ext/function/is-arguments":26,"es5-ext/object/is-value":45,"es5-ext/string/is-string":60,"es6-symbol":74}],66:[function(e,t,r){"use strict";var n,i=e("es5-ext/object/set-prototype-of"),o=e("d"),s=e("es6-symbol"),a=e("./"),c=Object.defineProperty;n=t.exports=function(e){if(!(this instanceof n))throw new TypeError("Constructor requires 'new'");e=String(e),a.call(this,e),c(this,"__length__",o("",e.length))},i&&i(n,a),delete n.prototype.constructor,n.prototype=Object.create(a.prototype,{_next:o(function(){if(this.__list__)return this.__nextIndex__=55296&&t<=56319?r+this.__list__[this.__nextIndex__++]:r})}),c(n.prototype,s.toStringTag,o("c","String Iterator"))},{"./":64,d:16,"es5-ext/object/set-prototype-of":52,"es6-symbol":74}],67:[function(e,t,r){"use strict";var n=e("./is-iterable");t.exports=function(e){if(!n(e))throw new TypeError(e+" is not iterable");return e}},{"./is-iterable":65}],68:[function(e,t,r){"use strict";t.exports=e("./is-implemented")()?Map:e("./polyfill")},{"./is-implemented":69,"./polyfill":73}],69:[function(e,t,r){"use strict";t.exports=function(){var e,t;if("function"!=typeof Map)return!1;try{e=new Map([["raz","one"],["dwa","two"],["trzy","three"]])}catch(e){return!1}return"[object Map]"===String(e)&&(3===e.size&&("function"==typeof e.clear&&("function"==typeof e.delete&&("function"==typeof e.entries&&("function"==typeof e.forEach&&("function"==typeof e.get&&("function"==typeof e.has&&("function"==typeof e.keys&&("function"==typeof e.set&&("function"==typeof e.values&&(!1===(t=e.entries().next()).done&&(!!t.value&&("raz"===t.value[0]&&"one"===t.value[1])))))))))))))}},{}],70:[function(e,t,r){"use strict";t.exports="undefined"!=typeof Map&&"[object Map]"===Object.prototype.toString.call(new Map)},{}],71:[function(e,t,r){"use strict";t.exports=e("es5-ext/object/primitive-set")("key","value","key+value")},{"es5-ext/object/primitive-set":51}],72:[function(e,t,r){"use strict";var n,i=e("es5-ext/object/set-prototype-of"),o=e("d"),s=e("es6-iterator"),a=e("es6-symbol").toStringTag,c=e("./iterator-kinds"),u=Object.defineProperties,l=s.prototype._unBind;n=t.exports=function(e,t){if(!(this instanceof n))return new n(e,t);s.call(this,e.__mapKeysData__,e),t&&c[t]||(t="key+value"),u(this,{__kind__:o("",t),__values__:o("w",e.__mapValuesData__)})},i&&i(n,s),n.prototype=Object.create(s.prototype,{constructor:o(n),_resolve:o(function(e){return"value"===this.__kind__?this.__values__[e]:"key"===this.__kind__?this.__list__[e]:[this.__list__[e],this.__values__[e]]}),_unBind:o(function(){this.__values__=null,l.call(this)}),toString:o(function(){return"[object Map Iterator]"})}),Object.defineProperty(n.prototype,a,o("c","Map Iterator"))},{"./iterator-kinds":71,d:16,"es5-ext/object/set-prototype-of":52,"es6-iterator":64,"es6-symbol":74}],73:[function(e,t,r){"use strict";var n,i=e("es5-ext/array/#/clear"),o=e("es5-ext/array/#/e-index-of"),s=e("es5-ext/object/set-prototype-of"),a=e("es5-ext/object/valid-callable"),c=e("es5-ext/object/valid-value"),u=e("d"),l=e("event-emitter"),f=e("es6-symbol"),p=e("es6-iterator/valid-iterable"),h=e("es6-iterator/for-of"),d=e("./lib/iterator"),g=e("./is-native-implemented"),b=Function.prototype.call,m=Object.defineProperties,y=Object.getPrototypeOf;t.exports=n=function(){var e,t,r,i=arguments[0];if(!(this instanceof n))throw new TypeError("Constructor requires 'new'");return r=g&&s&&Map!==n?s(new Map,y(this)):this,null!=i&&p(i),m(r,{__mapKeysData__:u("c",e=[]),__mapValuesData__:u("c",t=[])}),i?(h(i,function(r){var n=c(r)[0];r=r[1],-1===o.call(e,n)&&(e.push(n),t.push(r))},r),r):r},g&&(s&&s(n,Map),n.prototype=Object.create(Map.prototype,{constructor:u(n)})),l(m(n.prototype,{clear:u(function(){this.__mapKeysData__.length&&(i.call(this.__mapKeysData__),i.call(this.__mapValuesData__),this.emit("_clear"))}),delete:u(function(e){var t=o.call(this.__mapKeysData__,e);return-1!==t&&(this.__mapKeysData__.splice(t,1),this.__mapValuesData__.splice(t,1),this.emit("_delete",t,e),!0)}),entries:u(function(){return new d(this,"key+value")}),forEach:u(function(e){var t,r,n=arguments[1];for(a(e),r=(t=this.entries())._next();void 0!==r;)b.call(e,n,this.__mapValuesData__[r],this.__mapKeysData__[r],this),r=t._next()}),get:u(function(e){var t=o.call(this.__mapKeysData__,e);if(-1!==t)return this.__mapValuesData__[t]}),has:u(function(e){return-1!==o.call(this.__mapKeysData__,e)}),keys:u(function(){return new d(this,"key")}),set:u(function(e,t){var r,n=o.call(this.__mapKeysData__,e);return-1===n&&(n=this.__mapKeysData__.push(e)-1,r=!0),this.__mapValuesData__[n]=t,r&&this.emit("_add",n,e),this}),size:u.gs(function(){return this.__mapKeysData__.length}),values:u(function(){return new d(this,"value")}),toString:u(function(){return"[object Map]"})})),Object.defineProperty(n.prototype,f.iterator,u(function(){return this.entries()})),Object.defineProperty(n.prototype,f.toStringTag,u("c","Map"))},{"./is-native-implemented":70,"./lib/iterator":72,d:16,"es5-ext/array/#/clear":21,"es5-ext/array/#/e-index-of":22,"es5-ext/object/set-prototype-of":52,"es5-ext/object/valid-callable":55,"es5-ext/object/valid-value":56,"es6-iterator/for-of":62,"es6-iterator/valid-iterable":67,"es6-symbol":74,"event-emitter":82}],74:[function(e,t,r){"use strict";t.exports=e("./is-implemented")()?e("ext/global-this").Symbol:e("./polyfill")},{"./is-implemented":75,"./polyfill":80,"ext/global-this":85}],75:[function(e,t,r){"use strict";var n=e("ext/global-this"),i={object:!0,symbol:!0};t.exports=function(){var e,t=n.Symbol;if("function"!=typeof t)return!1;e=t("test symbol");try{String(e)}catch(e){return!1}return!!i[typeof t.iterator]&&(!!i[typeof t.toPrimitive]&&!!i[typeof t.toStringTag])}},{"ext/global-this":85}],76:[function(e,t,r){"use strict";t.exports=function(e){return!!e&&("symbol"==typeof e||!!e.constructor&&("Symbol"===e.constructor.name&&"Symbol"===e[e.constructor.toStringTag]))}},{}],77:[function(e,t,r){"use strict";var n=e("d"),i=Object.create,o=Object.defineProperty,s=Object.prototype,a=i(null);t.exports=function(e){for(var t,r,i=0;a[e+(i||"")];)++i;return a[e+=i||""]=!0,o(s,t="@@"+e,n.gs(null,function(e){r||(r=!0,o(this,t,n(e)),r=!1)})),t}},{d:16}],78:[function(e,t,r){"use strict";var n=e("d"),i=e("ext/global-this").Symbol;t.exports=function(e){return Object.defineProperties(e,{hasInstance:n("",i&&i.hasInstance||e("hasInstance")),isConcatSpreadable:n("",i&&i.isConcatSpreadable||e("isConcatSpreadable")),iterator:n("",i&&i.iterator||e("iterator")),match:n("",i&&i.match||e("match")),replace:n("",i&&i.replace||e("replace")),search:n("",i&&i.search||e("search")),species:n("",i&&i.species||e("species")),split:n("",i&&i.split||e("split")),toPrimitive:n("",i&&i.toPrimitive||e("toPrimitive")),toStringTag:n("",i&&i.toStringTag||e("toStringTag")),unscopables:n("",i&&i.unscopables||e("unscopables"))})}},{d:16,"ext/global-this":85}],79:[function(e,t,r){"use strict";var n=e("d"),i=e("../../../validate-symbol"),o=Object.create(null);t.exports=function(e){return Object.defineProperties(e,{for:n(function(t){return o[t]?o[t]:o[t]=e(String(t))}),keyFor:n(function(e){var t;for(t in i(e),o)if(o[t]===e)return t})})}},{"../../../validate-symbol":81,d:16}],80:[function(e,t,r){"use strict";var n,i,o,s=e("d"),a=e("./validate-symbol"),c=e("ext/global-this").Symbol,u=e("./lib/private/generate-name"),l=e("./lib/private/setup/standard-symbols"),f=e("./lib/private/setup/symbol-registry"),p=Object.create,h=Object.defineProperties,d=Object.defineProperty;if("function"==typeof c)try{String(c()),o=!0}catch(e){}else c=null;i=function(e){if(this instanceof i)throw new TypeError("Symbol is not a constructor");return n(e)},t.exports=n=function e(t){var r;if(this instanceof e)throw new TypeError("Symbol is not a constructor");return o?c(t):(r=p(i.prototype),t=void 0===t?"":String(t),h(r,{__description__:s("",t),__name__:s("",u(t))}))},l(n),f(n),h(i.prototype,{constructor:s(n),toString:s("",function(){return this.__name__})}),h(n.prototype,{toString:s(function(){return"Symbol ("+a(this).__description__+")"}),valueOf:s(function(){return a(this)})}),d(n.prototype,n.toPrimitive,s("",function(){var e=a(this);return"symbol"==typeof e?e:e.toString()})),d(n.prototype,n.toStringTag,s("c","Symbol")),d(i.prototype,n.toStringTag,s("c",n.prototype[n.toStringTag])),d(i.prototype,n.toPrimitive,s("c",n.prototype[n.toPrimitive]))},{"./lib/private/generate-name":77,"./lib/private/setup/standard-symbols":78,"./lib/private/setup/symbol-registry":79,"./validate-symbol":81,d:16,"ext/global-this":85}],81:[function(e,t,r){"use strict";var n=e("./is-symbol");t.exports=function(e){if(!n(e))throw new TypeError(e+" is not a symbol");return e}},{"./is-symbol":76}],82:[function(e,t,r){"use strict";var n,i,o,s,a,c,u,l=e("d"),f=e("es5-ext/object/valid-callable"),p=Function.prototype.apply,h=Function.prototype.call,d=Object.create,g=Object.defineProperty,b=Object.defineProperties,m=Object.prototype.hasOwnProperty,y={configurable:!0,enumerable:!1,writable:!0};a={on:n=function(e,t){var r;return f(t),m.call(this,"__ee__")?r=this.__ee__:(r=y.value=d(null),g(this,"__ee__",y),y.value=null),r[e]?"object"==typeof r[e]?r[e].push(t):r[e]=[r[e],t]:r[e]=t,this},once:i=function(e,t){var r,i;return f(t),i=this,n.call(this,e,r=function(){o.call(i,e,r),p.call(t,this,arguments)}),r.__eeOnceListener__=t,this},off:o=function(e,t){var r,n,i,o;if(f(t),!m.call(this,"__ee__"))return this;if(!(r=this.__ee__)[e])return this;if("object"==typeof(n=r[e]))for(o=0;i=n[o];++o)i!==t&&i.__eeOnceListener__!==t||(2===n.length?r[e]=n[o?0:1]:n.splice(o,1));else n!==t&&n.__eeOnceListener__!==t||delete r[e];return this},emit:s=function(e){var t,r,n,i,o;if(m.call(this,"__ee__")&&(i=this.__ee__[e]))if("object"==typeof i){for(r=arguments.length,o=new Array(r-1),t=1;t0&&a.length>o){a.warned=!0;var c=new Error("Possible EventEmitter memory leak detected. "+a.length+' "'+String(t)+'" listeners added. Use emitter.setMaxListeners() to increase limit.');c.name="MaxListenersExceededWarning",c.emitter=e,c.type=t,c.count=a.length,"object"==typeof console&&console.warn&&console.warn("%s: %s",c.name,c.message)}}else a=s[t]=r,++e._eventsCount;return e}function p(){if(!this.fired)switch(this.target.removeListener(this.type,this.wrapFn),this.fired=!0,arguments.length){case 0:return this.listener.call(this.target);case 1:return this.listener.call(this.target,arguments[0]);case 2:return this.listener.call(this.target,arguments[0],arguments[1]);case 3:return this.listener.call(this.target,arguments[0],arguments[1],arguments[2]);default:for(var e=new Array(arguments.length),t=0;t1&&(t=arguments[1]),t instanceof Error)throw t;var c=new Error('Unhandled "error" event. ('+t+")");throw c.context=t,c}if(!(r=s[e]))return!1;var u="function"==typeof r;switch(n=arguments.length){case 1:!function(e,t,r){if(t)e.call(r);else for(var n=e.length,i=b(e,n),o=0;o=0;s--)if(r[s]===t||r[s].listener===t){a=r[s].listener,o=s;break}if(o<0)return this;0===o?r.shift():function(e,t){for(var r=t,n=r+1,i=e.length;n=0;o--)this.removeListener(e,t[o]);return this},s.prototype.listeners=function(e){return d(this,e,!0)},s.prototype.rawListeners=function(e){return d(this,e,!1)},s.listenerCount=function(e,t){return"function"==typeof e.listenerCount?e.listenerCount(t):g.call(e,t)},s.prototype.listenerCount=g,s.prototype.eventNames=function(){return this._eventsCount>0?Reflect.ownKeys(this._events):[]}},{}],84:[function(e,t,r){var n=function(){if("object"==typeof self&&self)return self;if("object"==typeof window&&window)return window;throw new Error("Unable to resolve global `this`")};t.exports=function(){if(this)return this;try{Object.defineProperty(Object.prototype,"__global__",{get:function(){return this},configurable:!0})}catch(e){return n()}try{return __global__||n()}finally{delete Object.prototype.__global__}}()},{}],85:[function(e,t,r){"use strict";t.exports=e("./is-implemented")()?globalThis:e("./implementation")},{"./implementation":84,"./is-implemented":86}],86:[function(e,t,r){"use strict";t.exports=function(){return"object"==typeof globalThis&&(!!globalThis&&globalThis.Array===Array)}},{}],87:[function(e,t,r){r.read=function(e,t,r,n,i){var o,s,a=8*i-n-1,c=(1<>1,l=-7,f=r?i-1:0,p=r?-1:1,h=e[t+f];for(f+=p,o=h&(1<<-l)-1,h>>=-l,l+=a;l>0;o=256*o+e[t+f],f+=p,l-=8);for(s=o&(1<<-l)-1,o>>=-l,l+=n;l>0;s=256*s+e[t+f],f+=p,l-=8);if(0===o)o=1-u;else{if(o===c)return s?NaN:1/0*(h?-1:1);s+=Math.pow(2,n),o-=u}return(h?-1:1)*s*Math.pow(2,o-n)},r.write=function(e,t,r,n,i,o){var s,a,c,u=8*o-i-1,l=(1<>1,p=23===i?Math.pow(2,-24)-Math.pow(2,-77):0,h=n?0:o-1,d=n?1:-1,g=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(a=isNaN(t)?1:0,s=l):(s=Math.floor(Math.log(t)/Math.LN2),t*(c=Math.pow(2,-s))<1&&(s--,c*=2),(t+=s+f>=1?p/c:p*Math.pow(2,1-f))*c>=2&&(s++,c/=2),s+f>=l?(a=0,s=l):s+f>=1?(a=(t*c-1)*Math.pow(2,i),s+=f):(a=t*Math.pow(2,f-1)*Math.pow(2,i),s=0));i>=8;e[r+h]=255&a,h+=d,a/=256,i-=8);for(s=s<0;e[r+h]=255&s,h+=d,s/=256,u-=8);e[r+h-d]|=128*g}},{}],88:[function(e,t,r){"function"==typeof Object.create?t.exports=function(e,t){t&&(e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}))}:t.exports=function(e,t){if(t){e.super_=t;var r=function(){};r.prototype=t.prototype,e.prototype=new r,e.prototype.constructor=e}}},{}],89:[function(e,t,r){function n(e){return!!e.constructor&&"function"==typeof e.constructor.isBuffer&&e.constructor.isBuffer(e)}t.exports=function(e){return null!=e&&(n(e)||function(e){return"function"==typeof e.readFloatLE&&"function"==typeof e.slice&&n(e.slice(0,0))}(e)||!!e._isBuffer)}},{}],90:[function(e,t,r){var n={}.toString;t.exports=Array.isArray||function(e){return"[object Array]"==n.call(e)}},{}],91:[function(e,t,r){"use strict";var n=e("safe-buffer").Buffer,i=t.exports;for(var o in i.types={0:"reserved",1:"connect",2:"connack",3:"publish",4:"puback",5:"pubrec",6:"pubrel",7:"pubcomp",8:"subscribe",9:"suback",10:"unsubscribe",11:"unsuback",12:"pingreq",13:"pingresp",14:"disconnect",15:"auth"},i.codes={},i.types){var s=i.types[o];i.codes[s]=o}for(var a in i.CMD_SHIFT=4,i.CMD_MASK=240,i.DUP_MASK=8,i.QOS_MASK=3,i.QOS_SHIFT=1,i.RETAIN_MASK=1,i.LENGTH_MASK=127,i.LENGTH_FIN_MASK=128,i.SESSIONPRESENT_MASK=1,i.SESSIONPRESENT_HEADER=n.from([i.SESSIONPRESENT_MASK]),i.CONNACK_HEADER=n.from([i.codes.connack<>8,0),t.writeUInt8(255&e,1),t}t.exports={cache:o,generateCache:function(){for(var e=0;e=0&&e<128?1:e>=128&&e<16384?2:e>=16384&&e<2097152?3:e>=2097152&&e<268435456?4:0}(e),o=n.allocUnsafe(i);do{t=e%128|0,(e=e/128|0)>0&&(t|=128),o.writeUInt8(t,r++)}while(e>0);return{data:o,length:i}},generate4ByteBuffer:function(e){var t=n.allocUnsafe(4);return t.writeUInt32BE(e,0),t}}},{"safe-buffer":117}],95:[function(e,t,r){t.exports=function(){this.cmd=null,this.retain=!1,this.qos=0,this.dup=!1,this.length=-1,this.topic=null,this.payload=null}},{}],96:[function(e,t,r){"use strict";var n=e("bl"),i=e("inherits"),o=e("events").EventEmitter,s=e("./packet"),a=e("./constants"),c=e("debug")("mqtt-packet:parser");function u(e){if(!(this instanceof u))return new u(e);this.settings=e||{},this._states=["_parseHeader","_parseLength","_parsePayload","_newPacket"],this._resetState()}i(u,o),u.prototype._resetState=function(){c("_resetState: resetting packet, error, _list, and _stateCounter"),this.packet=new s,this.error=null,this._list=n(),this._stateCounter=0},u.prototype.parse=function(e){for(this.error&&this._resetState(),this._list.append(e),c("parse: current state: %s",this._states[this._stateCounter]);(-1!==this.packet.length||this._list.length>0)&&this[this._states[this._stateCounter]]()&&!this.error;)this._stateCounter++,c("parse: state complete. _stateCounter is now: %d",this._stateCounter),c("parse: packet.length: %d, buffer list length: %d",this.packet.length,this._list.length),this._stateCounter>=this._states.length&&(this._stateCounter=0);return c("parse: exited while loop. packet: %d, buffer list length: %d",this.packet.length,this._list.length),this._list.length},u.prototype._parseHeader=function(){var e=this._list.readUInt8(0);return this.packet.cmd=a.types[e>>a.CMD_SHIFT],this.packet.retain=0!=(e&a.RETAIN_MASK),this.packet.qos=e>>a.QOS_SHIFT&a.QOS_MASK,this.packet.dup=0!=(e&a.DUP_MASK),c("_parseHeader: packet: %o",this.packet),this._list.consume(1),!0},u.prototype._parseLength=function(){var e=this._parseVarByteNum(!0);return e&&(this.packet.length=e.value,this._list.consume(e.bytes)),c("_parseLength %d",e.value),!!e},u.prototype._parsePayload=function(){c("_parsePayload: payload %O",this._list);var e=!1;if(0===this.packet.length||this._list.length>=this.packet.length){switch(this._pos=0,this.packet.cmd){case"connect":this._parseConnect();break;case"connack":this._parseConnack();break;case"publish":this._parsePublish();break;case"puback":case"pubrec":case"pubrel":case"pubcomp":this._parseConfirmation();break;case"subscribe":this._parseSubscribe();break;case"suback":this._parseSuback();break;case"unsubscribe":this._parseUnsubscribe();break;case"unsuback":this._parseUnsuback();break;case"pingreq":case"pingresp":break;case"disconnect":this._parseDisconnect();break;case"auth":this._parseAuth();break;default:this._emitError(new Error("Not supported"))}e=!0}return c("_parsePayload complete result: %s",e),e},u.prototype._parseConnect=function(){var e,t,r,n,i,o;c("_parseConnect");var s={},u=this.packet;if(null===(e=this._parseString()))return this._emitError(new Error("Cannot parse protocolId"));if("MQTT"!==e&&"MQIsdp"!==e)return this._emitError(new Error("Invalid protocolId"));if(u.protocolId=e,this._pos>=this._list.length)return this._emitError(new Error("Packet too short"));if(u.protocolVersion=this._list.readUInt8(this._pos),3!==u.protocolVersion&&4!==u.protocolVersion&&5!==u.protocolVersion)return this._emitError(new Error("Invalid protocol version"));if(this._pos++,this._pos>=this._list.length)return this._emitError(new Error("Packet too short"));if(s.username=this._list.readUInt8(this._pos)&a.USERNAME_MASK,s.password=this._list.readUInt8(this._pos)&a.PASSWORD_MASK,s.will=this._list.readUInt8(this._pos)&a.WILL_FLAG_MASK,s.will&&(u.will={},u.will.retain=0!=(this._list.readUInt8(this._pos)&a.WILL_RETAIN_MASK),u.will.qos=(this._list.readUInt8(this._pos)&a.WILL_QOS_MASK)>>a.WILL_QOS_SHIFT),u.clean=0!=(this._list.readUInt8(this._pos)&a.CLEAN_SESSION_MASK),this._pos++,u.keepalive=this._parseNum(),-1===u.keepalive)return this._emitError(new Error("Packet too short"));if(5===u.protocolVersion){var l=this._parseProperties();Object.getOwnPropertyNames(l).length&&(u.properties=l)}if(null===(t=this._parseString()))return this._emitError(new Error("Packet too short"));if(u.clientId=t,c("_parseConnect: packet.clientId: %s",u.clientId),s.will){if(5===u.protocolVersion){var f=this._parseProperties();Object.getOwnPropertyNames(f).length&&(u.will.properties=f)}if(null===(r=this._parseString()))return this._emitError(new Error("Cannot parse will topic"));if(u.will.topic=r,c("_parseConnect: packet.will.topic: %s",u.will.topic),null===(n=this._parseBuffer()))return this._emitError(new Error("Cannot parse will payload"));u.will.payload=n,c("_parseConnect: packet.will.paylaod: %s",u.will.payload)}if(s.username){if(null===(o=this._parseString()))return this._emitError(new Error("Cannot parse username"));u.username=o,c("_parseConnect: packet.username: %s",u.username)}if(s.password){if(null===(i=this._parseBuffer()))return this._emitError(new Error("Cannot parse password"));u.password=i}return this.settings=u,c("_parseConnect: complete"),u},u.prototype._parseConnack=function(){c("_parseConnack");var e=this.packet;if(this._list.length<2)return null;if(e.sessionPresent=!!(this._list.readUInt8(this._pos++)&a.SESSIONPRESENT_MASK),5===this.settings.protocolVersion?e.reasonCode=this._list.readUInt8(this._pos++):e.returnCode=this._list.readUInt8(this._pos++),-1===e.returnCode||-1===e.reasonCode)return this._emitError(new Error("Cannot parse return code"));if(5===this.settings.protocolVersion){var t=this._parseProperties();Object.getOwnPropertyNames(t).length&&(e.properties=t)}c("_parseConnack: complete")},u.prototype._parsePublish=function(){c("_parsePublish");var e=this.packet;if(e.topic=this._parseString(),null===e.topic)return this._emitError(new Error("Cannot parse topic"));if(!(e.qos>0)||this._parseMessageId()){if(5===this.settings.protocolVersion){var t=this._parseProperties();Object.getOwnPropertyNames(t).length&&(e.properties=t)}e.payload=this._list.slice(this._pos,e.length),c("_parsePublish: payload from buffer list: %o",e.payload)}},u.prototype._parseSubscribe=function(){c("_parseSubscribe");var e,t,r,n,i,o,s,u=this.packet;if(1!==u.qos)return this._emitError(new Error("Wrong subscribe header"));if(u.subscriptions=[],this._parseMessageId()){if(5===this.settings.protocolVersion){var l=this._parseProperties();Object.getOwnPropertyNames(l).length&&(u.properties=l)}for(;this._pos=u.length)return this._emitError(new Error("Malformed Subscribe Payload"));r=(t=this._parseByte())&a.SUBSCRIBE_OPTIONS_QOS_MASK,o=0!=(t>>a.SUBSCRIBE_OPTIONS_NL_SHIFT&a.SUBSCRIBE_OPTIONS_NL_MASK),i=0!=(t>>a.SUBSCRIBE_OPTIONS_RAP_SHIFT&a.SUBSCRIBE_OPTIONS_RAP_MASK),n=t>>a.SUBSCRIBE_OPTIONS_RH_SHIFT&a.SUBSCRIBE_OPTIONS_RH_MASK,s={topic:e,qos:r},5===this.settings.protocolVersion&&(s.nl=o,s.rap=i,s.rh=n),c("_parseSubscribe: push subscription `%s` to subscription",s),u.subscriptions.push(s)}}},u.prototype._parseSuback=function(){c("_parseSuback");var e=this.packet;if(this.packet.granted=[],this._parseMessageId()){if(5===this.settings.protocolVersion){var t=this._parseProperties();Object.getOwnPropertyNames(t).length&&(e.properties=t)}for(;this._pos2&&(e.reasonCode=this._parseByte(),c("_parseConfirmation: packet.reasonCode `%d`",e.reasonCode)),e.length>3)){var t=this._parseProperties();Object.getOwnPropertyNames(t).length&&(e.properties=t)}return!0},u.prototype._parseDisconnect=function(){var e=this.packet;if(c("_parseDisconnect"),5===this.settings.protocolVersion){e.reasonCode=this._parseByte();var t=this._parseProperties();Object.getOwnPropertyNames(t).length&&(e.properties=t)}return c("_parseDisconnect result: true"),!0},u.prototype._parseAuth=function(){c("_parseAuth");var e=this.packet;if(5!==this.settings.protocolVersion)return this._emitError(new Error("Not supported auth packet for this version MQTT"));e.reasonCode=this._parseByte();var t=this._parseProperties();return Object.getOwnPropertyNames(t).length&&(e.properties=t),c("_parseAuth: result: true"),!0},u.prototype._parseMessageId=function(){var e=this.packet;return e.messageId=this._parseNum(),null===e.messageId?(this._emitError(new Error("Cannot parse messageId")),!1):(c("_parseMessageId: packet.messageId %d",e.messageId),!0)},u.prototype._parseString=function(e){var t,r=this._parseNum(),n=r+this._pos;return-1===r||n>this._list.length||n>this.packet.length?null:(t=this._list.toString("utf8",this._pos,n),this._pos+=r,c("_parseString: result: %s",t),t)},u.prototype._parseStringPair=function(){return c("_parseStringPair"),{name:this._parseString(),value:this._parseString()}},u.prototype._parseBuffer=function(){var e,t=this._parseNum(),r=t+this._pos;return-1===t||r>this._list.length||r>this.packet.length?null:(e=this._list.slice(this._pos,r),this._pos+=t,c("_parseBuffer: result: %o",e),e)},u.prototype._parseNum=function(){if(this._list.length-this._pos<2)return-1;var e=this._list.readUInt16BE(this._pos);return this._pos+=2,c("_parseNum: result: %s",e),e},u.prototype._parse4ByteNum=function(){if(this._list.length-this._pos<4)return-1;var e=this._list.readUInt32BE(this._pos);return this._pos+=4,c("_parse4ByteNum: result: %s",e),e},u.prototype._parseVarByteNum=function(e){c("_parseVarByteNum");for(var t,r=0,n=1,i=0,o=!0,s=this._pos?this._pos:0;r<5&&(i+=n*((t=this._list.readUInt8(s+r++))&a.LENGTH_MASK),n*=128,0!=(t&a.LENGTH_FIN_MASK));)if(this._list.length<=r){o=!1;break}return s&&(this._pos+=r),c("_parseVarByteNum: result: %o",o=!!o&&(e?{bytes:r,value:i}:i)),o},u.prototype._parseByte=function(){var e=this._list.readUInt8(this._pos);return this._pos++,c("_parseByte: result: %o",e),e},u.prototype._parseByType=function(e){switch(c("_parseByType: type: %s",e),e){case"byte":return 0!==this._parseByte();case"int8":return this._parseByte();case"int16":return this._parseNum();case"int32":return this._parse4ByteNum();case"var":return this._parseVarByteNum();case"string":return this._parseString();case"pair":return this._parseStringPair();case"binary":return this._parseBuffer()}},u.prototype._parseProperties=function(){c("_parseProperties");for(var e=this._parseVarByteNum(),t=this._pos+e,r={};this._pos65535||l%1!=0)return t.emit("error",new Error("Invalid keepalive")),!1;b+=2;if(b+=1,5===a){var m=I(t,d);if(!m)return!1;b+=m.length}if(c){if("object"!=typeof c)return t.emit("error",new Error("Invalid will")),!1;if(!c.topic||"string"!=typeof c.topic)return t.emit("error",new Error("Invalid will topic")),!1;if(b+=i.byteLength(c.topic)+2,b+=2,c.payload){if(!(c.payload.length>=0))return t.emit("error",new Error("Invalid will payload")),!1;"string"==typeof c.payload?b+=i.byteLength(c.payload):b+=c.payload.length}var y={};if(5===a){if(!(y=I(t,c.properties)))return!1;b+=y.length}}var _=!1;if(null!=p){if(!T(p))return t.emit("error",new Error("Invalid username")),!1;_=!0,b+=i.byteLength(p)+2}if(null!=h){if(!_)return t.emit("error",new Error("Username is required to use password")),!1;if(!T(h))return t.emit("error",new Error("Invalid password")),!1;b+=A(h)+2}t.write(n.CONNECT_HEADER),v(t,b),E(t,s),t.write(4===a?n.VERSION4:5===a?n.VERSION5:n.VERSION3);var S=0;S|=null!=p?n.USERNAME_MASK:0,S|=null!=h?n.PASSWORD_MASK:0,S|=c&&c.retain?n.WILL_RETAIN_MASK:0,S|=c&&c.qos?c.qos<0&&g(t,h);null!=m&&m.write();return u("publish: payload: %o",p),t.write(p)}(e,t,r);case"puback":case"pubrec":case"pubrel":case"pubcomp":return function(e,t,r){var o=r?r.protocolVersion:4,s=e||{},a=s.cmd||"puback",c=s.messageId,u=s.dup&&"pubrel"===a?n.DUP_MASK:0,l=0,f=s.reasonCode,p=s.properties,h=5===o?3:2;"pubrel"===a&&(l=1);if("number"!=typeof c)return t.emit("error",new Error("Invalid messageId")),!1;var d=null;if(5===o&&"object"==typeof p){if(!(d=C(t,p,r,h)))return!1;h+=d.length}t.write(n.ACKS[a][l][u][0]),v(t,h),g(t,c),5===o&&t.write(i.from([f]));null!==d&&d.write();return!0}(e,t,r);case"subscribe":return function(e,t,r){u("subscribe: packet: ");var o=r?r.protocolVersion:4,s=e||{},a=s.dup?n.DUP_MASK:0,c=s.messageId,l=s.subscriptions,f=s.properties,p=0;if("number"!=typeof c)return t.emit("error",new Error("Invalid messageId")),!1;p+=2;var h=null;if(5===o){if(!(h=I(t,f)))return!1;p+=h.length}if("object"!=typeof l||!l.length)return t.emit("error",new Error("Invalid subscriptions")),!1;for(var d=0;d2)return t.emit("error",new Error("Invalid subscriptions - invalid Retain Handling")),!1}p+=i.byteLength(b)+2+1}u("subscribe: writing to stream: %o",n.SUBSCRIBE_HEADER),t.write(n.SUBSCRIBE_HEADER[1][a?1:0][0]),v(t,p),g(t,c),null!==h&&h.write();for(var k=!0,x=0;x255)return e.emit("error",new Error("Invalid "+t+": "+r)),!1;o+=2;break;case"binary":if(r&&null===r)return e.emit("error",new Error("Invalid "+t+": "+r)),!1;o+=1+i.byteLength(r)+2;break;case"int16":if("number"!=typeof r||r<0||r>65535)return e.emit("error",new Error("Invalid "+t+": "+r)),!1;o+=3;break;case"int32":if("number"!=typeof r||r<0||r>4294967295)return e.emit("error",new Error("Invalid "+t+": "+r)),!1;o+=5;break;case"var":if("number"!=typeof r||r<0||r>4294967295)return e.emit("error",new Error("Invalid "+t+": "+r)),!1;o+=1+h(r).length;break;case"string":if("string"!=typeof r)return e.emit("error",new Error("Invalid "+t+": "+r)),!1;o+=3+i.byteLength(r.toString());break;case"pair":if("object"!=typeof r)return e.emit("error",new Error("Invalid "+t+": "+r)),!1;o+=Object.getOwnPropertyNames(r).reduce(function(e,t){var n=r[t];return Array.isArray(n)?e+=n.reduce(function(e,r){return e+=3+i.byteLength(t.toString())+2+i.byteLength(r.toString())},0):e+=3+i.byteLength(t.toString())+2+i.byteLength(r[t].toString()),e},0);break;default:return e.emit("error",new Error("Invalid property "+t+": "+r)),!1}return o}if(t)for(var s in t){var a=0,c=0,u=t[s];if(Array.isArray(u))for(var l=0;lo;){var a=i.shift();if(!a||!t[a])return!1;delete t[a],s=I(e,t)}return s}function O(e,t,r){switch(n.propertiesTypes[t]){case"byte":e.write(i.from([n.properties[t]])),e.write(i.from([+r]));break;case"int8":e.write(i.from([n.properties[t]])),e.write(i.from([r]));break;case"binary":e.write(i.from([n.properties[t]])),E(e,r);break;case"int16":e.write(i.from([n.properties[t]])),g(e,r);break;case"int32":e.write(i.from([n.properties[t]])),function(e,t){var r=d(t);u("write4ByteNumber: %o",r),e.write(r)}(e,r);break;case"var":e.write(i.from([n.properties[t]])),v(e,r);break;case"string":e.write(i.from([n.properties[t]])),w(e,r);break;case"pair":Object.getOwnPropertyNames(r).forEach(function(o){var s=r[o];Array.isArray(s)?s.forEach(function(r){e.write(i.from([n.properties[t]])),S(e,o.toString(),r.toString())}):(e.write(i.from([n.properties[t]])),S(e,o.toString(),s.toString()))});break;default:return e.emit("error",new Error("Invalid property "+t+" value: "+r)),!1}}function j(e,t,r){for(var n in v(e,r),t)if(t.hasOwnProperty(n)&&null!==t[n]){var i=t[n];if(Array.isArray(i))for(var o=0;o=1.5*r;return Math.round(e/r)+" "+n+(i?"s":"")}t.exports=function(e,t){t=t||{};var r=typeof e;if("string"===r&&e.length>0)return function(e){if((e=String(e)).length>100)return;var t=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(e);if(!t)return;var r=parseFloat(t[1]);switch((t[2]||"ms").toLowerCase()){case"years":case"year":case"yrs":case"yr":case"y":return r*c;case"weeks":case"week":case"w":return r*a;case"days":case"day":case"d":return r*s;case"hours":case"hour":case"hrs":case"hr":case"h":return r*o;case"minutes":case"minute":case"mins":case"min":case"m":return r*i;case"seconds":case"second":case"secs":case"sec":case"s":return r*n;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return r;default:return}}(e);if("number"===r&&isFinite(e))return t.long?function(e){var t=Math.abs(e);if(t>=s)return u(e,t,s,"day");if(t>=o)return u(e,t,o,"hour");if(t>=i)return u(e,t,i,"minute");if(t>=n)return u(e,t,n,"second");return e+" ms"}(e):function(e){var t=Math.abs(e);if(t>=s)return Math.round(e/s)+"d";if(t>=o)return Math.round(e/o)+"h";if(t>=i)return Math.round(e/i)+"m";if(t>=n)return Math.round(e/n)+"s";return e+"ms"}(e);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(e))}},{}],99:[function(e,t,r){var n=e("wrappy");function i(e){var t=function(){return t.called?t.value:(t.called=!0,t.value=e.apply(this,arguments))};return t.called=!1,t}function o(e){var t=function(){if(t.called)throw new Error(t.onceError);return t.called=!0,t.value=e.apply(this,arguments)},r=e.name||"Function wrapped with `once`";return t.onceError=r+" shouldn't be called more than once",t.called=!1,t}t.exports=n(i),t.exports.strict=n(o),i.proto=i(function(){Object.defineProperty(Function.prototype,"once",{value:function(){return i(this)},configurable:!0}),Object.defineProperty(Function.prototype,"onceStrict",{value:function(){return o(this)},configurable:!0})})},{wrappy:138}],100:[function(e,t,r){(function(e){"use strict";void 0===e||!e.version||0===e.version.indexOf("v0.")||0===e.version.indexOf("v1.")&&0!==e.version.indexOf("v1.8.")?t.exports={nextTick:function(t,r,n,i){if("function"!=typeof t)throw new TypeError('"callback" argument must be a function');var o,s,a=arguments.length;switch(a){case 0:case 1:return e.nextTick(t);case 2:return e.nextTick(function(){t.call(null,r)});case 3:return e.nextTick(function(){t.call(null,r,n)});case 4:return e.nextTick(function(){t.call(null,r,n,i)});default:for(o=new Array(a-1),s=0;s1)for(var r=1;r= 0x80 (not a basic code point)","invalid-input":"Invalid input"},S=l-f,k=Math.floor,x=String.fromCharCode;function E(e){throw new RangeError(w[e])}function I(e,t){for(var r=e.length,n=[];r--;)n[r]=t(e[r]);return n}function C(e,t){var r=e.split("@"),n="";return r.length>1&&(n=r[0]+"@",e=r[1]),n+I((e=e.replace(v,".")).split("."),t).join(".")}function O(e){for(var t,r,n=[],i=0,o=e.length;i=55296&&t<=56319&&i65535&&(t+=x((e-=65536)>>>10&1023|55296),e=56320|1023&e),t+=x(e)}).join("")}function A(e,t){return e+22+75*(e<26)-((0!=t)<<5)}function T(e,t,r){var n=0;for(e=r?k(e/d):e>>1,e+=k(e/t);e>S*p>>1;n+=l)e=k(e/S);return k(n+(S+1)*e/(e+h))}function P(e){var t,r,n,i,o,s,a,c,h,d,y,_=[],v=e.length,w=0,S=b,x=g;for((r=e.lastIndexOf(m))<0&&(r=0),n=0;n=128&&E("not-basic"),_.push(e.charCodeAt(n));for(i=r>0?r+1:0;i=v&&E("invalid-input"),((c=(y=e.charCodeAt(i++))-48<10?y-22:y-65<26?y-65:y-97<26?y-97:l)>=l||c>k((u-w)/s))&&E("overflow"),w+=c*s,!(c<(h=a<=x?f:a>=x+p?p:a-x));a+=l)s>k(u/(d=l-h))&&E("overflow"),s*=d;x=T(w-o,t=_.length+1,0==o),k(w/t)>u-S&&E("overflow"),S+=k(w/t),w%=t,_.splice(w++,0,S)}return j(_)}function M(e){var t,r,n,i,o,s,a,c,h,d,y,_,v,w,S,I=[];for(_=(e=O(e)).length,t=b,r=0,o=g,s=0;s<_;++s)(y=e[s])<128&&I.push(x(y));for(n=i=I.length,i&&I.push(m);n<_;){for(a=u,s=0;s<_;++s)(y=e[s])>=t&&yk((u-r)/(v=n+1))&&E("overflow"),r+=(a-t)*v,t=a,s=0;s<_;++s)if((y=e[s])u&&E("overflow"),y==t){for(c=r,h=l;!(c<(d=h<=o?f:h>=o+p?p:h-o));h+=l)S=c-d,w=l-d,I.push(x(A(d+S%w,0))),c=k(S/w);I.push(x(A(c,0))),o=T(r,v,n==i),r=0,++n}++r,++t}return I.join("")}if(a={version:"1.4.1",ucs2:{decode:O,encode:j},decode:P,encode:M,toASCII:function(e){return C(e,function(e){return _.test(e)?"xn--"+M(e):e})},toUnicode:function(e){return C(e,function(e){return y.test(e)?P(e.slice(4).toLowerCase()):e})}},i&&o)if(t.exports==i)o.exports=a;else for(c in a)a.hasOwnProperty(c)&&(i[c]=a[c]);else n.punycode=a}(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],103:[function(e,t,r){"use strict";function n(e,t){return Object.prototype.hasOwnProperty.call(e,t)}t.exports=function(e,t,r,o){t=t||"&",r=r||"=";var s={};if("string"!=typeof e||0===e.length)return s;var a=/\+/g;e=e.split(t);var c=1e3;o&&"number"==typeof o.maxKeys&&(c=o.maxKeys);var u=e.length;c>0&&u>c&&(u=c);for(var l=0;l=0?(f=g.substr(0,b),p=g.substr(b+1)):(f=g,p=""),h=decodeURIComponent(f),d=decodeURIComponent(p),n(s,h)?i(s[h])?s[h].push(d):s[h]=[s[h],d]:s[h]=d}return s};var i=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)}},{}],104:[function(e,t,r){"use strict";var n=function(e){switch(typeof e){case"string":return e;case"boolean":return e?"true":"false";case"number":return isFinite(e)?e:"";default:return""}};t.exports=function(e,t,r,a){return t=t||"&",r=r||"=",null===e&&(e=void 0),"object"==typeof e?o(s(e),function(s){var a=encodeURIComponent(n(s))+r;return i(e[s])?o(e[s],function(e){return a+encodeURIComponent(n(e))}).join(t):a+encodeURIComponent(n(e[s]))}).join(t):a?encodeURIComponent(n(a))+r+encodeURIComponent(n(e)):""};var i=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)};function o(e,t){if(e.map)return e.map(t);for(var r=[],n=0;n0?("string"==typeof t||s.objectMode||Object.getPrototypeOf(t)===u.prototype||(t=function(e){return u.from(e)}(t)),n?s.endEmitted?e.emit("error",new Error("stream.unshift() after end event")):w(e,s,t,!0):s.ended?e.emit("error",new Error("stream.push() after EOF")):(s.reading=!1,s.decoder&&!r?(t=s.decoder.write(t),s.objectMode||0!==t.length?w(e,s,t,!1):I(e,s)):w(e,s,t,!1))):n||(s.reading=!1));return function(e){return!e.ended&&(e.needReadable||e.lengtht.highWaterMark&&(t.highWaterMark=function(e){return e>=S?e=S:(e--,e|=e>>>1,e|=e>>>2,e|=e>>>4,e|=e>>>8,e|=e>>>16,e++),e}(e)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0))}function x(e){var t=e._readableState;t.needReadable=!1,t.emittedReadable||(h("emitReadable",t.flowing),t.emittedReadable=!0,t.sync?i.nextTick(E,e):E(e))}function E(e){h("emit readable"),e.emit("readable"),A(e)}function I(e,t){t.readingMore||(t.readingMore=!0,i.nextTick(C,e,t))}function C(e,t){for(var r=t.length;!t.reading&&!t.flowing&&!t.ended&&t.length=t.length?(r=t.decoder?t.buffer.join(""):1===t.buffer.length?t.buffer.head.data:t.buffer.concat(t.length),t.buffer.clear()):r=function(e,t,r){var n;eo.length?o.length:e;if(s===o.length?i+=o:i+=o.slice(0,e),0===(e-=s)){s===o.length?(++n,r.next?t.head=r.next:t.head=t.tail=null):(t.head=r,r.data=o.slice(s));break}++n}return t.length-=n,i}(e,t):function(e,t){var r=u.allocUnsafe(e),n=t.head,i=1;n.data.copy(r),e-=n.data.length;for(;n=n.next;){var o=n.data,s=e>o.length?o.length:e;if(o.copy(r,r.length-e,0,s),0===(e-=s)){s===o.length?(++i,n.next?t.head=n.next:t.head=t.tail=null):(t.head=n,n.data=o.slice(s));break}++i}return t.length-=i,r}(e,t);return n}(e,t.buffer,t.decoder),r);var r}function P(e){var t=e._readableState;if(t.length>0)throw new Error('"endReadable()" called on non-empty stream');t.endEmitted||(t.ended=!0,i.nextTick(M,t,e))}function M(e,t){e.endEmitted||0!==e.length||(e.endEmitted=!0,t.readable=!1,t.emit("end"))}function B(e,t){for(var r=0,n=e.length;r=t.highWaterMark||t.ended))return h("read: emitReadable",t.length,t.ended),0===t.length&&t.ended?P(this):x(this),null;if(0===(e=k(e,t))&&t.ended)return 0===t.length&&P(this),null;var n,i=t.needReadable;return h("need readable",i),(0===t.length||t.length-e0?T(e,t):null)?(t.needReadable=!0,e=0):t.length-=e,0===t.length&&(t.ended||(t.needReadable=!0),r!==e&&t.ended&&P(this)),null!==n&&this.emit("data",n),n},_.prototype._read=function(e){this.emit("error",new Error("_read() is not implemented"))},_.prototype.pipe=function(e,t){var n=this,o=this._readableState;switch(o.pipesCount){case 0:o.pipes=e;break;case 1:o.pipes=[o.pipes,e];break;default:o.pipes.push(e)}o.pipesCount+=1,h("pipe count=%d opts=%j",o.pipesCount,t);var c=(!t||!1!==t.end)&&e!==r.stdout&&e!==r.stderr?l:_;function u(t,r){h("onunpipe"),t===n&&r&&!1===r.hasUnpiped&&(r.hasUnpiped=!0,h("cleanup"),e.removeListener("close",m),e.removeListener("finish",y),e.removeListener("drain",f),e.removeListener("error",b),e.removeListener("unpipe",u),n.removeListener("end",l),n.removeListener("end",_),n.removeListener("data",g),p=!0,!o.awaitDrain||e._writableState&&!e._writableState.needDrain||f())}function l(){h("onend"),e.end()}o.endEmitted?i.nextTick(c):n.once("end",c),e.on("unpipe",u);var f=function(e){return function(){var t=e._readableState;h("pipeOnDrain",t.awaitDrain),t.awaitDrain&&t.awaitDrain--,0===t.awaitDrain&&a(e,"data")&&(t.flowing=!0,A(e))}}(n);e.on("drain",f);var p=!1;var d=!1;function g(t){h("ondata"),d=!1,!1!==e.write(t)||d||((1===o.pipesCount&&o.pipes===e||o.pipesCount>1&&-1!==B(o.pipes,e))&&!p&&(h("false write response, pause",n._readableState.awaitDrain),n._readableState.awaitDrain++,d=!0),n.pause())}function b(t){h("onerror",t),_(),e.removeListener("error",b),0===a(e,"error")&&e.emit("error",t)}function m(){e.removeListener("finish",y),_()}function y(){h("onfinish"),e.removeListener("close",m),_()}function _(){h("unpipe"),n.unpipe(e)}return n.on("data",g),function(e,t,r){if("function"==typeof e.prependListener)return e.prependListener(t,r);e._events&&e._events[t]?s(e._events[t])?e._events[t].unshift(r):e._events[t]=[r,e._events[t]]:e.on(t,r)}(e,"error",b),e.once("close",m),e.once("finish",y),e.emit("pipe",n),o.flowing||(h("pipe resume"),n.resume()),e},_.prototype.unpipe=function(e){var t=this._readableState,r={hasUnpiped:!1};if(0===t.pipesCount)return this;if(1===t.pipesCount)return e&&e!==t.pipes?this:(e||(e=t.pipes),t.pipes=null,t.pipesCount=0,t.flowing=!1,e&&e.emit("unpipe",this,r),this);if(!e){var n=t.pipes,i=t.pipesCount;t.pipes=null,t.pipesCount=0,t.flowing=!1;for(var o=0;o-1?i:o.nextTick;y.WritableState=m;var u=Object.create(e("core-util-is"));u.inherits=e("inherits");var l={deprecate:e("util-deprecate")},f=e("./internal/streams/stream"),p=e("safe-buffer").Buffer,h=n.Uint8Array||function(){};var d,g=e("./internal/streams/destroy");function b(){}function m(t,r){a=a||e("./_stream_duplex"),t=t||{};var n=r instanceof a;this.objectMode=!!t.objectMode,n&&(this.objectMode=this.objectMode||!!t.writableObjectMode);var i=t.highWaterMark,u=t.writableHighWaterMark,l=this.objectMode?16:16384;this.highWaterMark=i||0===i?i:n&&(u||0===u)?u:l,this.highWaterMark=Math.floor(this.highWaterMark),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;var f=!1===t.decodeStrings;this.decodeStrings=!f,this.defaultEncoding=t.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(e){!function(e,t){var r=e._writableState,n=r.sync,i=r.writecb;if(function(e){e.writing=!1,e.writecb=null,e.length-=e.writelen,e.writelen=0}(r),t)!function(e,t,r,n,i){--t.pendingcb,r?(o.nextTick(i,n),o.nextTick(x,e,t),e._writableState.errorEmitted=!0,e.emit("error",n)):(i(n),e._writableState.errorEmitted=!0,e.emit("error",n),x(e,t))}(e,r,n,t,i);else{var s=S(r);s||r.corked||r.bufferProcessing||!r.bufferedRequest||w(e,r),n?c(v,e,r,s,i):v(e,r,s,i)}}(r,e)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.bufferedRequestCount=0,this.corkedRequestsFree=new s(this)}function y(t){if(a=a||e("./_stream_duplex"),!(d.call(y,this)||this instanceof a))return new y(t);this._writableState=new m(t,this),this.writable=!0,t&&("function"==typeof t.write&&(this._write=t.write),"function"==typeof t.writev&&(this._writev=t.writev),"function"==typeof t.destroy&&(this._destroy=t.destroy),"function"==typeof t.final&&(this._final=t.final)),f.call(this)}function _(e,t,r,n,i,o,s){t.writelen=n,t.writecb=s,t.writing=!0,t.sync=!0,r?e._writev(i,t.onwrite):e._write(i,o,t.onwrite),t.sync=!1}function v(e,t,r,n){r||function(e,t){0===t.length&&t.needDrain&&(t.needDrain=!1,e.emit("drain"))}(e,t),t.pendingcb--,n(),x(e,t)}function w(e,t){t.bufferProcessing=!0;var r=t.bufferedRequest;if(e._writev&&r&&r.next){var n=t.bufferedRequestCount,i=new Array(n),o=t.corkedRequestsFree;o.entry=r;for(var a=0,c=!0;r;)i[a]=r,r.isBuf||(c=!1),r=r.next,a+=1;i.allBuffers=c,_(e,t,!0,t.length,i,"",o.finish),t.pendingcb++,t.lastBufferedRequest=null,o.next?(t.corkedRequestsFree=o.next,o.next=null):t.corkedRequestsFree=new s(t),t.bufferedRequestCount=0}else{for(;r;){var u=r.chunk,l=r.encoding,f=r.callback;if(_(e,t,!1,t.objectMode?1:u.length,u,l,f),r=r.next,t.bufferedRequestCount--,t.writing)break}null===r&&(t.lastBufferedRequest=null)}t.bufferedRequest=r,t.bufferProcessing=!1}function S(e){return e.ending&&0===e.length&&null===e.bufferedRequest&&!e.finished&&!e.writing}function k(e,t){e._final(function(r){t.pendingcb--,r&&e.emit("error",r),t.prefinished=!0,e.emit("prefinish"),x(e,t)})}function x(e,t){var r=S(t);return r&&(!function(e,t){t.prefinished||t.finalCalled||("function"==typeof e._final?(t.pendingcb++,t.finalCalled=!0,o.nextTick(k,e,t)):(t.prefinished=!0,e.emit("prefinish")))}(e,t),0===t.pendingcb&&(t.finished=!0,e.emit("finish"))),r}u.inherits(y,f),m.prototype.getBuffer=function(){for(var e=this.bufferedRequest,t=[];e;)t.push(e),e=e.next;return t},function(){try{Object.defineProperty(m.prototype,"buffer",{get:l.deprecate(function(){return this.getBuffer()},"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.","DEP0003")})}catch(e){}}(),"function"==typeof Symbol&&Symbol.hasInstance&&"function"==typeof Function.prototype[Symbol.hasInstance]?(d=Function.prototype[Symbol.hasInstance],Object.defineProperty(y,Symbol.hasInstance,{value:function(e){return!!d.call(this,e)||this===y&&(e&&e._writableState instanceof m)}})):d=function(e){return e instanceof this},y.prototype.pipe=function(){this.emit("error",new Error("Cannot pipe, not readable"))},y.prototype.write=function(e,t,r){var n,i=this._writableState,s=!1,a=!i.objectMode&&(n=e,p.isBuffer(n)||n instanceof h);return a&&!p.isBuffer(e)&&(e=function(e){return p.from(e)}(e)),"function"==typeof t&&(r=t,t=null),a?t="buffer":t||(t=i.defaultEncoding),"function"!=typeof r&&(r=b),i.ended?function(e,t){var r=new Error("write after end");e.emit("error",r),o.nextTick(t,r)}(this,r):(a||function(e,t,r,n){var i=!0,s=!1;return null===r?s=new TypeError("May not write null values to stream"):"string"==typeof r||void 0===r||t.objectMode||(s=new TypeError("Invalid non-string/buffer chunk")),s&&(e.emit("error",s),o.nextTick(n,s),i=!1),i}(this,i,e,r))&&(i.pendingcb++,s=function(e,t,r,n,i,o){if(!r){var s=function(e,t,r){e.objectMode||!1===e.decodeStrings||"string"!=typeof t||(t=p.from(t,r));return t}(t,n,i);n!==s&&(r=!0,i="buffer",n=s)}var a=t.objectMode?1:n.length;t.length+=a;var c=t.length-1))throw new TypeError("Unknown encoding: "+e);return this._writableState.defaultEncoding=e,this},Object.defineProperty(y.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),y.prototype._write=function(e,t,r){r(new Error("_write() is not implemented"))},y.prototype._writev=null,y.prototype.end=function(e,t,r){var n=this._writableState;"function"==typeof e?(r=e,e=null,t=null):"function"==typeof t&&(r=t,t=null),null!==e&&void 0!==e&&this.write(e,t),n.corked&&(n.corked=1,this.uncork()),n.ending||n.finished||function(e,t,r){t.ending=!0,x(e,t),r&&(t.finished?o.nextTick(r):e.once("finish",r));t.ended=!0,e.writable=!1}(this,n,r)},Object.defineProperty(y.prototype,"destroyed",{get:function(){return void 0!==this._writableState&&this._writableState.destroyed},set:function(e){this._writableState&&(this._writableState.destroyed=e)}}),y.prototype.destroy=g.destroy,y.prototype._undestroy=g.undestroy,y.prototype._destroy=function(e,t){this.end(),t(e)}}).call(this,e("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},e("timers").setImmediate)},{"./_stream_duplex":107,"./internal/streams/destroy":113,"./internal/streams/stream":114,_process:101,"core-util-is":14,inherits:88,"process-nextick-args":100,"safe-buffer":117,timers:120,"util-deprecate":134}],112:[function(e,t,r){"use strict";var n=e("safe-buffer").Buffer,i=e("util");t.exports=function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.head=null,this.tail=null,this.length=0}return e.prototype.push=function(e){var t={data:e,next:null};this.length>0?this.tail.next=t:this.head=t,this.tail=t,++this.length},e.prototype.unshift=function(e){var t={data:e,next:this.head};0===this.length&&(this.tail=t),this.head=t,++this.length},e.prototype.shift=function(){if(0!==this.length){var e=this.head.data;return 1===this.length?this.head=this.tail=null:this.head=this.head.next,--this.length,e}},e.prototype.clear=function(){this.head=this.tail=null,this.length=0},e.prototype.join=function(e){if(0===this.length)return"";for(var t=this.head,r=""+t.data;t=t.next;)r+=e+t.data;return r},e.prototype.concat=function(e){if(0===this.length)return n.alloc(0);if(1===this.length)return this.head.data;for(var t,r,i,o=n.allocUnsafe(e>>>0),s=this.head,a=0;s;)t=s.data,r=o,i=a,t.copy(r,i),a+=s.data.length,s=s.next;return o},e}(),i&&i.inspect&&i.inspect.custom&&(t.exports.prototype[i.inspect.custom]=function(){var e=i.inspect({length:this.length});return this.constructor.name+" "+e})},{"safe-buffer":117,util:12}],113:[function(e,t,r){"use strict";var n=e("process-nextick-args");function i(e,t){e.emit("error",t)}t.exports={destroy:function(e,t){var r=this,o=this._readableState&&this._readableState.destroyed,s=this._writableState&&this._writableState.destroyed;return o||s?(t?t(e):!e||this._writableState&&this._writableState.errorEmitted||n.nextTick(i,this,e),this):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(e||null,function(e){!t&&e?(n.nextTick(i,r,e),r._writableState&&(r._writableState.errorEmitted=!0)):t&&t(e)}),this)},undestroy:function(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)}}},{"process-nextick-args":100}],114:[function(e,t,r){t.exports=e("events").EventEmitter},{events:83}],115:[function(e,t,r){(r=t.exports=e("./lib/_stream_readable.js")).Stream=r,r.Readable=r,r.Writable=e("./lib/_stream_writable.js"),r.Duplex=e("./lib/_stream_duplex.js"),r.Transform=e("./lib/_stream_transform.js"),r.PassThrough=e("./lib/_stream_passthrough.js")},{"./lib/_stream_duplex.js":107,"./lib/_stream_passthrough.js":108,"./lib/_stream_readable.js":109,"./lib/_stream_transform.js":110,"./lib/_stream_writable.js":111}],116:[function(e,t,r){"use strict";t.exports=function(){if("function"!=typeof arguments[0])throw new Error("callback needed");if("number"!=typeof arguments[1])throw new Error("interval needed");var e;if(arguments.length>0){e=new Array(arguments.length-2);for(var t=0;t>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function a(e){var t=this.lastTotal-this.lastNeed,r=function(e,t,r){if(128!=(192&t[0]))return e.lastNeed=0,"�";if(e.lastNeed>1&&t.length>1){if(128!=(192&t[1]))return e.lastNeed=1,"�";if(e.lastNeed>2&&t.length>2&&128!=(192&t[2]))return e.lastNeed=2,"�"}}(this,e);return void 0!==r?r:this.lastNeed<=e.length?(e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):(e.copy(this.lastChar,t,0,e.length),void(this.lastNeed-=e.length))}function c(e,t){if((e.length-t)%2==0){var r=e.toString("utf16le",t);if(r){var n=r.charCodeAt(r.length-1);if(n>=55296&&n<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],r.slice(0,-1)}return r}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString("utf16le",t,e.length-1)}function u(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var r=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,r)}return t}function l(e,t){var r=(e.length-t)%3;return 0===r?e.toString("base64",t):(this.lastNeed=3-r,this.lastTotal=3,1===r?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString("base64",t,e.length-r))}function f(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+this.lastChar.toString("base64",0,3-this.lastNeed):t}function p(e){return e.toString(this.encoding)}function h(e){return e&&e.length?this.write(e):""}r.StringDecoder=o,o.prototype.write=function(e){if(0===e.length)return"";var t,r;if(this.lastNeed){if(void 0===(t=this.fillLast(e)))return"";r=this.lastNeed,this.lastNeed=0}else r=0;return r=0)return i>0&&(e.lastNeed=i-1),i;if(--n=0)return i>0&&(e.lastNeed=i-2),i;if(--n=0)return i>0&&(2===i?i=0:e.lastNeed=i-3),i;return 0}(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=r;var n=e.length-(r-this.lastNeed);return e.copy(this.lastChar,0,n),e.toString("utf8",t,n)},o.prototype.fillLast=function(e){if(this.lastNeed<=e.length)return e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,e.length),this.lastNeed-=e.length}},{"safe-buffer":117}],120:[function(e,t,r){(function(t,n){var i=e("process/browser.js").nextTick,o=Function.prototype.apply,s=Array.prototype.slice,a={},c=0;function u(e,t){this._id=e,this._clearFn=t}r.setTimeout=function(){return new u(o.call(setTimeout,window,arguments),clearTimeout)},r.setInterval=function(){return new u(o.call(setInterval,window,arguments),clearInterval)},r.clearTimeout=r.clearInterval=function(e){e.close()},u.prototype.unref=u.prototype.ref=function(){},u.prototype.close=function(){this._clearFn.call(window,this._id)},r.enroll=function(e,t){clearTimeout(e._idleTimeoutId),e._idleTimeout=t},r.unenroll=function(e){clearTimeout(e._idleTimeoutId),e._idleTimeout=-1},r._unrefActive=r.active=function(e){clearTimeout(e._idleTimeoutId);var t=e._idleTimeout;t>=0&&(e._idleTimeoutId=setTimeout(function(){e._onTimeout&&e._onTimeout()},t))},r.setImmediate="function"==typeof t?t:function(e){var t=c++,n=!(arguments.length<2)&&s.call(arguments,1);return a[t]=!0,i(function(){a[t]&&(n?e.apply(null,n):e.call(null),r.clearImmediate(t))}),t},r.clearImmediate="function"==typeof n?n:function(e){delete a[e]}}).call(this,e("timers").setImmediate,e("timers").clearImmediate)},{"process/browser.js":101,timers:120}],121:[function(e,t,r){"use strict";var n=e("../prototype/is");t.exports=function(e){if("function"!=typeof e)return!1;if(!hasOwnProperty.call(e,"length"))return!1;try{if("number"!=typeof e.length)return!1;if("function"!=typeof e.call)return!1;if("function"!=typeof e.apply)return!1}catch(e){return!1}return!n(e)}},{"../prototype/is":128}],122:[function(e,t,r){"use strict";var n=e("../value/is"),i=e("../object/is"),o=e("../string/coerce"),s=e("./to-short-string"),a=function(e,t){return e.replace("%v",s(t))};t.exports=function(e,t,r){if(!i(r))throw new TypeError(a(t,e));if(!n(e)){if("default"in r)return r.default;if(r.isOptional)return null}var s=o(r.errorMessage);throw n(s)||(s=t),new TypeError(a(s,e))}},{"../object/is":125,"../string/coerce":129,"../value/is":131,"./to-short-string":124}],123:[function(e,t,r){"use strict";t.exports=function(e){try{return e.toString()}catch(t){try{return String(e)}catch(e){return null}}}},{}],124:[function(e,t,r){"use strict";var n=e("./safe-to-string"),i=/[\n\r\u2028\u2029]/g;t.exports=function(e){var t=n(e);return null===t?"":(t.length>100&&(t=t.slice(0,99)+"…"),t=t.replace(i,function(e){switch(e){case"\n":return"\\n";case"\r":return"\\r";case"\u2028":return"\\u2028";case"\u2029":return"\\u2029";default:throw new Error("Unexpected character")}}))}},{"./safe-to-string":123}],125:[function(e,t,r){"use strict";var n=e("../value/is"),i={object:!0,function:!0,undefined:!0};t.exports=function(e){return!!n(e)&&hasOwnProperty.call(i,typeof e)}},{"../value/is":131}],126:[function(e,t,r){"use strict";var n=e("../lib/resolve-exception"),i=e("./is");t.exports=function(e){return i(e)?e:n(e,"%v is not a plain function",arguments[1])}},{"../lib/resolve-exception":122,"./is":127}],127:[function(e,t,r){"use strict";var n=e("../function/is"),i=/^\s*class[\s{/}]/,o=Function.prototype.toString;t.exports=function(e){return!!n(e)&&!i.test(o.call(e))}},{"../function/is":121}],128:[function(e,t,r){"use strict";var n=e("../object/is");t.exports=function(e){if(!n(e))return!1;try{return!!e.constructor&&e.constructor.prototype===e}catch(e){return!1}}},{"../object/is":125}],129:[function(e,t,r){"use strict";var n=e("../value/is"),i=e("../object/is"),o=Object.prototype.toString;t.exports=function(e){if(!n(e))return null;if(i(e)){var t=e.toString;if("function"!=typeof t)return null;if(t===o)return null}try{return""+e}catch(e){return null}}},{"../object/is":125,"../value/is":131}],130:[function(e,t,r){"use strict";var n=e("../lib/resolve-exception"),i=e("./is");t.exports=function(e){return i(e)?e:n(e,"Cannot use %v",arguments[1])}},{"../lib/resolve-exception":122,"./is":131}],131:[function(e,t,r){"use strict";t.exports=function(e){return void 0!==e&&null!==e}},{}],132:[function(e,t,r){"use strict";var n=e("punycode"),i=e("./util");function o(){this.protocol=null,this.slashes=null,this.auth=null,this.host=null,this.port=null,this.hostname=null,this.hash=null,this.search=null,this.query=null,this.pathname=null,this.path=null,this.href=null}r.parse=_,r.resolve=function(e,t){return _(e,!1,!0).resolve(t)},r.resolveObject=function(e,t){return e?_(e,!1,!0).resolveObject(t):t},r.format=function(e){i.isString(e)&&(e=_(e));return e instanceof o?e.format():o.prototype.format.call(e)},r.Url=o;var s=/^([a-z0-9.+-]+:)/i,a=/:[0-9]*$/,c=/^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,u=["{","}","|","\\","^","`"].concat(["<",">",'"',"`"," ","\r","\n","\t"]),l=["'"].concat(u),f=["%","/","?",";","#"].concat(l),p=["/","?","#"],h=/^[+a-z0-9A-Z_-]{0,63}$/,d=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,g={javascript:!0,"javascript:":!0},b={javascript:!0,"javascript:":!0},m={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},y=e("querystring");function _(e,t,r){if(e&&i.isObject(e)&&e instanceof o)return e;var n=new o;return n.parse(e,t,r),n}o.prototype.parse=function(e,t,r){if(!i.isString(e))throw new TypeError("Parameter 'url' must be a string, not "+typeof e);var o=e.indexOf("?"),a=-1!==o&&o127?M+="x":M+=P[B];if(!M.match(h)){var N=A.slice(0,C),U=A.slice(C+1),L=P.match(d);L&&(N.push(L[1]),U.unshift(L[2])),U.length&&(_="/"+U.join(".")+_),this.hostname=N.join(".");break}}}this.hostname.length>255?this.hostname="":this.hostname=this.hostname.toLowerCase(),j||(this.hostname=n.toASCII(this.hostname));var q=this.port?":"+this.port:"",F=this.hostname||"";this.host=F+q,this.href+=this.host,j&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),"/"!==_[0]&&(_="/"+_))}if(!g[S])for(C=0,T=l.length;C0)&&r.host.split("@"))&&(r.auth=j.shift(),r.host=r.hostname=j.shift());return r.search=e.search,r.query=e.query,i.isNull(r.pathname)&&i.isNull(r.search)||(r.path=(r.pathname?r.pathname:"")+(r.search?r.search:"")),r.href=r.format(),r}if(!k.length)return r.pathname=null,r.search?r.path="/"+r.search:r.path=null,r.href=r.format(),r;for(var E=k.slice(-1)[0],I=(r.host||e.host||k.length>1)&&("."===E||".."===E)||""===E,C=0,O=k.length;O>=0;O--)"."===(E=k[O])?k.splice(O,1):".."===E?(k.splice(O,1),C++):C&&(k.splice(O,1),C--);if(!w&&!S)for(;C--;C)k.unshift("..");!w||""===k[0]||k[0]&&"/"===k[0].charAt(0)||k.unshift(""),I&&"/"!==k.join("/").substr(-1)&&k.push("");var j,A=""===k[0]||k[0]&&"/"===k[0].charAt(0);x&&(r.hostname=r.host=A?"":k.length?k.shift():"",(j=!!(r.host&&r.host.indexOf("@")>0)&&r.host.split("@"))&&(r.auth=j.shift(),r.host=r.hostname=j.shift()));return(w=w||r.host&&k.length)&&!A&&k.unshift(""),k.length?r.pathname=k.join("/"):(r.pathname=null,r.path=null),i.isNull(r.pathname)&&i.isNull(r.search)||(r.path=(r.pathname?r.pathname:"")+(r.search?r.search:"")),r.auth=e.auth||r.auth,r.slashes=r.slashes||e.slashes,r.href=r.format(),r},o.prototype.parseHost=function(){var e=this.host,t=a.exec(e);t&&(":"!==(t=t[0])&&(this.port=t.substr(1)),e=e.substr(0,e.length-t.length)),e&&(this.hostname=e)}},{"./util":133,punycode:102,querystring:105}],133:[function(e,t,r){"use strict";t.exports={isString:function(e){return"string"==typeof e},isObject:function(e){return"object"==typeof e&&null!==e},isNull:function(e){return null===e},isNullOrUndefined:function(e){return null==e}}},{}],134:[function(e,t,r){(function(e){function r(t){try{if(!e.localStorage)return!1}catch(e){return!1}var r=e.localStorage[t];return null!=r&&"true"===String(r).toLowerCase()}t.exports=function(e,t){if(r("noDeprecation"))return e;var n=!1;return function(){if(!n){if(r("throwDeprecation"))throw new Error(t);r("traceDeprecation")?console.trace(t):console.warn(t),n=!0}return e.apply(this,arguments)}}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],135:[function(e,t,r){"function"==typeof Object.create?t.exports=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:t.exports=function(e,t){e.super_=t;var r=function(){};r.prototype=t.prototype,e.prototype=new r,e.prototype.constructor=e}},{}],136:[function(e,t,r){t.exports=function(e){return e&&"object"==typeof e&&"function"==typeof e.copy&&"function"==typeof e.fill&&"function"==typeof e.readUInt8}},{}],137:[function(e,t,r){(function(t,n){var i=/%[sdj%]/g;r.format=function(e){if(!m(e)){for(var t=[],r=0;r=o)return e;switch(e){case"%s":return String(n[r++]);case"%d":return Number(n[r++]);case"%j":try{return JSON.stringify(n[r++])}catch(e){return"[Circular]"}default:return e}}),c=n[r];r=3&&(n.depth=arguments[2]),arguments.length>=4&&(n.colors=arguments[3]),d(t)?n.showHidden=t:t&&r._extend(n,t),y(n.showHidden)&&(n.showHidden=!1),y(n.depth)&&(n.depth=2),y(n.colors)&&(n.colors=!1),y(n.customInspect)&&(n.customInspect=!0),n.colors&&(n.stylize=c),l(n,e,n.depth)}function c(e,t){var r=a.styles[t];return r?"["+a.colors[r][0]+"m"+e+"["+a.colors[r][1]+"m":e}function u(e,t){return e}function l(e,t,n){if(e.customInspect&&t&&k(t.inspect)&&t.inspect!==r.inspect&&(!t.constructor||t.constructor.prototype!==t)){var i=t.inspect(n,e);return m(i)||(i=l(e,i,n)),i}var o=function(e,t){if(y(t))return e.stylize("undefined","undefined");if(m(t)){var r="'"+JSON.stringify(t).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return e.stylize(r,"string")}if(b(t))return e.stylize(""+t,"number");if(d(t))return e.stylize(""+t,"boolean");if(g(t))return e.stylize("null","null")}(e,t);if(o)return o;var s=Object.keys(t),a=function(e){var t={};return e.forEach(function(e,r){t[e]=!0}),t}(s);if(e.showHidden&&(s=Object.getOwnPropertyNames(t)),S(t)&&(s.indexOf("message")>=0||s.indexOf("description")>=0))return f(t);if(0===s.length){if(k(t)){var c=t.name?": "+t.name:"";return e.stylize("[Function"+c+"]","special")}if(_(t))return e.stylize(RegExp.prototype.toString.call(t),"regexp");if(w(t))return e.stylize(Date.prototype.toString.call(t),"date");if(S(t))return f(t)}var u,v="",x=!1,E=["{","}"];(h(t)&&(x=!0,E=["[","]"]),k(t))&&(v=" [Function"+(t.name?": "+t.name:"")+"]");return _(t)&&(v=" "+RegExp.prototype.toString.call(t)),w(t)&&(v=" "+Date.prototype.toUTCString.call(t)),S(t)&&(v=" "+f(t)),0!==s.length||x&&0!=t.length?n<0?_(t)?e.stylize(RegExp.prototype.toString.call(t),"regexp"):e.stylize("[Object]","special"):(e.seen.push(t),u=x?function(e,t,r,n,i){for(var o=[],s=0,a=t.length;s=0&&0,e+t.replace(/\u001b\[\d\d?m/g,"").length+1},0)>60)return r[0]+(""===t?"":t+"\n ")+" "+e.join(",\n ")+" "+r[1];return r[0]+t+" "+e.join(", ")+" "+r[1]}(u,v,E)):E[0]+v+E[1]}function f(e){return"["+Error.prototype.toString.call(e)+"]"}function p(e,t,r,n,i,o){var s,a,c;if((c=Object.getOwnPropertyDescriptor(t,i)||{value:t[i]}).get?a=c.set?e.stylize("[Getter/Setter]","special"):e.stylize("[Getter]","special"):c.set&&(a=e.stylize("[Setter]","special")),C(n,i)||(s="["+i+"]"),a||(e.seen.indexOf(c.value)<0?(a=g(r)?l(e,c.value,null):l(e,c.value,r-1)).indexOf("\n")>-1&&(a=o?a.split("\n").map(function(e){return" "+e}).join("\n").substr(2):"\n"+a.split("\n").map(function(e){return" "+e}).join("\n")):a=e.stylize("[Circular]","special")),y(s)){if(o&&i.match(/^\d+$/))return a;(s=JSON.stringify(""+i)).match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(s=s.substr(1,s.length-2),s=e.stylize(s,"name")):(s=s.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),s=e.stylize(s,"string"))}return s+": "+a}function h(e){return Array.isArray(e)}function d(e){return"boolean"==typeof e}function g(e){return null===e}function b(e){return"number"==typeof e}function m(e){return"string"==typeof e}function y(e){return void 0===e}function _(e){return v(e)&&"[object RegExp]"===x(e)}function v(e){return"object"==typeof e&&null!==e}function w(e){return v(e)&&"[object Date]"===x(e)}function S(e){return v(e)&&("[object Error]"===x(e)||e instanceof Error)}function k(e){return"function"==typeof e}function x(e){return Object.prototype.toString.call(e)}function E(e){return e<10?"0"+e.toString(10):e.toString(10)}r.debuglog=function(e){if(y(o)&&(o=t.env.NODE_DEBUG||""),e=e.toUpperCase(),!s[e])if(new RegExp("\\b"+e+"\\b","i").test(o)){var n=t.pid;s[e]=function(){var t=r.format.apply(r,arguments);console.error("%s %d: %s",e,n,t)}}else s[e]=function(){};return s[e]},r.inspect=a,a.colors={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},a.styles={special:"cyan",number:"yellow",boolean:"yellow",undefined:"grey",null:"bold",string:"green",date:"magenta",regexp:"red"},r.isArray=h,r.isBoolean=d,r.isNull=g,r.isNullOrUndefined=function(e){return null==e},r.isNumber=b,r.isString=m,r.isSymbol=function(e){return"symbol"==typeof e},r.isUndefined=y,r.isRegExp=_,r.isObject=v,r.isDate=w,r.isError=S,r.isFunction=k,r.isPrimitive=function(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||void 0===e},r.isBuffer=e("./support/isBuffer");var I=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function C(e,t){return Object.prototype.hasOwnProperty.call(e,t)}r.log=function(){var e,t;console.log("%s - %s",(e=new Date,t=[E(e.getHours()),E(e.getMinutes()),E(e.getSeconds())].join(":"),[e.getDate(),I[e.getMonth()],t].join(" ")),r.format.apply(r,arguments))},r.inherits=e("inherits"),r._extend=function(e,t){if(!t||!v(t))return e;for(var r=Object.keys(t),n=r.length;n--;)e[r[n]]=t[r[n]];return e}}).call(this,e("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./support/isBuffer":136,_process:101,inherits:135}],138:[function(e,t,r){t.exports=function e(t,r){if(t&&r)return e(t)(r);if("function"!=typeof t)throw new TypeError("need wrapper function");Object.keys(t).forEach(function(e){n[e]=t[e]});return n;function n(){for(var e=new Array(arguments.length),r=0;r