#include "secc_port.h"
#include "GBT27930.h"


static int can_GBT27930_send_stop(GBT27930_t* dev, int REASON)
{
    ccu_port_t *ccu = (ccu_port_t*)dev->ccu;
    pcu_port_t *pcu = (pcu_port_t*)dev->pcu;
    memset(&dev->cst, 0, sizeof(dev->cst));
    switch (REASON)
    {
        case GBT_27930_STOP_SECC: dev->cst.chgReachedDemand = 1; break;
        case GBT_27930_STOP_CMD: dev->cst.chgManualTermination = 1;break;
        case GBT_27930_STOP_EVCC: dev->cst.chgBMSTermination = 1; break;
        case GBT_27930_STOP_BOXOVERTEMP: dev->cst.chgFaultTermination = 1; dev->cst.chgBoxOverTemp = 1; break;
        case GBT_27930_STOP_CONTACTOR: dev->cst.chgFaultTermination = 1; dev->cst.chgConnectorFalut = 1; break;
        case GBT_27930_STOP_LINEOVERTEMP: dev->cst.chgFaultTermination = 1; dev->cst.chgLineOverTemp = 1; break;
        case GBT_27930_STOP_TRANSTION: dev->cst.chgFaultTermination = 1; dev->cst.chgPowerTransmitFault = 1; break;
        case GBT_27930_STOP_EMERGENCY: dev->cst.chgFaultTermination = 1; dev->cst.chgEmergencyStop = 1; break;
        case GBT_27930_STOP_OTHERS: dev->cst.chgFaultTermination = 1; dev->cst.chgOtherFault = 1; break;
        case GBT_27930_STOP_VOLTAGE_MISTACH: dev->cst.chgFaultTermination = 1; dev->cst.chgVoltageAbnormal = 1; break;
        case GBT_27930_STOP_CURRENT_MISTACH: dev->cst.chgFaultTermination = 1; dev->cst.chgCurrentMismatch = 1; break;
        default: dev->cst.chgFaultTermination = 1; dev->cst.chgOtherFault = 1; break;
    }
    return can_GBT27930_send_CST(dev, &dev->cst);
}


static int can_GBT27930_send_timeout(GBT27930_t* dev, int STATE)
{
    ccu_port_t *ccu = (ccu_port_t*)dev->ccu;
    pcu_port_t *pcu = (pcu_port_t*)dev->pcu;

    memset(&dev->cem, 0, sizeof(dev->cem));
    switch(STATE)
    {
        case GBT_27930_TIMEOUT_BRM:{dev->cem.brm_timeout=1;}break;
        case GBT_27930_TIMEOUT_BCP:{dev->cem.bcp_timeout=1;}break;
        case GBT_27930_TIMEOUT_BRO:{dev->cem.bro_timeout=1;}break;
        case GBT_27930_TIMEOUT_BCS:{dev->cem.bcs_timeout=1;}break;
        case GBT_27930_TIMEOUT_BCL:{dev->cem.bcl_timeout=1;}break;
        case GBT_27930_TIMEOUT_BST:{dev->cem.bst_timeout=1;}break;
        case GBT_27930_TIMEOUT_BSD:{dev->cem.bsd_timeout=1;}break;
        default: {dev->cem.others=1;} break;
    }
    return can_GBT27930_send_CEM(dev, &dev->cem);
}

static int can_GBT27930_TryLock(GBT27930_t* dev, int timeout)
{
    secc_port_t* secc = (secc_port_t*)dev->secc;
    ccu_port_t *ccu = (ccu_port_t*)dev->ccu;
    pcu_port_t *pcu = (pcu_port_t*)dev->pcu;

    printd("Enter.\n");
    can_GBT27930_open_pipe(dev);
    if (secc->set_ELock_state(secc, 1, timeout) == 1)
    {
        pcu->update_ElecLock_state(pcu, 1);
        secc_request_power(secc, POWER_REQUEST_PLACE_HOLD, 0.0f, 0.0f);
        secc_set_state(secc, GUN_ELOCKED);
        return 1;
    }else{
        secc_set_error(secc, GUN_ELECLOCK_STALL);
    }
    return 0;
}

