#include "fru.h"
#include "com_IPMI_FRU.h"
#include    "goahead.h"
#include    "libipmi_IPM.h"
#include    "com_IPMIDefs.h"
#include    "ResultUtils.h"
#include    "cJSON.h"
#include    "libipmi_storlead_OEM.h"
#include    "libsensor.h"
#include    <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include "libipmi_ChassisDevice.h"
#include <time.h>
#include "com_BmcType.h"
#include <string.h>
#include "libipmi_fru.h"


/*获取FRU信息*/
void getFruChassisInfo(Webs *wp)
{
	int wRet = 0;
	uint32_t fru_size;
	OemFRUChassisInfo_T chassis_data;
	uint8_t fruIndex = 1;	//FRUDeviceID
	char *pTmpStr = NULL;
	uint8_t strLen = 0;

	char *_chassisPartNum=NULL;
	char *_chassisSerialNum=NULL;
	char *_chassisType=NULL;
	char *_chassisCustomField=NULL;
	IPMI20_UDS_SESSION_T    UDSSession;

	//Create session
	LIBIPMI_CreateSession(&UDSSession, DEFAULT_TIMEOUT);
	wRet = LIBIPMI_HL_GetFRUChassisData(&UDSSession,fruIndex,&fru_size,&chassis_data,DEFAULT_TIMEOUT);
	if(wRet==FRU_INVALID_HEADER_VERSION)
	{
		printf("Invalid FRU Header Version for ID : %d\n", fruIndex);
	}
	if(wRet==FRU_INVALID_AREA)
	{
		printf("FRU Invalid Area for ID : %d\n", fruIndex);
	}
	if(wRet!=0)
	{
		printf("Device not present for ID : %d\n", fruIndex);
	}
    //Close session
    LIBIPMI_CloseSession(&UDSSession );

    int i;
    uint8_t *pDebug = (uint8_t*)&chassis_data;
    printf("chassis_info %d: ", fru_size);
    for(i=0;i<fru_size;i++)
    	printf("%#x ", pDebug[i]);
    printf("\n");
	//_chassisPartNum
	strLen = chassis_data.Data[0] & 0x3F;
	pTmpStr = &chassis_data.Data[1];
	_chassisPartNum = walloc(strLen+1);
	memset(_chassisPartNum, 0, strLen+1);
	strncpy(_chassisPartNum, pTmpStr, strLen);
	
	//_chassisSerialNum
	pTmpStr += strLen;
	strLen = pTmpStr[0] & 0x3F;
	pTmpStr++;
	_chassisSerialNum = walloc(strLen+1);
	memset(_chassisSerialNum, 0, strLen+1);
	strncpy(_chassisSerialNum, pTmpStr, strLen);
	
	//extra info
	pTmpStr += strLen;
	strLen = pTmpStr[0] & 0x3F;
	pTmpStr++;
	_chassisCustomField = walloc(strLen+1);
	memset(_chassisCustomField, 0, strLen+1);
	strncpy(_chassisCustomField, pTmpStr, strLen);

	//_chassisType
	_chassisType = walloc(30);
	memset(_chassisType, 0, 30);
	switch(chassis_data.ChassisType)
	{
	case Other:
		strcpy(_chassisType, "Other");
		break;
	case ChassisUnknown:
		strcpy(_chassisType, "ChassisUnknown");
		break;
	case Desktop:
		strcpy(_chassisType, "Desktop");
		break;
	case LowProfileDesktop:
		strcpy(_chassisType, "LowProfileDesktop");
		break;
	case MiniTower:
		strcpy(_chassisType, "MiniTower");
		break;
	case Tower:
		strcpy(_chassisType, "Tower");
		break;
	case Portable:
		strcpy(_chassisType, "Portable");
		break;
	case Notebook:
		strcpy(_chassisType, "Notebook");
		break;
	case HandHeld:
		strcpy(_chassisType, "HandHeld");
		break;
	case DockingStation:
		strcpy(_chassisType, "DockingStation");
		break;
	case AllinOne:
		strcpy(_chassisType, "AllinOne");
		break;
	case SubNotebook:
		strcpy(_chassisType, "SubNotebook");
		break;
	case SpaceSaving:
		strcpy(_chassisType, "SpaceSaving");
		break;
	case LunchBox:
		strcpy(_chassisType, "LunchBox");
		break;
	case MainServerChassis:
		strcpy(_chassisType, "MainServerChassis");
		break;
	case SubChassis:
		strcpy(_chassisType, "SubChassis");
		break;
	case BusExpansionChassis:
		strcpy(_chassisType, "BusExpansionChassis");
		break;
	case PeripheralChassis:
		strcpy(_chassisType, "PeripheralChassis");
		break;
	case RAIDChassis:
		strcpy(_chassisType, "RAIDChassis");
		break;
	case RackMountChassis:
		strcpy(_chassisType, "RackMountChassis");
		break;
	default:
		strcpy(_chassisType, "Unknown");
		break;
	}		


	char *pStr;
    cJSON * root =  cJSON_CreateObject();
    cJSON * data =  cJSON_CreateObject();
    cJSON_AddItemToObject(root, "data", data);
    cJSON_AddStringToObject(root, "msg", "");
    cJSON_AddNumberToObject(root, "code", 200);

    //data
    cJSON_AddStringToObject(data, "Type", _chassisType);
    cJSON_AddStringToObject(data, "PN", _chassisPartNum);
    cJSON_AddStringToObject(data, "SN", _chassisSerialNum);
    cJSON_AddStringToObject(data, "OEM", _chassisCustomField);

    pStr = cJSON_PrintUnformatted(root);
    
    websSetStatus(wp, 200);
    websWriteHeaders(wp, -1, 0);	//Set length to -1 if unknown and transfer-chunk-encoding will be employed.
    websWriteEndHeaders(wp);
    int ret;
    websWrite(wp, "%s", pStr); 
    //printf("---> cJSON Str: %d \n%s\n", strlen(pStr), pStr);
    ret = websFlush(wp, 1);	//wait for all data to be written to the socket 
    if(ret != 1)
    	printf("websFlush ret = %d\n", ret);
    
    websDone(wp);

    if(pStr)
        wfree(pStr);
    if(root)
        cJSON_Delete(root);

    if(_chassisPartNum) 		wfree(_chassisPartNum);
	if(_chassisSerialNum) 		wfree(_chassisSerialNum);
	if(_chassisType) 			wfree(_chassisType);
	if(_chassisCustomField) 	wfree(_chassisCustomField);
	
	printf("getFruChassisInfo over!\n");
}

