#include "interface.h"
#include "modbusTCP_HW.h"
#include "goose_HW.h"
#include "mthread.h"
#include "ccu_config.h"
#include "pcuhw.h"

typedef struct hwpcu
{
    modbusTCP_HW_t modbusTCP;
    mthread_t threadTCP;
    uint32_t  GUN_Error[2];
    uint32_t  GUN_State[2];
} pcuhw_t;

static pcuhw_t hwpcu;

/*
***************************************************************************************************************
*/
static void pcuhw_GUNA_power_request(void* self, pcu_request_mode_t mode, float voltage, float current)
{
    pcuhw_t* dev = (pcuhw_t*)(((pcu_port_t*)self)->priv);
    printd("PCU->GUNA_error:%08x, GUNA_state:%08x, mode:%d\n", dev->GUN_Error[0], dev->GUN_State[0], mode);
    switch(mode)
    {
        case POWER_REQUEST_PLACE_FREE:{
            pthread_mutex_lock(&dev->modbusTCP.gooseA.mutex);
            dev->modbusTCP.gooseA.shutdown_request.connect_id = dev->modbusTCP.regs_0x1100[0x0E];//枪编号（华为主机的枪编号）
            dev->modbusTCP.gooseA.shutdown_request.serialnumb = 0xFFFF;
            dev->modbusTCP.gooseA.shutdown_request.reason = SRR_NORMAL;
            dev->modbusTCP.gooseA.shutdown_request.resv0 = 0xFFFF;
            dev->modbusTCP.gooseA.shutdown_request.resv1 = 0xFFFF;
            pthread_mutex_unlock(&dev->modbusTCP.gooseA.mutex);
            goose_HW_ShuntdownRequest(&dev->modbusTCP.gooseA);
        }break;

        case POWER_REQUEST_PLACE_HOLD:{
            pthread_mutex_lock(&dev->modbusTCP.gooseA.mutex);
            dev->modbusTCP.gooseA.power_request.connect_id = dev->modbusTCP.regs_0x1100[0x0E];
            dev->modbusTCP.gooseA.power_request.serialnumb = 0xFFFF;
            switch (dev->GUN_State[0])
            {
                case GUN_INSULATION: dev->modbusTCP.gooseA.power_request.type = PRT_INSLUATION_DETECTION_STOP;break;
                default:dev->modbusTCP.gooseA.power_request.type = PRT_ACDC_PLACEHOLDER;break;
            }
            dev->modbusTCP.gooseA.power_request.mode = PRM_CONSTANT_VOLTAGE;
            dev->modbusTCP.gooseA.power_request.requestV = 0;
            dev->modbusTCP.gooseA.power_request.requestI = 0;
            dev->modbusTCP.gooseA.power_request.resv0 = 0xFFFF;
            dev->modbusTCP.gooseA.power_request.resv1 = 0xFFFF;
            pthread_mutex_unlock(&dev->modbusTCP.gooseA.mutex);
            goose_HW_PowerRequest(&dev->modbusTCP.gooseA);
        }break;

        case POWER_REQUEST_INSULATION:{
            pthread_mutex_lock(&dev->modbusTCP.gooseA.mutex);
            dev->modbusTCP.gooseA.power_request.connect_id = dev->modbusTCP.regs_0x1100[0x0E];
            dev->modbusTCP.gooseA.power_request.serialnumb = 0xFFFF;
            dev->modbusTCP.gooseA.power_request.type = PRT_INSLUATION_DETECTION_START;
            dev->modbusTCP.gooseA.power_request.mode = PRM_CONSTANT_VOLTAGE;
            dev->modbusTCP.gooseA.power_request.requestV = voltage;
            dev->modbusTCP.gooseA.power_request.requestI = current;
            dev->modbusTCP.gooseA.power_request.resv0 = 0xFFFF;
            dev->modbusTCP.gooseA.power_request.resv1 = 0xFFFF;
            pthread_mutex_unlock(&dev->modbusTCP.gooseA.mutex);
            goose_HW_PowerRequest(&dev->modbusTCP.gooseA);
        }break;

        case POWER_REQUEST_SHUTDOWN:{
            pthread_mutex_lock(&dev->modbusTCP.gooseA.mutex);
            dev->modbusTCP.gooseA.power_request.connect_id = dev->modbusTCP.regs_0x1100[0x0E];
            dev->modbusTCP.gooseA.power_request.serialnumb = 0xFFFF;
            dev->modbusTCP.gooseA.power_request.type = PRT_INSLUATION_DETECTION_STOP;
            dev->modbusTCP.gooseA.power_request.mode = PRM_CONSTANT_VOLTAGE;
            dev->modbusTCP.gooseA.power_request.requestV = 0;
            dev->modbusTCP.gooseA.power_request.requestI = 0;
            dev->modbusTCP.gooseA.power_request.resv0 = 0xFFFF;
            dev->modbusTCP.gooseA.power_request.resv1 = 0xFFFF;
            pthread_mutex_unlock(&dev->modbusTCP.gooseA.mutex);
            goose_HW_PowerRequest(&dev->modbusTCP.gooseA);
        }break;

        case POWER_REQUEST_CONST_VOLTAGE:{
            pthread_mutex_lock(&dev->modbusTCP.gooseA.mutex);
            dev->modbusTCP.gooseA.power_request.connect_id = dev->modbusTCP.regs_0x1100[0x0E];
            dev->modbusTCP.gooseA.power_request.serialnumb = 0xFFFF;
            
            switch (dev->GUN_State[0])
            {
                case GUN_INSULATION: dev->modbusTCP.gooseA.power_request.type = PRT_INSLUATION_DETECTION_START;break;
                case GUN_PRECHARGE: dev->modbusTCP.gooseA.power_request.type = PRT_PRECHARGING;break;
                case GUN_CHARGING: dev->modbusTCP.gooseA.power_request.type = PRT_CHARGING;break;
                default:dev->modbusTCP.gooseA.power_request.type = PRT_CHARGING;break;
            }
            dev->modbusTCP.gooseA.power_request.mode = PRM_CONSTANT_VOLTAGE;
            dev->modbusTCP.gooseA.power_request.requestV = voltage;
            dev->modbusTCP.gooseA.power_request.requestI = current;
            dev->modbusTCP.gooseA.power_request.resv0 = 0xFFFF;
            dev->modbusTCP.gooseA.power_request.resv1 = 0xFFFF;
            pthread_mutex_unlock(&dev->modbusTCP.gooseA.mutex);
            goose_HW_PowerRequest(&dev->modbusTCP.gooseA);
        }break;

        case POWER_REQUEST_CONST_CURRENT:{
            pthread_mutex_lock(&dev->modbusTCP.gooseA.mutex);
            dev->modbusTCP.gooseA.power_request.connect_id = dev->modbusTCP.regs_0x1100[0x0E];
            dev->modbusTCP.gooseA.power_request.serialnumb = 0xFFFF;
            switch (dev->GUN_State[0])
            {
                case GUN_INSULATION: dev->modbusTCP.gooseA.power_request.type = PRT_INSLUATION_DETECTION_START;break;
                case GUN_PRECHARGE: dev->modbusTCP.gooseA.power_request.type = PRT_PRECHARGING;break;
                case GUN_CHARGING: dev->modbusTCP.gooseA.power_request.type = PRT_CHARGING;break;
                default:dev->modbusTCP.gooseA.power_request.type = PRT_CHARGING;break;
            }
            dev->modbusTCP.gooseA.power_request.mode = PRM_CONSTANT_CURRENT;
            dev->modbusTCP.gooseA.power_request.requestV = voltage;
            dev->modbusTCP.gooseA.power_request.requestI = current;
            dev->modbusTCP.gooseA.power_request.resv0 = 0xFFFF;
            dev->modbusTCP.gooseA.power_request.resv1 = 0xFFFF;
            pthread_mutex_unlock(&dev->modbusTCP.gooseA.mutex);
            goose_HW_PowerRequest(&dev->modbusTCP.gooseA);
        }break;
    }
}

