Kara 发表于 2019-5-16 16:06:45

机友分享 | 巧用机智云IoT云服务自动代码生成功能,实现ES...

机友分享 | 巧用机智云IoT云服务自动代码生成功能,实现ESP8266版智能定时插座
[ 本文概述]本案例是机智云IoT云服务的资深用户半颗心脏原创,主要讲述了如何巧用机智云IoT云服务的自动代码生成功能,快速实现硬件和软件APP开发,实现智能定时插座开发设计。
此外,作者还曾录制了《27个免费视频教学安卓APP开发》,以及发表《连载六部曲:机智云Android开源之旅》、《SoC方案实现定时开发》等博客,来帮助嵌入式爱好者从0 开始学会IoT云服务开发。
以下为分享原文:[ 一、前言]在写这篇博文前,我希望这机智云IoT云服务专题的笔记可以帮助更多入门物联网智能家居的小伙伴,我是2016年广东省电子设计大赛开始接触机智云的产品的,一路上也算是看到了他们的迅速发展。所以,记下一些笔记来分享下怎么接入这个强大的、免费提供服务器的物联网开发平台给大家介绍。共勉!!!
在当年还在大三的时候,嵌入式这种互联互通的在市面上还不是很常见的,直到阿里智能、百度dueros、京东微联和小米出来这个AI人工智能平台之后,整个物联网智能家居生态才真正地火热起来。我也是接入了好几个IoT云服务平台,感觉还是蛮好玩的;不得不说,是机智云IoT云服务这个平台开始带我走进物联网世界,阅读机智云IoT云服务的文档和相关物联网专有名词,不得不说,大学学的东西真少!至此,我准备建立一个新的博文篇,专门介绍接入机智云IoT云服务开发平台的方方面面,相信你一定会爱上她的。哈哈~
[ 二、机智云IoT云服务与其他平台有什么不同]我也是一个热爱学习的人,每天都要搞些新知识充电或者重温下旧知识写博文;在我接触许多的物联网平台,其共同的特点都是有免费提供设备的云服务的,像乐鑫云、安信可云、百度云、阿里物理套件和最近的开发快平台,尽管不完善某些功能。但是和设备通讯还是极速的,因为毕竟都几乎是MQTT协议。至于机智云IoT云服务为何会有一些与众不同呢?下面是我总结的几点:
[*] 自动生成代码,包括我们的常见的stm32主流系列,esp8266固件源代码;而且还有我们上位机的Android和ios源代码,以及跨平台的APICloud SDK;
[*] 机智云IoT云服务的开发者社区有很多的一些demo可以借鉴,经典的微信宠物屋,rgb七彩灯都是远程控制的;这些我后面都会详细为大家怎么实现;
[*] 说到认证和荣誉,每天在微信公众号可以看到官微在推文章,而且很出名的正点原子推出的stm32开发板也是在和机智云合作。
[*] 如果你是一名Android开发人员,不了解嵌入式开发的过程,你可以学习机智云提供的上位机的SDK参考,之后你就可以很轻松面对其他的设备SDK;而且可以自己琢磨下机智云的自动生成代码的源码,渗透下整个app的运作流程。
[*] 如果你是一名设备端开发人员,但是对设备接入服务器不熟悉,你可以去看下自动生成的esp8266的源代码,看下人家怎么写出标准的、高可行的代码;说白了,就是要学习人家的架构思想,编程逻辑;
[*] 这点没有什么好说的 ,在现在的资料开源的时代,我们可以借助一切,把自己的能力提升,而机智云IoT云服务免费开源的这些代码,就是对自己的职业发展的助力石。
[*]

[ 三、在机智云平台创建产品并自动生成代码]
[*]先看看整体效果:
[*]
[*][ 3.1 创建产品]第一步:创建产品;
在任何一个服务器上面,要想开发一个设备,那必须要先在服务器注册一个设备,访问机智云的开发者中心点我访问,和其他的厂家一样,都是需要创建数据点和数据点类型。本篇文章主要讲的是一个定时的智能插座(说白了就是单路继电器),所以只需要注册以下几个数据点即可:
注意数据点是一个产品的属性,当我们要控制设备或查询设备,都是通过数据点来操作的;
[*]
[*]
[*]