static int can_GBT27930_WaitAuthrized(GBT27930_t* dev, int timeout)
{
    int i;
    secc_port_t* secc = (secc_port_t*)dev->secc;
    ccu_port_t *ccu = (ccu_port_t*)dev->ccu;
    pcu_port_t *pcu = (pcu_port_t*)dev->pcu;

    printd("Enter.\n");

    pcu->get_PCU_maxVoltageCurrent(pcu, &secc->SECC_maxV, &secc->SECC_maxI);
    pcu->get_PCU_minVoltageCurrent(pcu, &secc->SECC_minV, &secc->SECC_minI);
    if (secc->request_KWh > 0)
    {
        secc_start_Transaction(secc);
        secc_set_state(secc, GUN_AUTHORIZED);
        return 1;
    }
    if (secc->request_SOC > 0)
    {
        secc_start_Transaction(secc);
        secc_set_state(secc, GUN_AUTHORIZED);
        return 1;
    }
    if (secc->request_Minutes > 0)
    {
        secc_start_Transaction(secc);
        secc_set_state(secc, GUN_AUTHORIZED);
        return 1;
    }
    //printd("step\n");
    return 0;
}

static int can_GBT27930_Handshake(GBT27930_t* dev)
{
    secc_port_t* secc = (secc_port_t*)dev->secc;
    ccu_port_t *ccu = (ccu_port_t*)dev->ccu;
    pcu_port_t *pcu = (pcu_port_t*)dev->pcu;

    printi("SECC(%d) Handshake...\n", secc->config->connectorId);
    secc->set_Aux12V_state(secc, 1);
    can_GBT27930_send_CHM(dev);
    int ret = can_GBT27930_wait(dev, GBT_27930_2015_BHM, BHM_TIMEOUT);
    if (ret == GBT_27930_2015_BHM)
    {
        printv("BMS->bhm.bmsMaxVoltage:%f\n", (float)(dev->bhm.bmsMaxVoltage)/10);
        secc_set_state(secc, GUN_INSULATION);
        return 1;
    }

    secc_set_state(secc, GUN_INSULATION);
    return 1;
    
    secc_set_error(secc, GUN_HANDSHAKE_FAULT);
    printd("GUN_Error:%08x, GUN_State:%08x\n", secc->GUN_Error, secc->GUN_State);
    return 0;
}

