#夏日挑战赛# 开发一个折叠屏micro的智能风扇案例 原创 精华

发布于 2022-7-29 17:10
浏览
4收藏

本文正在参加星光计划3.0–夏日挑战赛

一.前言

自从去年12月底无意中得知小熊派发布了一款折叠屏开发板,就一直心心念念的想要弄一块玩玩,当然花钱买是不能买的,就等着哪天意外能得到,这次意外终于来了,开发板顺利到手,因为一直在智能家居物联网行业,肯定先做一个物联网的智能家居小案例出来啦.
先爆美照:
#夏日挑战赛# 开发一个折叠屏micro的智能风扇案例-开源基础软件社区

二.开发环境搭建和代码获取

因为我也算"老鸿蒙"了,自己亲手和不亲手搭建的环境有一百多份了,搭建环境这肯定难不到我了,然后就是代码拉取了,跑到小熊派官方仓库去:https://gitee.com/bearpi/bearpi-hm_micro_small
先fork到自己仓库来,然后克隆下载一气呵成,美滋滋.

三.驱动编写

驱动这块就是用的官方的E53案例的驱动,使用的是IA1智慧农业,唯一不同的是我这边风扇不是直接GPIO驱动的,而是采用PWM驱动,具体请看代码:

int E53_IA1_Init(void)
{
    E53_GPIOInit(E53_IA1_LIGHT_GPIO,E53_GPIO_Out_PullNone);
    #if (defined MOTOR_WITH_PWM )&& (MOTOR_WITH_PWM==1)
        E53_PWMOpen(3);
        E53_PWMSetPeriod(4000);
        E53_PWMSetPolarity(0);
        // E53_PWMSetDuty(1);
        // E53_PWMStart();
    #else
    E53_GPIOInit(E53_IA1_MOTOR_GPIO,E53_GPIO_Out_PullNone);
    #endif
    E53_IICOpen();
    
    int ret0, ret1;
	ret0 = Init_BH1750();
    ret1 = Init_SHT30();
    OsalMDelay(180);
    return ret0 | ret1;
}

int E53_IA1_SetFanLevel(int level)
{
    int ret = -1;
#if (defined MOTOR_WITH_PWM )&& (MOTOR_WITH_PWM==1)
    if(level == 0){
        ret = E53_PWMStop();
    }else{

        if(level >5){
            level = 5;
        }
        E53_PWMSetDuty( (level*20)*MOTOR_DEFAULT_PERIOD/100 - 1);

        ret = E53_PWMStart();
    }
#else
    ret = E53_GPIOWrite(E53_IA1_LIGHT_GPIO,level? 1:0);

#endif

    return ret;
}

这里采用PWM通道3来达到控制风扇的目的,至于为什么是通道3,那个pwm的hcs文件里面写了呀(由原理图可知,风扇就在PA6):
#夏日挑战赛# 开发一个折叠屏micro的智能风扇案例-开源基础软件社区
还有一点需要注意的:这里的E53_PWMSetDuty()接口传入的并不是常见的百分比,而是一个实际的数字,如果我们需要按百分比调节马达的转速,需要自己去进行转化.

四.界面编写