static void pcuhw_GUNA_Update_error_state(void* self, uint32_t GUN_Error, uint32_t GUN_State)
{
    pcuhw_t* dev = (pcuhw_t*)(((pcu_port_t*)self)->priv);
    printd("GUN_Error:%08x, GUN_State:%08x\n", GUN_Error, GUN_State);

    if (dev->GUN_State[0] != GUN_PLUGOUT && GUN_State == GUN_PLUGOUT)
    {
        dev->modbusTCP.regs_0x1100[0x0B] = HW_WORK_MODE_PLUGIN_HOME;//工作状态
        modbusTCP_HW_report_registers(&dev->modbusTCP, 0x110B, &dev->modbusTCP.regs_0x1100[0x0B], 1);
    }

    if (dev->GUN_State[0] != GUN_PLUGIN  && GUN_State == GUN_PLUGIN)
    {
        dev->modbusTCP.regs_0x1100[0x0B] = HW_WORK_MODE_PLUGIN_EV;//工作状态
        modbusTCP_HW_report_registers(&dev->modbusTCP, 0x110B, &dev->modbusTCP.regs_0x1100[0x0B], 1);

        dev->modbusTCP.regs_0x1100[0x0D] = HW_FULLLINK_STATE;//连接状态
        modbusTCP_HW_report_registers(&dev->modbusTCP, 0x110D, &dev->modbusTCP.regs_0x1100[0x0D], 1);
    }

    if (dev->GUN_State[0] != GUN_PLUGIN && GUN_State == GUN_PLUGIN)
    {
        dev->modbusTCP.regs_0x1100[0x0D] = HW_SEMILINK_STATE;//半连接状态
        modbusTCP_HW_report_registers(&dev->modbusTCP, 0x110D, &dev->modbusTCP.regs_0x1100[0x0D], 1);
    }

    if (dev->GUN_State[0] != GUN_ELOCKED && GUN_State == GUN_ELOCKED)
    {
        dev->modbusTCP.regs_0x1100[0x0B] = HW_WORK_MODE_PRECHARGING;//工作状态
        modbusTCP_HW_report_registers(&dev->modbusTCP, 0x110B, &dev->modbusTCP.regs_0x1100[0x0B], 1);
    }
    if (dev->GUN_State[0] != GUN_INSULATION && GUN_State == GUN_INSULATION)
    {
        dev->modbusTCP.regs_0x1100[0x0B] = HW_WORK_MODE_PRECHARGING;//工作状态
        modbusTCP_HW_report_registers(&dev->modbusTCP, 0x110B, &dev->modbusTCP.regs_0x1100[0x0B], 1);
    }
    if (dev->GUN_State[0] != GUN_PRECHARGE && GUN_State == GUN_PRECHARGE)
    {
        dev->modbusTCP.regs_0x1100[0x0B] = HW_WORK_MODE_PRECHARGING;//工作状态
        modbusTCP_HW_report_registers(&dev->modbusTCP, 0x110B, &dev->modbusTCP.regs_0x1100[0x0B], 1);
    }

    if (dev->GUN_State[0] != GUN_CHARGING  && GUN_State == GUN_CHARGING)
    {
        dev->modbusTCP.regs_0x1100[0x0B] = HW_WORK_MODE_CHARGING;//工作状态
        modbusTCP_HW_report_registers(&dev->modbusTCP, 0x110B, &dev->modbusTCP.regs_0x1100[0x0B], 1);
    }

    dev->GUN_State[0] = GUN_State;
    dev->GUN_Error[0] = GUN_Error;
}

