/*
 * Main.c
 *
 *  Created on: 2019年8月6日
 *      Author: 7564
 */


#include <sys/time.h>
#include <sys/timeb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/shm.h>
#include <sys/mman.h>
#include <linux/wireless.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#include <unistd.h>
#include <stdarg.h>
#include <stdio.h>      /*標準輸入輸出定義*/
#include <stdlib.h>     /*標準函數庫定義*/
#include <unistd.h>     /*Unix 標準函數定義*/
#include <fcntl.h>      /*檔控制定義*/
#include <termios.h>    /*PPSIX 終端控制定義*/
#include <errno.h>      /*錯誤號定義*/
#include <errno.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <ifaddrs.h>
#include <math.h>
#include <stdbool.h>
#include "../../define.h"

typedef unsigned char           byte;
#define PASS                1
#define FAIL                -1
#define ARRAY_SIZE(A)       (sizeof(A) / sizeof(A[0]))
#define NO_DEFINE           255
#define DEFAULT_AC_INDEX    2

#define TTY_PATH            "/dev/tty"
#define STTY_US             "stty raw -echo -F "
#define STTY_DEF            "stty -raw echo -F "

struct SysConfigAndInfo         *ShmSysConfigAndInfo;
struct StatusCodeData           *ShmStatusCodeData;
struct PrimaryMcuData           *ShmPrimaryMcuData;
struct CHAdeMOData              *ShmCHAdeMOData;
struct CcsData                  *ShmCcsData;
struct GBTData                  *ShmGBTData;
struct FanModuleData            *ShmFanModuleData;
struct RelayModuleData          *ShmRelayModuleData;
struct LedModuleData            *ShmLedModuleData;
struct PsuData                  *ShmPsuData;

