【FFH】北向js应用:从点亮Led到原创嵌入式小项目-鸿蒙智能水表 原创 精华

dancehole
发布于 2022-10-10 17:15
浏览
7收藏

本篇分享一个编写简单的完整鸿蒙小项目的流程。
以本文制作一个智能水表的demo为例:
你需要先学会:

  • 点亮一个Led灯(没错只需要会点灯的北向代码即可,非常简单,本文也以此为模板制作)

声明:本文编译sdk版本为api7,IDE环境 3.0.0.800(3.0Beta2),语言基于为 JSUI

成果展示

小项目全部部署在基于openharmony的小熊派上,效果如图:
【FFH】北向js应用:从点亮Led到原创嵌入式小项目-鸿蒙智能水表-鸿蒙开发者社区

图片仅供演示,系统在设备中实际运行良好

一、确定功能

确定实现功能如下:

  • 获取传感器数据(水流量传感器)并实时渲染在屏幕上
  • 可以对水阀进行控制(发送控制指令)
  • 自动(手动)上报数据,发送给服务器/上位机以供后续处理
  • 其他(如统计数据,计算费用等…)

所有功能实现的代码都将贴在文章末尾,以供编译参考

二、添加南向接口并调用

==注意:南向部分需要自己实现,本项目内容可以参考 基于 OpenHarmony 的水流量监测系统==

其本质依然是gpio操作和一些基础知识组合,会点led后就可以放心大胆的上啦~

依照物联网项目的基本架构:端管云用,我们北向也可以类比依照这四点实现功能设计(不涉及后端)

  • 端:即感知识别层,用于信息生成
  • 管:信息的传输,用于信息传输,具体为调用通信接口与上位机通信
  • 云:信息处理
  • 用:信息应用:如微信小程序设计

我们参考Led点灯的接口,在 ==@system.app.d.ts== 末尾添加如下接口声明:

static ledcontrol(options: {
    code: number;
    success?: (res: string) => void;
    fail?: (res: string, code: number) => void;
    complete?: () => void;
  }): void;

没错,就是led灯的接口连名字都不带改的,我们利用回调函数返回的对象,在res对象里添加传感器数据:值 作为data内容,发送的命令码,即为对水阀的控制开关指令

在处理页面逻辑的文件上,我们也要添加主动调用接口的方法

/*index.js*/
app.ledcontrol({
    code:led.open,
    success(res){
        //解析数据并保存
    	},
    fail(res,code){

    	},
    complete(){
    
	}
})

三、添加通信接口(可选)

如有需要可以添加网络请求接粗体口,在api7(及以前)可以用@system.fetch,aip6后推荐使用@ohos.net.http (fetch不在维护,建议弃用)

//首先要导入鸿蒙的网络请求模块
import fetch from '@system.fetch';

try{
            fetch.fetch({
                url: 'http://127.0.0.1'+'?data='+this.rate,        //填写服务器地址
                responseType: 'json',
                success: res => {
                    this.code3="已连接"
                    let data = JSON.parse(res.data); //必须要加上
                    console.log(res.data)
                }
            });
                console.log("手动上报数据")
        }
        catch(e){
            console.log(e);
            this.code3="连接失败"
        }

如果报错,尝试在配置文件config.json里修改网络权限

默认在module模块下:

"reqPermissions": [
      {
        "name": "ohos.permission.GET_NETWORK_INFO"
      },
      {
        "name": "ohos.permission.SET_NETWORK_INFO"
      },
      {
        "name": "ohos.permission.INTERNET"
      }
    ],

轻量级穿戴设备似乎不支持网络通信接口,最后弃用改为南向上传(此处代码仅供参考)

提醒:由于需要传输的是南向部分传输过来的传感器数据,所以建议也在南向部分处理数据上传,以减小时延和精度误差等

四、其他

上位机(这里以微信小程序示例)主要负责远程监控与管理,设计如下:

控制面板页面设计 统计页面设计
【FFH】北向js应用:从点亮Led到原创嵌入式小项目-鸿蒙智能水表-鸿蒙开发者社区 【FFH】北向js应用:从点亮Led到原创嵌入式小项目-鸿蒙智能水表-鸿蒙开发者社区

页面仅代表功能演示,不代表实际数据

项目源代码:

::: hljs-center

index.hml

:::

