text: /*
   * Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *    http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <unistd.h>
  #include "cmsis_os2.h"
  #include "ohos_init.h"
  
  #include <dtls_al.h>
  #include <mqtt_al.h>
  #include <oc_mqtt_al.h>
  #include <oc_mqtt_profile.h>
  #include "E53_SC1.h"
  #include "wifi_connect.h"
  
  #define CONFIG_WIFI_SSID "BearPi" // 修改为自己的WiFi 热点账号
  
  #define CONFIG_WIFI_PWD "BearPi" // 修改为自己的WiFi 热点密码
  
  #define CONFIG_APP_SERVERIP "121.36.42.100"
  
  #define CONFIG_APP_SERVERPORT "1883"
  
  #define CONFIG_APP_DEVICEID "6012d1394b835702d79aa5a7_12334556443" // 替换为注册设备后生成的deviceid
  
  #define CONFIG_APP_DEVICEPWD "123456789" // 替换为注册设备后生成的密钥
  
  #define CONFIG_APP_LIFETIME 60 // seconds
  
  #define CONFIG_QUEUE_TIMEOUT (5 * 1000)
  
  #define MSGQUEUE_COUNT 16
  #define MSGQUEUE_SIZE 10
  #define CLOUD_TASK_STACK_SIZE (1024 * 10)
  #define CLOUD_TASK_PRIO 24
  #define SENSOR_TASK_STACK_SIZE (1024 * 4)
  #define SENSOR_TASK_PRIO 25
  #define TASK_DELAY 3
  
  typedef enum {
      en_msg_cmd = 0,
      en_msg_report,
  } en_msg_type_t;
  
  typedef struct {
      char* request_id;
      char* payload;
  } cmd_t;
  
  typedef struct {
      int lum;
  } report_t;
  
  typedef struct {
      en_msg_type_t msg_type;
      union {
          cmd_t cmd;
          report_t report;
      } msg;
  } app_msg_t;
  
  typedef struct {
      osMessageQueueId_t app_msg;
      int connected;
      int led;
  } app_cb_t;
  static app_cb_t g_app_cb;
  
  static void deal_report_msg(report_t* report)
  {
      oc_mqtt_profile_service_t service;
      oc_mqtt_profile_kv_t luminance;
      oc_mqtt_profile_kv_t led;
  
      if (g_app_cb.connected != 1) {
          return;
      }
  
      service.event_time = NULL;
      service.service_id = "Light";
      service.service_property = &luminance;
      service.nxt = NULL;
  
      luminance.key = "Luminance";
      luminance.value = &report->lum;
      luminance.type = EN_OC_MQTT_PROFILE_VALUE_INT;
      luminance.nxt = &led;
  
      led.key = "LightStatus";
      led.value = g_app_cb.led ? "ON" : "OFF";
      led.type = EN_OC_MQTT_PROFILE_VALUE_STRING;
      led.nxt = NULL;
  
      oc_mqtt_profile_propertyreport(NULL, &service);
      return;
  }
  
  // use this function to push all the message to the buffer
  static int msg_rcv_callback(oc_mqtt_profile_msgrcv_t* msg)
  {
      int ret = 0;
      char* buf;
      int buf_len;
      app_msg_t* app_msg;
  
      if ((msg == NULL) || (msg->request_id == NULL) || (msg->type != EN_OC_MQTT_PROFILE_MSG_TYPE_DOWN_COMMANDS)) {
          return ret;
      }
  
      buf_len = sizeof(app_msg_t) + strlen(msg->request_id) + 1 + msg->msg_len + 1;
      buf = malloc(buf_len);
      if (buf == NULL) {
          return ret;
      }
      app_msg = (app_msg_t*)buf;
      buf += sizeof(app_msg_t);
  
      app_msg->msg_type = en_msg_cmd;
      app_msg->msg.cmd.request_id = buf;
      buf_len = strlen(msg->request_id);
      buf += buf_len + 1;
      memcpy_s(app_msg->msg.cmd.request_id, buf_len, msg->request_id, buf_len);
      app_msg->msg.cmd.request_id[buf_len] = '\0';
  
      buf_len = msg->msg_len;
      app_msg->msg.cmd.payload = buf;
      memcpy_s(app_msg->msg.cmd.payload, buf_len, msg->msg, buf_len);
      app_msg->msg.cmd.payload[buf_len] = '\0';
  
      ret = osMessageQueuePut(g_app_cb.app_msg, &app_msg, 0U, CONFIG_QUEUE_TIMEOUT);
      if (ret != 0) {
          free(app_msg);
      }
  
      return ret;
  }
  static void oc_cmdresp(cmd_t* cmd, int cmdret)
  {
      oc_mqtt_profile_cmdresp_t cmdresp;
      ///< do the response
      cmdresp.paras = NULL;
      cmdresp.request_id = cmd->request_id;
      cmdresp.ret_code = cmdret;
      cmdresp.ret_name = NULL;
      (void)oc_mqtt_profile_cmdresp(NULL, &cmdresp);
  }
  ///< COMMAND DEAL
  #include <cJSON.h>
  static void deal_cmd_msg(cmd_t* cmd)
  {
      cJSON* obj_root;
      cJSON* obj_cmdname;
      cJSON* obj_paras;
      cJSON* obj_para;
  
      int cmdret = 1;
  
      obj_root = cJSON_Parse(cmd->payload);
      if (obj_root == NULL) {
          oc_cmdresp(cmd, cmdret);
      }
  
      obj_cmdname = cJSON_GetObjectItem(obj_root, "command_name");
      if (obj_cmdname == NULL) {
          cJSON_Delete(obj_root);
      }
      if (strcmp(cJSON_GetStringValue(obj_cmdname), "Light_Control_Led") == 0) {
          obj_paras = cJSON_GetObjectItem(obj_root, "paras");
          if (obj_paras == NULL) {
              cJSON_Delete(obj_root);
          }
          obj_para = cJSON_GetObjectItem(obj_paras, "Led");
          if (obj_para == NULL) {
              cJSON_Delete(obj_root);
          }
          ///< operate the LED here
          if (strcmp(cJSON_GetStringValue(obj_para), "ON") == 0) {
              g_app_cb.led = 1;
              LightStatusSet(ON);
              printf("Led On!\r\n");
          } else {
              g_app_cb.led = 0;
              LightStatusSet(OFF);
              printf("Led Off!\r\n");
          }
          cmdret = 0;
          oc_cmdresp(cmd, cmdret);
      }
  
      return;
  }
  
  static int CloudMainTaskEntry(void)
  {
      app_msg_t* app_msg;
      uint32_t ret;
  
      WifiConnect(CONFIG_WIFI_SSID, CONFIG_WIFI_PWD);
      dtls_al_init();
      mqtt_al_init();
      oc_mqtt_init();
  
      g_app_cb.app_msg = osMessageQueueNew(MSGQUEUE_COUNT, MSGQUEUE_SIZE, NULL);
      if (g_app_cb.app_msg == NULL) {
          printf("Create receive msg queue failed");
      }
      oc_mqtt_profile_connect_t connect_para;
      (void)memset_s(&connect_para, sizeof(connect_para), 0, sizeof(connect_para));
  
      connect_para.boostrap = 0;
      connect_para.device_id = CONFIG_APP_DEVICEID;
      connect_para.device_passwd = CONFIG_APP_DEVICEPWD;
      connect_para.server_addr = CONFIG_APP_SERVERIP;
      connect_para.server_port = CONFIG_APP_SERVERPORT;
      connect_para.life_time = CONFIG_APP_LIFETIME;
      connect_para.rcvfunc = msg_rcv_callback;
      connect_para.security.type = EN_DTLS_AL_SECURITY_TYPE_NONE;
      ret = oc_mqtt_profile_connect(&connect_para);
      if ((ret == (int)en_oc_mqtt_err_ok)) {
          g_app_cb.connected = 1;
          printf("oc_mqtt_profile_connect succed!\r\n");
      } else {
          printf("oc_mqtt_profile_connect faild!\r\n");
      }
  
      while (1) {
          app_msg = NULL;
          (void)osMessageQueueGet(g_app_cb.app_msg, (void**)&app_msg, NULL, 0xFFFFFFFF);
          if (app_msg != NULL) {
              switch (app_msg->msg_type) {
                  case en_msg_cmd:
                      deal_cmd_msg(&app_msg->msg.cmd);
                      break;
                  case en_msg_report:
                      deal_report_msg(&app_msg->msg.report);
                      break;
                  default:
                      break;
              }
              free(app_msg);
          }
      }
      return 0;
  }
  
  static int SensorTaskEntry(void)
  {
      app_msg_t* app_msg;
      int ret;
      float Lux;
  
      ret = E53SC1Init();
      if (ret != 0) {
          printf("E53_SC1 Init failed!\r\n");
          return;
      }
      while (1) {
          ret = E53SC1ReadData(&Lux);
          if (ret != 0) {
              printf("E53_SC1 Read Data failed!\r\n");
              return;
          }
          app_msg = malloc(sizeof(app_msg_t));
  
          printf("Lux data:%.2f\r\n", Lux);
          if (app_msg != NULL) {
              app_msg->msg_type = en_msg_report;
              app_msg->msg.report.lum = (int)Lux;
              if (osMessageQueuePut(g_app_cb.app_msg, &app_msg, 0U, CONFIG_QUEUE_TIMEOUT) != 0) {
                  free(app_msg);
              }
          }
          sleep(TASK_DELAY);
      }
      return 0;
  }
  
  static void IotMainTaskEntry(void)
  {
      osThreadAttr_t attr;
  
      attr.name = "CloudMainTaskEntry";
      attr.attr_bits = 0U;
      attr.cb_mem = NULL;
      attr.cb_size = 0U;
      attr.stack_mem = NULL;
      attr.stack_size = CLOUD_TASK_STACK_SIZE;
      attr.priority = CLOUD_TASK_PRIO;
  
      if (osThreadNew((osThreadFunc_t)CloudMainTaskEntry, NULL, &attr) == NULL) {
          printf("Failed to create CloudMainTaskEntry!\n");
      }
      attr.stack_size = SENSOR_TASK_STACK_SIZE;
      attr.priority = SENSOR_TASK_PRIO;
      attr.name = "SensorTaskEntry";
      if (osThreadNew((osThreadFunc_t)SensorTaskEntry, NULL, &attr) == NULL) {
          printf("Failed to create SensorTaskEntry!\n");
      }
  }
  
  APP_FEATURE_INIT(IotMainTaskEntry);