/*
 * Module_DcMeter.c
 *
 *  Created on: 2021/5/31
 *      Author: foluswen
 */
#include "Module_DcMeter.h"
#include "meterComm.h"
#include "Module_RatedCurrent.h"

/**
 * Initial share memory
 * @return
 */
int InitShareMemory()
{
	int result = PASS;
	int MeterSMId;

	//Initialize ShmSysConfigAndInfo
	if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo),  0777)) < 0)
    {
		DEBUG_ERROR("shmget ShmSysConfigAndInfo NG\n");
		result = FAIL;
	}
    else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1)
    {
    	DEBUG_ERROR("shmat ShmSysConfigAndInfo NG\n");
    	result = FAIL;
   	 }
    else
    {}

   	//Initialize ShmStatusCodeData
   	if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData),  0777)) < 0)
    {
   		DEBUG_ERROR("shmget ShmStatusCodeData NG\n");
   		result = FAIL;
	}
    else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
    {
    	DEBUG_ERROR("shmat ShmStatusCodeData NG\n");
    	result = FAIL;
   	}
    else
    {}

   	//Initialize ShmStatusCodeData
   	/*
   	if ((MeterSMId = shmget(ShmMeter_info, sizeof(struct METER_INFO),  0777)) < 0)
    {
   		DEBUG_ERROR("shmget ShmStatusCodeData NG\n");
   		result = FAIL;
	}
    else if ((ShmMeter_info = shmat(MeterSMId, NULL, 0)) == (void *) -1)
    {
    	DEBUG_ERROR("shmat ShmMeter_info NG\n");
    	result = FAIL;
   	}
    else
    {}
    */
    
    return result;
}