void getFruBoardInfo(Webs *wp)
{
	int wRet = 0;
	uint32_t fru_size;
	OemFRUBoardInfo_T board_data;
	uint8_t fruIndex = 1;	//FRUDeviceID
	char *pTmpStr = NULL;
	uint8_t strLen = 0;
	time_t tval;
	//char *mfrdate = NULL;
	static const uint32_t  secs_from_1970_1996 = 820450800;

	char *_boardMfr=NULL;
	char *_boardProductName=NULL;
	char *_boardSerialNum=NULL;
	char *_boardPartNum=NULL;
	char *_boardCustomField=NULL;
	char *_MfrDate = NULL;

	IPMI20_UDS_SESSION_T    UDSSession;

	//Create session
	LIBIPMI_CreateSession(&UDSSession, DEFAULT_TIMEOUT);
	wRet = LIBIPMI_HL_GetFRUBoardData(&UDSSession,fruIndex,&fru_size,&board_data,DEFAULT_TIMEOUT);
	if(wRet==FRU_INVALID_HEADER_VERSION)
	{
		printf("Invalid FRU Header Version for ID : %d\n", fruIndex);
	}
	if(wRet==FRU_INVALID_AREA)
	{
		printf("FRU Invalid Area for ID : %d\n", fruIndex);
	}
	if(wRet!=0)
	{
		printf("Device not present for ID : %d\n", fruIndex);
	}
    //Close session
    LIBIPMI_CloseSession(&UDSSession );

	//Manufactor
	strLen = board_data.Data[0] & 0x3F;
	pTmpStr = &board_data.Data[1];
	_boardMfr = walloc(strLen+1);
	memset(_boardMfr, 0, strLen+1);
	strncpy(_boardMfr, pTmpStr, strLen);

	//Product name
	pTmpStr += strLen;
	strLen = pTmpStr[0] & 0x3F;
	pTmpStr++;
	_boardProductName = walloc(strLen+1);
	memset(_boardProductName, 0, strLen+1);
	strncpy(_boardProductName, pTmpStr, strLen);

	//Serial number
	pTmpStr += strLen;
	strLen = pTmpStr[0] & 0x3F;
	pTmpStr++;
	_boardSerialNum = walloc(strLen+1);
	memset(_boardSerialNum, 0, strLen+1);
	strncpy(_boardSerialNum, pTmpStr, strLen);

	//Part number
	pTmpStr += strLen;
	strLen = pTmpStr[0] & 0x3F;
	pTmpStr++;
	_boardPartNum = walloc(strLen+1);
	memset(_boardPartNum, 0, strLen+1);
	strncpy(_boardPartNum, pTmpStr, strLen);

	//FILE ID
	pTmpStr += strLen;
	strLen = pTmpStr[0] & 0x3F;
	pTmpStr++;

	//Extra Info
	pTmpStr += strLen;
	strLen = pTmpStr[0] & 0x3F;
	pTmpStr++;
	_boardCustomField = walloc(strLen+1);
	memset(_boardCustomField, 0, strLen+1);
	strncpy(_boardCustomField, pTmpStr, strLen);

	//Date
	tval = ((board_data.MfgDateTime[2] << 16) + (board_data.MfgDateTime[1] << 8) + (board_data.MfgDateTime[0]));
	tval = tval * 60;
	tval = tval + secs_from_1970_1996;
	_MfrDate = asctime(localtime(&tval));

	char *pStr;
    cJSON * root =  cJSON_CreateObject();
    cJSON * data =  cJSON_CreateObject();
    cJSON_AddItemToObject(root, "data", data);
    cJSON_AddStringToObject(root, "msg", "");
    cJSON_AddNumberToObject(root, "code", 200);

    //data
    cJSON_AddStringToObject(data, "Date", _MfrDate);
    cJSON_AddStringToObject(data, "Mfr", _boardMfr);
    cJSON_AddStringToObject(data, "Name", _boardProductName);
    cJSON_AddStringToObject(data, "SN", _boardSerialNum);
    cJSON_AddStringToObject(data, "PN", _boardPartNum);
    cJSON_AddStringToObject(data, "OEM", _boardCustomField);

    pStr = cJSON_PrintUnformatted(root);
    
    websSetStatus(wp, 200);
    websWriteHeaders(wp, -1, 0);	//Set length to -1 if unknown and transfer-chunk-encoding will be employed.
    websWriteEndHeaders(wp);
    int ret;
    websWrite(wp, "%s", pStr); 
    //printf("---> cJSON Str: %d \n%s\n", strlen(pStr), pStr);
    ret = websFlush(wp, 1);	//wait for all data to be written to the socket 
    if(ret != 1)
    	printf("websFlush ret = %d\n", ret);
    
    websDone(wp);

    if(pStr)
        wfree(pStr);
    if(root)
        cJSON_Delete(root);

    if(_boardMfr) 				wfree(_boardMfr);
	if(_boardProductName) 		wfree(_boardProductName);
	if(_boardSerialNum) 		wfree(_boardSerialNum);
	if(_boardPartNum) 			wfree(_boardPartNum);
	if(_boardCustomField) 		wfree(_boardCustomField);
	if(_MfrDate) 				wfree(_MfrDate);
	
	printf("getFruChassisInfo over!\n");

}

