1# 编写通过JS应用控制LED灯 2在本示例将演示如何在系统中添加自定义JS API,达到能通过JS应用关闭灯、开启灯以及翻转灯的状态。希望通过本教程的学习,开发者能掌握如何在OpenHarmony中自定义JS API。 3 4**注:** 在学习本教程之前,请确保已经完成[编写一个点亮LED灯程序](./编写一个点亮LED灯程序.md)实验,因为本实验将依赖[编写一个点亮LED灯程序](./编写一个点亮LED灯程序.md)实验中开发的驱动,以下教程篇幅较长,请耐心仔细阅读。 5 6## 一、JS API接口开发 7 81. 添加控制LED灯的JS API接口 9 10 修改`foundation\ace\ace_engine_lite\frameworks\src\core\modules\app_module.h`,加入toggleLed JS API,("##start##"和"##end##"仅用来标识位置,添加完配置后删除这两行) 11 12 ``` 13 public: 14 ACE_DISALLOW_COPY_AND_MOVE(AppModule); 15 AppModule() = default; 16 ~AppModule() = default; 17 static JSIValue GetInfo(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum); 18 static JSIValue Terminate(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum); 19 ##start## 20 static JSIValue ToggleLed(const JSIValue thisVal, const JSIValue* args, uint8_t argsNum); 21 ##end## 22 #ifdef FEATURE_SCREEN_ON_VISIBLE 23 static JSIValue ScreenOnVisible(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum); 24 #endif 25 ``` 26 27 ``` 28 void InitAppModule(JSIValue exports) 29 { 30 JSI::SetModuleAPI(exports, "getInfo", AppModule::GetInfo); 31 JSI::SetModuleAPI(exports, "terminate", AppModule::Terminate); 32 ##start## 33 JSI::SetModuleAPI(exports, "ledcontrol", AppModule::ToggleLed); 34 ##end## 35 #ifdef FEATURE_SCREEN_ON_VISIBLE 36 JSI::SetModuleAPI(exports, "screenOnVisible", AppModule::ScreenOnVisible); 37 #endif 38 } 39 ``` 40 412. 编写控制LED灯c++ 业务代码 42 43 在`foundation\ace\ace_engine_lite\frameworks\src\core\modules\app_module.cpp`中加入控制LED灯c++ 业务代码("##start##"和"##end##"仅用来标识位置,添加完配置后删除这两行)。 44 45 ``` 46 #include "app_module.h" 47 #include "ace_log.h" 48 #include "js_app_context.h" 49 #ifdef FEATURE_SCREEN_ON_VISIBLE 50 #include "js_async_work.h" 51 #include "product_adapter.h" 52 #endif 53 54 ##start## 55 #include "hdf_sbuf.h" 56 #include "hdf_io_service_if.h" 57 58 #define LED_WRITE_READ 1 59 #define LED_SERVICE "hdf_led" 60 ##end## 61 62 namespace OHOS { 63 namespace ACELite { 64 const char * const AppModule::FILE_MANIFEST = "manifest.json"; 65 const char * const AppModule::KEY_APP_NAME = "appName"; 66 const char * const AppModule::KEY_VERSION_NAME = "versionName"; 67 const char * const AppModule::KEY_VERSION_CODE = "versionCode"; 68 69 ``` 70 71 ``` 72 struct AsyncParams : public MemoryHeap { 73 ACE_DISALLOW_COPY_AND_MOVE(AsyncParams); 74 AsyncParams() : result(nullptr), callback(nullptr), context(nullptr) {} 75 76 JSIValue result; 77 JSIValue callback; 78 JSIValue context; 79 }; 80 #endif 81 82 ##start## 83 84 static int OnDevEventReceived(void *priv, uint32_t id, struct HdfSBuf *data) 85 { 86 uint32_t value; 87 HdfSbufReadUint32(data, &value); 88 HILOG_ERROR(HILOG_MODULE_ACE,"%s: dev event received: %u %u\n", (char *)priv, id, value); 89 90 return HDF_SUCCESS; 91 } 92 93 static int GpioWriteRead(struct HdfIoService *serv, int32_t eventData, int32_t *val) 94 { 95 int ret = HDF_FAILURE; 96 struct HdfSBuf *data = HdfSbufObtainDefaultSize(); 97 struct HdfSBuf *reply = HdfSbufObtainDefaultSize(); 98 99 if (data == NULL || reply == NULL) { 100 HILOG_ERROR(HILOG_MODULE_ACE,"fail to obtain sbuf data\n"); 101 return ret; 102 } 103 104 if (!HdfSbufWriteUint8(data, (uint8_t)eventData)) 105 { 106 HILOG_ERROR(HILOG_MODULE_ACE,"fail to write sbuf\n"); 107 HdfSbufRecycle(data); 108 HdfSbufRecycle(reply); 109 return ret; 110 } 111 112 ret = serv->dispatcher->Dispatch(&serv->object, LED_WRITE_READ, data, reply); 113 if (ret != HDF_SUCCESS) 114 { 115 HILOG_ERROR(HILOG_MODULE_ACE,"fail to send service call\n"); 116 HdfSbufRecycle(data); 117 HdfSbufRecycle(reply); 118 return ret; 119 } 120 if (!HdfSbufReadInt32(reply, val)) 121 { 122 HILOG_ERROR(HILOG_MODULE_ACE,"fail to get service call reply\n"); 123 ret = HDF_ERR_INVALID_OBJECT; 124 HdfSbufRecycle(data); 125 HdfSbufRecycle(reply); 126 return ret; 127 } 128 HILOG_ERROR(HILOG_MODULE_ACE,"Get reply is: %d\n", val); 129 130 HdfSbufRecycle(data); 131 HdfSbufRecycle(reply); 132 return ret; 133 } 134 135 JSIValue AppModule::ToggleLed(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum) 136 { 137 HILOG_ERROR(HILOG_MODULE_ACE, "led button pressed."); 138 139 struct HdfIoService *serv = HdfIoServiceBind(LED_SERVICE); 140 if (serv == NULL) 141 { 142 HILOG_ERROR(HILOG_MODULE_ACE,"fail to get service2 %s\n", LED_SERVICE); 143 return JSI::CreateUndefined(); 144 } 145 146 if ((args == nullptr) || (argsNum == 0) || (JSI::ValueIsUndefined(args[0]))) { 147 return JSI::CreateUndefined(); 148 } 149 150 JSIValue success = JSI::GetNamedProperty(args[0], CB_SUCCESS); 151 JSIValue fail = JSI::GetNamedProperty(args[0], CB_FAIL); 152 JSIValue complete = JSI::GetNamedProperty(args[0], CB_COMPLETE); 153 154 int32_t num = (int32_t)JSI::GetNumberProperty(args[0], "code"); 155 156 int32_t replyData = 0; 157 158 if (GpioWriteRead(serv, num, &replyData)) 159 { 160 HILOG_ERROR(HILOG_MODULE_ACE,"fail to send event\n"); 161 JSI::CallFunction(fail, thisVal, nullptr, 0); 162 JSI::CallFunction(complete, thisVal, nullptr, 0); 163 JSI::ReleaseValueList(success, fail, complete); 164 return JSI::CreateUndefined(); 165 } 166 167 JSIValue result = JSI::CreateObject(); 168 JSI::SetNumberProperty(result, "led_status", replyData); 169 170 JSIValue argv[ARGC_ONE] = {result}; 171 JSI::CallFunction(success, thisVal, argv, ARGC_ONE); 172 JSI::CallFunction(complete, thisVal, nullptr, 0); 173 JSI::ReleaseValueList(success, fail, complete, result); 174 175 HdfIoServiceRecycle(serv); 176 177 return JSI::CreateUndefined(); 178 } 179 180 ##end## 181 182 JSIValue AppModule::GetInfo(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum) 183 { 184 JSIValue result = JSI::CreateUndefined(); 185 186 cJSON *manifest = ReadManifest(); 187 if (manifest == nullptr) { 188 HILOG_ERROR(HILOG_MODULE_ACE, "Fail to get the content of manifest."); 189 return result; 190 } 191 192 cJSON *appName = cJSON_GetObjectItem(manifest, KEY_APP_NAME); 193 cJSON *versionName = cJSON_GetObjectItem(manifest, KEY_VERSION_NAME); 194 cJSON *versionCode = cJSON_GetObjectItem(manifest, KEY_VERSION_CODE); 195 196 result = JSI::CreateObject(); 197 if (appName != nullptr && appName->type == cJSON_String) { 198 JSI::SetStringProperty(result, KEY_APP_NAME, appName->valuestring); 199 } 200 if (versionName != nullptr && versionName->type == cJSON_String) { 201 JSI::SetStringProperty(result, KEY_VERSION_NAME, versionName->valuestring); 202 } 203 if (versionCode != nullptr && versionCode->type == cJSON_Number) { 204 JSI::SetNumberProperty(result, KEY_VERSION_CODE, versionCode->valuedouble); 205 } 206 cJSON_Delete(manifest); 207 manifest = nullptr; 208 return result; 209 } 210 ``` 2113. 配置HDF头文件路径 212 213 在`foundation\ace\ace_engine_lite\ace_lite.gni`中添加HDF头文件路径。 214 215 ``` 216 ace_lite_include_dirs += [ 217 "//drivers/hdf_core/framework/ability/sbuf/include", 218 "//drivers/hdf_core/framework/include/core", 219 "//drivers/hdf_core/framework/include/utils", 220 "//drivers/hdf_core/adapter/uhdf/posix/include", 221 ] 222 ``` 2234. 添加编译依赖 224 225 修改`foundation\ace\ace_engine_lite\frameworks\BUILD.gn`,在`public_deps`中添加以下代码 226 ``` 227 "//drivers/hdf_core/adapter/uhdf/manager:hdf_core", 228 ``` 229 230 修改`foundation\ace\ace_engine_lite\test\ace_test_config.gni`,在`extra_deps`中添加以下代码 231 ``` 232 "//drivers/hdf_core/adapter/uhdf/manager:hdf_core", 233 ``` 234 235## 二、运行结果 236 237示例代码[编译、烧录](BearPi-HM_Micro开发板编译调试.md)后,参考[如何在开发板上安装HAP应用](如何在开发板上安装HAP应用.md)教程安装device/board/bearpi/bearpi_hm_micro/tools/hap_tools/hap_example目录下的LED.hap应用进行测试 238 239 240 241 242