Back to All
Project

MDM9206 Gizwits Cloud Connection


Skill Level Area of Focus Operating System Platform/Hardware Cloud Services/Platform
Intermediate Embedded, IoT RTOS Qualcomm® MDM920x LTE for IoT Gizwits Cloud Platform

This project is designed to use the GoKit4 development kit to send local data to the Gizwits cloud.

Objective

The main objective of this project is to get used to the Gizwits GoKit 4 development kit and cloud services.

Materials Required / Parts List / Tools

Gizwits

Source Code / Source Examples / Application Executable

Build / Assembly Instructions

Parts used

Below are the items used in this project:

  1. Mobile phone which has installed a universal APK provided by Gizwits cloud, and is used to see data from the local device
  2. GoKit4 development board
  3. USB data line, used to supply power to the GoKit4 board
  4. Win7 PC, allows user to view data from the local device on the Gizwits cloud

Deploying the project

  1. First step is to define products on the Gizwits cloud platform, including basic information, data points, hardware solution, etc.
  2. Generate code based on the SOC scheme. (Because the Gizwits cloud does not currently support generating code based on the MDM9206 platform, we need to choose ESP_826632M at hardware platform, then do some modifications.)
  3. Add local data which will be sent to Gizwits cloud.
  4. Register the mobile IoT card to NB-IoT network.
  5. Compile the code and flash the image.

 

How does it work?

First, we must know how data was sent to the Gizwits cloud.

The reporting process is as follows:

userTimeCB----->gizwitsHandle----->gizCheckReport---->gizDataPoints2ReportData----->gagentUploadData

demo-Gizwits-cloud-connection/main/main.c

void gagentMain( void )
{
    getFreeHeap();
    sensorInit();
    gizwitsInit();
}

The function "gagentMain" does the data forwarding and acts as an interaction bridge between the device data, cloud, and the application. Function "sensorInit", initiates the sensor peripherals along with a timer function called tx_timer_create.

void sensorInit(void)
{
    int32 ret = -1;
    gizLog(LOG_INFO,"Sensor initialization ...\n"); 
led_init();					//led  init
motor_init();					//motor init
heartrate_init();				//plusensor init
motion_init();				//adxl345 init
pressure_init();				//fsr402 init
    txm_module_object_allocate(&userTimer, sizeof(TX_TIMER));
    ret = tx_timer_create(userTimer, "userTimer", userTimerCB, NULL, 1,
                          200, TX_AUTO_ACTIVATE);			
    if(ret != TX_SUCCESS)
    {
        gizLog(LOG_WARNING,"Failed to create UserTimer.\n");
    }
}

"userTimeCB" is registered in "tx_timer_create", and the callback function is called back at regular intervals. It is used to obtain user data reports.

void ICACHE_FLASH_ATTR userTimerCB(void)
{
  gizLog(LOG_INFO,"in userTimerCB.....\n"); 
              static uint8_t ctime = 0;
              static uint8_t ccount = 0;
  int8_t status = 0;

  // set some value, which will be sent to GIzwits cloud.
  uint32_t pressure = 80;			//pressure
  uint32_t heartrate = 75;		              //heartbeat
  int32_t X_axis_Value = 50;	  	//x axis value
  int32_t Y_axis_Value = 60;                         //y axis value
  int32_t Z_axis_Value = 70;                         //z axis value
  
  if (QUERY_INTERVAL < ctime)			
  {
    ctime = 0;		//come in per 5 times
    //status = getHeartRateValue(&heartrate); 	//heartrate from Pulsesensor
    if( status )
    {
      gizLog(LOG_INFO,"get health info error\n"); 
        
    }
    currentDataPoint.valueHeartRateValue = heartrate;
    if(currentDataPoint.valueHeartRateValue > HEART_RATE_THRESHOLD)				{
      //set_gpio_value(0x00, led_pin_num_Pulsesensor);
    }
    //status = getaxis(&X_axis_Value,&Y_axis_Value,&Z_axis_Value);	//axis from ADXL345
    if( status )
    {
      gizLog(LOG_INFO,"get stepcount error\n"); 
          
    }
    currentDataPoint.valueX_axis_Value = X_axis_Value;
    currentDataPoint.valueY_axis_Value = Y_axis_Value;
    currentDataPoint.valueZ_axis_Value = Z_axis_Value;		
    if(currentDataPoint.valueX_axis_Value > X_AXIS_THRESHOLD || currentDataPoint.valueY_axis_Value > Y_AXIS_THRESHOLD
                  || currentDataPoint.valueZ_axis_Value > Z_AXIS_THRESHOLD)		
    {
      //set_gpio_value(0x00, led_pin_num_motion);
    }
    //status = getPressValue(&pressure);		//pressure pressure sensor
    if( status )
    {
      gizLog(LOG_INFO,"get pressure error\n"); 
    }
    currentDataPoint.valuePressure_Value = pressure;

    if (currentDataPoint.valuePressure_Value >= PRESSURE_THRESHOLD)			
    {
      set_gpio_value(0x00, motor_pin_num);
    }
    gizLog(LOG_INFO,"begin to upload data\n"); 
    gizwitsHandle((dataPoint_t *)&currentDataPoint);
    ccount++;				//record collect times
    gizLog(LOG_INFO,"ccount = %d\n", ccount); 
  }
    ctime++;  
}