void getFruProductInfo(Webs *wp)
{
	int wRet = 0;
	uint32_t fru_size;
	OemFRUProductInfo_T product_data;
	uint8_t fruIndex = 1;	//FRUDeviceID
	char *pTmpStr = NULL;
	uint8_t strLen = 0;
	
	char *_ProductName=NULL;
	char *_ProductPartNum=NULL;
	char *_ProductVersion=NULL;
	char *_ProductSerialNum=NULL;
	char *_productCustomField=NULL;
	char *_MfrName=NULL;
	IPMI20_UDS_SESSION_T    UDSSession;

	//Create session
	LIBIPMI_CreateSession(&UDSSession, DEFAULT_TIMEOUT);
	wRet = LIBIPMI_HL_GetFRUProductData(&UDSSession,fruIndex,&fru_size,&product_data,DEFAULT_TIMEOUT);
	if(wRet==FRU_INVALID_HEADER_VERSION)
	{
		printf("Invalid FRU Header Version for ID : %d\n", fruIndex);
	}
	if(wRet==FRU_INVALID_AREA)
	{
		printf("FRU Invalid Area for ID : %d\n", fruIndex);
	}
	if(wRet!=0)
	{
		printf("Device not present for ID : %d\n", fruIndex);
	}
    //Close session
    LIBIPMI_CloseSession(&UDSSession );

	//Manufactor
	strLen = product_data.Data[0] & 0x3F;
	pTmpStr = &product_data.Data[1];
	_MfrName = walloc(strLen+1);
	memset(_MfrName, 0, strLen+1);
	strncpy(_MfrName, pTmpStr, strLen);

	//Product Name
	pTmpStr += strLen;
	strLen = pTmpStr[0] & 0x3F;
	pTmpStr++;
	_ProductName = walloc(strLen+1);
	memset(_ProductName, 0, strLen+1);
	strncpy(_ProductName, pTmpStr, strLen);

	//Part Number
	pTmpStr += strLen;
	strLen = pTmpStr[0] & 0x3F;
	pTmpStr++;
	_ProductPartNum = walloc(strLen+1);
	memset(_ProductPartNum, 0, strLen+1);
	strncpy(_ProductPartNum, pTmpStr, strLen);

	//Version
	pTmpStr += strLen;
	strLen = pTmpStr[0] & 0x3F;
	pTmpStr++;
	_ProductVersion = walloc(strLen+1);
	memset(_ProductVersion, 0, strLen+1);
	strncpy(_ProductVersion, pTmpStr, strLen);

	//Serial Number
	pTmpStr += strLen;
	strLen = pTmpStr[0] & 0x3F;
	pTmpStr++;
	_ProductSerialNum = walloc(strLen+1);
	memset(_ProductSerialNum, 0, strLen+1);
	strncpy(_ProductSerialNum, pTmpStr, strLen);

	//Assert Tag
	pTmpStr += strLen;
	strLen = pTmpStr[0] & 0x3F;
	pTmpStr++;
	// _AssetTag = walloc(strLen+1);
	// memset(_AssetTag, 0, strLen+1);
	// strncpy(_AssetTag, pTmpStr, strLen);

	//File ID
	pTmpStr += strLen;
	strLen = pTmpStr[0] & 0x3F;
	pTmpStr++;
	// _FRUFileID = walloc(strLen+1);
	// memset(_FRUFileID, 0, strLen+1);
	// strncpy(_FRUFileID, pTmpStr, strLen);

	//Extra info
	pTmpStr += strLen;
	strLen = pTmpStr[0] & 0x3F;
	pTmpStr++;
	_productCustomField = walloc(strLen+1);
	memset(_productCustomField, 0, strLen+1);
	strncpy(_productCustomField, pTmpStr, strLen);

	char *pStr;
    cJSON * root =  cJSON_CreateObject();
    cJSON * data =  cJSON_CreateObject();
    cJSON_AddItemToObject(root, "data", data);
    cJSON_AddStringToObject(root, "msg", "");
    cJSON_AddNumberToObject(root, "code", 200);
    cJSON_AddStringToObject(data, "Mfr", _MfrName);
    cJSON_AddStringToObject(data, "Name", _ProductName);
    cJSON_AddStringToObject(data, "PN", _ProductPartNum);
    cJSON_AddStringToObject(data, "Ver", _ProductVersion);
    cJSON_AddStringToObject(data, "SN", _ProductSerialNum);
    cJSON_AddStringToObject(data, "OEM", _productCustomField);
    pStr = cJSON_PrintUnformatted(root);
    
    websSetStatus(wp, 200);
    websWriteHeaders(wp, -1, 0);	//Set length to -1 if unknown and transfer-chunk-encoding will be employed.
    websWriteEndHeaders(wp);
    int ret;
    websWrite(wp, "%s", pStr); 
    //printf("---> cJSON Str: %d \n%s\n", strlen(pStr), pStr);
    ret = websFlush(wp, 1);	//wait for all data to be written to the socket 
    if(ret != 1)
    	printf("websFlush ret = %d\n", ret);
    
    websDone(wp);

    if(pStr)
        wfree(pStr);
    if(root)
        cJSON_Delete(root);

    if(_MfrName) 				wfree(_MfrName);
    if(_ProductName) 			wfree(_ProductName);
	if(_ProductPartNum) 		wfree(_ProductPartNum);
	if(_ProductVersion) 		wfree(_ProductVersion);
	if(_ProductSerialNum) 		wfree(_ProductSerialNum);
	if(_productCustomField) 	wfree(_productCustomField);
	
	printf("getFruChassisInfo over!\n");

}