static void pcuhw_GUNA_Update_GUN_type(void *self, gun_type_t GUN_type)
{
    pcuhw_t* dev = (pcuhw_t*)(((pcu_port_t*)self)->priv);
    switch(GUN_type)
    {
        case GUN_TYPE_CCS1:     hwpcu.modbusTCP.regs_0x1100[0x04] = 1;break;
        case GUN_TYPE_CCS2:     hwpcu.modbusTCP.regs_0x1100[0x04] = 2;break;
        case GUN_TYPE_CHADEMO:  hwpcu.modbusTCP.regs_0x1100[0x04] = 3;break;
        case GUN_TYPE_GBDC:     hwpcu.modbusTCP.regs_0x1100[0x04] = 4;break;
        default:                hwpcu.modbusTCP.regs_0x1100[0x04] = 1; break;
    }
}

static void pcuhw_GUNA_Update_K1K2_state(void *self, int K1, int K2)
{
    pcuhw_t* dev = (pcuhw_t*)(((pcu_port_t*)self)->priv);
    if (K1==1 && K2==1){
        dev->modbusTCP.regs_0x1100[0x54] = 1;//接触器状态
        modbusTCP_HW_report_registers(&dev->modbusTCP, 0x1154, &dev->modbusTCP.regs_0x1100[0x54], 1);
    }
        
    if (K1==0 && K2==0){
        dev->modbusTCP.regs_0x1100[0x54] = 0;//接触器状态
        modbusTCP_HW_report_registers(&dev->modbusTCP, 0x1154, &dev->modbusTCP.regs_0x1100[0x54], 1);
    }
}

static void pcuhw_GUNA_Update_ELock_state(void *self, int lock_state)
{
    pcuhw_t* dev = (pcuhw_t*)(((pcu_port_t*)self)->priv);
    dev->modbusTCP.regs_0x1100[0x56] = lock_state;//电子锁状态
    modbusTCP_HW_report_registers(&dev->modbusTCP, 0x1156, &dev->modbusTCP.regs_0x1100[0x56], 1);
}

static void pcuhw_GUNA_Update_MLock_state(void *self, int lock_state)
{
    pcuhw_t* dev = (pcuhw_t*)(((pcu_port_t*)self)->priv);
    dev->modbusTCP.regs_0x1100[0x56] = lock_state;//电子锁状态
    modbusTCP_HW_report_registers(&dev->modbusTCP, 0x1156, &dev->modbusTCP.regs_0x1100[0x56], 1);
}

static void pcuhw_GUNA_Update_K1K2_voltate(void *self, float voltage)
{
    pcuhw_t* dev = (pcuhw_t*)(((pcu_port_t*)self)->priv);
    uint32_t* valueV = (uint32_t*)&voltage;

    dev->modbusTCP.regs_0x1100[0x14] = (valueV[0]>>0) & 0xFFFF;
    dev->modbusTCP.regs_0x1100[0x13] = (valueV[0]>>16) & 0xFFFF;

    modbusTCP_HW_report_registers(&dev->modbusTCP, 0x1113, &dev->modbusTCP.regs_0x1100[0x13], 2);
}

static void pcuhw_GUNA_Get_PCU_maxVoltateCurrent(void *self, float *maxV, float *maxI)
{
    pcuhw_t* dev = (pcuhw_t*)(((pcu_port_t*)self)->priv);
    uint32_t maxV32 = (dev->modbusTCP.regs_0x2100[0x00]<<16)|dev->modbusTCP.regs_0x2100[0x01];
    uint32_t maxI32 = (dev->modbusTCP.regs_0x2100[0x02]<<16)|dev->modbusTCP.regs_0x2100[0x03];
    float *maxVF32 = (float*)&maxV32;
    float *maxIF32 = (float*)&maxI32;
    if (maxVF32[0] < 10) maxVF32[0] = 1000;
    maxV[0] = maxVF32[0];
    maxI[0] = maxIF32[0];
}

static void pcuhw_GUNA_Get_PCU_minVoltageCurrent(void *self, float *minV, float *minI)
{
    pcuhw_t* dev = (pcuhw_t*)(((pcu_port_t*)self)->priv);
    uint32_t minV32 = (dev->modbusTCP.regs_0x2100[0x05]<<16)|dev->modbusTCP.regs_0x2100[0x06];
    uint32_t minI32 = (dev->modbusTCP.regs_0x2100[0x07]<<16)|dev->modbusTCP.regs_0x2100[0x08];
    float *minVF32 = (float*)&minV32;
    float *minIF32 = (float*)&minI32;
    minV[0] = minVF32[0];
    minI[0] = minIF32[0];
}

static void pcuhw_GUNA_Get_PCU_maxPermittedPower(void *self, float *power)
{
    pcuhw_t* dev = (pcuhw_t*)(((pcu_port_t*)self)->priv);
    uint32_t maxP32 = (dev->modbusTCP.regs_0x2100[0x0D]<<16)|dev->modbusTCP.regs_0x2100[0x0E];
    float *maxPF32 = (float*)&maxP32;
    if (maxPF32[0] < 10)
    {
        maxPF32[0] = 400;
    }
    power[0] = maxPF32[0];

}

static void pcuhw_GUNA_Get_PCU_outputPower(void *self, float *power)
{
    pcuhw_t* dev = (pcuhw_t*)(((pcu_port_t*)self)->priv);
    uint32_t ratedP32 = (dev->modbusTCP.regs_0x2100[0x09]<<16)|dev->modbusTCP.regs_0x2100[0x0A];
    float *ratedPF32 = (float*)&ratedP32;
    power[0] = ratedPF32[0];
}