static int can_GBT27930_Insulation(GBT27930_t* dev)
{
    secc_port_t* secc = (secc_port_t*)dev->secc;
    ccu_port_t *ccu = (ccu_port_t*)dev->ccu;
    pcu_port_t *pcu = (pcu_port_t*)dev->pcu;

    printi("SECC(%d) Insulation...\n", secc->config->connectorId);
    int64_t now_ms = systime_ms();
    int64_t end_ms = systime_ms() + 60000;

    if (secc->set_K1K2_state(secc, 0, 1000) == 1) 
    {
        pcu->update_K1K2_state(pcu, 0, 0);
    }else {
        secc_set_error(secc, GUN_CONTACTOR_FAULT);
        return -1;
    }

    for (now_ms = systime_ms(); now_ms <= end_ms; now_ms = systime_ms())
    {
        if (0.0f <= secc->VMeters && secc->VMeters < 10.0f) { break; }
        msleep(100);
    }

    if (now_ms >= end_ms)
    {
        if (secc->VMeters < 0.0f)
        {
            secc_set_error(secc, BMS_VOLTAGE_INVERSE);
        }else{
            secc_set_error(secc, BMS_CONTACTOR_FAULT);
        }
        return -1;
    }

    if (secc->set_K1K2_state(secc, 1, 1000) == 1) 
    {
        pcu->update_K1K2_state(pcu, 1, 1);
    }else {
        secc_set_error(secc, GUN_CONTACTOR_FAULT);
        return -1;
    }

    float Vimd = ((float)dev->bhm.bmsMaxVoltage)/10;
    Vimd = fminf(Vimd, 1000.0f);
    Vimd = fmaxf(Vimd, 500.0f);

    secc->set_IMD_state(secc, 1);
    secc_request_power(secc, POWER_REQUEST_INSULATION, Vimd, 0);

    printd("now_ms:%lld, end_ms:%lld, now<=end(%d)\n", now_ms, end_ms, (now_ms<=end_ms));
    end_ms = systime_ms() + 60000;
    for (now_ms = systime_ms(); now_ms <= end_ms; now_ms = systime_ms())
    {
        printd("secc->VGround:%f, secc->VMeters:%f, Vimd:%f, Rimd:%f\n", secc->VGround, secc->VMeters, Vimd, secc->RGround);
        if (secc->VGround >= 200.0f)
        {
            if (secc->RGround > (secc->VGround * 100.0f))
            {
                secc->set_IMD_state(secc, 0);
                secc_request_power(secc, POWER_REQUEST_SHUTDOWN, 0, 0);
                if (secc->set_K1K2_state(secc, 0, 1000) == 1) 
                {
                    pcu->update_K1K2_state(pcu, 0, 0);
                }
                printd("GUN_Error:%08x, GUN_State:%08x\n", secc->GUN_Error, secc->GUN_State);
                uint8_t bmsACK = 0x00;
                can_GBT27930_send_CRM(dev, bmsACK, 0xFFFFFFFF, NULL);
                secc_set_state(secc, GUN_PRECHARGE);
                return 1;
            }
        }
        msleep(200);
    }
    secc->set_IMD_state(secc, 0);
    secc_request_power(secc, POWER_REQUEST_SHUTDOWN, 0, 0);
    secc_set_error(secc, GUN_INSULATION_FAULT);
    printd("now_ms:%lld, end_ms:%lld, now<=end(%d)\n", now_ms, end_ms, (now_ms<=end_ms));
    return 0;
}