// /*获取FRU信息*/
// void getFruInfo(Webs *wp)
// {
// 	int wRet = 0;
// 	uint32_t fru_size;
// 	OemFRUData_T fru_data;
// 	uint8_t fruIndex = 1;	//FRUDeviceID
// 	char *pTmpStr = NULL;
// 	uint8_t strLen = 0;

// 	time_t tval;
// 	//char *mfrdate = NULL;
// 	static const uint32_t  secs_from_1970_1996 = 820450800;

// 	char *_chassisPartNum=NULL;
// 	char *_chassisSerialNum=NULL;
// 	char *_chassisType=NULL;
// 	char *_chassisCustomField=NULL;
// 	char *_boardMfr=NULL;
// 	char *_boardProductName=NULL;
// 	char *_boardSerialNum=NULL;
// 	char *_boardPartNum=NULL;
// 	char *_boardCustomField=NULL;
// 	char *_MfrName=NULL;
// 	char *_MfrDate = NULL;
// 	char *_ProductName=NULL;
// 	char *_ProductPartNum=NULL;
// 	char *_ProductVersion=NULL;
// 	char *_ProductSerialNum=NULL;
// 	char *_productCustomField=NULL;
// 	IPMI20_UDS_SESSION_T    UDSSession;

// 	//Create session
// 	LIBIPMI_CreateSession(&UDSSession, DEFAULT_TIMEOUT);
// 	wRet = LIBIPMI_HL_GetFRUData(&UDSSession,fruIndex,&fru_size,&fru_data,DEFAULT_TIMEOUT);
// 	if(wRet==FRU_INVALID_HEADER_VERSION)
// 	{
// 		printf("Invalid FRU Header Version for ID : %d\n", fruIndex);
// 	}
// 	if(wRet==FRU_INVALID_AREA)
// 	{
// 		printf("FRU Invalid Area for ID : %d\n", fruIndex);
// 	}
// 	if(wRet!=0)
// 	{
// 		printf("Device not present for ID : %d\n", fruIndex);
// 	}
//     //Close session
//     LIBIPMI_CloseSession(&UDSSession );