static void pcuhw_GUNA_Update_MeterEnergyPower(void *self, float energy, float power)
{
    pcuhw_t* dev = (pcuhw_t*)(((pcu_port_t*)self)->priv);
    double meter_energy = energy;
    uint32_t* value = (uint32_t*)&meter_energy;

    dev->modbusTCP.regs_0x1100[0x03] = (value[0]>>0) & 0xFFFF;
    dev->modbusTCP.regs_0x1100[0x02] = (value[0]>>16) & 0xFFFF;
    dev->modbusTCP.regs_0x1100[0x01] = (value[1]>>0) & 0xFFFF;
    dev->modbusTCP.regs_0x1100[0x00] = (value[1]>>16) & 0xFFFF;
}

static void pcuhw_GUNA_Update_MeterVoltageCurrent(void *self, float voltage, float current)
{
    pcuhw_t* dev = (pcuhw_t*)(((pcu_port_t*)self)->priv);
    uint32_t* valueV = (uint32_t*)&voltage;
    uint32_t* valueI = (uint32_t*)&current;

    dev->modbusTCP.regs_0x1100[0x08] = (valueV[0]>>0) & 0xFFFF;
    dev->modbusTCP.regs_0x1100[0x07] = (valueV[0]>>16) & 0xFFFF;

    dev->modbusTCP.regs_0x1100[0x0A] = (valueI[0]>>0) & 0xFFFF;
    dev->modbusTCP.regs_0x1100[0x09] = (valueI[0]>>16) & 0xFFFF;
}

static void pcutc_GUNA_Update_EV_BatteryVoltage(void *self, float voltage)
{

}


static void pcuhw_GUNA_Update_maxPermittedCurrent(void *self, float maxI)
{
    pcuhw_t* dev = (pcuhw_t*)(((pcu_port_t*)self)->priv);
    uint32_t* current = (uint32_t*)&maxI;

    dev->modbusTCP.regs_0x1100[0x06] = (current[0]>>0) & 0xFFFF;
    dev->modbusTCP.regs_0x1100[0x05] = (current[0]>>16) & 0xFFFF;

    dev->modbusTCP.regs_0x1100[0x03] = (current[0]>>0) & 0xFFFF;
    dev->modbusTCP.regs_0x1100[0x02] = (current[0]>>16) & 0xFFFF;
}


pcu_port_t pcuhwA = 
{
    .priv = &hwpcu,
    
    .update_GUN_type = pcuhw_GUNA_Update_GUN_type,
    .update_GUN_error_state = pcuhw_GUNA_Update_error_state,
    .update_K1K2_state = pcuhw_GUNA_Update_K1K2_state,
    .update_ElecLock_state = pcuhw_GUNA_Update_ELock_state,
    .update_K1K2_voltate = pcuhw_GUNA_Update_K1K2_voltate,
    .update_Meter_EnergyPower = pcuhw_GUNA_Update_MeterEnergyPower,
    .update_Meter_VoltageCurrent = pcuhw_GUNA_Update_MeterVoltageCurrent,
    .update_EV_BatteryPower = pcutc_GUNA_Update_EV_BatteryVoltage,
    .set_GUNLine_PermittedVoltageCurrent = pcuhw_GUNA_Update_maxPermittedCurrent,
    .get_PCU_maxVoltageCurrent = pcuhw_GUNA_Get_PCU_maxVoltateCurrent,
    .get_PCU_minVoltageCurrent = pcuhw_GUNA_Get_PCU_minVoltageCurrent,
    .get_PCU_maxPermittedPower = pcuhw_GUNA_Get_PCU_maxPermittedPower,


    .request_Power = pcuhw_GUNA_power_request,
};

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

