/*
 * OutputTask.c
 *
 *  Created on: 2020�~2��25��
 *      Author: 7564
 */

#include 	"OutputTask.h"

int Uart5Fd;
int PresentRPM;

char *relayRs485PortName = "/dev/ttyS5";

int InitComPort5()
{
	int fd;
	struct termios tios;

	fd = open(relayRs485PortName, O_RDWR);
	if(fd <= 0)
	{
		printf("InitComPort NG\n");
		sleep(5);
		return -1;
	}
	ioctl (fd, TCGETS, &tios);
	tios.c_cflag = B115200 | CS8 | CLOCAL | CREAD;
	tios.c_lflag = 0;
	tios.c_iflag = 0;
	tios.c_oflag = 0;
	tios.c_cc[VMIN]=0;
	tios.c_cc[VTIME]=(byte)0;		// timeout 0.5 second
	tios.c_lflag=0;
	tcflush(fd, TCIFLUSH);
	ioctl (fd, TCSETS, &tios);

	return fd;
}

unsigned char Set_Fan_Speed(unsigned char fd, int rpm)
{
	unsigned char result = FAIL;

	PresentRPM = rpm;
	if(rpm >= 14000)
	{
		rpm = 14000;
	}
	if(rpm < 0)
	{
		rpm = 0;
	}

	unsigned char tx[15] = {0xaa, 0x00, 0x02, 0x81, 0x08, 0x00, (rpm & 0xFF), ((rpm >> 8) & 0xFF), (rpm & 0xFF), ((rpm >> 8) & 0xFF), (rpm & 0xFF), ((rpm >> 8) & 0xFF), (rpm & 0xFF), ((rpm >> 8) & 0xFF), 0x00};
	unsigned char rx[512];
	unsigned char chksum = 0x00;

	for(int idx = 0;idx<(tx[4] | tx[5]<<8);idx++)
		chksum ^= tx[6+idx];
	tx[14] = chksum;

	unsigned char len = tranceive(fd, tx, sizeof(tx), rx);
	if(len > 6)
	{
		if (len < 6+(rx[4] | rx[5]<<8))
			return result;

		chksum = 0x00;
		for(int idx = 0;idx<(rx[4] | rx[5]<<8);idx++)
		{
			chksum ^= rx[6+idx];
		}

		if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
		   (rx[2] == tx[1]) &&
		   (rx[1] == tx[2]) &&
		   (rx[3] == tx[3]) &&
		   rx[6] == PASS)
		{
			result = PASS;
		}
	}

	return result;
}

bool isOpen;

int InitComPort()
{
	int fd;
	struct termios tios;

	fd = open(priPortName, O_RDWR);
	if(fd<=0)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("open 407 Communication port NG \n");
		#endif
		return -1;
	}
	ioctl (fd, TCGETS, &tios);
	tios.c_cflag = B115200| CS8 | CLOCAL | CREAD;
	tios.c_lflag = 0;
	tios.c_iflag = 0;
	tios.c_oflag = 0;
	tios.c_cc[VMIN]=0;
	tios.c_cc[VTIME]=(unsigned char)1;
	tios.c_lflag=0;
	tcflush(fd, TCIFLUSH);
	ioctl (fd, TCSETS, &tios);

	return fd;
}

unsigned long GetTimeoutValue(struct timeval _sour_time)
{
	struct timeval _end_time;
	gettimeofday(&_end_time, NULL);

	return 1000000 * (_end_time.tv_sec - _sour_time.tv_sec) + _end_time.tv_usec - _sour_time.tv_usec;
}

void ShowMainMsg()
{
	printf("Max Vol : %f, Max Cur : %d, POW : %d \n", UnSafeDataInfo->PSU_VOLTAGE,
			UnSafeDataInfo->PSU_CURRENT, UnSafeDataInfo->PSU_POWER);
	printf("=> ");
}

void ChkButtonStatus()
{
	if (Button1 == PRESS && !leftBtnPush)
	{
		if(!leftBtnPush)
		{
			leftBtnPush = true;
			if (_charging_mode == CHARGING_MODE_STOP)
			{
				_charging_mode = CHARGING_MODE_START;
				printf("****************** Switch to Charging Mode ******************\n");
			}
		}
		else if (Button1 == RELEASE)
		{
			if(leftBtnPush)
			{
				leftBtnPush = false;
			}
		}
	}

	if (Button2 == PRESS && !rightBtnPush)
	{
		if(!rightBtnPush)
		{
			rightBtnPush = true;
			if (_charging_mode == CHARGING_MODE_START)
			{
				_charging_mode = CHARGING_MODE_TERMINATING;
				printf("****************** Switch to Stop Mode ******************\n");
			}
		}
		else if (Button2 == RELEASE)
		{
			if(rightBtnPush)
			{
				rightBtnPush = false;
			}
		}
	}
}

