MDM9206 Gizwits Cloud Connection

Skill LevelArea of FocusOperating SystemPlatform/HardwareCloud Services/Platform
IntermediateEmbedded, IoTRTOSQualcomm® MDM920x LTE for IoTGizwits Cloud Platform

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

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

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.

  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 cloud dashboard showing data from the local device.

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

NameEmailTitle/Company
Zhen[email protected]Thundersoft
Rong[email protected]Thundersoft
Jie[email protected]Thundersoft
Kou[email protected]Thundersoft
Eric[email protected]Thundersoft