static void pcuhw_GUNB_power_request(void* self, pcu_request_mode_t mode, float voltage, float current)
{
    pcuhw_t* dev = (pcuhw_t*)(((pcu_port_t*)self)->priv);
    printd("PCU->GUNB_error:%08x, GUNB_state:%08x, mode:%d\n", dev->GUN_Error[1], dev->GUN_State[1], mode);
    switch(mode)
    {
        case POWER_REQUEST_PLACE_FREE:{
            pthread_mutex_lock(&dev->modbusTCP.gooseB.mutex);
            dev->modbusTCP.gooseB.shutdown_request.connect_id = dev->modbusTCP.regs_0x1D00[0x0E];//枪编号（华为主机的枪编号）
            dev->modbusTCP.gooseB.shutdown_request.serialnumb = 0xFFFF;
            dev->modbusTCP.gooseB.shutdown_request.reason = SRR_NORMAL;
            dev->modbusTCP.gooseB.shutdown_request.resv0 = 0xFFFF;
            dev->modbusTCP.gooseB.shutdown_request.resv1 = 0xFFFF;
            pthread_mutex_unlock(&dev->modbusTCP.gooseB.mutex);
            goose_HW_ShuntdownRequest(&dev->modbusTCP.gooseB);
        }break;

        case POWER_REQUEST_PLACE_HOLD:{
            pthread_mutex_lock(&dev->modbusTCP.gooseB.mutex);
            dev->modbusTCP.gooseB.power_request.connect_id = dev->modbusTCP.regs_0x1D00[0x0E];
            dev->modbusTCP.gooseB.power_request.serialnumb = 0xFFFF;
            switch (dev->GUN_State[1])
            {
                case GUN_INSULATION: dev->modbusTCP.gooseB.power_request.type = PRT_INSLUATION_DETECTION_STOP;break;
                default:dev->modbusTCP.gooseB.power_request.type = PRT_ACDC_PLACEHOLDER;break;
            }
            dev->modbusTCP.gooseB.power_request.mode = PRM_CONSTANT_VOLTAGE;
            dev->modbusTCP.gooseB.power_request.requestV = 0;
            dev->modbusTCP.gooseB.power_request.requestI = 0;
            dev->modbusTCP.gooseB.power_request.resv0 = 0xFFFF;
            dev->modbusTCP.gooseB.power_request.resv1 = 0xFFFF;
            pthread_mutex_unlock(&dev->modbusTCP.gooseB.mutex);
            goose_HW_PowerRequest(&dev->modbusTCP.gooseB);
        }break;

        case POWER_REQUEST_INSULATION:{
            pthread_mutex_lock(&dev->modbusTCP.gooseB.mutex);
            dev->modbusTCP.gooseB.power_request.connect_id = dev->modbusTCP.regs_0x1D00[0x0E];
            dev->modbusTCP.gooseB.power_request.serialnumb = 0xFFFF;
            dev->modbusTCP.gooseB.power_request.type = PRT_INSLUATION_DETECTION_START;
            dev->modbusTCP.gooseB.power_request.mode = PRM_CONSTANT_VOLTAGE;
            dev->modbusTCP.gooseB.power_request.requestV = voltage;
            dev->modbusTCP.gooseB.power_request.requestI = current;
            dev->modbusTCP.gooseB.power_request.resv0 = 0xFFFF;
            dev->modbusTCP.gooseB.power_request.resv1 = 0xFFFF;
            pthread_mutex_unlock(&dev->modbusTCP.gooseB.mutex);
            goose_HW_PowerRequest(&dev->modbusTCP.gooseB);
        }break;

        case POWER_REQUEST_SHUTDOWN:{
            pthread_mutex_lock(&dev->modbusTCP.gooseB.mutex);
            dev->modbusTCP.gooseB.power_request.connect_id = dev->modbusTCP.regs_0x1D00[0x0E];
            dev->modbusTCP.gooseB.power_request.serialnumb = 0xFFFF;
            dev->modbusTCP.gooseB.power_request.type = PRT_INSLUATION_DETECTION_STOP;
            dev->modbusTCP.gooseB.power_request.mode = PRM_CONSTANT_VOLTAGE;
            dev->modbusTCP.gooseB.power_request.requestV = 0;
            dev->modbusTCP.gooseB.power_request.requestI = 0;
            dev->modbusTCP.gooseB.power_request.resv0 = 0xFFFF;
            dev->modbusTCP.gooseB.power_request.resv1 = 0xFFFF;
            pthread_mutex_unlock(&dev->modbusTCP.gooseB.mutex);
            goose_HW_PowerRequest(&dev->modbusTCP.gooseB);
        }break;

        case POWER_REQUEST_CONST_VOLTAGE:{
            pthread_mutex_lock(&dev->modbusTCP.gooseB.mutex);
            dev->modbusTCP.gooseB.power_request.connect_id = dev->modbusTCP.regs_0x1D00[0x0E];
            dev->modbusTCP.gooseB.power_request.serialnumb = 0xFFFF;
            switch (dev->GUN_State[1])
            {
                case GUN_INSULATION: dev->modbusTCP.gooseB.power_request.type = PRT_INSLUATION_DETECTION_START;break;
                case GUN_PRECHARGE: dev->modbusTCP.gooseB.power_request.type = PRT_PRECHARGING;break;
                case GUN_CHARGING: dev->modbusTCP.gooseB.power_request.type = PRT_CHARGING;break;
                default:dev->modbusTCP.gooseB.power_request.type = PRT_CHARGING;break;
            }
            dev->modbusTCP.gooseB.power_request.mode = PRM_CONSTANT_VOLTAGE;
            dev->modbusTCP.gooseB.power_request.requestV = voltage;
            dev->modbusTCP.gooseB.power_request.requestI = current;
            dev->modbusTCP.gooseB.power_request.resv0 = 0xFFFF;
            dev->modbusTCP.gooseB.power_request.resv1 = 0xFFFF;
            pthread_mutex_unlock(&dev->modbusTCP.gooseB.mutex);
            goose_HW_PowerRequest(&dev->modbusTCP.gooseB);
        }break;

        case POWER_REQUEST_CONST_CURRENT:{
            pthread_mutex_lock(&dev->modbusTCP.gooseB.mutex);
            dev->modbusTCP.gooseB.power_request.connect_id = dev->modbusTCP.regs_0x1D00[0x0E];
            dev->modbusTCP.gooseB.power_request.serialnumb = 0xFFFF;
            switch (dev->GUN_State[1])
            {
                case GUN_INSULATION: dev->modbusTCP.gooseB.power_request.type = PRT_INSLUATION_DETECTION_START;break;
                case GUN_PRECHARGE: dev->modbusTCP.gooseB.power_request.type = PRT_PRECHARGING;break;
                case GUN_CHARGING: dev->modbusTCP.gooseB.power_request.type = PRT_CHARGING;break;
                default:dev->modbusTCP.gooseB.power_request.type = PRT_CHARGING;break;
            }
            dev->modbusTCP.gooseB.power_request.mode = PRM_CONSTANT_CURRENT;
            dev->modbusTCP.gooseB.power_request.requestV = voltage;
            dev->modbusTCP.gooseB.power_request.requestI = current;
            dev->modbusTCP.gooseB.power_request.resv0 = 0xFFFF;
            dev->modbusTCP.gooseB.power_request.resv1 = 0xFFFF;
            pthread_mutex_unlock(&dev->modbusTCP.gooseB.mutex);
            goose_HW_PowerRequest(&dev->modbusTCP.gooseB);
        }break;
    }
}