"gizwitsHandle" is used to complete the change of device data at the following location.

demo-Gizwits-cloud-connection/Gizwits/gizwits_protocol.c

int8_t ICACHE_FLASH_ATTR gizwitsHandle(dataPoint_t *dataPoint)
{
    if(NULL == dataPoint)
    {
        gizLog(LOG_WARNING,"!!! gizReportData Error \n");
        return (-1);
    }
    //Regularly report conditional
    if((1 == gizCheckReport(dataPoint, (dataPoint_t *)&gizwitsProtocol.gizLastDataPoint)))
    {
        gizDataPoints2ReportData(dataPoint, &gizwitsProtocol.reportData.devStatus);
        gizwitsProtocol.reportData.action = ACTION_REPORT_DEV_STATUS;
        gagentUploadData(NULL, (uint8_t *)&gizwitsProtocol.reportData, sizeof(gizwitsReport_t),getConnectM2MStatus(),gizwitsProtocol.mac, uploadDataCBFunc);
        gizLog(LOG_INFO,"~~~reportData \n"); 
        //printf_bufs((uint8_t *)&gizwitsProtocol.reportData, sizeof(gizwitsReport_t));
        gizMemcpy((uint8_t *)&gizwitsProtocol.gizLastDataPoint, (uint8_t *)dataPoint, sizeof(dataPoint_t));
    }
    return 0;
}
gizCheckReport is used to determine whether to report the current status data.
static int8_t ICACHE_FLASH_ATTR gizCheckReport(dataPoint_t *cur, dataPoint_t *last)
{
    int8_t ret = 0;
    static uint32_t lastReportTime = 0;
    uint32_t currentTime = 0;
    if((NULL == cur) || (NULL == last))
    {
        gizLog(LOG_WARNING,"gizCheckReport Error , Illegal Param\n");
        return -1;
    }
    currentTime = gizGetTimerCount();
    if(last->valueLedValue != cur->valueLedValue)
    {
        gizLog(LOG_INFO,"valueLedValue Changed\n");
        ret = 1;
}
.......
    if(last->valuePressure_Value != cur->valuePressure_Value)
    {
        if(currentTime - lastReportTime >= REPORT_TIME_MAX)
        {
            gizLog(LOG_INFO, "valuePressure_Value Changed\n");
            ret = 1;
        }
    }
    if(1 == ret)
    {
        lastReportTime = gizGetTimerCount();
    }
    return ret;
}

gizDataPoints2ReportData is used to complete the conversion of user area data to report type data.

