26 Star 129 Fork 69

小熊派开源社区 / BearPi-HM_Micro_small

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
智慧路灯E53_SC1扩展板功能使用指导.md 16.66 KB
一键复制 编辑 原始数据 按行查看 历史
Laowang-BearPi 提交于 2022-04-29 18:30 . add Micro JS APP code

智慧路灯E53_SC1扩展板功能使用指导

说明:
 本案例使用E53_SC1(智慧路灯模块)进行开发。目前已经适配好E53接口的底层驱动放在 device/st/drivers路径下面,感兴趣的读者可以去翻阅一下。另外,E53模组的底层驱动也已经可以直接调用。用户层可以通过获取驱动发布的服务使用模块。

下面将讲解E53_SC1的使用教程

驱动开发

JS接口适配

烧录运行

一、E53_SC1驱动开发

  1. 确定目录结构。

    在device\st\driver路径下新建E53_SC1文件夹,并创建驱动文件E53_SC1_hdf.c和编译构建文件BUILD.gn 。

    .
    └─ device        
        └─ st
            └─ drivers
                └─ e53_driver
                    └─ E53_SC1
                        │─ E53_SC1_hdf.c
                        │─ inc
                        └─ src
    
    
  2. E53_SC1驱动实现

    驱动实现包含驱动业务代码和驱动入口注册,在E53_SC1_hdf.c文件中添加以下代码:

    #include <stdint.h>
    #include <string.h>
    
    #include "E53_SC1.h"
    #include "E53_Common.h"
    
    #include "hdf_device_desc.h" 
    #include "hdf_log.h"         
    #include "device_resource_if.h"
    #include "osal_io.h"
    #include "osal_mem.h"
    #include "gpio_if.h"
    #include "osal_time.h"
    
    
    static uint8_t LightStatus;
    static float lux_data;
    
    typedef enum {
        E53_SC1_Start = 0,
        E53_SC1_Stop,
        E53_SC1_Read,
        E53_SC1_SetLight,
    }E53_SC1Ctrl;
    
    int32_t E53_SC1_DriverDispatch(struct HdfDeviceIoClient *client, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply)
    {
        int ret = -1;
        char *replay_buf;
    
        HDF_LOGE("E53 driver dispatch");
        if (client == NULL || client->device == NULL) {
            HDF_LOGE("E53 driver device is NULL");
            return HDF_ERR_INVALID_OBJECT;
        }
        switch (cmdCode) {
            case E53_SC1_Start:
                ret = E53_SC1Init();
                if (ret != 0) {
                    HDF_LOGE("E53 SC1 Init err");
                    return HDF_FAILURE;
                }
                ret = HdfSbufWriteString(reply, "E53 SC1 Init successful");
                if (ret == 0) {
                    HDF_LOGE("reply failed");
                    return HDF_FAILURE;
                }
                break;
            case E53_SC1_Stop:
                ret = E53_SC1DeInit();
                if (ret != 0) {
                    HDF_LOGE("E53 SC1 DeInit err");
                    return HDF_FAILURE;
                }
                ret = HdfSbufWriteString(reply, "E53 SC1 DeInit successful");
                if (ret == 0) {
                    HDF_LOGE("reply failed");
                    return HDF_FAILURE;
                }
                break;
            /* 接收到用户态发来的LED_WRITE_READ命令 */
            case E53_SC1_Read:
                ret = E53_SC1ReadData(&lux_data);
                if (ret != 0) {
                    HDF_LOGE("E53 SC1 Read Data err");
                    return HDF_FAILURE;
                }
                replay_buf = OsalMemAlloc(100);
                (void)memset_s(replay_buf, 100, 0, 100);
                sprintf(replay_buf, "{\"Lux\":%.2f,\"LED\":\"%s\"}", lux_data, LightStatus ? "ON" : "OFF");
                /* 把传感器数据写入reply, 可被带至用户程序 */
                if (!HdfSbufWriteString(reply, replay_buf)) {
                    HDF_LOGE("replay is fail");
                    return HDF_FAILURE;
                }
                OsalMemFree(replay_buf);
                break;
            case E53_SC1_SetLight:
                const char* readdata = HdfSbufReadString(data);
                if (strcmp(readdata, "ON") == 0) {
                    E53_SC1LightStatusSet(ON);
                    LightStatus = 1;
                } else if (strcmp(readdata, "OFF") == 0) {
                    E53_SC1LightStatusSet(OFF);
                    LightStatus = 0;
                } else {
                    HDF_LOGE("Command wrong!");
                    return HDF_FAILURE;
                }
                replay_buf = OsalMemAlloc(100);
                (void)memset_s(replay_buf, 100, 0, 100);
                sprintf(replay_buf, "{\"Lux\":%.2f,\"LED\":\"%s\"}", lux_data, LightStatus ? "ON" : "OFF");
                /* 把传感器数据写入reply, 可被带至用户程序 */
                if (!HdfSbufWriteString(reply, replay_buf)) {
                    HDF_LOGE("replay is fail");
                    return HDF_FAILURE;
                }
                OsalMemFree(replay_buf);
                break;
    
            default:
                return HDF_FAILURE;
        }
        return HDF_SUCCESS;
    }
    
    
    //驱动对外提供的服务能力,将相关的服务接口绑定到HDF框架
    static int32_t Hdf_E53_SC1_DriverBind(struct HdfDeviceObject *deviceObject)
    {
        if (deviceObject == NULL) {
            HDF_LOGE("e53 driver bind failed!");
            return HDF_ERR_INVALID_OBJECT;
        }
        static struct IDeviceIoService e53Driver = {
            .Dispatch = E53_SC1_DriverDispatch,
        };
        deviceObject->service = (struct IDeviceIoService *)(&e53Driver);
        HDF_LOGD("E53 driver bind success");
        return HDF_SUCCESS;
    }
    
    // static struct E53_SC1Hooks hooks = {
    //     .E53_SC1Init = sc1Init,
    //     .E53_SC1DeInit = sc1DeInit,
    //     .E53_SC1LightGpioSet = sc1GpioSet,
    //     .E53_SC1_IICWriteFunc = sc1E53_IICWrite,
    //     .E53_SC1_IICReadFunc = sc1E53_IICRead,
    //     .E53_SC1_IICWriteReadFunc = sc1E53_IICWriteRead,
    // };
    
    static int32_t Hdf_E53_SC1_DriverInit(struct HdfDeviceObject *device)
    {
        return HDF_SUCCESS;
    }
    
    // 驱动资源释放的接口
    void Hdf_E53_SC1_DriverRelease(struct HdfDeviceObject *deviceObject)
    {
        if (deviceObject == NULL) {
            HDF_LOGE("Led driver release failed!");
            return;
        }
        HDF_LOGD("Led driver release success");
        return;
    }
    
    
    // 定义驱动入口的对象,必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量
    static struct HdfDriverEntry g_E53DriverEntry = {
        .moduleVersion = 1,
        .moduleName = "HDF_E53_SC1",
        .Bind = Hdf_E53_SC1_DriverBind,
        .Init = Hdf_E53_SC1_DriverInit,
        .Release = Hdf_E53_SC1_DriverRelease,
    };
    
    // 调用HDF_INIT将驱动入口注册到HDF框架中
    HDF_INIT(g_E53DriverEntry);
  3. 驱动配置

    驱动设备描述

    HDF框架加载驱动所需要的信息来源于HDF框架定义的驱动设备描述,因此基于HDF框架开发的驱动必须要在HDF框架定义的device_info.hcs配置文件中添加对应的设备描述,所以我们需要在device\st\bearpi_hm_micro\liteos_a\hdf_config\device_info\device_info.hcs中添加E53_SC1设备描述。 "##start##"和"##end##"之间为新增配置("##start##"和"##end##"仅用来标识位置,添加完配置后删除这两行)

    device_adc :: device {
        device0 :: deviceNode {
            policy = 0;
            priority = 50;
            permission = 0644;
            moduleName = "HDF_PLATFORM_ADC_MANAGER";
            serviceName = "HDF_PLATFORM_ADC_MANAGER";
        }
        device1 :: deviceNode {
            policy = 0;
            priority = 55;
            permission = 0644;
            moduleName = "stm32mp157_adc_driver";
            deviceMatchAttr = "st_stm32mp157_adc";
        }
    }
    ##start##
    device_e53 :: device {  
    
            priority = 30;                
            device_sc1 :: deviceNode {             
                policy = 2;                     
                priority = 130; 
                preload = 1;                               
                permission = 0777;              
                moduleName = "HDF_E53_SC1";        
                serviceName = "hdf_e53_sc1";    
            }
    }
    ##end##