// 	//Get ChassisInfo
// 	if(fru_data.CommonHeader.ChassisInfoAreaStartOffset != 0)
// 	{
// 		//_chassisPartNum
// 		strLen = fru_data.ChassisInfo.Data[0] & 0x3F;
// 		pTmpStr = &fru_data.ChassisInfo.Data[1];
// 		_chassisPartNum = walloc(strLen+1);
// 		memset(_chassisPartNum, 0, strLen+1);
// 		strncpy(_chassisPartNum, pTmpStr, strLen);
		
// 		//_chassisSerialNum
// 		pTmpStr += strLen;
// 		strLen = pTmpStr[0] & 0x3F;
// 		pTmpStr++;
// 		_chassisSerialNum = walloc(strLen+1);
// 		memset(_chassisSerialNum, 0, strLen+1);
// 		strncpy(_chassisSerialNum, pTmpStr, strLen);
		
// 		//extra info
// 		pTmpStr += strLen;
// 		strLen = pTmpStr[0] & 0x3F;
// 		pTmpStr++;
// 		_chassisCustomField = walloc(strLen+1);
// 		memset(_chassisCustomField, 0, strLen+1);
// 		strncpy(_chassisCustomField, pTmpStr, strLen);

// 		//_chassisType
// 		_chassisType = walloc(30);
// 		memset(_chassisType, 0, 30);
// 		switch(fru_data.ChassisInfo.ChassisType)
// 		{
// 		case Other:
// 			strcpy(_chassisType, "Other");
// 			break;
//     	case ChassisUnknown:
// 			strcpy(_chassisType, "ChassisUnknown");
// 			break;
//     	case Desktop:
// 			strcpy(_chassisType, "Desktop");
// 			break;
//     	case LowProfileDesktop:
// 			strcpy(_chassisType, "LowProfileDesktop");
// 			break;
//     	case MiniTower:
// 			strcpy(_chassisType, "MiniTower");
// 			break;
//     	case Tower:
// 			strcpy(_chassisType, "Tower");
// 			break;
//     	case Portable:
// 			strcpy(_chassisType, "Portable");
// 			break;
//     	case Notebook:
// 			strcpy(_chassisType, "Notebook");
// 			break;
//     	case HandHeld:
// 			strcpy(_chassisType, "HandHeld");
// 			break;
//     	case DockingStation:
// 			strcpy(_chassisType, "DockingStation");
// 			break;
//     	case AllinOne:
// 			strcpy(_chassisType, "AllinOne");
// 			break;
//     	case SubNotebook:
// 			strcpy(_chassisType, "SubNotebook");
// 			break;
//     	case SpaceSaving:
// 			strcpy(_chassisType, "SpaceSaving");
// 			break;
//     	case LunchBox:
// 			strcpy(_chassisType, "LunchBox");
// 			break;
//     	case MainServerChassis:
// 			strcpy(_chassisType, "MainServerChassis");
// 			break;
//     	case SubChassis:
// 			strcpy(_chassisType, "SubChassis");
// 			break;
//     	case BusExpansionChassis:
// 			strcpy(_chassisType, "BusExpansionChassis");
// 			break;
//     	case PeripheralChassis:
// 			strcpy(_chassisType, "PeripheralChassis");
// 			break;
//     	case RAIDChassis:
// 			strcpy(_chassisType, "RAIDChassis");
// 			break;
//     	case RackMountChassis:
// 			strcpy(_chassisType, "RackMountChassis");
// 			break;
// 		default:
// 			strcpy(_chassisType, "Unknown");
// 			break;
// 		}		
// 	}
	