static void pcuhw_GUNB_Update_error_state(void* self, uint32_t GUN_Error, uint32_t GUN_State)
{
    pcuhw_t* dev = (pcuhw_t*)(((pcu_port_t*)self)->priv);

    printd("GUN_Error:%08x, GUN_State:%08x\n", GUN_Error, GUN_State);

    if (dev->GUN_State[1] != GUN_PLUGOUT && GUN_State == GUN_PLUGOUT)
    {
        dev->modbusTCP.regs_0x1D00[0x0B] = HW_WORK_MODE_PLUGIN_HOME;//工作状态
        modbusTCP_HW_report_registers(&dev->modbusTCP, 0x1D0B, &dev->modbusTCP.regs_0x1D00[0x0B], 1);
    }

    if (dev->GUN_State[1] != GUN_PLUGIN && GUN_State == GUN_PLUGIN)
    {
        dev->modbusTCP.regs_0x1D00[0x0B] = HW_WORK_MODE_PLUGIN_EV;//工作状态
        modbusTCP_HW_report_registers(&dev->modbusTCP, 0x1D0B, &dev->modbusTCP.regs_0x1D00[0x0B], 1);

        dev->modbusTCP.regs_0x1D00[0x0D] = HW_FULLLINK_STATE;//连接状态
        modbusTCP_HW_report_registers(&dev->modbusTCP, 0x1D0D, &dev->modbusTCP.regs_0x1D00[0x0D], 1);
    }

    if (dev->GUN_State[1] != GUN_PLUGIN && GUN_State == GUN_PLUGIN)
    {
        dev->modbusTCP.regs_0x1D00[0x0D] = HW_SEMILINK_STATE;//半连接状态
        modbusTCP_HW_report_registers(&dev->modbusTCP, 0x1D0D, &dev->modbusTCP.regs_0x1D00[0x0D], 1);
    }

    if (dev->GUN_State[1] != GUN_CHARGING && GUN_State == GUN_CHARGING)
    {
        dev->modbusTCP.regs_0x1D00[0x0B] = HW_WORK_MODE_CHARGING;//工作状态
        modbusTCP_HW_report_registers(&dev->modbusTCP, 0x1D0B, &dev->modbusTCP.regs_0x1D00[0x0B], 1);
    }

    if (dev->GUN_State[1] != GUN_ELOCKED && GUN_State == GUN_ELOCKED)
    {
        dev->modbusTCP.regs_0x1D00[0x0B] = HW_WORK_MODE_PRECHARGING;//工作状态
        modbusTCP_HW_report_registers(&dev->modbusTCP, 0x1D0B, &dev->modbusTCP.regs_0x1D00[0x0B], 1);
    }
    if (dev->GUN_State[1] != GUN_INSULATION && GUN_State == GUN_INSULATION)
    {
        dev->modbusTCP.regs_0x1D00[0x0B] = HW_WORK_MODE_PRECHARGING;//工作状态
        modbusTCP_HW_report_registers(&dev->modbusTCP, 0x1D0B, &dev->modbusTCP.regs_0x1D00[0x0B], 1);
    }
    if (dev->GUN_State[1] != GUN_PRECHARGE && GUN_State == GUN_PRECHARGE)
    {
        dev->modbusTCP.regs_0x1D00[0x0B] = HW_WORK_MODE_PRECHARGING;//工作状态
        modbusTCP_HW_report_registers(&dev->modbusTCP, 0x1D0B, &dev->modbusTCP.regs_0x1D00[0x0B], 1);
    }
    dev->GUN_State[1] = GUN_State;
    dev->GUN_Error[1] = GUN_Error; 
}

static void pcuhw_GUNB_Update_GUN_type(void *self, gun_type_t GUN_type)
{
    pcuhw_t* dev = (pcuhw_t*)(((pcu_port_t*)self)->priv);
    switch(GUN_type)
    {
        case GUN_TYPE_CCS1:     hwpcu.modbusTCP.regs_0x1D00[0x04] = 1;break;
        case GUN_TYPE_CCS2:     hwpcu.modbusTCP.regs_0x1D00[0x04] = 2;break;
        case GUN_TYPE_CHADEMO:  hwpcu.modbusTCP.regs_0x1D00[0x04] = 3;break;
        case GUN_TYPE_GBDC:     hwpcu.modbusTCP.regs_0x1D00[0x04] = 4;break;
        default:                hwpcu.modbusTCP.regs_0x1D00[0x04] = 1; break;
    }
}

static void pcuhw_GUNB_Update_K1K2_state(void *self, int K1, int K2)
{
    pcuhw_t* dev = (pcuhw_t*)(((pcu_port_t*)self)->priv);
    if (K1==1 && K2==1){
        dev->modbusTCP.regs_0x1D00[0x54] = 1;//接触器状态
        modbusTCP_HW_report_registers(&dev->modbusTCP, 0x1D54, &dev->modbusTCP.regs_0x1D00[0x54], 1);
    }
        
    if (K1==0 && K2==0){
        dev->modbusTCP.regs_0x1D00[0x54] = 0;//接触器状态
        modbusTCP_HW_report_registers(&dev->modbusTCP, 0x1D54, &dev->modbusTCP.regs_0x1D00[0x54], 1);
    }
}

static void pcuhw_GUNB_Update_ELock_state(void *self, int lock_state)
{
    pcuhw_t* dev = (pcuhw_t*)(((pcu_port_t*)self)->priv);
    dev->modbusTCP.regs_0x1D00[0x56] = lock_state;//电子锁状态
    modbusTCP_HW_report_registers(&dev->modbusTCP, 0x1D56, &dev->modbusTCP.regs_0x1D00[0x56], 1);
}