//==========================================
// Main loop
//==========================================
int main(void)
{
	ParsingRatedCur modelnameInfo = {0};
	Meter_Info meter_info[4];
	uint8_t pollingIndex = 0;
	uint8_t	meterIndex = 0;
	uint8_t failCount[4];

#ifndef DEBUG_STANDALONG
	// Initialize share memory
	if(InitShareMemory() == FAIL)
	{
		DEBUG_ERROR("InitShareMemory NG\n");

		if(ShmStatusCodeData!=NULL)
		{
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FailToCreateShareMemory=ON;
		}
		sleep(5);
		return -1;
	}

	RatedCurrentParsing((char*)ShmSysConfigAndInfo->SysConfig.ModelName, &modelnameInfo);

#else
	modelnameInfo.GetGunCount = 4;

#endif//DEBUG_STANDALONG

	
	// Initialize DC meter model
	/*
	 *	TODO:
	 *		1. Maybe need to parse configuration by model name
	 */
	meterInitialize(METER_MODEL_LEM_L18005A);
	
	
	DEBUG_INFO("modelnameInfo.GetGunCount : %d \n", modelnameInfo.GetGunCount);

	// Main loop
	for(;;)
	{
		for(uint8_t gun_index=0;gun_index<modelnameInfo.GetGunCount;gun_index++)
		{
			if(gun_index == 0)
				meterIndex = 0;
			meterIndex = gun_index;

			if(modelnameInfo.ParsingInfo[gun_index].GunType != Gun_Type_AC)
			{
				meterApiAssign(meterIndex);
				
				for(pollingIndex=0;pollingIndex<4;pollingIndex++)
				{
					switch(pollingIndex)
					{
						case 0:
							if(readCurrent(&meter_info[meterIndex]) != FAIL)
							{
								#ifndef DEBUG_STANDALONG
								/*
								 *	TODO:
								 *		1. Synchronize data to share memory
								 */
								 
								 ShmSysConfigAndInfo->SysInfo.DcMeterInfo[meterIndex].presentCurrent = meter_info[meterIndex].presentCurrent;
								 #ifdef DEBUG_SHAREMEM_LOG
								 DEBUG_INFO("shm Output current %d : %.3f A\n", meterIndex, ShmSysConfigAndInfo->SysInfo.DcMeterInfo[meterIndex].presentCurrent);
								 #endif
								 
								#else
								DEBUG_INFO("Output current %d : %.3f A\n", meterIndex, meter_info[meterIndex].presentCurrent);
								#endif//DEBUG_STANDALONG
								//pollingIndex++;
								failCount[meterIndex] = 0;
							}
							else
							{
								if(failCount[meterIndex] < 10)
									failCount[meterIndex]++;
							}
							break;
						case 1:
							if(readVoltage(&meter_info[meterIndex]) != FAIL)
							{
								#ifndef DEBUG_STANDALONG
								/*
								 *	TODO:
								 *		1. Synchronize data to share memory
								 */
								 
								ShmSysConfigAndInfo->SysInfo.DcMeterInfo[meterIndex].presetVoltage = meter_info[meterIndex].presetVoltage;
								#ifdef DEBUG_SHAREMEM_LOG
								DEBUG_INFO("shm Output voltage %d : %.3f V\n", meterIndex, ShmSysConfigAndInfo->SysInfo.DcMeterInfo[meterIndex].presetVoltage);
								#endif
								#else
								DEBUG_INFO("Output voltage %d : %.3f V\n", meterIndex, meter_info[meterIndex].presetVoltage);
								#endif//DEBUG_STANDALONG
								//pollingIndex++;
								failCount[meterIndex] = 0;
							}
							else
							{
								if(failCount[meterIndex] < 10)
									failCount[meterIndex]++;
							}
							break;
						case 2:
							if(readPower(&meter_info[meterIndex]) != FAIL)
							{
								#ifndef DEBUG_STANDALONG
								/*
								 *	TODO:
								 *		1. Synchronize data to share memory
								 */
								 
								ShmSysConfigAndInfo->SysInfo.DcMeterInfo[meterIndex].presentPower = meter_info[meterIndex].presentPower;
								#ifdef DEBUG_SHAREMEM_LOG
								DEBUG_INFO("shm Output power %d : %.3f kw\n", meterIndex, ShmSysConfigAndInfo->SysInfo.DcMeterInfo[meterIndex].presentPower);
								#endif
								#else
								DEBUG_INFO("Output power %d : %.3f kw\n", meterIndex, meter_info[meterIndex].presentPower);
								#endif//DEBUG_STANDALONG
								//pollingIndex++;
								failCount[meterIndex] = 0;
							}
							else
							{
								if(failCount[meterIndex] < 10)
									failCount[meterIndex]++;
							}
							break;
						case 3:
							if(readEnergy(&meter_info[meterIndex]) != FAIL)
							{
								#ifndef DEBUG_STANDALONG
								/*
								 *	TODO:
								 *		1. Synchronize data to share memory
								 */
								 
								ShmSysConfigAndInfo->SysInfo.DcMeterInfo[meterIndex].totlizeImportEnergy = meter_info[meterIndex].totlizeImportEnergy;
								#ifdef DEBUG_SHAREMEM_LOG
								DEBUG_INFO("shm Totalize import energy %d : %.3f kwh\n", meterIndex, ShmSysConfigAndInfo->SysInfo.DcMeterInfo[meterIndex].totlizeImportEnergy);
								#endif
								ShmSysConfigAndInfo->SysInfo.DcMeterInfo[meterIndex].totlizeExportEnergy = meter_info[meterIndex].totlizeExportEnergy;
								#ifdef DEBUG_SHAREMEM_LOG
								DEBUG_INFO("shm Totalize export energy %d : %.3f kwh\n", meterIndex, ShmSysConfigAndInfo->SysInfo.DcMeterInfo[meterIndex].totlizeExportEnergy);
								#endif
								#else
								DEBUG_INFO("Totalize import energy %d : %.3f kwh\n", meterIndex, meter_info[meterIndex].totlizeImportEnergy);   
								DEBUG_INFO("Totalize export energy %d : %.3f kwh\n", meterIndex, meter_info[meterIndex].totlizeExportEnergy);
								#endif//DEBUG_STANDALONG
								//pollingIndex++;
								failCount[meterIndex] = 0;
							}
							else
							{
								if(failCount[meterIndex] < 10)
									failCount[meterIndex]++;
							}
							break;
						default:
							pollingIndex = 0;
							break;
					}
				}

				//meterIndex++;
			}

			
			if(failCount[meterIndex] >= 8)
			{
				//if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MeterCommTimeout)
				//{
					DEBUG_ERROR("Meter communication timeout");
					ShmSysConfigAndInfo->SysInfo.DcMeterInfo[meterIndex].LinkStatus = 2;
					ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MeterCommTimeout = ON;
				//}
			}
			else
			{
				ShmSysConfigAndInfo->SysInfo.DcMeterInfo[meterIndex].LinkStatus = 1; 
				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MeterCommTimeout = OFF;
			}
			
			DEBUG_INFO("Meter %d - LinkStatus %d :  failCount: %d \n", meterIndex, ShmSysConfigAndInfo->SysInfo.DcMeterInfo[meterIndex].LinkStatus,failCount[meterIndex]);
			usleep(200000);
		}
				
	}



	return -1;
}