// 	//Get BoardInfo
// 	if(fru_data.CommonHeader.BoardInfoAreaStartOffset != 0)
// 	{
// 		//Manufactor
// 		strLen = fru_data.BoardInfo.Data[0] & 0x3F;
// 		pTmpStr = &fru_data.BoardInfo.Data[1];
// 		_boardMfr = walloc(strLen+1);
// 		memset(_boardMfr, 0, strLen+1);
// 		strncpy(_boardMfr, pTmpStr, strLen);

// 		//Product name
// 		pTmpStr += strLen;
// 		strLen = pTmpStr[0] & 0x3F;
// 		pTmpStr++;
// 		_boardProductName = walloc(strLen+1);
// 		memset(_boardProductName, 0, strLen+1);
// 		strncpy(_boardProductName, pTmpStr, strLen);

// 		//Serial number
// 		pTmpStr += strLen;
// 		strLen = pTmpStr[0] & 0x3F;
// 		pTmpStr++;
// 		_boardSerialNum = walloc(strLen+1);
// 		memset(_boardSerialNum, 0, strLen+1);
// 		strncpy(_boardSerialNum, pTmpStr, strLen);

// 		//Part number
// 		pTmpStr += strLen;
// 		strLen = pTmpStr[0] & 0x3F;
// 		pTmpStr++;
// 		_boardPartNum = walloc(strLen+1);
// 		memset(_boardPartNum, 0, strLen+1);
// 		strncpy(_boardPartNum, pTmpStr, strLen);