二、JS接口层的适配

  1. 添加控制E53_SC1的JS API接口

    修改foundation\ace\ace_engine_lite\frameworks\src\core\modules\app_module.h,加入E53SC1Service JS API,("##start##"和"##end##"仅用来标识位置,添加完配置后删除这两行)

    public:
    ACE_DISALLOW_COPY_AND_MOVE(AppModule);
    AppModule() = default;
    ~AppModule() = default;
    static JSIValue GetInfo(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum);
    static JSIValue Terminate(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum);
    ##start##
    static JSIValue E53SC1Service(const JSIValue thisVal, const JSIValue* args, uint8_t argsNum);
    ##end##
    #ifdef FEATURE_SCREEN_ON_VISIBLE
        static JSIValue ScreenOnVisible(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum);
    #endif
    void InitAppModule(JSIValue exports)
    {
        JSI::SetModuleAPI(exports, "getInfo", AppModule::GetInfo);
        JSI::SetModuleAPI(exports, "terminate", AppModule::Terminate);
    ##start##
        JSI::SetModuleAPI(exports, "e53sc1service", AppModule::E53SC1Service);
    ##end##
    #ifdef FEATURE_SCREEN_ON_VISIBLE
        JSI::SetModuleAPI(exports, "screenOnVisible", AppModule::ScreenOnVisible);
    #endif
    }
  2. 编写控制E53_SC1的c++ 业务代码

    foundation\ace\ace_engine_lite\frameworks\src\core\modules\app_module.cpp中加入控制E53_SC1的c++ 业务代码("##start##"和"##end##"仅用来标识位置,添加完配置后删除这两行)。

    #include "app_module.h"
    #include "ace_log.h"
    #include "js_app_context.h"
    #ifdef FEATURE_SCREEN_ON_VISIBLE
    #include "js_async_work.h"
    #include "product_adapter.h"
    #endif
    
    ##start##
    #include "hdf_sbuf.h"
    #include "hdf_io_service_if.h"
    
    #define E53_SC1_SERVICE "hdf_e53_sc1"
    ##end##
    
    namespace OHOS {
    namespace ACELite {
    const char * const AppModule::FILE_MANIFEST = "manifest.json";
    const char * const AppModule::KEY_APP_NAME = "appName";
    const char * const AppModule::KEY_VERSION_NAME = "versionName";
    const char * const AppModule::KEY_VERSION_CODE = "versionCode";
    
    struct AsyncParams : public MemoryHeap {
        ACE_DISALLOW_COPY_AND_MOVE(AsyncParams);
        AsyncParams() : result(nullptr), callback(nullptr), context(nullptr) {}
    
        JSIValue result;
        JSIValue callback;
        JSIValue context;
    };
    #endif
    
    ##start##
    
    static int E53SC1Control(struct HdfIoService *serv, int32_t cmd, const char* buf, char **val)
    {
        int ret = HDF_FAILURE;
        struct HdfSBuf *data = HdfSBufObtainDefaultSize();
        struct HdfSBuf *reply = HdfSBufObtainDefaultSize();
    
        if (data == NULL || reply == NULL) {
            HILOG_ERROR(HILOG_MODULE_ACE,"fail to obtain sbuf data\n");
            return ret;
        }
    
        if (!HdfSbufWriteString(data, buf))
        {
            HILOG_ERROR(HILOG_MODULE_ACE,"fail to write sbuf\n");
            HdfSBufRecycle(data);
            HdfSBufRecycle(reply);
            return ret;
        }
    
        ret = serv->dispatcher->Dispatch(&serv->object, cmd, data, reply);
        if (ret != HDF_SUCCESS)
        {
            HILOG_ERROR(HILOG_MODULE_ACE,"fail to send service call\n");
            HdfSBufRecycle(data);
            HdfSBufRecycle(reply);
            return ret;
        }
    
        *val = (char *)(HdfSbufReadString(reply));
        if(val ==NULL){
            HILOG_ERROR(HILOG_MODULE_ACE,"fail to get service call reply\n");
            ret = HDF_ERR_INVALID_OBJECT;
            HdfSBufRecycle(data);
            HdfSBufRecycle(reply);
            return ret;
    
        }
    
        HILOG_ERROR(HILOG_MODULE_ACE,"Get reply is: %s\n", *val);
    
        HdfSBufRecycle(data);
        HdfSBufRecycle(reply);
        return ret;
    }
    
    JSIValue AppModule::E53SC1Service(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)
    {
        struct HdfIoService *serv = HdfIoServiceBind(E53_SC1_SERVICE);
        if (serv == NULL)
        {
            HILOG_ERROR(HILOG_MODULE_ACE,"fail to get service %s\n", E53_SC1_SERVICE);
            return JSI::CreateUndefined();
        }
    
        if ((args == nullptr) || (argsNum == 0) || (JSI::ValueIsUndefined(args[0]))) {
            return JSI::CreateUndefined();
        }
    
        JSIValue success = JSI::GetNamedProperty(args[0], CB_SUCCESS);
        JSIValue fail = JSI::GetNamedProperty(args[0], CB_FAIL);
        JSIValue complete = JSI::GetNamedProperty(args[0], CB_COMPLETE);
    
        int32_t cmd = (int32_t)JSI::GetNumberProperty(args[0], "cmd");  
        char *data = (char *)JSI::GetStringProperty(args[0], "data");
        HILOG_ERROR(HILOG_MODULE_ACE, "cmd is: %d\n", cmd);
        HILOG_ERROR(HILOG_MODULE_ACE,"data is: %s\n", data);
        char *replyData;
    
        if (E53SC1Control(serv, cmd, data, &replyData))
        {
            HILOG_ERROR(HILOG_MODULE_ACE,"fail to send event\n");
            JSI::CallFunction(fail, thisVal, nullptr, 0);
            JSI::CallFunction(complete, thisVal, nullptr, 0);
            JSI::ReleaseValueList(success, fail, complete);
            return JSI::CreateUndefined();
        }
    
        JSIValue result = JSI::CreateObject();
    
        JSI::SetStringProperty(result, "e53_sc1", replyData);
        JSIValue argv[ARGC_ONE] = {result};
        JSI::CallFunction(success, thisVal, argv, ARGC_ONE);
        JSI::CallFunction(complete, thisVal, nullptr, 0);
        JSI::ReleaseValueList(success, fail, complete, result);
    
        HdfIoServiceRecycle(serv);
    
        return JSI::CreateUndefined();
    }
    
    ##end##
    
    JSIValue AppModule::GetInfo(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)
    {
        JSIValue result = JSI::CreateUndefined();
    
        cJSON *manifest = ReadManifest();
        if (manifest == nullptr) {
            HILOG_ERROR(HILOG_MODULE_ACE, "Fail to get the content of manifest.");
            return result;
        }
    
        cJSON *appName = cJSON_GetObjectItem(manifest, KEY_APP_NAME);
        cJSON *versionName = cJSON_GetObjectItem(manifest, KEY_VERSION_NAME);
        cJSON *versionCode = cJSON_GetObjectItem(manifest, KEY_VERSION_CODE);
    
        result = JSI::CreateObject();
        if (appName != nullptr && appName->type == cJSON_String) {
            JSI::SetStringProperty(result, KEY_APP_NAME, appName->valuestring);
        }
        if (versionName != nullptr && versionName->type == cJSON_String) {
            JSI::SetStringProperty(result, KEY_VERSION_NAME, versionName->valuestring);
        }
        if (versionCode != nullptr && versionCode->type == cJSON_Number) {
            JSI::SetNumberProperty(result, KEY_VERSION_CODE, versionCode->valuedouble);
        }
        cJSON_Delete(manifest);
        manifest = nullptr;
        return result;
    }
  3. 配置HDF头文件路径

    foundation\ace\ace_engine_lite\ace_lite.gni中添加HDF头文件路径。

    ace_lite_include_dirs += [
        "//drivers/framework/ability/sbuf/include",
        "//drivers/framework/include/core",
        "//drivers/framework/include/utils",
        "//drivers/adapter/uhdf/posix/include",
    ]
  4. 添加编译依赖

    修改foundation\ace\ace_engine_lite\frameworks\BUILD.gn,在public_deps中添加以下代码

    "//drivers/adapter/uhdf/manager:hdf_core",

    修改foundation\ace\ace_engine_lite\test\ace_test_config.gni,在extra_deps中添加以下代码

    "//drivers/adapter/uhdf/manager:hdf_core",

三、运行结果

  1. 烧录:

    参考编译烧录

  2. 安装Hap应用: 参考安装HAP应用教程安装applications/BearPi/BearPi-HM_Micro/tools/hap_tools/hap_example目录下的Micro_E53.hap应用进行测试,源码请参考Micro_E53 JS 应用源码

  3. 运行结果 点击屏幕图标可以对E53_SC1进行控制。

回到文章顶部

C
1
https://gitee.com/bearpi/bearpi-hm_micro_small.git
git@gitee.com:bearpi/bearpi-hm_micro_small.git
bearpi
bearpi-hm_micro_small
BearPi-HM_Micro_small
master

搜索帮助