static int can_GBT27930_PreCharge(GBT27930_t* dev)
{
    int ret;
    secc_port_t *secc = (secc_port_t*)dev->secc;
    ccu_port_t *ccu = (ccu_port_t*)dev->ccu;
    pcu_port_t *pcu = (pcu_port_t*)dev->pcu;

    //----------等待车端BRM就绪----------
    can_GBT27930_send_CRM(dev, 0x00, 0xFFFFFFFF, NULL);
    ret = can_GBT27930_wait(dev, GBT_27930_2015_BRM, BRM_TIMEOUT);
    if (ret != GBT_27930_2015_BRM)
    {
        can_GBT27930_send_timeout(dev, GBT_27930_TIMEOUT_BRM);
        secc_set_error(secc, GUN_PRECHARGE_FAULT);
        return GBT_27930_2015_ERROR;
    }
    
    //----------等待车端电池电压----------
    can_GBT27930_send_CRM(dev, 0xAA, 0xFFFFFFFF, NULL);
    ret = can_GBT27930_wait(dev, GBT_27930_2015_BCP, BCP_TIMEOUT);
    if (ret != GBT_27930_2015_BCP)
    {
        can_GBT27930_send_timeout(dev, GBT_27930_TIMEOUT_BCP);
        secc_set_error(secc, GUN_PRECHARGE_FAULT);
        return GBT_27930_2015_ERROR;
    }
    
    printi("SECC(%d).bcp.bmsPermitttedMaxVoltage:%d, bmsPermitttedMaxCurrent:%d, bmsNominalTotalkWH:%d, bmsVoltage:%d \n", secc->config->connectorId, dev->bcp.bmsPermitttedMaxVoltage, dev->bcp.bmsPermitttedMaxCurrent, dev->bcp.bmsNominalTotalkWH, dev->bcp.bmsVoltage);
    printd("SECC(%d) PreCharging.maxVoltage:%f,minVoltage:%f, maxCurrent:%f, minCurrent:%f\n", secc->config->connectorId, secc->SECC_maxV, secc->SECC_minV, secc->SECC_maxI, secc->SECC_minI);
    if (dev->bcp.bmsPermitttedMaxVoltage < secc->SECC_minV)
    {
        can_GBT27930_send_stop(dev, GBT_27930_STOP_VOLTAGE_MISTACH);
        secc_set_error(secc, GUN_PRECHARGE_FAULT);
        printd("SECC(%d) BMS Battery Voltage exceed the range of SECC\n", secc->config->connectorId);
        return GBT_27930_2015_ERROR;
    }
    else
    {
        can_GBT27930_send_CTS(dev, NULL);
    }
    
    //----------通知车端启动绝缘检测---------
    dev->cml.chgMaxOutputVoltage = (uint16_t)(secc->SECC_maxV*10 + 0.5);
    dev->cml.chgMinOutputVoltage = (uint16_t)(secc->SECC_minV*10 + 0.5);
    dev->cml.chgMaxOutputCurrent = (uint16_t)(secc->SECC_maxI*10 + 0.5);
    dev->cml.chgMinOutputCurrent = (uint16_t)(secc->SECC_minI*10 + 0.5);
    can_GBT27930_send_CML(dev, &dev->cml);
    ret = can_GBT27930_wait(dev, GBT_27930_2015_BRO, BRO_0x00_TIMEOUT);
    if (ret != GBT_27930_2015_BRO)
    {
        can_GBT27930_send_timeout(dev, GBT_27930_TIMEOUT_BRO);
        secc_set_error(secc, GUN_PRECHARGE_FAULT);
        printd("SECC(%d) BMS Insulation timeout or fault.\n", secc->config->connectorId);
        return GBT_27930_2015_ERROR;
    }

    //----------等待车端绝缘检测完成----------
    can_GBT27930_send_CML(dev, &dev->cml);
    ret = can_GBT27930_wait(dev, GBT_27930_2015_BRO, BRO_0xAA_TIMEOUT);
    if (ret != GBT_27930_2015_BRO)
    {
        can_GBT27930_send_timeout(dev, GBT_27930_TIMEOUT_BRO);
        secc_set_error(secc, GUN_PRECHARGE_FAULT);
        printd("SECC(%d) BMS Insulation timeout or fault.\n", secc->config->connectorId);
        return GBT_27930_2015_ERROR;
    }    

    //----------开始调整桩端电压----------
    can_GBT27930_send_CRO(dev, 0x00);
    for(int i=0; i<60000; i+=200)
    {
        float VBattery = ((float)dev->bcp.bmsVoltage) / 10;
        float VDelta = fabs(secc->VGround - secc->VMeters);
        printd("SECC(%d) SECC_minV:%f, VMeters:%f, SECC_maxV:%f, VGround:%f, VDelta:%f\n", secc->config->connectorId, secc->SECC_minV, secc->VMeters, secc->SECC_maxV, secc->VGround, VDelta);
        if (secc->SECC_minV < secc->VMeters &&  secc->VMeters < secc->SECC_maxV && (VDelta < (secc->VGround*0.1f) || VDelta < (secc->VMeters*0.1f)))
        {
            printd("SECC(%d).VMeters:%f, VGround:%f\n", secc->config->connectorId, secc->VMeters, secc->VGround);
            secc_set_state(secc, GUN_CHARGING);
            return 1;
        }else{
            printd("SECC(%d).VMeters:%f, VGround:%f, VBattery:%f\n", secc->config->connectorId, secc->VMeters, secc->VGround, VBattery);
            secc_request_power(secc, POWER_REQUEST_CONST_VOLTAGE, VBattery, 0.0f);
        }
        msleep(200);
    }
    secc_set_error(secc, GUN_PRECHARGE_FAULT);
    return GBT_27930_2015_ERROR;
}