static void pcuhw_GUNB_Update_MLock_state(void *self, int lock_state)
{
    pcuhw_t* dev = (pcuhw_t*)(((pcu_port_t*)self)->priv);
    dev->modbusTCP.regs_0x1D00[0x56] = lock_state;//电子锁状态
    modbusTCP_HW_report_registers(&dev->modbusTCP, 0x1D56, &dev->modbusTCP.regs_0x1D00[0x56], 1);
}

static void pcuhw_GUNB_Update_K1K2_voltate(void *self, float voltage)
{
    pcuhw_t* dev = (pcuhw_t*)(((pcu_port_t*)self)->priv);
    uint32_t* valueV = (uint32_t*)&voltage;

    dev->modbusTCP.regs_0x1D00[0x14] = (valueV[0]>>0) & 0xFFFF;
    dev->modbusTCP.regs_0x1D00[0x13] = (valueV[0]>>16) & 0xFFFF;
    modbusTCP_HW_report_registers(&dev->modbusTCP, 0x1D13, &dev->modbusTCP.regs_0x1D00[0x13], 2);
}

static void pcuhw_GUNB_Get_PCU_maxVoltateCurrent(void *self, float *maxV, float *maxI)
{
    pcuhw_t* dev = (pcuhw_t*)(((pcu_port_t*)self)->priv);
    uint32_t maxV32 = (dev->modbusTCP.regs_0x2D00[0x00]<<16)|dev->modbusTCP.regs_0x2D00[0x01];
    uint32_t maxI32 = (dev->modbusTCP.regs_0x2D00[0x02]<<16)|dev->modbusTCP.regs_0x2D00[0x03];
    float *maxVF32 = (float*)&maxV32;
    float *maxIF32 = (float*)&maxI32;
    if (maxVF32[0] < 10) maxVF32[0] = 1000;
    maxV[0] = maxVF32[0];
    maxI[0] = maxIF32[0];
}

static void pcuhw_GUNB_Get_PCU_minVoltageCurrent(void *self, float *minV, float *minI)
{
    pcuhw_t* dev = (pcuhw_t*)(((pcu_port_t*)self)->priv);
    uint32_t minV32 = (dev->modbusTCP.regs_0x2D00[0x05]<<16)|dev->modbusTCP.regs_0x2D00[0x06];
    uint32_t minI32 = (dev->modbusTCP.regs_0x2D00[0x07]<<16)|dev->modbusTCP.regs_0x2D00[0x08];
    float *minVF32 = (float*)&minV32;
    float *minIF32 = (float*)&minI32;
    minV[0] = minVF32[0];
    minI[0] = minIF32[0];
}

static void pcuhw_GUNB_Get_PCU_maxPermittedPower(void *self, float *power)
{
    pcuhw_t* dev = (pcuhw_t*)(((pcu_port_t*)self)->priv);
    uint32_t maxP32 = (dev->modbusTCP.regs_0x2D00[0x0D]<<16)|dev->modbusTCP.regs_0x2D00[0x0E];
    float *maxPF32 = (float*)&maxP32;
    if (maxPF32[0] < 10)
    {
        maxPF32[0] = 400;
    }
    power[0] = maxPF32[0];
}

static void pcuhw_GUNB_Get_PCU_outputPower(void *self, float *power)
{
    pcuhw_t* dev = (pcuhw_t*)(((pcu_port_t*)self)->priv);
    uint32_t ratedP32 = (dev->modbusTCP.regs_0x2D00[0x09]<<16)|dev->modbusTCP.regs_0x2D00[0x0A];
    float *ratedPF32 = (float*)&ratedP32;
    power[0] = ratedPF32[0];
}

static void pcuhw_GUNB_Update_MeterEnergyPower(void *self, float energy, float power)
{
    pcuhw_t* dev = (pcuhw_t*)(((pcu_port_t*)self)->priv);
    double meter_energy = energy;
    uint32_t* value = (uint32_t*)&meter_energy;

    dev->modbusTCP.regs_0x1D00[0x03] = (value[0]>>0) & 0xFFFF;
    dev->modbusTCP.regs_0x1D00[0x02] = (value[0]>>16) & 0xFFFF;
    dev->modbusTCP.regs_0x1D00[0x01] = (value[1]>>0) & 0xFFFF;
    dev->modbusTCP.regs_0x1D00[0x00] = (value[1]>>16) & 0xFFFF;
}

static void pcuhw_GUNB_Update_MeterVoltageCurrent(void *self, float voltage, float current)
{
    pcuhw_t* dev = (pcuhw_t*)(((pcu_port_t*)self)->priv);
    uint32_t* valueV = (uint32_t*)&voltage;
    uint32_t* valueI = (uint32_t*)&current;

    dev->modbusTCP.regs_0x1D00[0x08] = (valueV[0]>>0) & 0xFFFF;
    dev->modbusTCP.regs_0x1D00[0x07] = (valueV[0]>>16) & 0xFFFF;

    dev->modbusTCP.regs_0x1D00[0x0A] = (valueI[0]>>0) & 0xFFFF;
    dev->modbusTCP.regs_0x1D00[0x09] = (valueI[0]>>16) & 0xFFFF;
}

static void pcutc_GUNB_Update_EV_BatteryVoltage(void *self, float voltage)
{

}

static void pcuhw_GUNB_Update_maxPermittedCurrent(void *self, float maxI)
{
    pcuhw_t* dev = (pcuhw_t*)(((pcu_port_t*)self)->priv);
    uint32_t* current = (uint32_t*)&maxI;

    dev->modbusTCP.regs_0x1D00[0x06] = (current[0]>>0) & 0xFFFF;
    dev->modbusTCP.regs_0x1D00[0x05] = (current[0]>>16) & 0xFFFF;

    dev->modbusTCP.regs_0x1D00[0x03] = (current[0]>>0) & 0xFFFF;
    dev->modbusTCP.regs_0x1D00[0x02] = (current[0]>>16) & 0xFFFF;
}


