参考资料 
海思技术论坛注册:https://developer.hisilicon.com/forum/all 
嵌入式物联网学习资料总入口:https://developer.hisilicon.com/postDetail?tid=0206112614830760003 
海思技术论坛https://developer.hisilicon.com/forum/all 
2023海思嵌入式大赛学习文档仓库Gitee:https://gitee.com/HiSpark/HiSpark_NICU2023 
HUAWEI_Cloud与Android Studio开发联动:https://blog.csdn.net/weixin_43351158/article/details/124476656 
工程结构分析 
工程目录 
1 2 3 4 5 6 7 8 9 . └── applications     └── sample         └── wifi-iot             └── app                 │── my_first_app     //业务my_first_app文件夹                 │  │── hello_world.c //业务代码                 │  └── BUILD.gn      //编译脚本                 └── BUILD.gn 
hello_world.c文件代码结构 
1 2 3 4 5 6 7 8 9 #include  <stdio.h>  #include  "ohos_init.h"  #include  "ohos_types.h"  void  HelloWorld (void ) {     printf ("___________>>>>>>>>>>>>>>>>>>>> [DEMO] Hello world.\n" ); } SYS_RUN(HelloWorld); 
SYS_RUN定义在ohos_init.h文件中,是HarmonyOS启动恢复模块接口启动业务 。
用于将业务构建成静态库 的BUILD.gn文件代码结构路径:./applications/sample/wifi-iot/app/my_first_app/BUILD.gn(与下面的模块编译build.gn不一样,请格外注意)
1 2 3 4 5 6 7 8 9 10 11 //目标业务 static_library("myapp") {      //源文件路径     sources = [         "hello_world.c"     ]     //头文件路径     include_dirs = [         "//utils/native/lite/include"     ] } 
指定需参与构建的特性模块 的BUILD.gn文件代码结构路径:./applications/sample/wifi-iot/app/BUILD.gn
1 2 3 4 5 6 7 8 9 import("//build/lite/config/component/lite_component.gni") lite_component("app") {     features = [         "my_first_app:myapp",     ] } 
my_first_app是相对路径,指向./applications/sample/wifi-iot/app/my_first_app/BUILD.gn。
myapp是目标,指向./applications/sample/wifi-iot/app/my_first_app/BUILD.gn中的static_library(“myapp”)。
Hi3861其他代码结构 
Hi3861平台配置文件 
hi3861平台配置文件位于:vendor\hisilicon\hispark_pegasus\config.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 {     "product_name" :  "wifiiot_hispark_pegasus" ,      "ohos_version" :  "OpenHarmony 1.0" ,      "device_company" :  "hisilicon" ,      "board" :  "hispark_pegasus" ,      "kernel_type" :  "liteos_m" ,      "kernel_version" :  "" ,      "subsystems" :  [        {                   "subsystem" :  "applications" ,          "components" :  [            {  "component" :  "wifi_iot_sample_app" ,  "features" : [ ]  }          ]        } ,        {                   "subsystem" :  "iot_hardware" ,          "components" :  [            {  "component" :  "iot_controller" ,  "features" : [ ]  }          ]        } ,        {                   "subsystem" :  "hiviewdfx" ,          "components" :  [            {  "component" :  "hilog_lite" ,  "features" : [ ]  }          ]        } ,        {          "subsystem" :  "distributed_schedule" ,          "components" :  [            {  "component" :  "samgr_lite" ,  "features" : [ ]  }          ]        } ,        {          "subsystem" :  "security" ,          "components" :  [            {  "component" :  "hichainsdk" ,  "features" : [ ]  } ,            {  "component" :  "deviceauth_lite" ,  "features" : [ ]  } ,            {  "component" :  "huks" ,  "features" :              [                "disable_huks_binary = false" ,                "disable_authenticate = false" ,                "huks_use_lite_storage = true" ,                "huks_use_hardware_root_key = true" ,                "huks_config_file = \"hks_config_lite.h\"" ,                "huks_mbedtls_path = \"//device/hisilicon/hispark_pegasus/sdk_liteos/third_party/mbedtls/include/\""              ]            }          ]        } ,        {          "subsystem" :  "startup" ,          "components" :  [            {  "component" :  "bootstrap_lite" ,  "features" : [ ]  } ,            {  "component" :  "syspara_lite" ,  "features" :              [                "enable_ohos_startup_syspara_lite_use_thirdparty_mbedtls = false"              ]            }          ]        } ,        {          "subsystem" :  "communication" ,          "components" :  [            {  "component" :  "wifi_lite" ,  "features" : [ ]  } ,            {  "component" :  "softbus_lite" ,  "features" : [ ]  } ,            {  "component" :  "wifi_aware" ,  "features" : [ ] }          ]        } ,        {          "subsystem" :  "update" ,          "components" :  [            {  "component" :  "ota_lite" ,  "features" : [ ]  }          ]        } ,        {          "subsystem" :  "iot" ,          "components" :  [            {  "component" :  "iot_link" ,  "features" : [ ]  }          ]        } ,        {          "subsystem" :  "utils" ,          "components" :  [            {  "component" :  "file" ,  "features" : [ ]  } ,            {  "component" :  "kv_store" ,  "features" : [ ]  } ,            {  "component" :  "os_dump" ,  "features" : [ ]  }          ]        } ,        {          "subsystem" :  "vendor" ,          "components" :  [            {  "component" :  "hi3861_sdk" ,  "target" :  "//device/hisilicon/hispark_pegasus/sdk_liteos:wifiiot_sdk" ,  "features" : [ ]  }          ]        }      ] ,      "third_party_dir" :  "//device/hisilicon/hispark_pegasus/sdk_liteos/third_party" ,      "product_adapter_dir" :  "//vendor/hisilicon/hispark_pegasus/hals"    }  
hi3861用的是liteos-m 内核,但是目前hi3681的liteos-m被芯片rom化 了,固化在芯片内部了。所以在harmonyOS代码是找不到hi3861的内核部分。
Hi3861启动流程 
第一个入口函数 
路径:.\src\device\hisilicon\hispark_pegasus\sdk_liteos\app\wifiiot_app\app_main.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 hi_void app_main (hi_void)  { #ifdef  CONFIG_FACTORY_TEST_MODE         printf ("factory test mode!\r\n" ); #endif      const  hi_char* sdk_ver = hi_get_sdk_version();     printf ("sdk ver:%s\r\n" , sdk_ver);     hi_flash_partition_table *ptable = HI_NULL;     peripheral_init();     peripheral_init_no_sleep(); #ifndef  CONFIG_FACTORY_TEST_MODE     hi_lpc_register_wakeup_entry(peripheral_init); #endif      hi_u32 ret = hi_factory_nv_init(HI_FNV_DEFAULT_ADDR, HI_NV_DEFAULT_TOTAL_SIZE, HI_NV_DEFAULT_BLOCK_SIZE);     if  (ret != HI_ERR_SUCCESS) {         printf ("factory nv init fail\r\n" );     }          ret = hi_flash_partition_init();     if  (ret != HI_ERR_SUCCESS) {         printf ("flash partition table init fail:0x%x \r\n" , ret);     }     ptable = hi_get_partition_table();     ret = hi_nv_init(ptable->table[HI_FLASH_PARTITON_NORMAL_NV].addr, ptable->table[HI_FLASH_PARTITON_NORMAL_NV].size,         HI_NV_DEFAULT_BLOCK_SIZE);     if  (ret != HI_ERR_SUCCESS) {         printf ("nv init fail\r\n" );     } #ifndef  CONFIG_FACTORY_TEST_MODE     hi_upg_init(); #endif           hi_fs_init();     (hi_void)hi_event_init(APP_INIT_EVENT_NUM, HI_NULL);     hi_sal_init();          hi_syserr_watchdog_debug(HI_FALSE);          hi_syserr_record_crash_info(HI_TRUE);     hi_lpc_init();     hi_lpc_register_hw_handler(config_before_sleep, config_after_sleep); #if  defined(CONFIG_AT_COMMAND) || defined(CONFIG_FACTORY_TEST_MODE)     ret = hi_at_init();     if  (ret == HI_ERR_SUCCESS) {         hi_at_sys_cmd_register();     } #endif                 #ifndef  CONFIG_FACTORY_TEST_MODE #ifndef  ENABLE_SHELL_DEBUG #ifdef  CONFIG_DIAG_SUPPORT     (hi_void)hi_diag_init(); #endif  #else      (hi_void)hi_shell_init(); #endif      tcpip_init(NULL , NULL ); #endif      ret = hi_wifi_init(APP_INIT_VAP_NUM, APP_INIT_USR_NUM);     if  (ret != HISI_OK) {         printf ("wifi init failed!\n" );     } else  {         printf ("wifi init success!\n" );     }     app_demo_task_release_mem();  #ifndef  CONFIG_FACTORY_TEST_MODE     app_demo_upg_init(); #ifdef  CONFIG_HILINK     ret = hilink_main();     if  (ret != HISI_OK) {         printf ("hilink init failed!\n" );     } else  {         printf ("hilink init success!\n" );     } #endif  #endif      OHOS_Main(); } 
最后一行调用OHOS_Main()代码:
路径:.\src\device\hisilicon\hispark_pegasus\sdk_liteos\app\wifiiot_app\src
1 2 3 4 5 6 7 8 9 10 11 12 13 14 void  OHOS_Main () { #if  defined(CONFIG_AT_COMMAND) || defined(CONFIG_FACTORY_TEST_MODE)     hi_u32 ret;     ret = hi_at_init();     if  (ret == HI_ERR_SUCCESS) {         hi_u32 ret2 = hi_at_register_cmd(G_OHOS_AT_FUNC_TBL, OHOS_AT_FUNC_NUM);         if  (ret2 != HI_ERR_SUCCESS) {             printf ("Register ohos failed!\n" );         }     } #endif      OHOS_SystemInit(); } 
OHOS_SystemInit函数进行鸿蒙系统的初始化。
路径:D:\DevEcoProjects\first_test\src\base\startup\bootstrap_lite\services\source\system_init.c
1 2 3 4 5 6 7 8 9 10 void  OHOS_SystemInit (void ) {     MODULE_INIT(bsp);     MODULE_INIT(device);     MODULE_INIT(core);     SYS_INIT(service);     SYS_INIT(feature);     MODULE_INIT(run);     SAMGR_Bootstrap(); } 
主要是初始化了一些相关模块、系统,包括有bsp、device(设备)。其中最终的是MODULE_INIT(run);负责调用所有run段的代码:前面application中使用SYS_RUN()宏设置的函数名 。
一、GPIO的使用 
API说明 
1. IoTGpioInit() 
作用:初始化指定的IO口
1 2 IoTGpioInit(IOT_IO_NAME_GPIO_9); 
依赖库:src\base\iot_hardware\peripheral\interfaces\kits\iot_gpio.h, 说明如下
1 2 3 4 5 6 7 8 9 10 unsigned  int  IoTGpioInit (unsigned  int  id) ;
2. IoSetFunc() 
作用:配置指定IO的复用功能
1 2 IoSetFunc(IOT_IO_NAME_GPIO_9, IOT_IO_FUNC_GPIO_9_GPIO); 
依赖库:src\applications\sample\wifi-iot\app\led_demo\hal_iot_gpio_ex.c
1 2 3 4 5 6 7 unsigned  int  IoSetFunc (unsigned  int  id, unsigned  char  val) {     if  (id >= HI_GPIO_IDX_MAX) {         return  IOT_FAILURE;     }     return  hi_io_set_func((hi_io_name)id, val); } 
3. IoTGpioSetDir() 
作用:设置指定IO的管脚方向
1 2 IoTGpioSetDir(IOT_IO_NAME_GPIO_9, IOT_GPIO_DIR_OUT); 
依赖库:src\base\iot_hardware\peripheral\interfaces\kits\iot_gpio.h, 说明如下
1 2 3 4 5 6 7 8 9 10 11 unsigned  int  IoTGpioSetDir (unsigned  int  id, IotGpioDir dir) ;
4. IoTGpioSetOutputVal() 
作用:设置指定IO的输出电平
1 2 3 4 5 6    IoTGpioSetOutputVal(IOT_IO_NAME_GPIO_9, IOT_GPIO_VALUE0); 
二、GPIO使用进阶 
API说明 
1. IoSetPull() 
作用:设置指定IO的上下拉电阻
1 2 3 4 5 IoSetPull(IOT_IO_NAME_GPIO_0, IOT_IO_PULL_UP); 
依赖库:src\applications\sample\wifi-iot\app\led_demo\hal_iot_gpio_ex.c
1 2 3 4 5 6 7 8 IOT_IO_PULL_NONE, IOT_IO_PULL_UP, IOT_IO_PULL_DOWN, IOT_IO_PULL_MAX 
2. IoTGpioRegisterIsrFunc() 
作用:设置指定GPIO的中断功能
1 2 3 4 5 6 7 IoTGpioRegisterIsrFunc(IOT_IO_NAME_GPIO_0, IOT_INT_TYPE_EDGE,                        IOT_GPIO_EDGE_RISE_LEVEL_HIGH, LeftBCounterHandler, NULL ); 
依赖库:src\base\iot_hardware\peripheral\interfaces\kits\iot_gpio.h,IotGpioIntType intType说明如下
1 2 3 4 IOT_INT_TYPE_LEVEL = 0 , IOT_INT_TYPE_EDGE 
第三个参数IotGpioIntPolarity intPolarity说明如下:
1 2 3 4 IOT_GPIO_EDGE_FALL_LEVEL_LOW = 0 , IOT_GPIO_EDGE_RISE_LEVEL_HIGH 
第四个参数GpioIsrCallbackFunc func,为自己编写的中断触发时的回调函数名,第五个参数char *arg为中断回调函数中使用的参数的指针。
作用:读取指定GPIO的电平
1 2 3 4 5  IoTGpioGetInputVal(IOT_IO_NAME_GPIO_8, &value); 
依赖库:src\base\iot_hardware\peripheral\interfaces\kits\iot_gpio.h, IOT_GPIO_VALUE1为高电平,IOT_GPIO_VALUE0为低电平。
I2C总线开发 
1. I2C总线开发基础 
I2C通信中,主机通过时钟线SCL发送时钟信号,通过数据线SDA发送数据(包括从机地址、指令、数据包等),在发送完一帧数据后,需要等待从机的响应,才能继续发送下一帧数据,因此I2C属于同步通信。
2. 单I2C轮询 
(1)IoTI2cInit() 
作用:以指定的波特率初始化I2C设备。
1 2 3 4 #define  IOT_I2C_IDX_BAUDRATE (400 * 1000)  #define  CW2015_I2C_IDX 0  IoTI2cInit(CW2015_I2C_IDX, IOT_I2C_IDX_BAUDRATE); 
依赖库:src\base\iot_hardware\peripheral\interfaces\kits\iot_i2c.h
(2)IoTI2cDeinit() 
作用:关闭/去初始化指定的I2C设备。
1 2 unsigned  int  IoTI2cDeinit (unsigned  int  id) ;
依赖库:src\base\iot_hardware\peripheral\interfaces\kits\iot_i2c.h
(3)IoTI2cWrite() 
作用:向指定的I2C设备写入数据。
1 2 3 4 5 6 7 8 #define  LSM6DS_I2C_IDX 0 uint32_t  retval = IoTI2cWrite(LSM6DS_I2C_IDX, LSM6DS_WRITE_ADDR, buffer, buffLen);
依赖库:src\base\iot_hardware\peripheral\interfaces\kits\iot_i2c.h
(4)IoTI2cRead() 
作用:从指定的I2C设备读取数据。
1 2 3 4 5 6 unsigned  int  IoTI2cRead (unsigned  int  id, unsigned  short  deviceAddr, unsigned  char  *data, unsigned  int  dataLen)
依赖库:src\base\iot_hardware\peripheral\interfaces\kits\iot_i2c.h
(5)IoTI2cSetBaudrate() 
作用:设置指定I2C设备的波特率。
1 2 3 unsigned  int  IoTI2cSetBaudrate (unsigned  int  id, unsigned  int  baudrate) ;
依赖库:src\base\iot_hardware\peripheral\interfaces\kits\iot_i2c.h
3. I2C中断触发 
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 195  void  I2CBusExampleEntry (void ) 196 { 197      osThreadAttr_t attr;198  199      I2CBusInit();200      IoTWatchDogDisable();201  202      attr.name = "NFCTask" ;203      attr.attr_bits = 0U ;204      attr.cb_mem = NULL ;205      attr.cb_size = 0U ;206      attr.stack_mem = NULL ;207      attr.stack_size = 5  * 1024 ; 208      attr.priority = osPriorityNormal;209  210      211      if  (osThreadNew((osThreadFunc_t)NFCTask, NULL , &attr) == NULL ) {212          printf ("[NFCTask] Failed to create NFCTask!\n" );213      }214  215      216      attr.name = "CW2015Task" ;217      if  (osThreadNew((osThreadFunc_t)CW2015Task, NULL , &attr) == NULL ) {218          printf ("[CW2015Task] Failed to create CW2015Task!\n" );219      }220  221      222      attr.name = "FunKeyTask" ;223      if  (osThreadNew((osThreadFunc_t)FunKeyTask, NULL , &attr) == NULL ) {224          printf ("[FunKeyTask] Failed to create FunKeyTask!\n" );225      }226  227      228      attr.name = "LSM6DSTask" ;229      if  (osThreadNew((osThreadFunc_t)LSM6DSTask, NULL , &attr) == NULL ) {230          printf ("[LSM6DSTask] Failed to create LSM6DSTask!\n" );231      }232  }233  234  APP_FEATURE_INIT(I2CBusExampleEntry);
软件烧录成功后,按一下开发板的RESET按键复位开发板,可以在OLED屏幕上面看到陀螺仪方向角实时数据以及电池电量数据,当手机靠近小车的NFC模块时,NFC会拉起手机的淘宝应用,且可以通过S1、S2、S3功能按键来控制三个交通灯的亮灭,说明我们使用I2C总线,实现同时轮询多个设备的实验成功。
PWM接口开发 
1. IoTPwmInit() 
作用:初始化指定PWM端口
1 2 3  #define  IOT_PWM_PORT_PWM1   1  IoTPwmInit(IOT_PWM_PORT_PWM1); 
依赖库:src\base\iot_hardware\peripheral\interfaces\kits\iot_pwm.h
2. IoTPwmStart() 
作用:启动PWM信号输出
1 2 3 4 5 6 7 #define  IOT_PWM_PORT_PWM2   2 #define  IOT_FREQ            65535 #define  IOT_DUTY            50 IoTPwmStart(IOT_PWM_PORT_PWM2, IOT_DUTY, IOT_FREQ); 
依赖库:src\base\iot_hardware\peripheral\interfaces\kits\iot_pwm.h
3. IoTPwmStop() 
作用:停止PWM信号输出
1 2 #define  IOT_PWM_PORT_PWM2   2 IoTPwmStop(IOT_PWM_PORT_PWM2); 
依赖库:src\base\iot_hardware\peripheral\interfaces\kits\iot_pwm.h
IoTPwmDeinit() 
作用:释放/去初始化指定PWM端口
1 2 #define  IOT_PWM_PORT_PWM2   2 IoTPwmDeinit(IOT_PWM_PORT_PWM2); 
依赖库:src\base\iot_hardware\peripheral\interfaces\kits\iot_pwm.h
GPIO模拟PWM信号 
Sg92r舵机原理 
Sg92舵机的控制需要产生一个20ms 的脉冲信号,以0.5ms到2.5ms 的高电平 来控制舵机的角度;高电平持续时间对应角度如下表所示。
高电平持续时间 
角度 
 
 
0.5ms 
0° 
 
1.0ms 
45° 
 
1.5ms 
90° 
 
2.0ms 
135° 
 
2.5ms 
180° 
 
 
代码核心 
1 2 3 4 5 6 7 8 9 30  void  SetAngle (unsigned  int  duty) 31 { 32      unsigned  int  time = FREQ_TIME;33  34      IoTGpioSetOutputVal(IOT_IO_NAME_GPIO_2, IOT_GPIO_VALUE1);35      hi_udelay(duty);36      IoTGpioSetOutputVal(IOT_IO_NAME_GPIO_2, IOT_GPIO_VALUE0);37      hi_udelay(time - duty);38  }
ADC开发 
1.AdcRead() 
作用:根据输入参数从指定的ADC通道读取一段采样数据
1 2 3 4 5 6 ret = AdcRead(idx, &data, IOT_ADC_EQU_MODEL_4, IOT_ADC_CUR_BAIS_DEFAULT, 0xff ); 
依赖库:src\applications\sample\wifi-iot\app\lth1550_demo\iot_adc.h
UART开发 
1. IoTUartInit() 
作用:初始化指定UART端口
1 2 3 4 5 6 ret = IoTUartInit(HI_UART_IDX_1, &uart_attr); if  (ret != IOT_SUCCESS) {    printf ("Init Uart1 Falied Error No : %d\n" , ret);     return ; } 
依赖库:src\base\iot_hardware\peripheral\interfaces\kits\iot_uart.h
三、定时器使用——以频率测量为例 
主要函数 
1. osTimerId_t periodic_tid = osTimerNew(cb_timeout_periodic, osTimerPeriodic, NULL, NULL); 
作用:创建一个新的定时器,命名为periodic_tid,其变量名称为osTimerId_t。
参数说明:
cb_timeout_periodic:回调函数; 
osTimerPeriodic:定时器类型; 
NULL:(第一个)回调函数参数; 
NULL:(第二个)定时器属性 
 
periodic_tid常用于确保定时器已创建成功,如下所示:
1 2 3 4 5 6 7 8 9 if  (periodic_tid == NULL )     {         printf ("[Timer Test] osTimerNew(periodic timer) failed.\r\n" );         return ;     }  else      {         printf ("[Timer Test] osTimerNew(periodic timer) success, tid: %p.\r\n" ,periodic_tid);     } 
2. osTimerStart(periodic_tid, 100); 
说明:100个时钟周期 调用一次回调函数cb_timeout_periodic 的定时器
periodic_tid:定时器ID; 
100:定时器周期,单位为时钟周期,即100个时钟周期调用一次回调函数 
 
3. void cb_timeout_periodic(void) 
说明:定时器回调函数,无输入参数,无返回值。
频率测量原理 
定时器每记过1个中断执行周期,期间开启上升沿输入捕获记录从低到高电平的变化个数num。由定时器中断执行周期 /num 可得到一个上升沿所占用的时钟周期,取倒数即可得到频率。
问题来了,Hi3861的系统时钟我找不到接口(骂骂咧咧.gif)
四、对华为云板端互联代码的分析:app_demo_iot.c 
1. static void DemoMsgRcvCallBack(int qos, char *topic, char *payload) 
代码结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 static  void  DemoMsgRcvCallBack (int  qos, char  *topic, char  *payload) {     const  char  *requesID;     char  *tmp;     IoTCmdResp resp;     printf ("RCVMSG:QOS:%d TOPIC:%s PAYLOAD:%s\r\n" , qos, topic, payload);          TrafficLightMsgRcvCallBack(payload);     tmp = strstr (topic, CN_COMMAND_INDEX);     if  (tmp != NULL ) {                           requesID = tmp + strlen (CN_COMMAND_INDEX);         resp.requestID = requesID;         resp.respName = NULL ;         resp.retCode = 0 ;            resp.paras = NULL ;         (void )IoTProfileCmdResp(CONFIG_DEVICE_PWD, &resp);     } } 
1 2 3 4 5 6 7 8 9 10 11 static  void  TrafficLightMsgRcvCallBack (char  *payload) {     printf ("PAYLOAD:%s\r\n" , payload);     if  (strstr (payload, TRAFFIC_LIGHT_CMD_CONTROL_MODE) != NULL ) {         if  (strstr (payload, TRAFFIC_LIGHT_RED_ON_PAYLOAD) != NULL ) {              RedLight();         } else  if  (strstr (payload, TRAFFIC_LIGHT_RED_OFF_PAYLOAD) != NULL ) {             RedOff();         }     } } 
解析:
该函数为回调函数,需要传入三个参数:qos、topic、payload,分别为服务质量、消息主题、消息内容(负载)。 
调用TrafficLightMsgRcvCallBack函数处理消息内容。 
tmp = strstr(topic, CN_COMMAND_INDEX);用于在topic里查找 CN_COMMAND_INDEX 宏定义的字符串。如果找到了,说明这是一个来自平台的命令。 
IoTCmdResp resp;用于创建一个 IoTCmdResp 类型的结构体 resp 并设置其字段。其中,requestID 字段设置为之前计算出的请求ID,respName 字段设置为NULL,retCode 字段设置为0表示成功,paras 字段设置为NULL。 
 
让我们看看IoTCmdResp里面的内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 typedef  struct  {    int   retCode;      const  char    *respName;      const  char    *requestID;     IoTProfileKV  *paras;   }IoTCmdResp; typedef  struct  {    void     *nxt;       const  char    *key;     const  char    *value;     int    iValue;     float   LedValue;     IoTDataType  type; }IoTProfileKV; 
2. traffic light:1.control module 
代码结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 void  IotPublishSample (void ) {     IoTProfileService service;     IoTProfileKV property;     printf ("traffic light:control module\r\n" );     memset_s(&property, sizeof (property), 0 , sizeof (property));      property.type = EN_IOT_DATATYPE_STRING;     property.key = "ControlModule" ;     if  (g_lightStatus == 0 ) {         property.value = "RED_LED_ON" ;     } else  {         property.value = "RED_LED_OFF" ;     }     memset_s(&service, sizeof (service), 0 , sizeof (service));     service.serviceID = "TrafficLight" ;     service.serviceProperty = &property;     IoTProfilePropertyReport(CONFIG_DEVICE_ID, &service); } 
IoTProfilePropertyReport代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 int  IoTProfilePropertyReport (char  *deviceID, IoTProfileService *payload) {     int  ret = -1 ;     char  *topic;     char  *msg;     if  ((deviceID == NULL ) || (payload == NULL ) || (payload->serviceID == NULL ) || (payload->serviceProperty == NULL )) {         return  ret;     }     topic = MakeTopic(CN_PROFILE_TOPICFMT_PROPERTYREPORT, deviceID, NULL );     if  (topic == NULL ) {         return  ret;     }          msg = MakeProfilePropertyReport(payload);     if  ((topic != NULL ) && (msg != NULL )) {         ret = IotSendMsg(0 , topic, msg);     }     hi_free(0 , topic);     cJSON_free(msg);          return  ret; } 
解析:指向 property 变量 。
3.demo main task entry 
代码结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 static  void  DemoEntry (void ) {     ConnectToHotspot();      RedLedInit();       CJsonInit();       IoTMain();         IoTSetMsgCallback(DemoMsgRcvCallBack);       TaskMsleep(30000 );      while  (1 ) {                  TaskMsleep(TASK_SLEEP_1000MS);                  IotPublishSample();     } } 
IoTSetMsgCallback代码:
1 2 3 4 5 int  IoTSetMsgCallback (FnMsgCallBack msgCallback) {     g_ioTAppCb.msgCallBack = msgCallback;     return  0 ; } 
运行示例程序的输出结果:
1 2 3 4 5 6 7 traffic light:control module //执行IotPublishSample函数, SNDMSG:QOS:0 TOPIC:$oc/devices/6457560a4f1d680324508724_123456789/sys/properties/report PAYLOAD:{"services":[{"service_id":"TrafficLight","properties":{"ControlModule":"RED_LED_OFF"}}]} MSGSEND:SUCCESS ProcessQueueMsg 
华为云端操作 
ref:https://gitee.com/HiSpark/HiSpark_NICU2023/blob/master/4.5 物联网应用开发.md#452华为云的智能交通灯上报 
1.创建产与相关属性 
点击左边任务栏的“产品”同时选择控制台地址为“北京四”,然后点击最右上角的“创建产品”(产品名称可自定义)。注意:创建产品时如果所属空间为NULL,请先实名注册。
创建成功后,点击查看详情,点击“自定义模型”创建用户自己的模型:
根据自己需要自己定义,如为模型添加服务:“TrafficLight”,服务类型:“TrafficLight”,服务描述:“交通灯”,点击确定;新增属性为属性名称:“ControlModule”,数据类型:“String”,访问权限:“可读,可写”,长度:“255”,点击确定;新增命令为命令名称:“ControlModule”,新增参数:“TrafficLight”,数据类型:“String”,长度:“255”。
命令下发是 平台向设备下发设备控制命令  ,需要设备及时将命令的执行结果返回给平台。如果设备没有回应,平台会认为命令执行超时 .设备在收到平台下发的命令后,返回给平台的执行结果。  这些响应参数可以携带设备执行操作成功或失败后的响应参数.
点击左边任务栏的“设备”,然后注册设备图,注册创建的产品,用户根据自己需要随意填写,填写完成后,可以看到设备状态显示为未注册。
配置完成,如下:
2.工程移植 
将oc_demo里的关于设备响应的函数抹去,因为此次工程只需要设备上报的功能。上报函数如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 void  IotPublishSample_Temp_ControlModule (void ) {     IoTProfileService service;     IoTProfileKV property;     printf ("Temp:control module\r\n" );     memset_s(&property, sizeof (property), 0 , sizeof (property));     property.type = EN_IOT_DATATYPE_STRING;     property.key = "Temp_ControlModule" ;     property.value = (char )temperature;     memset_s(&service, sizeof (service), 0 , sizeof (service));     service.serviceID = "Temp" ;     service.serviceProperty = &property;     IoTProfilePropertyReport(CONFIG_DEVICE_ID, &service); } void  IotPublishSample_Humi_ControlModule (void ) {     IoTProfileService service;     IoTProfileKV property;     printf ("Humi:control module\r\n" );     memset_s(&property, sizeof (property), 0 , sizeof (property));     property.type = EN_IOT_DATATYPE_STRING;     property.key = "Humi_ControlModule" ;     property.value = (char )humidity;     memset_s(&service, sizeof (service), 0 , sizeof (service));     service.serviceID = "Humi" ;     service.serviceProperty = &property;     IoTProfilePropertyReport(CONFIG_DEVICE_ID, &service); } void  IotPublishSample_Gas_ControlModule (void ) {     IoTProfileService service;     IoTProfileKV property;     printf ("Gas:control module\r\n" );     memset_s(&property, sizeof (property), 0 , sizeof (property));     property.type = EN_IOT_DATATYPE_STRING;     property.key = "Gas_ControlModule" ;     property.value = (char )gasSensorResistance;     memset_s(&service, sizeof (service), 0 , sizeof (service));     service.serviceID = "Gas" ;     service.serviceProperty = &property;     IoTProfilePropertyReport(CONFIG_DEVICE_ID, &service); } static  void  DemoEntry (void ) {     ConnectToHotspot();     CJsonInit();     IoTMain();     TaskMsleep(30000 );      while  (1 ) {                  TaskMsleep(TASK_SLEEP_1000MS);                  IotPublishSample_Temp_ControlModule();         IotPublishSample_Humi_ControlModule();         IotPublishSample_Gas_ControlModule();     } } 
3. 云设备的激活 
利用https://iot-tool.obs-website.cn-north-4.myhuaweicloud.com/  生成Clientld,Username,Password。
将下图地方设备ID复制到DeviceId,密钥复制到DeviceSecret,点击Generate即可。
本次工程生成后的结果:
ClientId:64a98f799415fc7a573be8f0_Temp_Humi_Gas_Detector_0_0_2023070818
修改applications/sample/wifi-iot/app/oc_demo/目录下iot_config.h中,WiFi名称和WiFi密码,搜索字段CONFIG_AP_SSID:代表WiFi名称;CONFIG_AP_PWD:代表WiFi密码(板子需要连接的WiFi)。
1 2 3 4 #define  CONFIG_AP_SSID  "MIX4"   #define  CONFIG_AP_PWD  "ez20020328"   
修改applications/sample/wifi-iot/app/oc_demo/目录下iot_config.h中搜索CONFIG_DEVICE_ID和CONFIG_DEVICE_PWD,CONFIG_CLIENTID这三个字段。CONFIG_DEVICE_ID和CONFIG_DEVICE_PWD,CONFIG_CLIENTID,三个字段配置参数见上:
1 2 3 4 5 6 7 #define  CONFIG_DEVICE_ID  "64a98f799415fc7a573be8f0_Temp_Humi_Gas_Detector"  #define  CONFIG_DEVICE_PWD "d500d9f5e8b5ad551b4b90181d8f22f0166b8afa91540e8b4bd995648665e483"  #define  CONFIG_CLIENTID "64a98f799415fc7a573be8f0_Temp_Humi_Gas_Detector_0_0_2023070818"  
在华为云如下界面点击总览,可以看到平台接入地址,点击进去之后可以看到设备接入MQTT字样如下图所示,复制“xxxxxxx.iot-mqtts.cn-north-4.myhuaweicloud.com ”字段,将该字段写到./applications/sample/wifi-iot/app/oc_demo/iot_main.c中CN_IOT_SERVER字段中。具体修改如下图所示。
报错? 
=======KERNEL PANIC=======
syserr info start Exception Information reg info memory info task info track_info Call Stack Call Stack end 
🤔内核被我写爆了???
经过多方排查,发现property.value只能传进字符串,不能识别的格式,会导致内核崩溃。(虽然工程编译没有问题,其背后原因不得而知,可能需要请教海思的工程师)
修复之后:
作品设想 
1. 作品功能 
A.基础设施智能化建设解决方案 
将小区分为社区门口、单元门、电梯间、入户门、停车场、公共区域、设备间7 个重点区域,对门禁、道闸、对讲、梯控、视频监控、周界防范、信息发布、停车管理、设备检测等进行基础设施智能化开发与建设,为智慧社区整体方案提供支撑,基础设施见图:
最终敲定功能:
主要工作:Hi3861开发板学习、各种传感器选型、解决方案敲定等。
B.物业综合服务平台 
该平台用于:完成人员管理、养老服务、卫生服务、信息发布、收缴费管理、报事报修、车辆管理、便民服务等功能开发;为物业提供社区基础数据、日常业务管理工具,通过数据共享和应用聚合向政府提供社区管理通道、向居民提供社区服务。平台服务与应用见图4:
主要工作:华为云服务的学习与配置,物业综合服务平台的开发。
项目故事 
物业<->USER/业主<->政府/社区 双向的故事 双向的沟通交流,贴近居民生活,提高居民生活质量。
海思CAMP 
项目管理方法 
传感器选型 
电能监控模块 
艾锐达IM1253B交直流电压电流功率电量测量电能采集电测计量模块https://item.taobao.com/item.htm?spm=a21n57.1.0.0.7b90523cKNbIy1&id=571489221834&ns=1&abbucket=0#detail 
流量计模块 
系统时钟拿不到就是寄,不用了((╯‵□′)╯︵┻━┻)