<div class="container">
    <div class="title-view">
        <div class="top-view" onclick="exit">
            <text class="back-btn"> 退出   </text>
            <text class="date"> 运行时长  0d 0h {{min}}m {{sec}} s   </text>
            <text class="deviceid"> 设备{{info}}   </text>
        </div>
    </div>

    <div class='main'>

        <div class='title_l'>
            <text class="text">
                {{ title }}
            </text>
            <text class="text">
                {{rate_L}} L
            </text>
            <text class="text_small">
                {{rate}} ml
            </text>

        </div>
        <div class='title_r'>
            <text class="text">
                运行状态
            </text>
            <text class="text_s">
                工作状态 : {{code1}}
            </text>
            <text class="text_s">
                水阀状态 : {{code2}}
            </text>
            <text class="text_s">
                上位机 : {{code3}}
            </text>
        </div>
    </div>

    <div class="ledAction" >
        <div class="ledAction-view" onclick="senddata">

            <text class="ledAction-btn">
                手动上报
            </text>
        </div>
        <div class="ledAction-view" onclick="close">

            <text class="ledAction-btn">
                关闭水阀
            </text>
        </div>
        <div class="ledAction-view" onclick="openDoor">

            <text class="ledAction-btn">
                开阀计水
            </text>
        </div>
    </div>
</div>

::: hljs-center

index.css

:::


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

}

swiper{
    height: 60%;
    width: 100%;
    background-color: greenyellow;
}

.main{
    margin: 10px;
    width: 100%;
    height: 60%;
    flex-direction:row;
    align-items: center;
    /*background-color: cadetblue;*/
}

.title_l {
    width: 50%;
    height: 280px;
    font-size: 40px;
    text-align: center;
    flex-direction: column;

}
.title_r {
    margin-top: 10px;
    width: 40%;
    height: 240px;
    font-size: 40px;
    text-align: center;
    background-color: black;
    border-radius: 50px;
    flex-direction: column;
    opacity: 0.9;
    border-color: white;
    border-width: 2px;
    padding: 10px;
    margin: 10px;
}

.text{
    font-size: 40px;
    text-align: center;
    width: 100%;
    height: 35%;
}

.text_small{
    font-size: 33px;
    text-align: center;
    width: 100%;
    height: 20%;
}


.text_s{
    font-size: 30px;
    left: 12px;
    width: 100%;
    margin-left:10px ;
}

.ledImg{
    width: 200px;
    height: 150px;
    margin-top: 10px;
    font-size: 40px;
}

.ledAction{
    height: 50px;
    width: 100%;
    flex-direction: row;
    justify-content: space-around;
    align-items: center;

}

.ledAction-view{
    width: 120px;
    height: 50px;
    flex-direction: column;
    justify-content: center;
    align-items: center;
}

.ledAction-img{
    width: 60px;
    height: 60px;
}

.ledAction-btn{
    width: 120px;
    margin-top: 10px;
    font-size: 30px;
    text-align: center;
}

.title-view{
    width: 100%;
    height: 60px;
    margin: 1px;
    flex-direction: column;
    display: flex;
    background-color: midnightblue;
}
.title{
    width: 100%;
    height: 300px;
    margin: 1px;
    flex-direction: row;
    display: flex;
    background-color: darkblue;
}

.top-view{
    height: 60px;
    width: 100%;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    display: flex;
    text-align: center;
}
.back-img{
    height: 30px;
    width: 30px;
    margin-left: 10px;
}

.back-btn{
    font-size: 30px;
    width: 25%;
    padding: 20px;
}

.date{
    font-size: 30px;
    width: 50%;
}
.deviceid{
    font-size: 30px;
    width: 20%;
}

::: hljs-center

index.js

:::


var led = {open:1,close:0,change:2}
import app from '@system.app';
import router from "@system.router";



