发 帖  
[讨论] 小e开发平台源代码说明
2016-1-8 12:02:32  3308 源代码
分享
小e开发平台是首款微信语音控制开发板,集成软+硬+云+APP全套解决方案,帮助工程师将产品开发周期从半年降至一个月源码。

小e智能硬件开源开发平台(开源资料下载地址)
http://bbs.elecfans.com/jishu_536930_1_1.html

小e智能硬件开源开发平台众筹地址:http://z.elecfans.com/3?bbswz

目录如下:
   图片1.png

目录说明:
bin   编译固件生成目录、boot、配置参数bin文件所在
et_app 用户应用程序所在目录
extra_include  一些第三方库头文件目录
include 系统相关头文件所在目录
ld 连接器相关一些东西
lib 系统相关一些库(如LWIP之类的)
third_party 第三方源码库和相关源代码(如操作系统,JOSN
tools 编译过程中一些工具
Makefile  编译的Makefile文件
LICENSE、 README.md 都是一些说明文本文件


et_app 是应用程序的主目录,下面就这目录进行下一步说明
图片2.png
.output 编译过程中一些早间文件
driver 驱动相应源代码目录
include 头文件所在目录
sample_lib 示例库文件所在目录(没有使用)
user 用户应用程序所在目录
gen_misc.bat  编译整个工程源码脚本
gen_misc.sh  编译整个工程源友脚本(linux  使用)
makefile  Makefile文件
readme.txt 说明文件

user 目录是应用程序所在目录,下面进一步说明
图片3.png

user_main.c 应用程序入口函数所在文件
et_user_app.c 主应用程序所在
factory.c 工厂测试代码所在,可以不关注
wifi_led.c wifi LED灯控制程序所在
Makefile  makefile 管理文件

特别说明一下,如果开发者要新增加文件,可以直接在这个目录下面增加.c 文件,把.h文件放在和级目录的inlcude目录下面,就可以了。

下面分析对于主要文件的函数进行一下说明,让大家了解整个源码实现过程:

user_main.c  中的 user_init 这是整个应用程序的入口函数,程序先进入这里执行:
  1. void user_init(void)

  2. {        

  3. key_gpio_t key;

  4. struct station_config config;

  5. struct ip_info info;

  6. et_uchar result=0;

  7.     os_printf("now SDK version:%s\n", system_get_sdk_version());



  8. if(get_fac_norm_mode(&result) != SPI_FLASH_RESULT_OK)

  9. {

  10. os_printf("get_fac_norm_mode error, NORMAL mode\n");

  11. }

  12. if(result == FAC_MODE)

  13. {

  14. os_printf("run in factory mode\n");

  15. uart_init_new_uart1(BIT_RATE_115200);

  16. UART_SetPrintPort(UART1);

  17. uart_init_new(BIT_RATE_9600, result);

  18. return;

  19. }



  20. os_printf("run in normal mode\n");

  21. // show logo

  22. user_show_logo();



  23. if (RETURN_OK != user_get_work_mode(&work_mode))

  24. {

  25. os_printf("get work mode fail !!!\n");

  26. return;

  27. }



  28. if (RETURN_OK != user_init_work_mode(work_mode, result))

  29. {

  30. os_printf("init work mode fail !!!\n");

  31. return;

  32. }

  33. // wifi led control

  34. xTaskCreate(user_wifi_led_control, "wifi_led_control", 256, NULL, 2, NULL);

  35. //wifi event handle

  36. wifi_set_event_handler_cb(et_wifi_event_cb);

  37. memset(&key, 0, sizeof(key_gpio_t));

  38. key.key_gpio_pin = AIRKISS_KEY_IO_PIN;

  39. key.key_num = AIRKISS_KEY_IO_NUM;



  40. airkiss_key_init(&key);

  41. wifi_set_opmode(STATION_MODE);



  42. wifi_reconnect_start_flag = 0;



  43. xTaskCreate(airkiss_key_poll_task, "smartconfig_task", 256, NULL, 2, NULL);



  44. memset(&config, 0, sizeof(struct station_config));

  45. if(wifi_station_get_config_default(&config) == true)

  46. {

  47. os_printf("ssid=%s\n", config.ssid);

  48. wifi_station_set_config_current(&config);

  49. //for static ip set

  50. /*wifi_station_dhcpc_stop();

  51. IP4_ADDR(&info.ip, 192, 168, 1, 43);

  52. IP4_ADDR(&info.gw, 192, 168, 1, 1);

  53. IP4_ADDR(&info.netmask, 255, 255, 255, 0);

  54. wifi_set_ip_info(STATION_IF, &info);*/

  55. }

  56. os_timer_disarm(&test_timer);

  57.            os_timer_setfn(&test_timer, (os_timer_func_t *)user_esp_platform_check_ip, NULL);

  58.            os_timer_arm(&test_timer, 1000, 0);



  59. }
复制代码



然后从这个源码里,可以看出,这进而进行了一系列的操作,先是判断是正常模式,还是工厂生产模式,如果是正常模式,接下通过ADC读取当时的程序所在模式(就是档位开关,这就是一档(显示屏,温度)等的由来),接着创建WIFI指示灯和airkiss工作线程,然后会试图去连接WIFI,并启动定时器去监听WIFI连接是否完成。

在监听WIFI是否完成的定时器回调函数里:

  1. void ICACHE_FLASH_ATTR

  2. user_esp_platform_check_ip(void)

  3. {        

  4. static et_uint32 time = 0;

  5. struct ip_info ipconfig;



  6. os_timer_disarm(&test_timer);        

  7. //get ip info of ESP8266 station

  8. wifi_get_ip_info(STATION_IF, &ipconfig);

  9. if (wifi_station_get_connect_status() == STATION_GOT_IP && ipconfig.ip.addr != 0)

  10. {

  11. os_printf("got ip !!! \r\n");

  12. user_set_wifi_led_on();

  13. if (user_main_start_flag == 0)

  14. {

  15. user_main_start_flag = 1;

  16. xTaskCreate(et_user_main, "et_user_main", 512, NULL, 5, NULL);

  17. }

  18. wifi_reconnect_start_flag = 1;

  19. }

  20. else

  21. {

  22. if (wifi_station_get_connect_status() == STATION_WRONG_PASSWORD

  23. || wifi_station_get_connect_status() == STATION_NO_AP_FOUND

  24. || wifi_station_get_connect_status() == STATION_CONNECT_FAIL)

  25. {

  26. if ((system_get_time() - time) >= 5000000)

  27. {        

  28. os_printf("connect fail wrong password or ssid wrong!!! \r\n");

  29. time = system_get_time();

  30. }

  31. if (air_kiss_start_flag == 1)

  32. {

  33. wifi_station_set_reconnect_policy(false);

  34. smartconfig_stop();

  35. air_kiss_start_flag = 0;

  36. }

  37.     }

  38. //re-arm timer to check ip

  39. os_timer_setfn(&test_timer, (os_timer_func_t *)user_esp_platform_check_ip, NULL);

  40. os_timer_arm(&test_timer, 1000, 0);

  41. }

  42. }



  43. 我们可以看到,如果获取IP地址成功,将会启动et_user_main线程开始真正的任务循环,同时会点亮LED显示灯。



  44. 在et_user_app.c 的et_user_main中,



  45. void  et_user_main(void *pvParameters)

  46. {

  47. et_int32 rc = -1;

  48. et_int32 num = 0;

  49. id_info_t *id;

  50. /*        g_cloud_con_para.auto_relogin = TRUE;

  51. g_cloud_con_para.clr_offline_mes = TRUE;

  52. g_cloud_con_para.server_addr = ADDRESS;

  53. g_cloud_con_para.server_port = PORT;*/

  54. os_printf("ET U-SDK var%s\n",et_sdk_var());

  55. to_stop_app = 0;



  56. id = (id_info_t *)malloc(sizeof(id_info_t));

  57. if(id == NULL)

  58. {

  59. os_printf("et_user_main, malloc id failed\n");

  60. return ;

  61. }

  62. memset(id, 0, sizeof(id_info_t));

  63. if(get_uid(id) != SPI_FLASH_RESULT_OK)

  64. {

  65. os_printf("et_user_main, get_uid error\n");

  66. free(id);

  67. return ;

  68. }

  69. id->uid[UID_LEN - 1] = '\0';

  70. id->appkey[APPKEY_LEN - 1] = '\0';

  71. g_cloud_handle = et_create_context(id->uid, id->appkey, SECRETKEY);

  72. if(NULL == g_cloud_handle)

  73. os_printf("Init et account failed\n");

  74. et_set_callback(g_cloud_handle,et_message_process, et_event_process);

  75. rc = et_start_svr(g_cloud_handle);



  76. if(rc != 0)

  77. {

  78. os_printf("et_start_svr fail\n");

  79. }

  80. do

  81. {

  82. rc = et_login_cloud(g_cloud_handle, g_cloud_con_para);



  83. if(rc != 0)

  84. {

  85. os_printf("login_cloud fail\n");

  86. }

  87. num++;

  88. vTaskDelay(num*100*portTICK_RATE_MS);

  89. }while(rc != 0 && num < 3 && to_stop_app == 0);



  90. if(rc == 0)

  91. {

  92. os_printf("now start init friend\n");        

  93. init_clients();

  94. //        rc = et_get_buddies_online(g_cloud_handle);

  95. rc = et_req_buddies_list(g_cloud_handle, LIST_ONLINE);

  96. if(rc < 0)

  97. os_printf("Get online buddies failed\n");

  98. else

  99. os_printf("Get online buddies sucess\n");

  100. rc = et_sub_allbuddies_state(g_cloud_handle);

  101. if(rc < 0)

  102. os_printf("Sub all buddies state failed\n");

  103. else

  104. os_printf("Sub all buddies state sucess\n");

  105. }

  106. free(id);

  107. vTaskDelete(NULL);

  108. return ;

  109. }
复制代码


从上面可以看出来,在这个函数里,主要读取flash里的APPKEYUID等信息,从而创建与ilink 服务器的连接,以后接收来自微信(或者手机APPWEB网页等其它方式)的消息,同时也可以向他们回复相应的消息(备注:关于这部分代码实现过程,请参考文档《小e-API用户手册》),这里就是详细说明。现在只说明一下,收到消息的回调函数里

  1. void et_message_process(et_int32 type, et_char *send_userid, et_char *topic_name, et_int32 topic_len, et_context_mes_type *message)

  2. {

  3. et_dfs_file_info_type i_file_info;

  4. struct hostent *ip_addr = NULL;

  5. et_char server_ip[32];

  6. int rc = -1;

  7. switch(type)

  8. {

  9. case MES_CHAT_TO_CHAT:

  10. os_printf("Chat mes from %s:%s\n", send_userid, topic_name);

  11. memset(g_user_id, 0, sizeof(g_user_id));

  12. snprintf(g_user_id, sizeof(g_user_id), "%s",send_userid);

  13. parse_msg_from_mqtt(message->payload, message->payload_len);

  14. break;

  15. case MES_FILE_TRANSFERS:

  16. os_printf("File trans mes from %s:%s\n", send_userid, topic_name);

  17. memset(&i_file_info, 0, sizeof(et_dfs_file_info_type));

  18. rc = et_file_info(g_cloud_handle,message->payload, &i_file_info);

  19. if(rc == -1)

  20. os_printf("file info parse failed\n");



  21. ip_addr = gethostbyname(i_file_info.source_ip_addr);

  22. if(ip_addr == NULL)

  23. {

  24. os_printf("lb gethostbyname fail\n");

  25. return;

  26. }

  27. memset(i_file_info.source_ip_addr, 0, sizeof(i_file_info.source_ip_addr));

  28. strcpy(i_file_info.source_ip_addr, inet_ntoa(*(ip_addr->h_addr)));

  29. while(write_flash_end)

  30. {

  31. os_delay_us(5);

  32. }

  33. et_down_file(g_cloud_handle,&i_file_info, write_flash_callback);

  34. break;

  35. case MES_FROM_GROUP_SUBTOPIC:

  36. os_printf("Group mes from %s:%s\n", send_userid, topic_name);

  37. snprintf(g_user_id, sizeof(g_user_id), "%s",send_userid);

  38. if(topic_len+1 > sizeof(g_group_id))

  39. {

  40. memcpy(g_group_id, topic_name, topic_len);

  41. g_group_message = 1;

  42. }

  43. parse_msg_from_mqtt(message->payload, message->payload_len);

  44. break;

  45. case MES_FROM_LOCAL:

  46. os_printf("Local mes from %s:%s\n", send_userid, topic_name);

  47. memset(g_user_id, 0, sizeof(g_user_id));

  48. snprintf(g_user_id, sizeof(g_user_id), "%s",send_userid);

  49. parse_msg_from_mqtt(message->payload, message->payload_len);

  50. break;

  51. case MES_NOTICE_ADD_BUDDY:

  52. os_printf("You are be add buddy by %s:%s\n", send_userid, topic_name);

  53. break;

  54. case MES_NOTICE_REMOVE_BUDDY:

  55. os_printf("You are be remove buddy by %s:%s\n", send_userid, topic_name);

  56. break;

  57. case MES_USER_OFFLINE:

  58. os_printf("%s Offline:%s\n", send_userid, topic_name);

  59. break;

  60. case MES_USER_ONLINE:

  61. os_printf("%s Online:%s\n", send_userid, topic_name);

  62. break;

  63. case MES_USER_STATUS:

  64. os_printf("%s Status:%s\n", send_userid, topic_name);

  65. break;

  66. case MES_ONLINE_BUDDIES_LIST:

  67. os_printf("Get online buddies list%s:%s\n", send_userid, topic_name);

  68. break;

  69. }

  70. #ifdef USER_PRINT_DEBUG

  71. os_printf("message: id%d, qos%d-->\n", message->mes_id, message->mes_qos);

  72. if(MES_CHAT_TO_CHAT == type || MES_FROM_GROUP_SUBTOPIC == type || MES_FROM_LOCAL == type )

  73. {

  74. print_hex("payload:", message->payload, message->payload_len);

  75. }

  76. else

  77. {

  78. os_printf("payload len:%d\n", message->payload_len);

  79. if(message->payload_len > 0)

  80. os_printf("payload:%s\n", message->payload);

  81. }

  82. #endif

  83. }
复制代码


会根据微信(或者手机APP),发过来控制消息,进入函数parse_msg_from_mqtt,怎么消息命令解析,从而进行相应操作(如查询温度,点RGB灯等),并且回复相应操作和数据。
这样基本流程就说完了。

1
2016-1-8 12:02:32   评论
5 个讨论
谢谢版版分享, 我马上更新到试用帖子里面去,
2016-1-8 17:25:12 评论

举报

不错的文章,好好学习学习
2016-1-8 21:03:32 评论

举报

谢谢分享,等小e回来之后要好好学习学习
2016-1-25 15:41:15 评论

举报

收藏了谩慢看,要是能整理成一个文件提供下载就好了
2016-2-18 22:07:38 评论

举报

下资料还要积分,要是能打包成一个多好啊
2016-2-18 22:09:50 评论

举报

只有小组成员才能发言,加入小组>>

588个成员聚集在这个小组

加入小组

创建小组步骤

关闭

站长推荐 上一条 /7 下一条

快速回复 返回顶部 返回列表