// 		//FILE ID
// 		pTmpStr += strLen;
// 		strLen = pTmpStr[0] & 0x3F;
// 		pTmpStr++;

// 		//Extra Info
// 		pTmpStr += strLen;
// 		strLen = pTmpStr[0] & 0x3F;
// 		pTmpStr++;
// 		_boardCustomField = walloc(strLen+1);
// 		memset(_boardCustomField, 0, strLen+1);
// 		strncpy(_boardCustomField, pTmpStr, strLen);

// 		//Date
// 		tval = ((fru_data.BoardInfo.MfgDateTime[2] << 16) + (fru_data.BoardInfo.MfgDateTime[1] << 8) + (fru_data.BoardInfo.MfgDateTime[0]));
// 		tval = tval * 60;
// 		tval = tval + secs_from_1970_1996;
// 		_MfrDate = asctime(localtime(&tval));
// 	}

// 	//Get Product Info
// 	if(fru_data.CommonHeader.ProductInfoAreaStartOffset != 0)
// 	{
// 		//Manufactor
// 		strLen = fru_data.ProductInfo.Data[0] & 0x3F;
// 		pTmpStr = &fru_data.ProductInfo.Data[1];
// 		_MfrName = walloc(strLen+1);
// 		memset(_MfrName, 0, strLen+1);
// 		strncpy(_MfrName, pTmpStr, strLen);

// 		//Product Name
// 		pTmpStr += strLen;
// 		strLen = pTmpStr[0] & 0x3F;
// 		pTmpStr++;
// 		_ProductName = walloc(strLen+1);
// 		memset(_ProductName, 0, strLen+1);
// 		strncpy(_ProductName, pTmpStr, strLen);

// 		//Part Number
// 		pTmpStr += strLen;
// 		strLen = pTmpStr[0] & 0x3F;
// 		pTmpStr++;
// 		_ProductPartNum = walloc(strLen+1);
// 		memset(_ProductPartNum, 0, strLen+1);
// 		strncpy(_ProductPartNum, pTmpStr, strLen);

// 		//Version
// 		pTmpStr += strLen;
// 		strLen = pTmpStr[0] & 0x3F;
// 		pTmpStr++;
// 		_ProductVersion = walloc(strLen+1);
// 		memset(_ProductVersion, 0, strLen+1);
// 		strncpy(_ProductVersion, pTmpStr, strLen);

// 		//Serial Number
// 		pTmpStr += strLen;
// 		strLen = pTmpStr[0] & 0x3F;
// 		pTmpStr++;
// 		_ProductSerialNum = walloc(strLen+1);
// 		memset(_ProductSerialNum, 0, strLen+1);
// 		strncpy(_ProductSerialNum, pTmpStr, strLen);

// 		//Assert Tag
// 		pTmpStr += strLen;
// 		strLen = pTmpStr[0] & 0x3F;
// 		pTmpStr++;
// 		// _AssetTag = walloc(strLen+1);
// 		// memset(_AssetTag, 0, strLen+1);
// 		// strncpy(_AssetTag, pTmpStr, strLen);

// 		//File ID
// 		pTmpStr += strLen;
// 		strLen = pTmpStr[0] & 0x3F;
// 		pTmpStr++;
// 		// _FRUFileID = walloc(strLen+1);
// 		// memset(_FRUFileID, 0, strLen+1);
// 		// strncpy(_FRUFileID, pTmpStr, strLen);

// 		//Extra info
// 		pTmpStr += strLen;
// 		strLen = pTmpStr[0] & 0x3F;
// 		pTmpStr++;
// 		_productCustomField = walloc(strLen+1);
// 		memset(_productCustomField, 0, strLen+1);
// 		strncpy(_productCustomField, pTmpStr, strLen);
// 	}