void GetModuleCountCallback(byte group, byte count)
{
	printf("group = %d, count = %d \n", group, count);
	if (group == SYSTEM_CMD)
		UnSafeDataInfo->PSU_COUNT = count;
}

void GetAvailableCapCallback(byte address, short maxVol, short minVol, short maxCur, short totalPow)
{
	int _groupPower = 0, _groupCurrent = 0;

	UnSafeDataInfo->PsuModule[address].PSU_VOLTAGE_INFO = maxVol;
	UnSafeDataInfo->PsuModule[address].PSU_CURRENT_INFO = maxCur;
	UnSafeDataInfo->PsuModule[address].PSU_POWER_INFO = totalPow;

	for (byte index = 0; index < UnSafeDataInfo->PSU_COUNT; index++)
	{
		_groupCurrent += UnSafeDataInfo->PsuModule[address].PSU_CURRENT_INFO;
		_groupPower += UnSafeDataInfo->PsuModule[address].PSU_POWER_INFO;
	}

	UnSafeDataInfo->PSU_VOLTAGE = maxVol;
	UnSafeDataInfo->PSU_CURRENT = _groupCurrent;
	UnSafeDataInfo->PSU_POWER = _groupPower;
}

void GetStatusCallback(byte group, byte address, byte temp, int alarm)
{
	printf("alarm = %d \n", alarm);
}

void GetInputVoltageCallback(byte address, unsigned short vol1, unsigned short vol2, unsigned short vol3)
{
	printf("vol1 = %d, vol2 = %d, vol3 = %d \n", vol1, vol2, vol3);
}

int CreateShareMemory()
{
	int MeterSMId;

	if ((MeterSMId = shmget(ShmTestKey,	sizeof(struct UnSafeData), IPC_CREAT | 0777)) < 0)
	{
		return 0;
	}
	else if ((UnSafeDataInfo = shmat(MeterSMId, NULL, 0))	== (void *) -1)
	{
		return 0;
	}
	memset(UnSafeDataInfo, 0, sizeof(struct UnSafeData));

	return 1;
}

static void get_char(char *word)
{
    fd_set rfds;
    struct timeval tv;

    FD_ZERO(&rfds);
    FD_SET(0, &rfds);
    tv.tv_sec = 0;
    tv.tv_usec = 10; //wait input timout time

    //if input
    if (select(1, &rfds, NULL, NULL, &tv) > 0)
    {
    	fgets(word, 128, stdin);
    }
}

void GetInputString()
{
	char word[128];
	char newString[7][10];
	int i, j, ctr;

	get_char(word);

	if (strlen(word) == 0)
	    return;
	//fgets(word, sizeof(word), stdin);

	j = 0;
	ctr = 0;
	for (i = 0; i <= (strlen(word)); i++) {
		if (word[i] == ' ' || word[i] == '\0' || word[i] == 10) {
			newString[ctr][j] = '\0';
			ctr++;
			j = 0;
		} else {
			newString[ctr][j] = word[i];
			j++;
		}
	}

	VOLTAGE = atof(newString[0]);
	CURRENT = atof(newString[1]);
	FANRPM = atoi(newString[2]);
	if (VOLTAGE <= UnSafeDataInfo->PSU_VOLTAGE && CURRENT <= UnSafeDataInfo->PSU_CURRENT)
	{
		//printf("OutputVol = %f, OutputCur = %f \n", VOLTAGE, CURRENT);
	}
	else
	{
		ShowMainMsg();
	}
}

void GetIavailableCallback(byte address, unsigned short Iavail, unsigned short Vext)
{
	//printf("address = %d, Iavail = %d, Vext = %d \n", address, Iavail, Vext);
}

void GetOutputAndTempCallback(byte address, unsigned short outputVol,
		unsigned short outputCur, unsigned short outputPower, unsigned char Temperature)
{
	//printf("***Output Value and Temp*** address = %d, Vol = %d, Cur = %d, Pow = %d, Temp = %d \n",
	//		address, outputVol, outputCur, outputPower, Temperature);
}

void GetModuleStatusCallback(byte address, unsigned char isErr, unsigned char status,
		unsigned char err1, unsigned char err2, unsigned char err3, unsigned char err4)
{
	//int alarm = (err2 << 24) | (err3 << 16) | (err4 << 8);

	// err2 == state 2
	// err3 == state 1
	// err4 == state 0
	//printf("***Status*** address = %d, alarm = %d \n", address, alarm);
//	printf("***Status*** address = %d, err1 = %d, err2 = %d, err3 = %d, err4 = %d \n",
//			address, err1,err2,err3,err4);
}

void GetModuleInputCallback(byte address, unsigned short inputR,
		unsigned short inputS, unsigned short inputT)
{

}