struct ChargingInfoData         *_chargingData[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
struct ChargingInfoData         *ac_chargingInfo[AC_QUANTITY];

char *msg = "state : get gun state (index) \n"
        "card : scanning card (x) : \n"
        "gun : get gun plugit state (index) \n"
        "lock : get gun locked state (index) \n"
        "self : self test state (x) \n"
        "ver : ver of board (407 or index or rb or fan) \n"
        "ac : get ac relay state (x) \n";

bool FindChargingInfoData(byte target, struct ChargingInfoData **chargingData)
{
    for (byte index = 0; index < CHAdeMO_QUANTITY; index++)
    {
        if (ShmSysConfigAndInfo->SysInfo.ChademoChargingData[index].Index == target)
        {
            chargingData[target] = &ShmSysConfigAndInfo->SysInfo.ChademoChargingData[index];
            return true;
        }
    }

    for (byte index = 0; index < CCS_QUANTITY; index++)
    {
        if (ShmSysConfigAndInfo->SysInfo.CcsChargingData[index].Index == target)
        {
            chargingData[target] = &ShmSysConfigAndInfo->SysInfo.CcsChargingData[index];
            return true;
        }
    }

    for (byte index = 0; index < GB_QUANTITY; index++)
    {
        if (ShmSysConfigAndInfo->SysInfo.GbChargingData[index].Index == target)
        {
            chargingData[target] = &ShmSysConfigAndInfo->SysInfo.GbChargingData[index];
            return true;
        }
    }

    return false;
}

bool FindAcChargingInfoData(byte target, struct ChargingInfoData **acChargingData)
{
    if (target < AC_QUANTITY)
    {
        acChargingData[target] = &ShmSysConfigAndInfo->SysInfo.AcChargingData[target];
        return true;
    }

    return false;
}

int InitShareMemory()
{
    int result = PASS;
    int MeterSMId;

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

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

    if (CHAdeMO_QUANTITY > 0) {
        if ((MeterSMId = shmget(ShmCHAdeMOCommKey, sizeof(struct CHAdeMOData),
        IPC_CREAT | 0777)) < 0) {
            result = FAIL;
        } else if ((ShmCHAdeMOData = shmat(MeterSMId, NULL, 0))
                == (void *) -1) {
            result = FAIL;
        } else {
        }
    }

    if (CCS_QUANTITY > 0) {
        if ((MeterSMId = shmget(ShmCcsCommKey, sizeof(struct CcsData),
        IPC_CREAT | 0777)) < 0) {
            result = FAIL;
        } else if ((ShmCcsData = shmat(MeterSMId, NULL, 0)) == (void *) -1) {
            result = FAIL;
        } else {
        }
    }

    if (GB_QUANTITY > 0) {
        if ((MeterSMId = shmget(ShmGBTCommKey, sizeof(struct GBTData),
        IPC_CREAT | 0777)) < 0) {
            return 0;
        } else if ((ShmGBTData = shmat(MeterSMId, NULL, 0)) == (void *) -1) {
            return 0;
        }
        memset(ShmGBTData, 0, sizeof(struct GBTData));
    }

    if ((MeterSMId = shmget(ShmPrimaryMcuKey, sizeof(struct PrimaryMcuData), IPC_CREAT | 0777)) < 0)
    {
        result = FAIL;
    }
    else if ((ShmPrimaryMcuData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
    {
        result = FAIL;
    }

    if ((MeterSMId = shmget(ShmFanBdKey, sizeof(struct FanModuleData),  IPC_CREAT | 0777)) < 0)
    {
        result = FAIL;
    }
    else if ((ShmFanModuleData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
    {
        result = FAIL;
    }

    if ((MeterSMId = shmget(ShmRelayBdKey, sizeof(struct RelayModuleData),  IPC_CREAT | 0777)) < 0)
    {
        result = FAIL;
    }
    else if ((ShmRelayModuleData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
    {
        result = FAIL;
    }

    if ((MeterSMId = shmget(ShmLedBdKey, sizeof(struct LedModuleData),  0777)) < 0)
    {
        result = FAIL;
    }
    else if ((ShmLedModuleData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
    {
        result = FAIL;
    }

    if ((MeterSMId = shmget(ShmPsuKey, sizeof(struct PsuData),  IPC_CREAT | 0777)) < 0)
    {
        result = FAIL;
    }
    else if ((ShmPsuData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
    {
        result = FAIL;
    }

    return result;
}

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 RunStatusProc(char *v1, char *v2)
{
    if (strcmp(v1, "ac") == 0)
    {
        if (!FindAcChargingInfoData(0, &ac_chargingInfo[0]))
        {
            printf("FindChargingInfoData (AC) false \n");
        }
        printf("AC Status = %d \n", ac_chargingInfo[0]->ConnectorPlugIn);
        return;
    }

    int _index = atoi(v1);
    if (_index <= 1)
    {
        if (!FindChargingInfoData(_index, &_chargingData[0]))
        {
            printf ("FindChargingInfoData error\n");
            return;
        }

        if (strcmp(v2, "-1") == 0 || strcmp(v2, "") == 0)
        {
            // get
            printf ("index = %x, status = %x (%d)\n", _index, _chargingData[_index]->SystemStatus, _chargingData[_index]->IsAvailable);
            printf ("SystemTimeoutFlag = %d, PageIndex = %d\n",
                    ShmSysConfigAndInfo->SysInfo.SystemTimeoutFlag, ShmSysConfigAndInfo->SysInfo.PageIndex);
        }
        else
        {
            // set
            _chargingData[_index]->SystemStatus = atoi(v2);
        }
    }
    else
    {
        if (!FindAcChargingInfoData(0, &ac_chargingInfo[0]))
        {
            printf("FindChargingInfoData (AC) false \n");
        }

        if (strcmp(v2, "-1") == 0 || strcmp(v2, "") == 0)
        {
            // get
            printf ("AC Type, status = %x (%d)\n", ac_chargingInfo[0]->SystemStatus, ac_chargingInfo[0]->IsAvailable);
        }
        else
        {
            // set
            ac_chargingInfo[0]->SystemStatus = atoi(v2);
        }
    }
}

void RunCardProc(char *v1, char *v2)
{
    if (strcmp(v1, "-1") == 0 || strcmp(v1, "") == 0)
    {
        if (ShmSysConfigAndInfo->SysInfo.WaitForPlugit)
        {
            ShmSysConfigAndInfo->SysInfo.WaitForPlugit = 0x00;
            printf ("SysInfo.WaitForPlugit = %x \n", ShmSysConfigAndInfo->SysInfo.WaitForPlugit);
        }
        else
        {
            ShmSysConfigAndInfo->SysInfo.WaitForPlugit = 0x01;
            printf ("SysInfo.WaitForPlugit = %x \n", ShmSysConfigAndInfo->SysInfo.WaitForPlugit);
        }
    }
    else
    {
        strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
        memcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, v1, strlen(v1));
        ShmSysConfigAndInfo->SysConfig.UserId[strlen(v1)] = '\0';
        printf("StartUserId = %s \n", ShmSysConfigAndInfo->SysConfig.UserId);
    }
}

void RunGunPlugitProc(char *v1, char *v2)
{
    int _index = atoi(v1);
    if (!FindChargingInfoData(_index, &_chargingData[0]))
    {
        printf("FindChargingInfoData error\n");
        return;
    }

    if (strcmp(v2, "-1") == 0 || strcmp(v2, "") == 0)
    {
        // get
        printf("index = %x, plug it = %x\n", _index, _chargingData[_index]->ConnectorPlugIn);
    }
    else
    {
        // set
        _chargingData[_index]->ConnectorPlugIn = atoi(v2);
    }
}

void GetGunLockStatusProc(char *v1, char *v2)
{
    int _index = atoi(v1);
    if (!FindChargingInfoData(_index, &_chargingData[0]))
    {
        printf("FindChargingInfoData error\n");
        return;
    }
    if (strcmp(v2, "-1") != 0 && strcmp(v2, "") != 0)
    {
        _chargingData[_index]->GunLocked = atoi(v2);
    }

    printf("Gun Locked Status = %d \n", _chargingData[_index]->GunLocked);
}

void SetSystemIDProc()
{
    char *systemId = "Alston_Test";
    memcpy(&ShmSysConfigAndInfo->SysConfig.SystemId, systemId, strlen(systemId));
}

void RunSelfProc()
{
    printf("self test status = %x\n", ShmSysConfigAndInfo->SysInfo.SelfTestSeq);
}

void GetFwVerProc(char *v1)
{
    if (strcmp(v1, "407") == 0)
    {
        printf("407 FW Version = %s \n", ShmPrimaryMcuData->version);
    }
    else if (strcmp(v1, "0") == 0 || strcmp(v1, "1") == 0)
    {
        int _index = atoi(v1);

        if (_index == 0)
            printf("Gun 0 FW Version = %s \n", ShmSysConfigAndInfo->SysInfo.Connector1FwRev);
        else if (_index == 1)
            printf("Gun 1 FW Version = %s \n", ShmSysConfigAndInfo->SysInfo.Connector2FwRev);
    }
    else if (strcmp(v1, "rb") == 0)
    {
        printf("RB Version = %s \n", ShmSysConfigAndInfo->SysInfo.RelayModuleFwRev);
    }
    else if (strcmp(v1, "fan") == 0)
    {
        printf("FAN Version = %s \n", ShmSysConfigAndInfo->SysInfo.FanModuleFwRev);
    }
    else if (strcmp(v1, "dc") == 0)
    {
        printf("DC Main Version = %s \n", ShmSysConfigAndInfo->SysInfo.CsuRootFsFwRev);
    }
    else if (strcmp(v1, "led") == 0)
    {
        printf("LED Version = %s \n", ShmSysConfigAndInfo->SysInfo.LedModuleFwRev);
    }
    else if (strcmp(v1, "ac") == 0)
    {
        if (!FindAcChargingInfoData(0, &ac_chargingInfo[0]))
        {
            printf("FindChargingInfoData (AC) false \n");
        }
        printf("AC Version = %s \n", ac_chargingInfo[0]->version);
    }
}

void CreateOneError(char *v1)
{
    int value = atoi(v1);

    ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PrimaryStestFail = value;
    ShmSysConfigAndInfo->SysConfig.BillingData.isBilling = value;
}

void GetAuthorizeFlag(char *v1)
{
    if (strcmp(v1, "-1") == 0|| strcmp(v1, "") == 0)
        printf("AuthorizeFlag = %d \n", ShmSysConfigAndInfo->SysInfo.AuthorizeFlag);
    else
        ShmSysConfigAndInfo->SysInfo.AuthorizeFlag = atoi(v1);
}

void GetOrClearId(char *v1)
{
    int _index = atoi(v1);

    if (!FindChargingInfoData(_index, &_chargingData[0]))
    {
        printf("FindChargingInfoData error\n");
        return;
    }
    printf("Card Number = %s \n", _chargingData[_index]->StartUserId);
}

void FwUpdateFlagProc()
{
    ShmSysConfigAndInfo->SysInfo.FirmwareUpdate = 0x01;
}

void CheckAcStatus(char *v1)
{
    if (strcmp(v1, "-1") == 0|| strcmp(v1, "") == 0)
    {
        printf("AC Status = %d \n", ShmSysConfigAndInfo->SysInfo.AcContactorStatus);
    }
}

void SetCableChkStatus(char *v1, char *v2)
{
    int _index = atoi(v1);
    if (!FindChargingInfoData(_index, &_chargingData[0]))
    {
        printf ("FindChargingInfoData error\n");
        return;
    }

    _chargingData[_index]->GroundFaultStatus = atoi(v2);
}

void SetPowerValue(char *v1, char *v2)
{
    int _index = atoi(v1);
    float _Current = atof(v2);
    // 盲沖的時候才允許使用~
    if (_chargingData[_index]->Type != 9)
        return;

    if (!FindChargingInfoData(_index, &_chargingData[0]))
    {
        printf ("FindChargingInfoData error\n");
        return;
    }

    _chargingData[_index]->EvBatterytargetCurrent = _Current;
}

void GetSystemInfo()
{
    printf ("ModelName = %s \n", ShmSysConfigAndInfo->SysConfig.ModelName);
    printf ("SerialNumber = %s \n", ShmSysConfigAndInfo->SysConfig.SerialNumber);
    printf ("InternetConn = %d \n", ShmSysConfigAndInfo->SysInfo.InternetConn);

    printf ("MaxChargingPower = %d, MaxChargingCurrent = %d \n",
            ShmSysConfigAndInfo->SysConfig.MaxChargingPower,
            ShmSysConfigAndInfo->SysConfig.MaxChargingCurrent);
}

void ChangeGunNum()
{
    if (ShmSysConfigAndInfo->SysInfo.CurGunSelected + 1 < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount)
    {
        ShmSysConfigAndInfo->SysInfo.CurGunSelected += 1;
        ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = NO_DEFINE;
    }
    else if (ShmSysConfigAndInfo->SysConfig.AcConnectorCount > 0 &&
            ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc == NO_DEFINE)
        ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = DEFAULT_AC_INDEX;
    else
    {
        ShmSysConfigAndInfo->SysInfo.CurGunSelected = 0;
        ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = NO_DEFINE;
    }
}

void GetGunSelectedNum(char *v1)
{
    if (strcmp(v1, "-1") == 0 || strcmp(v1, "") == 0)
    {
        if (AC_QUANTITY > 0 &&
            ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc != NO_DEFINE)
        {
            printf("connector select changed = AC \n");
        }
        else
            printf("connector selected = %d \n", ShmSysConfigAndInfo->SysInfo.CurGunSelected);
    }
    else
    {
        int _index = atoi(v1);
        if (_index <= 1)
        {
            ShmSysConfigAndInfo->SysInfo.CurGunSelected = _index;
            ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = NO_DEFINE;
            printf("connector select changed = %d \n", _index);
        }
        else if (AC_QUANTITY > 0)
        {
            ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = DEFAULT_AC_INDEX;
            printf("connector select changed = AC \n");
        }
    }
}

void SetFanSpeed(char *v1)
{
    int speed = atoi(v1);

    ShmFanModuleData->TestFanSpeed = speed;
}

void GetFanSpeed()
{
    printf("ShmFanModuleData->PresentFan1Speed = %d \n", ShmFanModuleData->PresentFan1Speed);
    printf("ShmFanModuleData->PresentFan2Speed = %d \n", ShmFanModuleData->PresentFan2Speed);
    printf("ShmFanModuleData->PresentFan3Speed = %d \n", ShmFanModuleData->PresentFan3Speed);
    printf("ShmFanModuleData->PresentFan4Speed = %d \n", ShmFanModuleData->PresentFan4Speed);
}

void SetDebugMode(char *v1)
{
    int mode = atoi(v1);

    ShmSysConfigAndInfo->SysConfig.SwitchDebugFlag = mode;
}

void SetGFDMode(char *v1)
{
    int mode = atoi(v1);

    ShmSysConfigAndInfo->SysConfig.AlwaysGfdFlag = mode;
}

void GetPsuTemp()
{
    for (byte index = 0; index < ShmPsuData->GroupCount; index++)
    {
        for (byte count = 0; count < ShmPsuData->PsuGroup[index].GroupPresentPsuQuantity; count++)
        {
            printf("PSU Temp = %d \n", ShmPsuData->PsuGroup[index].PsuModule[count].ExletTemp);
        }
    }
}

void GetAcInputVol()
{
    printf("L1N_L12 = %f, L2N_L23 = %f, L3N_L31 = %f \n",
            ShmSysConfigAndInfo->SysInfo.InputVoltageR,
            ShmSysConfigAndInfo->SysInfo.InputVoltageS,
            ShmSysConfigAndInfo->SysInfo.InputVoltageT);
}

void GetPsuInformation(char *v1)
{
    printf("**********************AC Contact needed*************************\n");
    if(strcmp(v1, "count") == 0)
    {
        for (int i = 0; i < 4; i++)
        {
            printf("Group Index = %d, Module Count = %d \n", i, ShmPsuData->PsuGroup[i].GroupPresentPsuQuantity);
        }
    }
    else if(strcmp(v1, "ver") == 0)
    {
        for (int i = 0; i < ShmPsuData->SystemPresentPsuQuantity; i++)
        {
            printf("Psu Index = %d, PriVersion = %s, SecVersion = %s \n",
                    i, ShmPsuData->PsuVersion[i].FwPrimaryVersion, ShmPsuData->PsuVersion[i].FwSecondVersion);
        }

        for (int i = 0; i < ShmPsuData->GroupCount; i++)
        {
            for (int j = 0; j < ShmPsuData->PsuGroup[i].GroupPresentPsuQuantity; j++)
            {
                printf("Group Index = %d, Psu Index = %d, Version = %s \n",
                    i, j, ShmPsuData->PsuGroup[i].PsuModule[j].FwVersion);
            }
        }
    }
    else if(strcmp(v1, "cap") == 0)
    {
        for (int i = 0; i < ShmPsuData->GroupCount; i++)
        {
            printf("Group Index = %d, MaxCur = %d, Power = %d \n",
                    i, ShmPsuData->PsuGroup[i].GroupAvailableCurrent, ShmPsuData->PsuGroup[i].GroupAvailablePower);
        }
    }
    else if (strcmp(v1, "output") == 0)
    {
        for (int i = 0; i < ShmPsuData->GroupCount; i++)
        {
            printf("Group Index = %d, OutputV = %d, OutputC = %d \n",
                    i, ShmPsuData->PsuGroup[i].GroupPresentOutputVoltage, ShmPsuData->PsuGroup[i].GroupPresentOutputCurrent);
        }
    }
    printf("*************************************************\n");
}

void GetConnectorCapInfo(char *v1)
{
    int _GunIndex = atoi(v1);

    if (!FindChargingInfoData(_GunIndex, &_chargingData[0]))
    {
        printf ("FindChargingInfoData error\n");
        return;
    }

    printf ("Charger Max Current = %d, Max Power = %d \n",
            ShmSysConfigAndInfo->SysConfig.MaxChargingCurrent * 10,
            ShmSysConfigAndInfo->SysConfig.MaxChargingPower * 10);

    printf ("Index = %d, MaxPow = %f, MaxVol = %f, MaxCur = %f\n",
            _GunIndex,
            _chargingData[_GunIndex]->RealMaxPower,
            _chargingData[_GunIndex]->RealMaxVoltage,
            _chargingData[_GunIndex]->RealMaxCurrent);
}

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 RunUnconditionalChargeIndex1(char *v1, char *v2, char *v3)
{
    int _GunIndex = atoi(v1);
    float _Voltage = atof(v2);
    float _Current = atof(v3);
    unsigned char PreviousSystemStatus = 0xff;

    if (!FindChargingInfoData(_GunIndex, &_chargingData[0]))
    {
        printf ("FindChargingInfoData error\n");
        return;
    }

    printf ("ReqVoltage = %f, ReqCurrent = %f\n", _Voltage, _Current);

    if(_Voltage > 1000 || _Voltage < 50)
    {
        printf ("Input Voltage over range\n");
        return;
    }

//    if(_Current > 100 || _Current < 2){
//
//        printf ("Input Current over range\n");
//        return;
//    }

    //測試期間先跳過自我測試 _STEST_COMPLETE = 0xfe
    //ShmSysConfigAndInfo->SysInfo.SelfTestSeq = 0xfe;

    //kill ev task
    system("killall Module_EvComm");

    //_Voltage = (_Voltage * 10);
    //_Current = (_Current * 10);

    //system(STTY_US TTY_PATH);

    while(true)
    {
        //fix gun 1
        ShmSysConfigAndInfo->SysInfo.CurGunSelected = _GunIndex;

        switch(_chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus)
        {
            case S_IDLE:
            {
                if(PreviousSystemStatus != _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus)
                {
                    PreviousSystemStatus = _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus;

                    printf ("[UnconditionalCharge - S_IDLE]\n");

                }

                ShmSysConfigAndInfo->SysInfo.StartToChargingFlag = 0x01;
                _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus = S_PREPARNING;
            }
            break;


            case S_PREPARNING:
            {
                if(PreviousSystemStatus != _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus)
                {
                    PreviousSystemStatus = _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus;

                    printf ("[UnconditionalCharge - S_PREPARNIN]\n");

                    //等待 AC Relay 搭上且找到模組 (main 在此 statue 其它 task 會去做完)
                    printf ("wait find module\n");

                }
                //main 會在此階段判斷以下資料跳到下一個 state
                //用來得知 AC 是否有搭上 (搭上模組的資訊才會出來) 因為每次  AC_Contactor


                //ShmPsuData->SystemPresentPsuQuantity;
                //ShmPsuData->PsuGroup[gun_index].GroupPresentPsuQuantity;
                //ShmPsuData->PsuGroup[gun_index].GroupAvailablePower;
                //_chargingData[gun_index]->AvailableChargingPower;

                //等待 AC Relay 搭上且找到模組 (main 在此 statue 其它 task 會去做完)
                //sleep(10);

                //清除 main timeout 機制
                _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->TimeoutFlag = 0;
                //不論是什麼 type 的槍都固意設成 Chademo 不跑 Prechage step
                _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->Type = 9;

            }
            break;

            case S_PREPARING_FOR_EV:
            {
                if(PreviousSystemStatus != _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus)
                {
                    PreviousSystemStatus = _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus;

                    printf ("[UnconditionalCharge - S_PREPARING_FOR_EV]\n");
                    printf ("ReqVoltage = %f, ReqCurrent = %f \n", _Voltage * 10,_Current * 10);

                }
                //清除 main timeout 機制
                _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->TimeoutFlag = 0;
                //不論是什麼 type 的槍都固意設成 Chademo 不跑 Prechage step
                _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->Type = 9;

                //充電電壓電流
                _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->EvBatterySoc = 50;
                _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->EvBatterytargetVoltage = 500;
                _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->EvBatterytargetCurrent = 2;
                _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->AvailableChargingCurrent = 1000;

                //****** 注意~此行為是防止 K1K2 先開導到無法升壓 ( Relay Board 在此 state 還未搭上 K1K2 )
                //確定模組己升壓完成
                //if(_chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->PresentChargingVoltage <=  (3000+500) &&
                //  _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->PresentChargingVoltage >=  (3000-500) )
                {
                    printf ("Precharge Done = %f \n", _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->PresentChargingVoltage);
                    //EV done
                    _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus = S_PREPARING_FOR_EVSE;
                }

            }
            break;


            case S_PREPARING_FOR_EVSE:
            {
                if(PreviousSystemStatus != _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus)
                {
                    PreviousSystemStatus = _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus;

                    printf ("[UnconditionalCharge - S_PREPARING_FOR_EVSE]\n");

                }
                //printf ("tar vol = %d \n", _Voltage);
                //printf ("tar cur = %d \n", _Current);

                //清除 main timeout 機制
                _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->TimeoutFlag = 0;
                //不論是什麼 type 的槍都固意設成 Chademo 不跑 Prechage step
                _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->Type = 9;

                //充電電壓電流
                _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->EvBatterySoc = 50;
                _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->EvBatterytargetVoltage = 500;
                _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->EvBatterytargetCurrent = 2;
                _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->AvailableChargingCurrent = 1000;

                //printf ("tar vol_ = %d \n", _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->EvBatterytargetVoltage);
               // printf ("tar cur_ = %d \n", _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->EvBatterytargetCurrent);

                //****** 注意~此行為是防止 K1K2 先開導到無法升壓 ( Relay Board 在此 state 還未搭上 K1K2 )
                //確定模組己升壓完成
                if(_chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->GroundFaultStatus == 0x01 ||
                    _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->GroundFaultStatus == 0x03)
                {
                    printf ("First Ground Fault State (%d)\n",_chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->GroundFaultStatus);
                    printf ("Wait K1K2 = %f \n", _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->PresentChargingVoltage);
                    sleep(5);
                    //EV done
                    _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus = S_CHARGING;
                }
                else if (_chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->GroundFaultStatus > 0x02)
                {
                    printf ("First Ground Fault check Fail (%d)\n",_chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->GroundFaultStatus);
                    _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus = S_TERMINATING;
                }

            }
            break;

            case S_CHARGING:
            {
                if(PreviousSystemStatus != _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus)
                {
                    PreviousSystemStatus = _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus;

                    //充電電壓電流
                    _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->EvBatterySoc = 50;
                    _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->EvBatterytargetVoltage = _Voltage;
                    _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->EvBatterytargetCurrent = _Current;
                    _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->AvailableChargingCurrent = 1000;

                    printf ("[UnconditionalCharge - S_CHARGING]\n");
                }

                //ev task do this
                _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->PresentChargingPower =
                        ((float)((_chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->PresentChargingVoltage) * (_chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->PresentChargingCurrent)) / 1000);

                if (_chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->GroundFaultStatus == 0x02){
                     printf ("Charging Ground Fault check Fail (%d)\n",_chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->GroundFaultStatus);
                    _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus = S_TERMINATING;
                }
            }
            break;

            case S_TERMINATING:
            {
                if(PreviousSystemStatus != _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus)
                {
                    PreviousSystemStatus = _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus;
                    system("/root/Module_EvComm &");

                    printf ("[UnconditionalCharge - S_TERMINATING]\n");
                    //無阻塞偵測 keybaord 結束
                    system(STTY_DEF TTY_PATH);
                }

                sleep(3);
                _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus = S_COMPLETE;
                return;
            }
            break;

            case S_COMPLETE:
            {
                if(PreviousSystemStatus != _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus)
                {
                    PreviousSystemStatus = _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus;

                    printf ("[UnconditionalCharge - S_COMPLETE]\n");
                }
                sleep(3);
                return;
            }
            break;
        }

        char word[128];
        char newString[7][10];
        int i,j,ctr;

        memset(word, 0x00, sizeof(word));
        get_char(word);

        if (strlen(word) == 0)
            continue;

        j=0; ctr=0;
        strcpy(newString[1], "-1");
        strcpy(newString[2], "-1");
        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++;
            }
        }

        if(strcmp(newString[0], "chg") == 0)
        {
            if (strcmp(newString[1], "-1") == 0 || strcmp(newString[1], "") == 0)
               continue;
            if (strcmp(newString[2], "-1") == 0 || strcmp(newString[2], "") == 0)
               continue;

            float _vol = atof(newString[1]);
            float _cur = atof(newString[2]);

            if (_cur <= 0 || _cur <= 0)
               continue;

            printf("vol = %f, cur = %f \n", _vol, _cur);
            _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->EvBatterytargetVoltage = _vol;
            _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->EvBatterytargetCurrent = _cur;
        }
        else if (strcmp(newString[0], "c") == 0)
        {
            printf("stop \n\r");
            ShmSysConfigAndInfo->SysInfo.StartToChargingFlag = 0x00;
            _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus = S_TERMINATING;
        }

        usleep(100000);
    }
}

int main(void)
{
    if(InitShareMemory() == FAIL)
    {
        printf ("InitShareMemory = FAIL \n");
        if(ShmStatusCodeData != NULL)
        {
            ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FailToCreateShareMemory=1;
        }
        sleep(5);
        return 0;
    }

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

        fgets(word, sizeof(word), stdin);

        j=0; ctr=0;
        strcpy(newString[1], "-1");
        strcpy(newString[2], "-1");
        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++;
            }
        }

        if(strcmp(newString[0], "state") == 0)
        {
            if (strcmp(newString[1], "-1") == 0 || strcmp(newString[1], "") == 0)
                continue;

            // 槍狀態
            RunStatusProc(newString[1], newString[2]);
        }
        else if(strcmp(newString[0], "card") == 0)
        {
            // 刷卡狀態
            RunCardProc(newString[1], newString[2]);
        }
        else if(strcmp(newString[0], "gun") == 0)
        {
            if (strcmp(newString[1], "-1") == 0 || strcmp(newString[1], "") == 0)
                continue;

            // 插槍狀態
            RunGunPlugitProc(newString[1], newString[2]);
        }
        else if(strcmp(newString[0], "lock") == 0)
        {
            if (strcmp(newString[1], "-1") == 0 || strcmp(newString[1], "") == 0)
                continue;

            // 插槍狀態
            GetGunLockStatusProc(newString[1], newString[2]);
        }
        else if(strcmp(newString[0], "sysid") == 0)
        {
            // 測試 sys id
            SetSystemIDProc();
        }
        else if(strcmp(newString[0], "self") == 0)
        {
            // CSU 自我檢測狀態
            RunSelfProc(newString[1]);
        }
        else if(strcmp(newString[0], "ver") == 0)
        {
            if (strcmp(newString[1], "-1") == 0 || strcmp(newString[1], "") == 0)
                continue;
            // 取 FW 版號
            GetFwVerProc(newString[1]);
        }
        else if (strcmp(newString[0], "update") == 0)
        {
            // 更新
            FwUpdateFlagProc(newString[1]);
        }
        else if (strcmp(newString[0], "ac") == 0)
        {
            // AC contactor 狀態
            CheckAcStatus(newString[1]);
        }
        else if (strcmp(newString[0], "cable") == 0)
        {
            if (strcmp(newString[1], "-1") == 0 || strcmp(newString[1], "") == 0)
                continue;
            // cable check pass
            SetCableChkStatus(newString[1], newString[2]);
        }
        else if (strcmp(newString[0], "pow") == 0)
        {
            if (strcmp(newString[1], "-1") == 0 || strcmp(newString[1], "") == 0)
                continue;
            // cable check pass
            SetPowerValue(newString[1], newString[2]);
        }
        else if (strcmp(newString[0], "model") == 0)
        {
            GetSystemInfo();
        }
        else if(strcmp(newString[0], "select") == 0)
        {
            // 取得 / 設定 當前選的槍號
            GetGunSelectedNum(newString[1]);
        }
        else if(strcmp(newString[0], "change") == 0)
        {
            // 模擬按鈕改變選槍
            ChangeGunNum();
        }
        else if(strcmp(newString[0], "fan") == 0)
        {
            // 設定風扇速度
            SetFanSpeed(newString[1]);
        }
        else if(strcmp(newString[0], "speed") == 0)
        {
            // 取得風扇速度
            GetFanSpeed();
        }
        else if(strcmp(newString[0], "debug") == 0)
        {
            // 設定 debug mode
            SetDebugMode(newString[1]);
        }
        else if (strcmp(newString[0], "gfd") == 0)
        {
            // 設定盲沖使用 GFD 功能
            SetGFDMode(newString[1]);
        }
        else if(strcmp(newString[0], "temp") == 0)
        {
            // 取得 PSU 溫度
            GetPsuTemp();
        }
        else if(strcmp(newString[0], "acin") == 0)
        {
            // 取得三向輸入電壓
            GetAcInputVol();
        }
        else if(strcmp(newString[0], "psu") == 0)
        {
            //如果連一個參數都沒有 (此命令不理會) 加上判斷第二參數
            if (strcmp(newString[1], "-1") == 0 || strcmp(newString[1], "") == 0)
            {
                printf ("PSU : Param fail..Please retry again......\n");
                continue;
            }

            // 取得 PSU 資訊
            GetPsuInformation(newString[1]);
        }
        else if (strcmp(newString[0], "cap") == 0)
        {
            GetConnectorCapInfo(newString[1]);
        }
        else if(strcmp(newString[0], "error") == 0)
        {
            CreateOneError(newString[1]);
        }
        else if (strcmp(newString[0], "auth") == 0)
        {
            GetAuthorizeFlag(newString[1]);
        }
        else if (strcmp(newString[0], "id") == 0)
        {
            GetOrClearId(newString[1]);
        }
        else if(strcmp(newString[0], "strchg") == 0)
        {
            //如果連一個參數都沒有 (此命令不理會) 加上判斷第二參數
            if (strcmp(newString[1], "-1") == 0 || strcmp(newString[1], "") == 0 ||
                    strcmp(newString[2], "-1") == 0 || strcmp(newString[2], "") == 0)
            {
                printf ("Input cmd fail ------  strchg [vol 150-1000] [cru 2-100]\n");
                continue;
            }

            // 槍狀態
            RunUnconditionalChargeIndex1(newString[1], newString[2], newString[3]);
        }
        else
            printf ("%s\n", msg);
        usleep(100000);
    }

    return 0;
}