// 	char *pStr1, *pStr2, *pStr3;
//     cJSON * chassis =  cJSON_CreateObject();
//     cJSON * board =  cJSON_CreateObject();
//     cJSON * product =  cJSON_CreateObject();
//     //chassis
//     cJSON_AddStringToObject(chassis, "Type", _chassisType);
//     cJSON_AddStringToObject(chassis, "PN", _chassisPartNum);
//     cJSON_AddStringToObject(chassis, "SN", _chassisSerialNum);
//     cJSON_AddStringToObject(chassis, "OEM", _chassisCustomField);

//     //board
//     cJSON_AddStringToObject(board, "Date", _MfrDate);
//     cJSON_AddStringToObject(board, "Mfr", _boardMfr);
//     cJSON_AddStringToObject(board, "Name", _boardProductName);
//     cJSON_AddStringToObject(board, "SN", _boardSerialNum);
//     cJSON_AddStringToObject(board, "PN", _boardPartNum);
//     cJSON_AddStringToObject(board, "OEM", _boardCustomField);

//     //product
//     cJSON_AddStringToObject(product, "Mfr", _MfrName);
//     cJSON_AddStringToObject(product, "Name", _ProductName);
//     cJSON_AddStringToObject(product, "PN", _ProductPartNum);
//     cJSON_AddStringToObject(product, "Ver", _ProductVersion);
//     cJSON_AddStringToObject(product, "SN", _ProductSerialNum);
//     cJSON_AddStringToObject(product, "OEM", _productCustomField);

//     pStr1 = cJSON_PrintUnformatted(chassis);
//     pStr2 = cJSON_PrintUnformatted(board);
//     pStr3 = cJSON_PrintUnformatted(product);
    
//     websSetStatus(wp, 200);
//     websWriteHeaders(wp, -1, 0);	//Set length to -1 if unknown and transfer-chunk-encoding will be employed.
//     websWriteEndHeaders(wp);
//     int ret;
//     //websWrite(wp, "{\n");
//     websWrite(wp, "%s", pStr1); printf("---> cJSON Str1: %d \n%s\n", strlen(pStr1), pStr1);
//     //websWrite(wp, "%s", pStr2); printf("---> cJSON Str2: %d \n%s\n", strlen(pStr2), pStr2);
//     //websWrite(wp, "%s", pStr3); printf("---> cJSON Str3: %d \n%s\n", strlen(pStr3), pStr3);
//     //websWrite(wp, "msg:\"\",\ncode:200\n}");
    
//     ret = websFlush(wp, 1);	//wait for all data to be written to the socket 
//     //if(ret != 1)
//     	printf("websFlush ret = %d\n", ret);
    
//     websDone(wp);

//     if(pStr1)
//         wfree(pStr1);
//     if(pStr2)
//         wfree(pStr2);
//     if(pStr3)
//         wfree(pStr3);
//     if(chassis)
//         cJSON_Delete(chassis);
//     if(board)
//         cJSON_Delete(board);
//     if(product)
//         cJSON_Delete(product);

//     if(_chassisPartNum) 		wfree(_chassisPartNum);
// 	if(_chassisSerialNum) 		wfree(_chassisSerialNum);
// 	if(_chassisType) 			wfree(_chassisType);
// 	if(_chassisCustomField) 	wfree(_chassisCustomField);
// 	if(_boardMfr) 				wfree(_boardMfr);
// 	if(_boardProductName) 		wfree(_boardProductName);
// 	if(_boardSerialNum) 		wfree(_boardSerialNum);
// 	if(_boardPartNum) 			wfree(_boardPartNum);
// 	if(_boardCustomField) 		wfree(_boardCustomField);
// 	if(_MfrName) 				wfree(_MfrName);
// 	if(_MfrDate) 				wfree(_MfrDate);
// 	if(_ProductName) 			wfree(_ProductName);
// 	if(_ProductPartNum) 		wfree(_ProductPartNum);
// 	if(_ProductVersion) 		wfree(_ProductVersion);
// 	if(_ProductSerialNum) 		wfree(_ProductSerialNum);
// 	if(_productCustomField) 	wfree(_productCustomField);
// 	printf("getFruInfo over!\n");
// }