static int8_t ICACHE_FLASH_ATTR gizDataPoints2ReportData(dataPoint_t *dataPoints , devStatus_t *devStatusPtr)
{
    if((NULL == dataPoints) || (NULL == devStatusPtr))
    {
        gizLog(LOG_WARNING,"gizDataPoints2ReportData Error , Illegal Param\n");
        return -1;
    }
    gizMemset((uint8_t *)devStatusPtr->wBitBuf,0,sizeof(devStatusPtr->wBitBuf));
gizStandardCompressValue(LedValue_BYTEOFFSET,LedValue_BITOFFSET,LedValue_LEN,(uint8_t *)devStatusPtr,dataPoints->valueLedValue);
gizStandardCompressValue(MotorValue_BYTEOFFSET,MotorValue_BITOFFSET,MotorValue_LEN,(uint8_t *)devStatusPtr,dataPoints->valueMotorValue);
    gizByteOrderExchange((uint8_t *)devStatusPtr->wBitBuf,sizeof(devStatusPtr->wBitBuf));
    devStatusPtr->valueHeartRateValue = gizY2X(HeartRateValue_RATIO,  HeartRateValue_ADDITION, dataPoints->valueHeartRateValue); 
    devStatusPtr->valueX_axis_Value = exchangeBytes(gizY2X(X_axis_Value_RATIO,  X_axis_Value_ADDITION, dataPoints->valueX_axis_Value)); 
    devStatusPtr->valueY_axis_Value = exchangeBytes(gizY2X(Y_axis_Value_RATIO,  Y_axis_Value_ADDITION, dataPoints->valueY_axis_Value)); 
    devStatusPtr->valueZ_axis_Value = exchangeBytes(gizY2X(Z_axis_Value_RATIO,  Z_axis_Value_ADDITION, dataPoints->valueZ_axis_Value)); 
    devStatusPtr->valuePressure_Value = exchangeBytes(gizY2X(Pressure_Value_RATIO,  Pressure_Value_ADDITION, dataPoints->valuePressure_Value)); 
    return 0;
}

"gagentUploadData" is used to send the reported data to the communication module.

After the above steps, user area data will be uploaded to the Gizwits cloud. Below are some usage instructions to test the project.

Usage Instructions

  1. Download code from github according to the repository in “https://github.com/ThunderSoft-XA/demo-Gizwits-cloud-connection”
  2. Compile the code and flash the image to GoKit4 development kit.
  3. Use USB data line to supply power.
  4. Click on “Device log” in Gizwits cloud to check if device is online.
  5. When the device is online, click “view” button, and you will see data from the local device that was sent to Gizwits cloud.
Gizwits

You can also see that data from an Android phone with a universal APK provided by Gizwits cloud, and it’s easy to operate.

Opinions expressed in the content posted here are the personal opinions of the original authors, and do not necessarily reflect those of Qualcomm Incorporated or its subsidiaries ("Qualcomm"). The content is provided for informational purposes only and is not meant to be an endorsement or representation by Qualcomm or any other party. This site may also provide links or references to non-Qualcomm sites and resources. Qualcomm makes no representations, warranties, or other commitments whatsoever about any non-Qualcomm sites or third-party resources that may be referenced, accessible from, or linked to this site.

Project Authors
Thunder Software Technology (Shenzhen) Co., Ltd.
Shenzhen
Zhen
Rong
Kou
Jie
Eric

Sign up for the Developer Newsletter.

Get software and hardware tool resources to help optimize your development delivered to your inbox weekly.

© Qualcomm Technologies, Inc. and/or its affiliated companies.

Snapdragon and Qualcomm branded products are products of Qualcomm Technologies, Inc. and/or its subsidiaries. Qualcomm patents are licensed by Qualcomm Incorporated.

Note: Certain services and materials may require you to accept additional terms and conditions before accessing or using those items.

References to "Qualcomm" may mean Qualcomm Incorporated, or subsidiaries or business units within the Qualcomm corporate structure, as applicable.

Qualcomm Incorporated includes our licensing business, QTL, and the vast majority of our patent portfolio. Qualcomm Technologies, Inc., a subsidiary of Qualcomm Incorporated, operates, along with its subsidiaries, substantially all of our engineering, research and development functions, and substantially all of our products and services businesses, including our QCT semiconductor business.

Materials that are as of a specific date, including but not limited to press releases, presentations, blog posts and webcasts, may have been superseded by subsequent events or disclosures.

Nothing in these materials is an offer to sell or license any of the services or materials referenced herein.