static int can_GBT27930_Charging(GBT27930_t* dev)
{
    int ret;
    secc_port_t* secc = (secc_port_t*)dev->secc;
    ccu_port_t *ccu = (ccu_port_t*)dev->ccu;
    pcu_port_t *pcu = (pcu_port_t*)dev->pcu;

    printi("SECC(%d) Charging...\n", secc->config->connectorId);
    
    secc->started_UTC = time(NULL);
    secc->started_KWh = secc->EMeters;

    if (secc->set_K1K2_state(secc, 1, 1000) == 1) 
    {
        pcu->update_K1K2_state(pcu, 1, 1);
    }else {
        secc_set_error(secc, GUN_CONTACTOR_FAULT);
        return GBT_27930_2015_ERROR;
    }
    printi("step\n");
    //----------开始等待车端电压需求和总状态报文----------
    {
        memset(&dev->ccs, 0, sizeof(dev->ccs));
        dev->ccs.chgOutputting = 0x1;
        dev->ccs.chgChargedMinutes = (time(NULL) - secc->started_UTC + 30)/60;
        dev->ccs.chgOutputVoltage = (uint16_t)(secc->VMeters*10 + 0.5);
        dev->ccs.chgOutputCurrent = (uint16_t)(secc->IMeters*10 + 0.5);
    }
    int64_t bcl_ms = systime_ms();
    int64_t bcs_ms = systime_ms();
    int64_t bsm_ms = systime_ms();
    int64_t now_ms = systime_ms();
    int64_t ccs_ms = systime_ms();
    printi("step\n");
    can_GBT27930_send_CRO(dev, 0xAA);
    printi("step\n");
    ret = can_GBT27930_wait(dev, GBT_27930_2015_BCL, BCL_TIMEOUT);
    printi("step\n");
    while(secc_should_stop(secc) != 1)
    {
        int ret = can_GBT27930_wait(dev, GBT_27930_2015_BCS|GBT_27930_2015_BCL|GBT_27930_2015_BSM, 1000);
        switch(ret)
        {
            case GBT_27930_2015_BCL:
            {
                bcl_ms = systime_ms();
                // if (dev->bcl.bmsChargeMode != dev->bcl_last.bmsChargeMode || dev->bcl.bmsVoltage_request != dev->bcl_last.bmsVoltage_request || dev->bcl.bmsCurrent_request != dev->bcl_last.bmsCurrent_request)
                {
                    float voltage = (((float)dev->bcl.bmsVoltage_request) / 10);
                    float current = (((float)dev->bcl.bmsCurrent_request) / 10);
                    printi("SECC(%d) BCL voltage:%f, current:%f, mode:%d\n", secc->config->connectorId, voltage, current, dev->bcl.bmsChargeMode);
                    if (dev->bcl.bmsChargeMode == 1) { secc_request_power(secc, POWER_REQUEST_CONST_VOLTAGE, voltage, current); }
                    if (dev->bcl.bmsChargeMode == 2) { secc_request_power(secc, POWER_REQUEST_CONST_CURRENT, voltage, current); }
                }
            }break;
            case GBT_27930_2015_BCS:
            {
                bcs_ms = systime_ms();
                secc->EV_Charging_current = ((float)dev->bcs.chargingCurrent) / 10;
                secc->EV_Charging_voltage = ((float)dev->bcs.chargingVoltage) / 10;
                secc->EV_Estimate_Minutes = dev->bcs.bmsChargingNeedMinutes;
                secc->SOC = dev->bcs.bmsSOC;
                printi("SECC(%d)  BCS(%fV, %fA, %dM, %dP)\n", secc->config->connectorId, secc->EV_Charging_voltage, secc->EV_Charging_current, secc->EV_Estimate_Minutes, secc->SOC);
                secc_report_MeterValues(secc);
            }break;
            case GBT_27930_2015_BSM:
            {
                bsm_ms = systime_ms();
                float voltage = (((float)dev->bcl.bmsVoltage_request) / 10);
                float current = (((float)dev->bcl.bmsCurrent_request) / 10);
                if (dev->bsm.bmsPowerPermitted == 0x0  && dev->bsm_last.bmsPowerPermitted == 1)
                {   //暂停
                    printi("SECC(%d) BSM(%d).%s\n", secc->config->connectorId, dev->bsm.bmsPowerPermitted, "suspend");
                    secc_request_power(secc, POWER_REQUEST_SHUTDOWN, voltage, current);
                }
                if (dev->bsm.bmsPowerPermitted == 0x1 && dev->bsm_last.bmsPowerPermitted == 0)
                {   //继续
                    printi("SECC(%d) BSM(%d).%s\n", secc->config->connectorId, dev->bsm.bmsPowerPermitted, "continue");
                    if (dev->bcl.bmsChargeMode = 0x01) { secc_request_power(secc, POWER_REQUEST_CONST_VOLTAGE, voltage, current); }
                    if (dev->bcl.bmsChargeMode = 0x02) { secc_request_power(secc, POWER_REQUEST_CONST_CURRENT, voltage, current); }
                }
            }break;
            case GBT_27930_2015_BRO: break;
            default:{
                printe("step, ret:%d\n", ret);
                can_GBT27930_send_timeout(dev, GBT_27930_TIMEOUT_BCS);
                secc_set_error(secc, GUN_CHARGING_FAULT);
                return GBT_27930_2015_ERROR;
            }break;
        }
        now_ms = systime_ms();
        if ((now_ms - bcl_ms) > BCL_TIMEOUT) { printi("SECC(%d) timeout(bcl:%lld, bcs:%lld, bsm:%lld)\n", secc->config->connectorId, (now_ms - bcl_ms), (now_ms - bcs_ms), (now_ms - bsm_ms)); break;}
        if ((now_ms - bcs_ms) > BCS_TIMEOUT) { printi("SECC(%d) timeout(bcl:%lld, bcs:%lld, bsm:%lld)\n", secc->config->connectorId, (now_ms - bcl_ms), (now_ms - bcs_ms), (now_ms - bsm_ms)); break;}
        if ((now_ms - bsm_ms) > BSM_TIMEOUT) { printi("SECC(%d) timeout(bcl:%lld, bcs:%lld, bsm:%lld)\n", secc->config->connectorId, (now_ms - bcl_ms), (now_ms - bcs_ms), (now_ms - bsm_ms)); break;}
        if ((now_ms - ccs_ms) > BCL_TIMEOUT)
        {
            printi("SECC(%d) CCS VMeters:%f, IMeters:%f, EMeters:%f\n", secc->config->connectorId,secc->VMeters,secc->IMeters,secc->EMeters);
            memset(&dev->ccs, 0, sizeof(dev->ccs));
            dev->ccs.chgOutputting = 0x1;
            dev->ccs.chgChargedMinutes = (time(NULL) - secc->started_UTC + 30)/60;
            dev->ccs.chgOutputVoltage = (uint16_t)(secc->VMeters*10 + 0.5);
            dev->ccs.chgOutputCurrent = (uint16_t)(secc->IMeters*10 + 0.5);
            can_GBT27930_send_CCS(dev, &dev->ccs);
            ccs_ms = systime_ms();
        }
    }
    printi("step\n");
    secc_set_state(secc, GUN_STOPPING);
    return GBT_27930_2015_NORMAL;
}