[*][ 3.2 自动生成代码]我觉得,自动生成代码是最舒服的,因为不用自己搭建框架;也不用管数据怎么发送和接受,只需要在下发和上发的函数做自己的处理即可:看到服务—–>MCU开发,我们选择soc方案,选择esp8266_32M,因为我们Gokit3拓展板用的是esp8266-12f模块,注意下面那个product key是从上面的基本信息复制下来的。
[*]
[*]
[*][ 3.3 修改硬件代码]
在机智云的Gokit3的拓展板上面,引出的脚有限;我仔细看看,只有一个脚是引出来了,是GPIO0,那我就准备用它自带的按键2来实现配网,而连接继电器那个是GPIO0,通过拓展版的原理图可以看到,按键二是连接到GPIO14的,所以,简化后的原理图就是这样的:
[*]


①:增加GPIO口的驱动;上面的图可以看到,我们继电器的是GPIO0,毫不疑问,我们首先初始化这个端脚:
[*]    //初始化GPIO
[*]    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0);
[*]    GPIO_OUTPUT_SET(GPIO_ID_PIN(0), 0);

②:机智云自动生成的代码是针对开发板Gokit3的,所以我们不需要增加按键驱动代码,我们上面看到是GPIO014作为按键,毫不疑问,我们只需要初始化这个端脚即可:注意我们进入一键配网的时候,要做出对应的状态,长按按键2,我这里做出的状态是继电器开关2次,表示成功进到一键配网的状态;
[*]//仅仅定义 gpio14 按键中断
[*]#define GPIO_KEY_NUM                            1                        
[*]#define KEY_0_IO_MUX                            PERIPHS_IO_MUX_MTMS_U   
[*]#define KEY_0_IO_NUM                            14                        
[*]#define KEY_0_IO_FUNC                           FUNC_GPIO14               
[*]LOCAL key_typedef_t * singleKey;                           
[*]LOCAL keys_typedef_t keys;                                                

在我们的长按触发事件方法如下处理:
[*]LOCAL void ICACHE_FLASH_ATTR keyLongPress(void)
[*]{
[*]    GIZWITS_LOG("#### key2 long press, airlink mode\n");
[*]    //进入一键配网
[*]    gizwitsSetMode(WIFI_AIRLINK_MODE);
[*]    GPIO_OUTPUT_SET(GPIO_ID_PIN(0), 0);
[*]    os_delay_us(100000);
[*]    //开关2次
[*]    GPIO_OUTPUT_SET(GPIO_ID_PIN(0), 1);
[*]    os_delay_us(100000);
[*]    GPIO_OUTPUT_SET(GPIO_ID_PIN(0), 0);
[*]    os_delay_us(100000);
[*]    GPIO_OUTPUT_SET(GPIO_ID_PIN(0), 1);
[*]    os_delay_us(100000);
[*]    GPIO_OUTPUT_SET(GPIO_ID_PIN(0), 0);
[*]}

我们希望短按也可以开关继电器,so,在我们的短按触发事件方法如下处理:
[*]LOCAL void ICACHE_FLASH_ATTR keyShortPress(void) {
[*]

[*]    if (isOpen) {
[*]      isOpen = false;
[*]      GPIO_OUTPUT_SET(GPIO_ID_PIN(0), 0); //关继电器
[*]    } else {
[*]      isOpen = true;
[*]      GPIO_OUTPUT_SET(GPIO_ID_PIN(0), 1);//开继电器
[*]    }
[*]}

③:我们现在注意力转移到这来gizwits_product.c文件,里面的gizwitsEventProcess()方法是我们处理收到手机指令处理,对比下我们的 数据点就明白了!