int main(void)
{
	isOpen =false;

	if(CreateShareMemory() == 0)
	{
		printf("CreateShareMemory fail. \n");
		return 0;
	}
	RefreshModuleCount(&GetModuleCountCallback);
	RefreshAvailableCap(&GetAvailableCapCallback);

	RefreshStatus(&GetStatusCallback);
	RefreshInputVol(&GetInputVoltageCallback);

	RefreshIavailable(&GetIavailableCallback);

	AutoMode_RefreshOutputAndTemp(&GetOutputAndTempCallback);
	AutoMode_RefreshModuleStatus(&GetModuleStatusCallback);
	AutoMode_RefreshModuleInput(&GetModuleInputCallback);

	Uart1Fd = InitComPort();
	Uart5Fd = InitComPort5();
	libInitialize = InitialCommunication();

	if (Uart1Fd < 0 || !libInitialize)
	{
		printf("Initial port fail. \n");
		return 0;
	}

	if(Uart5Fd < 0)
	{
		printf("(Internal) open port error. \n");
		return 0;
	}

	sleep(5);
	gettimeofday(&_cmdSubPriority_time, NULL);
	VOLTAGE = 0.0;
	CURRENT = 0.0;

	SwitchPower(SYSTEM_CMD, PSU_POWER_OFF);
//	while (1)
//	{
//		printf("++++++++++++++2++++++++++++++++++++++++++++++++++++++\n");
//		SetWalkInConfig(0, YES, 0);
//		SetWalkInConfig(1, NO, 0);
//		printf("++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
//		sleep(1);
//	}
//
//	sleep(1);
//		printf("++++++++++++++2++++++++++++++++++++++++++++++++++++++\n");
//		SetWalkInConfig(SYSTEM_CMD, NO, 0);
//		printf("++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
//	return 0;
	while (1)
	{
		GetInputGpioStatus();
		//ChkButtonStatus();
		// ���� Walk-in mode (default 5s -> 2s)
		SetWalkInConfig(SYSTEM_CMD, NO, 0);

		int time = GetTimeoutValue(_cmdSubPriority_time) / 1000;
		while(isGetCount == YES)
		{
			if (_charging_mode == CHARGING_MODE_START)
			{
				// ���o�Ҷ���X�B�w�q�y��O
				GetModuleIavailable(0);
			}

			GetInputString();
			if (VOLTAGE > 150 && CURRENT >= 0)
				_charging_mode = CHARGING_MODE_START;
			else
				_charging_mode = CHARGING_MODE_TERMINATING;
			//printf("_charging_mode = %d \n", _charging_mode);

			if(PresentRPM != FANRPM)
			{
				if(Set_Fan_Speed(Uart5Fd, FANRPM) == PASS)
				{
					printf("Set Fan RPM: %d OK\n", FANRPM);
				}
				else
				{
					printf("Set Fan RPM: %d Fail\n", FANRPM);
				}
			}

			switch(_charging_mode)
			{
				case CHARGING_MODE_START:
				{
					if (!isOpen)
					{
						SwitchPower(SYSTEM_CMD, PSU_POWER_ON);
						FlashLed(SYSTEM_CMD, PSU_FLASH_ON);

						isOpen = true;
						//SetDirModulePresentOutput(0,
						//						VOLTAGE * 10,
						//						CURRENT * 10,
						//						0x01,
						//						0x01);
					}
					PresentOutputVol(SYSTEM_CMD, VOLTAGE * 10, CURRENT * 10);
				}
					break;
				case CHARGING_MODE_TERMINATING:
				{
					if (isOpen)
					{
						//SetDirModulePresentOutput(0,
						//	VOLTAGE * 10,
						//	CURRENT * 10,
						//	0x00,
						//	0x01);
						SwitchPower(SYSTEM_CMD, PSU_POWER_OFF);
						FlashLed(SYSTEM_CMD, PSU_FLASH_NORMAL);


						isOpen = false;
					}
				}
					break;
			}
			//GetStatus(0);
			//GetModuleInput(0);
			sleep(1);
		}

		if (UnSafeDataInfo->PSU_COUNT <= 0)
		{
			if (time > 1000)
			{
				printf("Step 1 : GetModuleCount...... \n");
				GetModuleCount(SYSTEM_CMD);
				gettimeofday(&_cmdSubPriority_time, NULL);
			}
		}
		else if (time < 5000)
		{
			printf("Step 2 : GetModuleCap...... \n");
			GetModuleCap(0);

			SwitchPower(SYSTEM_CMD, PSU_POWER_OFF);
			FlashLed(SYSTEM_CMD, PSU_FLASH_NORMAL);
		}
		else
		{
			ShowMainMsg();
			isGetCount = YES;
		}

		sleep(1);
	}

	return 0;
}