界面这里用DevcoStudio3Beta4编写,首先要去官网下载工具,然后再创建工程,注意创建工程的时候选择(Lite)Empty Ablility,如下图:
#夏日挑战赛# 开发一个折叠屏micro的智能风扇案例-开源基础软件社区
然后是相关参数的填写,注意设备类型选SmartVision智慧屏:
#夏日挑战赛# 开发一个折叠屏micro的智能风扇案例-开源基础软件社区
然后就进入工程界面了,等待一会等系统配置好工程之后,打开右边的模拟器,添加一个新设备或者修改设备的分辨率为800*480,如下图:
#夏日挑战赛# 开发一个折叠屏micro的智能风扇案例-开源基础软件社区
做好这些事情之后就可以安心的编写界面了,值得一提的是,API6还有好多东西不支持,比如button组建,竟然没有,比如图片的缩放属性:object-fit就没有 用图片的时候就相当难受了,只能忍一忍吧,还能怎么办,期待早点做好.
#夏日挑战赛# 开发一个折叠屏micro的智能风扇案例-开源基础软件社区
#夏日挑战赛# 开发一个折叠屏micro的智能风扇案例-开源基础软件社区
值得一提的是,咱们OpenHarmony的北向编程是有专门的教程网址的,大家可别迷路了:
https://docs.openharmony.cn/pages/v3.1/zh-cn/application-dev/application-dev-guide.md/
#夏日挑战赛# 开发一个折叠屏micro的智能风扇案例-开源基础软件社区
下面是我的拙作及相关代码:
模拟器界面:
#夏日挑战赛# 开发一个折叠屏micro的智能风扇案例-开源基础软件社区
实际界面会有点不同:
#夏日挑战赛# 开发一个折叠屏micro的智能风扇案例-开源基础软件社区
相关hml代码:

<div class="container">
    <div class="title-view">
        <text class="btn_exit" onclick="onExit">
            {{textExit}}
        </text>
        <text  onclick="onSetting">
            设置
        </text>

    </div>
    <text class="title">
        {{ title }}
    </text>

    <image class="img" src="/common/head.png">    </image>
    <text >当前风速:{{currentLevel}}</text>
    <slider class="fan-level"  min="0" max="5" value="0" step="1" mode="inset" showtips="true" onchange="setLevel"></slider>
    <div class="led-div">

        <text >LED灯</text>
        <switch class="led-switch" showtext="true" texton="open" textoff="close" checked="true" @change="switchChange"></switch>
    </div>


</div>

css代码:

.container {
    width: 100%;
    height: 100%;
    justify-content: flex-start;
    align-items: center;
    flex-direction: column;
}

.title {
    width: 100%;
    font-size: 30px;
    justify-content: center;
    text-align: center;
/*    align-items: center;*/
/*    flex-direction: row;*/

}

.img{
    width:120px;
    height: 120px;
    justify-content: center;
    object-fit: cover;


}

.led-div{
    flex-direction: row;
    width:100%;
    height: 50;

    justify-content: space-around;
}

.title-view{
    width:100%;
    height: 50;
    flex-direction: row;
    justify-content: space-between;
}

.fan-level{
    flex-direction: row;
    scrollbar-color: aqua;
    background-color: #b7e3f3;
    width:400;
    height: 50;

}

.btn_exit{
    font-size: 30fp;
    background-color: red;
    align-items: center;
/*    width:60;*/
/*    height: 30;*/
}

.led-switch{
    width: 50;
    height: 50;

}

.prg{
    width:100px;
    height: 100px;
    justify-content: center;
/*    object-fit: contain;*/


}

然后是js代码:

import app from "@system.app"

export default {
    data: {
        textExit:"<退出",
        title: "物联风景-智能风扇",
        currentLevel:0,
    },
    onInit() {

    },

    onExit() {
        console.log("on exit")
        app.terminate()
    },
    setLevel(e){

        this.currentLevel = e.value;

        console.debug("fan level " +e.value+" send success")

        app.fan_level({
            level:e.value,
            success:(res) =>{
                console.log("fan level send success:"+res)
            } ,
            fail:(res,code) =>{
                console.log("fan level send failed:"+res+",code:"+code)
            } ,
            complete:() =>{
                console.log("fan level complete")
            } ,
        })

    },

    switchChange(e){
        if(e.checked){

            console.debug("打开灯")
        }else{

            console.debug("关闭灯")
        }

        app.set_led({
            onOff:e.checked ? 1 : 0 ,
            success:(res) =>{
                console.debug("set_led send success:"+res)
            } ,
            fail:(res,code) =>{
                console.debug("set_led send failed:"+res+",code:"+code)
            } ,
            complete:() =>{
                console.debug("set_led complete")
            } ,

        })
    },
}

