1# Third-Party SDK Integration<a name="EN-US_TOPIC_0000001051612018"></a> 2 3To build a more open and complete Internet of Things \(IoT\) ecosystem, OpenHarmony has opened up a group of directories to integrate SDKs provided by different vendors. This guide describes how to integrate SDKs into OpenHarmony based on the Hi3861 board. 4 5## Planning a Directory Structure<a name="section1736472718351"></a> 6 7A third-party SDK consists of a static library and the adaption code. The SDK service logic is compiled to obtain the static library **libs** through the hardware module tool chain. Each module has its corresponding **libs**. The southbound APIs of the SDK are different from the APIs of OpenHarmony. The difference can be shielded by using the adaptation code **adapter**. Different modules can share the same **adapter**. 8 9Based on the preceding features, third-party SDK directories can be divided as follows in the OpenHarmony directory structure: 10 11- domains/iot/link/: The **adapter** is stored in this directory and is decoupled from the module. 12- device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/: The service library **libs** is stored in this directory and is bound to the module. 13 14You must perform the following steps before adaptation. The following uses the demolink SDK as an example. 15 161. Create vendor directories, **domains/iot/link/demolink/** and **device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/demolink/**, to isolate different vendors. 172. Create the **domains/iot/link/demolink/BUILD.gn** file to build the adaptation code. 183. Create the **device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/demolink/libs/** directory to store the service library **libs**. 19 20``` 21. 22├── domains 23│ └── iot 24│ └── link 25│ ├── demolink 26│ │ └── BUILD.gn 27│ ├── libbuild 28│ │ └── BUILD.gn 29│ └── BUILD.gn 30└── device 31 └── hisilicon 32 └── hispark_pegasus 33 └── sdk_liteos 34 └── 3rd_sdk 35 └── demolink 36 └── libs 37``` 38 39## Building the Service **libs**<a name="section442815485351"></a> 40 41Generally, the platform SDK service is provided as a static library. After obtaining the OpenHarmony code, the platform vendor needs to compile the service library **libs** based on the corresponding hardware module vendor and save the compilation result to the **device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/demolink/libs/** directory. The following describes how to build the service library **libs**. 42 43OpenHarmony has planned the **domains/iot/link/libbuild/** directory for compiling the service library **libs**. This directory contains the **domains/iot/link/libbuild/BUILD.gn** and **domains/iot/link/BUILD.gn** files. The directory structure is as follows: 44 45``` 46. 47└── domains 48 └── iot 49 └── link 50 ├── demolink 51 │ └── BUILD.gn 52 ├── libbuild 53 │ └── BUILD.gn 54 └── BUILD.gn 55``` 56 57Before building **libs**, you must perform the following steps: 58 591. Place the service source code files \(including **.c** and **.h** files\) in the **domains/iot/link/libbuild/** directory. 60 61 ``` 62 . 63 └── domains 64 └── iot 65 └── link 66 ├── demolink 67 │ ├── demosdk_adapter.c 68 │ ├── demosdk_adapter.h 69 │ └── BUILD.gn 70 ├── libbuild 71 │ ├── demosdk.c 72 │ ├── demosdk.h 73 │ └── BUILD.gn 74 └── BUILD.gn 75 ``` 76 772. Adapt to the **domains/iot/link/libbuild/BUILD.gn** file and restore the file after the compilation is complete. 78 79 In the **BUILD.gn** file, **sources** specifies the source file to build and **include\_dirs** specifies the path of the dependent header file so that the target build result is the static library **libdemosdk.a**. 80 81 ``` 82 static_library("demosdk") { 83 sources = [ 84 "demosdk.c" 85 ] 86 include_dirs = [ 87 "//domains/iot/link/libbuild", 88 "//domains/iot/link/demolink" 89 ] 90 } 91 ``` 92 933. Adapt to the **domains/iot/link/BUILD.gn** file and restore the file after the compilation is complete. 94 95 The **BUILD.gn** file is used to specify build entries. You need to enter all static library entries to be compiled in **features** so that the **domains/iot/link/libbuild/BUILD.gn** file is used in the build. 96 97 ``` 98 import("//build/lite/config/subsystem/lite_subsystem.gni") 99 import("//build/lite/config/component/lite_component.gni") 100 lite_subsystem("iot") { 101 subsystem_components = [ 102 ":link" 103 ] 104 } 105 lite_component("link") { 106 features = [ 107 "libbuild:demosdk" 108 ] 109 } 110 ``` 111 112 113After the preceding operations are complete, run the **hb build -T //domains/iot/link:iot** command in the root directory of the code and then check whether the target library file is generated in the **out/hispark\_pegasus/wifiiot\_hispark\_pegasus/libs/** directory. 114 115![](figures/device-wlan-sdk-files.png) 116 117Copy the library file to the **device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/demolink/libs/** directory and delete the **.c** and **.h** files from the **domains/iot/link/libbuild/** directory. 118 119## Compiling Adaptation Code<a name="section3984721113613"></a> 120 121## Compiling Code<a name="section830417531286"></a> 122 123The APIs used in the platform SDK are different from the OpenHarmony APIs and cannot be directly used. Therefore, the adaptation code **adapter** is required for intermediate conversion. This section uses **DemoSdkCreateTask** in **domains/iot/link/demolink/demosdk\_adapter.c** as an example to describe how to compile adaptation code on OpenHarmony. 124 1251. Check the description, parameters, and return values of the **DemoSdkCreateTask** API to adapt. 126 127 ``` 128 struct TaskPara { 129 char *name; 130 void *(*func)(char* arg); 131 void *arg; 132 unsigned char prio; 133 unsigned int size; 134 }; 135 136 /* 137 * Create a thread for the IoT OS. 138 * Returns 0 if the operation is successful; returns a non-zero value otherwise. 139 */ 140 int DemoSdkCreateTask(unsigned int *handle, const struct TaskPara *para); 141 ``` 142 1432. Check the OpenHarmony API document, select an API with similar features, and compare the parameters and usage. This guide uses **osThreadNew** as an example. By comparing this API with **DemoSdkCreateTask**, you can find that the parameters on which the two APIs depend are basically the same, but the structures to which the parameters belong are different. 144 145 ``` 146 typedef struct { 147 const char *name; ///< name of the thread 148 uint32_t attr_bits; ///< attribute bits 149 void *cb_mem; ///< memory for control block 150 uint32_t cb_size; ///< size of provided memory for control block 151 void *stack_mem; ///< memory for stack 152 uint32_t stack_size; ///< size of stack 153 osPriority_t priority; ///< initial thread priority (default: osPriorityNormal) 154 TZ_ModuleId_t tz_module; ///< TrustZone module identifier 155 uint32_t reserved; ///< reserved (must be 0) 156 } osThreadAttr_t; 157 158 /// Create a thread and add it to Active Threads. 159 /// \param[in] func thread function. 160 /// \param[in] argument pointer that is passed to the thread function as start argument. 161 /// \param[in] attr thread attributes; NULL: default values. 162 /// \return thread ID for reference by other functions or NULL in case of error. 163 osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAttr_t *attr); 164 ``` 165 1663. Perform code adaptation to shield the difference. 167 168 ``` 169 int DemoSdkCreateTask(unsigned int *handle, const struct TaskPara *para) 170 { 171 osThreadAttr_t attr = {0}; 172 osThreadId_t threadId; 173 if (handle == 0 || para == 0) { 174 return DEMOSDK_ERR; 175 } 176 if (para->func == 0) { 177 return DEMOSDK_ERR; 178 } 179 if (para->name == 0) { 180 return DEMOSDK_ERR; 181 } 182 attr.name = para->name; 183 attr.priority = para->prio; 184 attr.stack_size = para->size; 185 threadId = osThreadNew((osThreadFunc_t)para->func, para->arg, &attr); 186 if (threadId == 0) { 187 printf("osThreadNew fail\n"); 188 return DEMOSDK_ERR; 189 } 190 *(unsigned int *)handle = (unsigned int)threadId; 191 return DEMOSDK_OK; 192 } 193 ``` 194 195 196## Compiling a Script<a name="section13500201173710"></a> 197 198After completing code adaptation, create the **BUILD.gn** file in the directory where the **adapter** is located. This file can be used to compile the adaptation code into a static library and link the static library to the **bin** package during the entire package build. In the **domains/iot/link/demolink/BUILD.gn** file, **sources** specifies the source files to be used in the build and **include\_dirs** specifies the path of the dependent header file so that the target build result is the static library **libdemolinkadapter.a**. 199 200``` 201import("//build/lite/config/component/lite_component.gni") 202static_library("demolinkadapter") { 203 sources = [ 204 "demosdk_adapter.c" 205 ] 206 include_dirs = [ 207 "//kernel/liteos-m/kal/cmsis", 208 "//domains/iot/link/demolink" 209 ] 210} 211``` 212 213Modify the **domains/iot/link/BUILD.gn** file so that the **domain/iot/hilink/BUILD.gn** file is used in the build. 214 215``` 216import("//build/lite/config/subsystem/lite_subsystem.gni") 217import("//build/lite/config/component/lite_component.gni") 218lite_subsystem("iot") { 219 subsystem_components = [ 220 ":link" 221 ] 222} 223lite_component("link") { 224 features = [ 225 "demolink:demolinkadapter" 226 ] 227} 228``` 229 230## Compiling Service Code<a name="section8754114803918"></a> 231 232After the service library **libs** and adaptation code are ready, compile the service entry function to call the service entry of the third-party SDK. 233 234The following uses **demolink** as an example to describe how to compile code in **applications/sample/wifi-iot/app/** to call the **demosdk** entry function. 235 2361. Create a directory. 237 238 Before compiling a service, you must create a directory \(or a directory structure\) in **applications/sample/wifi-iot/app/** to store service source code files. 239 240 For example, add the service directory **demolink** to the app, and create the service entry code **helloworld.c** and compile the **BUILD.gn** file. 241 242 ``` 243 . 244 └── applications 245 └── sample 246 └── wifi-iot 247 └── app 248 │── demolink 249 │ │── helloworld.c 250 │ └── BUILD.gn 251 └── BUILD.gn 252 ``` 253 2542. Compile service code. 255 256 Compile the service entry function **DemoSdkMain** in the **helloworld.c** file, call the service entry **DemoSdkEntry** of **demolink**, and call the entry function through **SYS\_RUN\(\)** to start the service. 257 258 ``` 259 #include "hos_init.h" 260 #include "demosdk.h" 261 262 void DemoSdkMain(void) 263 { 264 DemoSdkEntry(); 265 } 266 267 SYS_RUN(DemoSdkMain); 268 ``` 269 2703. Compile build scripts. 271 272 Add the **applications/sample/wifi-iot/app/demolink/BUILD.gn** file, specify the paths of the source code and header file, and compile the static library file **libexample\_demolink.a**. 273 274 ``` 275 static_library("example_demolink") { 276 sources = [ 277 "helloworld.c" 278 ] 279 include_dirs = [ 280 "//utils/native/lite/include", 281 "//domains/iot/link/libbuild" 282 ] 283 } 284 ``` 285 286 Modify the **applications/sample/wifi-iot/app/BUILD.gn** file so that **demolink** is used in compilation. 287 288 ``` 289 import("//build/lite/config/component/lite_component.gni") 290 lite_component("app") { 291 features = [ 292 "demolink:example_demolink" 293 ] 294 } 295 ``` 296 297 298## Runtime<a name="section7737749184012"></a> 299 300Run the **hb build** command in the root directory of the code to compile and output the version package. Start **demolink**. The following shows the running result, which is consistent with the expected result of **demolink**. 301 302``` 303ready to OS start 304sdk ver:Hi3861V100R001C00SPC024 2020-08-05 16:30:00 305formatting spiffs... 306FileSystem mount ok. 307wifi init success! 308it is demosdk entry. 309it is demo biz: hello world. 310it is demo biz: hello world. 311``` 312 313## End<a name="section153301392411"></a> 314 315The third-party SDK integration is complete. 316 317