[*]    //开关指令
[*]    case EVENT_lightOnOff:
[*]            currentDataPoint.valuelightOnOff = dataPointPtr->valuelightOnOff;
[*]            GIZWITS_LOG("Evt: EVENT_lightOnOff %d \n", currentDataPoint.valuelightOnOff)
[*]            ;
[*]            if (0x01 == currentDataPoint.valuelightOnOff) {
[*]                //user handle
[*]                GPIO_OUTPUT_SET(GPIO_ID_PIN(0), 0);
[*]            } else {
[*]                //user handle
[*]                GPIO_OUTPUT_SET(GPIO_ID_PIN(0), 1);
[*]            }
[*]            break;
[*]   //定时器使能指令
[*]      case EVENT_isTimerOpen:
[*]            currentDataPoint.valueisTimerOpen = dataPointPtr->valueisTimerOpen;
[*]            GIZWITS_LOG("Evt: EVENT_isTimerOpen %d \n", currentDataPoint.valueisTimerOpen)
[*]            ;
[*]            if (0x01 == currentDataPoint.valueisTimerOpen) {
[*]                //user handle
[*]                //if current is not at timer
[*]                if (currentDataPoint.valuetimerOpen == 0
[*]                        || currentDataPoint.valuetimerOpen < 0)
[*]                  currentDataPoint.valueisTimerOpen=false;
[*]                  os_timer_disarm(&os_timer);
[*]

[*]            } else {
[*]

[*]                os_timer_disarm(&os_timer);
[*]                currentDataPoint.valuetimerOpen = 0;
[*]            }
[*]

[*]            break;
[*] //定时时间下发;注意此刻上报要把定时器使能开启置位1
[*]      case EVENT_timerOpen:
[*]            currentDataPoint.valuetimerOpen = dataPointPtr->valuetimerOpen;
[*]            GIZWITS_LOG("Evt:EVENT_timerOpen %d\n",currentDataPoint.valuetimerOpen)
[*]            ;
[*]            //add
[*]            currentDataPoint.valueisTimerOpen = true;//把定时器使能开启置位1
[*]            os_timer_disarm(&os_timer);
[*]            os_timer_setfn(&os_timer, (ETSTimerFunc *) (Led_Task_Run),
[*]            NULL);
[*]            os_timer_arm(&os_timer, 2000, true);//开启定时器,计数开始,反复测试只有2000才是接近一秒
[*]            break;

④、看看我们的定时器执行的任务,我们这里利用定时器每秒自动重载,达到我们APP下发的计数之后,执行开灯指令;
[*] void Led_Task_Run() {
[*]    GIZWITS_LOG("Led_Task_Run...\r\n");
[*]    GIZWITS_LOG("Led_Task_Run:%d\r\n",currentDataPoint.valuetimerOpen);
[*]

[*]    if (0x01 == currentDataPoint.valueisTimerOpen) {
[*]      //启动定时器
[*]      mCountTimes--;
[*]      currentDataPoint.valuetimerOpen = mCountTimes / 60;
[*]      if (currentDataPoint.valuetimerOpen == 0) {
[*]            currentDataPoint.valuetimerOpen = 0;
[*]            currentDataPoint.valueisTimerOpen = false;
[*]            currentDataPoint.valuelightOnOff = false;
[*]            //计数达到目标,继电器吸合
[*]            GPIO_OUTPUT_SET(GPIO_ID_PIN(0), 1);
[*]            os_timer_arm(&os_timer, 2000, true);
[*]      }
[*]    } else {
[*]      currentDataPoint.valuetimerOpen = 0;
[*]      currentDataPoint.valueisTimerOpen = false;
[*]      os_timer_arm(&os_timer, 2000, true);
[*]    }
[*]}

⑤:修改makeFile文件:因为自动生成的代码是没有OTA的地址烧录的,那么我们修改下即可:
[*]BOOT?=new
[*]APP?=1
[*]SPI_SPEED?=40
[*]SPI_MODE?=QIO
[*]SPI_SIZE_MAP?=6