五.JSI接口添加

在liteOS-a内核上,想要用UI控制硬件,就必须制作JSI接口,这个在小熊派官方文档里面也有介绍,制作JSI接口之前必须保证命令行方式绑定服务和驱动都OK,这里给出小熊派的官方文档吧:
https://gitee.com/bearpi/bearpi-hm_micro_small/blob/master/applications/BearPi/BearPi-HM_Micro/docs/device-dev/通过JS应用控制LED灯.md
然后是北向编程的文档地址:
https://gitee.com/bearpi/bearpi-hm_micro_app/blob/master/docs/led控制案例.md
有的这些地址,你也能通过漂亮的UI界面来控制硬件了.
下面的我的代码示例:

JSIValue AppModule::FanLevel(const JSIValue thisVal, const JSIValue* args, uint8_t argsNum)
{
    HILOG_INFO(HILOG_MODULE_ACE, "==> FanLevel\n");
    struct HdfIoService *serv = HdfIoServiceBind(E53_IA1_SERVICE);
    if (serv == NULL)
    {
        HILOG_ERROR(HILOG_MODULE_ACE,"fail to get service %s\n", E53_IA1_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);

    int cmd = E53_IA1_FanLevel;
    // int32_t cmd = (int32_t)JSI::GetNumberProperty(args[0], "cmd");  
    int level= (int)JSI::GetNumberProperty(args[0], "level");
    char data =level+'0';
    HILOG_ERROR(HILOG_MODULE_ACE, "cmd is: %d\n", cmd);
    HILOG_ERROR(HILOG_MODULE_ACE,"level is: %d\n", level);
    HILOG_ERROR(HILOG_MODULE_ACE,"data is: %c\n", data);
    char *replyData;

    if (E53IA1Control(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, "fan level", 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();
}

JSIValue AppModule::SetLed(const JSIValue thisVal, const JSIValue* args, uint8_t argsNum)
{
    HILOG_INFO(HILOG_MODULE_ACE, "==> SetLed\n");
    struct HdfIoService *serv = HdfIoServiceBind(E53_IA1_SERVICE);
    if (serv == NULL)
    {
        HILOG_ERROR(HILOG_MODULE_ACE,"fail to get service %s\n", E53_IA1_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);

   int cmd = E53_IA1_SetLight;
    // int32_t cmd = (int32_t)JSI::GetNumberProperty(args[0], "cmd");  
    int onOff= (int)JSI::GetNumberProperty(args[0], "onOff");
    const char *data = onOff ? "ON" : "OFF";
    HILOG_ERROR(HILOG_MODULE_ACE, "cmd is: %d\n", cmd);
    HILOG_ERROR(HILOG_MODULE_ACE,"data is: %s\n", data);
    char *replyData;

    if (E53IA1Control(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, "set led", 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();
}

六.安装Hap包

安装Hap包首先需要编译然后导出hap包,在编译出的hap包上右键选择在文件管理器打开:
#夏日挑战赛# 开发一个折叠屏micro的智能风扇案例-开源基础软件社区
#夏日挑战赛# 开发一个折叠屏micro的智能风扇案例-开源基础软件社区
然后需要准备一张SD卡和读卡器,按照小熊派官方的教程很轻松就能做到.
文档地址:https://gitee.com/bearpi/bearpi-hm_micro_small/blob/master/applications/BearPi/BearPi-HM_Micro/docs/device-dev/如何在开发板上安装HAP应用.md
实际过程如图所示:
#夏日挑战赛# 开发一个折叠屏micro的智能风扇案例-开源基础软件社区

七.作品展示

到这一步就算完成作品了,请看视频效果:
https://ost.51cto.com/show/15314

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2022-7-29 21:45:46修改
7
收藏 4
回复
举报
回复
添加资源
添加资源将有机会获得更多曝光,你也可以直接关联已上传资源 去关联
    相关推荐