static int can_GBT27930_Finishing(GBT27930_t* dev)
{
    secc_port_t* secc = (secc_port_t*)dev->secc;
    ccu_port_t *ccu = (ccu_port_t*)dev->ccu;
    pcu_port_t *pcu = (pcu_port_t*)dev->pcu;

    printi("SECC(%d) Finishing...\n", secc->config->connectorId);

    secc_request_power(secc, POWER_REQUEST_PLACE_FREE, 0, 0);
    secc_stop_Transaction(secc);
    {
        dev->csd.chgCode = 0x81828385;
        dev->csd.chgCumulativeKWH = (uint16_t)((secc->EMeters - secc->started_KWh) * 10);
        dev->csd.chgCumulativeMintues = (time(NULL) - secc->started_UTC + 30)/60;
        can_GBT27930_send_CSD(dev, &dev->csd);
        can_GBT27930_wait(dev, GBT_27930_2015_BSD, 1000);
    }

    printd("step\n");

    if (secc->GUN_Error == 0)
    {
        int64_t now_ms = systime_ms();
        int64_t end_ms = systime_ms() + 5000;
        for (now_ms = systime_ms(); now_ms <= end_ms; now_ms = systime_ms())
        {
            float bmsA = secc->IMeters;
            if (bmsA < 5.0f) { break; }
            msleep(100);
        }
    }

    printd("step\n");

    if (secc->set_K1K2_state(secc, 0, 1000) == 1) 
    {
        pcu->update_K1K2_state(pcu, 0, 0);
    }else {
        secc_set_error(secc, GUN_CONTACTOR_FAULT);
    }
    
    printd("step\n");

    secc->set_Aux12V_state(secc, 0);

    printd("step\n");

    if (secc->set_ELock_state(secc, 0, 1000)==1)
    {
        pcu->update_ElecLock_state(pcu, 0); 
    }else{
        secc_set_error(secc, GUN_ELECLOCK_STALL);
    }

    printd("step\n");

    secc->request_Minutes = 0;
    secc->request_SOC = 0;
    secc->request_KWh = 0;
    secc->reserve_on = 0;
    secc->reservationId = 0;
    secc->started_KWh = 0;
    secc->started_UTC = 0;
    secc->SOC = 0;
    secc->EV_Charging_current = 0;
    secc->EV_Charging_voltage = 0;
    secc->EV_Estimate_Minutes = 0;
    secc->transactionId = 0;

    printd("step\n");
    
    can_GBT27930_close_pipe(dev);

	printd("GUN_Error:%08x, GUN_State:%08x\n", secc->GUN_Error, secc->GUN_State);
    secc_set_state(secc, GUN_PLUGIN);
    printd("step\n");
    return GBT_27930_2015_NORMAL;
}