export default {
    data: {
        title: '当日累计:',
        statu:'0',
        rate: 0,
        rate_L:0,

        sec:0,
        min:0,

        info:"正常",
        tmp_rate:-1,
        curr_rate:0,
        code1:0,
        code2:"关闭",
        code3:"未连接",

        timer:0,
        time:0,

    },

    onInit(){           //初始化
        //this.openDoor()
        this.startTimer()
        this.info="初始化.."
    },

    exit(e){
        console.log("terminate!")
        app.terminate()
    },



    startTimer()  {
         this.time= setInterval(()=>{
             //this.getRate()
             this.runtime()
         },1000);
     },

    runtime(){
        this.sec++
        if(this.sec===60){
            this.sec=0
            this.min++
        }
    },

    getRate(){

        let that=this
            try{
                //that.rate++
                app.ledcontrol({
                    code:led.open,
                    success(res){
                        //console.log("data show1")
                        that.tmp_rate=that.rate
                        that.rate =  (Number(JSON.stringify(res.led_status)))
                        that.curr_rate=that.rate-that.tmp_rate
                        that.code1=that.curr_rate
                    },
                    fail(res,code){
                        console.log("get fail")
                    },
                    complete(){

                    }
                })

            }catch(e){
                console.log(err)
                this.device_id="err"
            }

    },



    openDoor(e){
        console.log("open")
        this.info="运行中"
        this.code2="开启"
        //function
        function closeapp()
        {
            console.log("close")
            //clearInterval(timer);
            //数据归0
        }

        const ShowRate = ()=>
        {
            this.time++
            this.device_id++;
            //console.log(this.time)
            //if(this.time===300)closeapp()
            let that=this

            app.ledcontrol({
                code:led.open,
                success(res){
                    //console.log("data show1")
                    that.rate =  (Number(JSON.stringify(res.led_status)))
                },
                fail(res,code){

                },
                complete(){

                }
            })

        }
        this.rate=-1;

        try{
            this.timer= setInterval(function(){ShowRate()},100);
        }catch(e){
            console.error("err"+e)
            this.info="计时器故障"
        }

        /*这里有一个关于类里This的指向问题,这里使用匿名函数处理 ()=>{}
        不可以使用function(),因为由于类特性,在function里的this指向change_per_second的rate变量,而无法访问到default类的rate变量
        但是匿名函数里this会逐层上找

        */
    },


    close(e){

        console.log("close timer")
        this.info="关闭"
        this.code2="关闭"
        try{
            clearInterval(this.timer)
        }catch{
            this.info="故障"
        }

        //this.rate =0;
        let that = this

        app.ledcontrol({            //关闭水阀命令
            code:led.close,
            success(res){
                that.statu = res.led_status
            },
            fail(res,code){

            },
            complete(){

            }
        })
    },

    datalist(){

    },

    senddata(){
        try{
            fetch.fetch({
                url: 'http://127.0.0.1'+'?data='+this.rate,        //填写服务器地址
                responseType: 'json',
                success: res => {
                    this.code3="已连接"
                    let data = JSON.parse(res.data); //必须要加上
                    console.log(res.data)
                }
            });
                console.log("手动上报数据")
        }
        catch(e){
            console.log(e);
            this.code3="连接失败"
        }
    },

}


::: hljs-center

:::

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
dancehole-project.zip 1001.8K 28次下载
已于2022-10-10 17:15:08修改
11
收藏 7
回复
举报
7条回复
按时间正序
/
按时间倒序
红叶亦知秋
红叶亦知秋

实现智能家居的一小步

回复
2022-10-10 17:29:49
物联风景
物联风景

不错不错,学有所成了

1
回复
2022-10-11 10:25:44
liurick
liurick

打通南北不错的项目

回复
2022-10-11 17:57:37
带带小老弟
带带小老弟

节约用水是需要一直做下去的事业

回复
2022-10-12 10:42:28
喝一大口可乐
喝一大口可乐

从点灯开始 —> 学会亿点知识 —> 成为大佬

回复
2022-10-12 15:33:23
冰淇淋爱我
冰淇淋爱我

设计开关水阀的目的是啥呢?

回复
2022-10-14 14:56:10
dancehole
dancehole 回复了 冰淇淋爱我
设计开关水阀的目的是啥呢?

问的很好,这属于一开始画的大饼(bushi)但是没完全实现的内容:水阀可以做到精准控水,和远程控水两个功能;

对应实际生活中,水表可以检测某水龙头/水管漏水的情况,然后自动/远程关闭。

另外就是在储水时可以不必等待,比如我习惯打水的时候顺便上个洗手间,但又怕水打满溢出了,有了这个我可以控制“装五百毫升”就关水 这一操作,

1
回复
2022-10-16 09:38:34
回复
    相关推荐