pcu_port_t pcuhwB = 
{
    .priv = &hwpcu,
    
    .update_GUN_type = pcuhw_GUNB_Update_GUN_type,
    .update_GUN_error_state = pcuhw_GUNB_Update_error_state,
    .update_K1K2_state = pcuhw_GUNB_Update_K1K2_state,
    .update_ElecLock_state = pcuhw_GUNB_Update_ELock_state,
    .update_K1K2_voltate = pcuhw_GUNB_Update_K1K2_voltate,
    .update_Meter_EnergyPower = pcuhw_GUNB_Update_MeterEnergyPower,
    .update_Meter_VoltageCurrent = pcuhw_GUNB_Update_MeterVoltageCurrent,
    .update_EV_BatteryPower = pcutc_GUNB_Update_EV_BatteryVoltage,
    .set_GUNLine_PermittedVoltageCurrent = pcuhw_GUNB_Update_maxPermittedCurrent,

    .get_PCU_maxVoltageCurrent = pcuhw_GUNB_Get_PCU_maxVoltateCurrent,
    .get_PCU_minVoltageCurrent = pcuhw_GUNB_Get_PCU_minVoltageCurrent,
    .get_PCU_maxPermittedPower = pcuhw_GUNB_Get_PCU_maxPermittedPower,

    .request_Power = pcuhw_GUNB_power_request,
};

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

void pcuhw_Update_GUNA_mac_addr(void)
{
    pthread_mutex_lock(&hwpcu.modbusTCP.gooseA.mutex);
    dump_U16String_To_U8String(hwpcu.modbusTCP.gooseA.dst_mac, &hwpcu.modbusTCP.regs_0x2100[0x11], 3);
    dump_U16String_To_U8String(hwpcu.modbusTCP.gooseB.dst_mac, &hwpcu.modbusTCP.regs_0x2100[0x11], 3);
    pthread_mutex_unlock(&hwpcu.modbusTCP.gooseA.mutex);
    // printline(hwpcu.modbusTCP.gooseA.dst_mac, 6, "GUNA.recv.mac");
}

void pcuhw_Update_GUNB_mac_addr(void)
{
    pthread_mutex_lock(&hwpcu.modbusTCP.gooseB.mutex);
    dump_U16String_To_U8String(hwpcu.modbusTCP.gooseA.dst_mac, &hwpcu.modbusTCP.regs_0x2D00[0x11], 3);
    dump_U16String_To_U8String(hwpcu.modbusTCP.gooseB.dst_mac, &hwpcu.modbusTCP.regs_0x2D00[0x11], 3);
    pthread_mutex_unlock(&hwpcu.modbusTCP.gooseB.mutex);
    // printline(hwpcu.modbusTCP.gooseB.dst_mac, 6, "GUNB.recv.mac");
}

void pcuhw_Update_GUNA_HMAC(void)
{
    pthread_mutex_lock(&hwpcu.modbusTCP.gooseA.mutex);
    dump_U16String_To_U8String(hwpcu.modbusTCP.gooseA.HMAC, &hwpcu.modbusTCP.regs_0x2100[0x15], 24);
    pthread_mutex_unlock(&hwpcu.modbusTCP.gooseA.mutex);
    // printline(hwpcu.modbusTCP.gooseA.HMAC, 48, "GUNB.recv.HMAC");
}

void pcuhw_Update_GUNB_HMAC(void)
{
    pthread_mutex_lock(&hwpcu.modbusTCP.gooseB.mutex);
    dump_U16String_To_U8String(hwpcu.modbusTCP.gooseB.HMAC, &hwpcu.modbusTCP.regs_0x2D00[0x15], 24);
    pthread_mutex_unlock(&hwpcu.modbusTCP.gooseB.mutex);
    // printline(hwpcu.modbusTCP.gooseB.HMAC, 48, "GUNB.recv.HMAC");
}

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

void pcuhw_Stub_init(void)
{
    pcuhw_t* dev = (pcuhw_t*)&hwpcu;
    GUN_config_t* config = (GUN_config_t*)ccu_config.GUN_config;
    modbusTCP_HW_init(&dev->modbusTCP);

    pcuhwA.update_GUN_type(&pcuhwA, config[0].GUN_Type);
    pcuhwB.update_GUN_type(&pcuhwB, config[1].GUN_Type);

    pcuhwA.set_GUNLine_PermittedVoltageCurrent(&pcuhwA, config[0].GUN_maxI);
    pcuhwB.set_GUNLine_PermittedVoltageCurrent(&pcuhwB, config[1].GUN_maxI);

    dump_U8String_To_U16String(&dev->modbusTCP.regs_0x1100[0x4D], dev->modbusTCP.gooseA.src_mac, 6);
    dump_U8String_To_U16String(&dev->modbusTCP.regs_0x1D00[0x4D], dev->modbusTCP.gooseB.src_mac, 6);

    mthread_init(&dev->threadTCP, modbusTCP_HW_loop, &dev->modbusTCP);
}

void pcuhw_Stub_exit(void)
{
    pcuhw_t* dev = (pcuhw_t*)&hwpcu;

    dev->modbusTCP.gooseA.quit = 1;
    dev->modbusTCP.gooseB.quit = 1;
    dev->modbusTCP.quit = 1;

    mthread_exit(&dev->threadTCP);
    modbusTCP_HW_exit(&dev->modbusTCP);
}


