⑥:修改gizwits_protocol.c文件的宏定义:修改定时上报的间隔时间:
[*]#define USER_TIME_MS 5000   
https://mmbiz.qpic.cn/mmbiz_png/uTN1Mhj0TqM0L7mdZdSJKAMdzLJW3bLxgdCXzjhvxIQMVhqj0u5wSef035Q7boYuibkoC8hvY2VRtgmCeibUTjfw/640?wx_fmt=png[ 四、修改Android代码]因为安卓代码是直接生成的,所以我们只需要修改下控制界面的UI即可;如下:需要注意的是,自动生成的代码下发定时时间时候,是可以看到具体时间的,毕竟拖动条嘛!这里的话,我准备用一个弹窗,然后用户选择确定时候,自动计算时间差下发给设备。具体的时间差算法如下:

[*]    /**
[*]   * 返回一个将要的时间,单位是s
[*]   *
[*]   * @param temptimers 开始工作的时间四位数 格式 1025 表示 10:25
[*]   * @return 将在这个时间之后启动
[*]   */
[*]    public static int creatTimers(String temptimers) {
[*]

[*]      int returnTimers = 0;
[*]      int times = Integer.parseInt(temptimers);
[*]      Calendar mCalendar = Calendar.getInstance();
[*]      //把当前时间转为 1234格式
[*]      int NowTimes = mCalendar.get(Calendar.HOUR_OF_DAY) * 100 + mCalendar.get(Calendar.MINUTE);
[*]      //如果设置定时的时间大于现在的时间 比如 当前是 10:23,设置的时间是 12:35
[*]      if (NowTimes >= times) {
[*]            returnTimers = 24 * 3600 - (creatMinute(NowTimes) - creatMinute(times));
[*]      } else {
[*]            returnTimers = (creatMinute(times) - creatMinute(NowTimes));
[*]      }
[*]      return returnTimers;
[*]    }
[*]

[*]    /**
[*]   * @param afterTimes 多少分钟之后的时间点;范围无限
[*]   * @return 15:25 表示15点25分
[*]   */
[*]    public static String creatAfterTime(int afterTimes) {
[*]

[*]      String value = null;
[*]      //先确定传来的数值有多少个小时,多少分钟
[*]      int hour = afterTimes / 60;
[*]      int minute = afterTimes % 60;
[*]

[*]      Calendar mCalendar = Calendar.getInstance();
[*]      //把当前时间转为 1234格式
[*]      int NowHour = mCalendar.get(Calendar.HOUR_OF_DAY);
[*]      int NowMinute = mCalendar.get(Calendar.MINUTE);
[*]

[*]      if (NowHour + hour > 23)
[*]            NowHour -= 24;
[*]

[*]      if ((minute + NowMinute) > 0)
[*]            value = (NowHour + hour) + ":" + (minute + NowMinute);
[*]      else
[*]            value = (NowHour + hour) + ":0" + (minute + NowMinute);
[*]

[*]      return value;
[*]    }
[*]

[*]

[*]    private static int creatMinute(int timers) {
[*]

[*]      int[] value = new int;
[*]      value = timers % 10000 % 1000 % 100 % 10; //个位
[*]      value = timers / 10 % 1000 % 100 % 10;//十位
[*]      value = timers / 100 % 100 % 10;//百位
[*]      value = timers / 1000 % 10;//千位
[*]      return value * 60 + value * 600 + value * 3600 + value * 10 * 3600;
[*]

[*]    }

[ 五、下载]esp8266硬件代码+Android上位机源代码下载https://download.csdn.net/download/xh870189248/10553157
机智云IoT云服务专题的免费所有资料,持续更新,欢迎starhttps://github.com/xuhongv/Gokit3-Resource相关推荐:
[*]27个免费视频教你学安卓APP开发
[*]连载六部曲:机智云Android开源之旅
[*]Android自定义View系列(时间轴、桌面空间、刮刮乐)

                                                                   扫一扫,开启您的IoT云服务开发之旅


文章由 IoT云服务开发平台 机智云 www.gizwits.com 整理发布

页: [1]
查看完整版本: 机友分享 | 巧用机智云IoT云服务自动代码生成功能,实现ES...