/******************************************************************************/

void* can_GBT27930_loop(void* argv)
{
    GBT27930_t* dev = (GBT27930_t*)argv;
    secc_port_t* secc = (secc_port_t*)dev->secc;
    ccu_port_t *ccu = (ccu_port_t*)dev->ccu;
    pcu_port_t *pcu = (pcu_port_t*)dev->pcu;
    printd("Enter.\n");

    while (dev->quit == 0)
    {
        uint32_t state = secc_recv_error_state(secc, 1000);
        if (state == 0) continue;
        switch(state)
        {
            case GUN_STARTUP:       { can_GBT27930_TryLock(dev, 60000);printccui("step\n"); }break;
            case GUN_ELOCKED:       { can_GBT27930_WaitAuthrized(dev, 60000);printccui("step\n"); } break;
            case GUN_AUTHORIZED:    { can_GBT27930_Handshake(dev);printccui("step\n"); } break;
            case GUN_INSULATION:    { can_GBT27930_Insulation(dev); } break;
            case GUN_PRECHARGE:     { can_GBT27930_PreCharge(dev); } break;
            case GUN_CHARGING:      { can_GBT27930_Charging(dev); } break;
            case GUN_SUSPEND:                                       break;
            case GUN_STOPPING:      { can_GBT27930_Finishing(dev); } break;
            default:                { }break;
        }
        if (secc->GUN_Error) { printi("secc->GUN_Error:%08x, %ld\n", secc->GUN_Error, secc->GUN_Error);break;}
    }
    printd("Leave.\n");
    can_GBT27930_Finishing(dev);
    return NULL;
}

int secc_init_can(void* secc_self)
{
    printd("step\n");
    secc_port_t* secc = (secc_port_t*)secc_self;
    printd("step\n");
    GBT27930_t *dev = (GBT27930_t*)secc->priv;
    printd("step\n");
    dev->ccu = secc->ccu;
    dev->pcu = secc->pcu;
    socketpair(AF_UNIX, SOCK_STREAM, 0, secc->fp);
    printd("step\n");
    return can_GBT27930_init(dev, secc->config->can_ifname);
}

void secc_exit_can(void* secc_self)
{
    printd("step\n");
    secc_port_t* secc = (secc_port_t*)secc_self;
    printd("step\n");
    GBT27930_t *dev = (GBT27930_t*)secc->priv;
    printd("step\n");
    secc->manul_stop = true;
    printd("step\n");
    if (secc->fp[0] > 0)
    {
        shutdown(secc->fp[0], SHUT_RDWR);
        close(secc->fp[0]);
        secc->fp[0] = -1;
    }
    if (secc->fp[1] > 0)
    {
        shutdown(secc->fp[1], SHUT_RDWR);
        close(secc->fp[1]);
        secc->fp[1] = -1;
    }
    printd("step\n");
    can_GBT27930_exit(dev);
}


