#include "serial_control.h" #include "usart.h" #include "charger_control.h" #include "board.h" #include "psu_control.h" #include "debug.h" #include #ifdef USE_WEB_INTERFACE extern volatile SC_Source_t g_sc_command_source; IsolationStatusPacket_t ISO = { .isolationResistance = 0xFFFF }; uint8_t config_initialized = 0; ConfigBlock_t config = { .location = "RUS", .chargerNumber = 00001, .unixTime = 1721651966, }; // Единая функция-обработчик всех команд со switch-case void SC_CommandHandler(ReceivedCommand_t* cmd) { uint8_t response_code = RESP_FAILED; switch (cmd->command) { // Команды БЕЗ аргументов case CMD_GET_STATUS: // Логика получения информации monitoring_data_callback(); // Отправляем с нормальным приоритетом SC_SendPacket((uint8_t*)&statusPacket, sizeof(statusPacket), CMD_GET_STATUS); return; // Специальный ответ уже отправлен case CMD_GET_INFO: SC_SendPacket((uint8_t*)&infoPacket, sizeof(infoPacket), CMD_GET_INFO); return; case CMD_GET_LOG: debug_buffer_send(); return; // Ответ формируется внутри debug_buffer_send // Команды С аргументами case CMD_SET_CONFIG: if (cmd->argument_length == sizeof(ConfigBlock_t)) { memcpy(&config, cmd->argument, sizeof(ConfigBlock_t)); config_initialized = 1; log_printf(LOG_INFO, "Set Config: %s %d\n", config.location, config.chargerNumber); response_code = RESP_SUCCESS; break; } response_code = RESP_FAILED; break; case CMD_SET_POWER_LIMIT: if (cmd->argument_length == 1) { PSU0.power_limit = ((uint8_t*)cmd->argument)[0] * 1000; log_printf(LOG_INFO, "Power limit: %d\n", PSU0.power_limit); //CONN.connState = (((uint8_t*)cmd->argument)[0])/4; response_code = RESP_SUCCESS; break; } response_code = RESP_FAILED; break; case CMD_CHARGE_PERMIT: if (cmd->argument_length == 1) { CONN.connControl = ((uint8_t*)cmd->argument)[0]; log_printf(LOG_INFO, "Charge permit: %d\n", CONN.connControl); response_code = RESP_SUCCESS; break; } response_code = RESP_FAILED; break; case CMD_TEST_PSU: // if (cmd->argument_length == sizeof(PSU_TestMode_t)) { // memcpy(&PSU_TestMode, cmd->argument, sizeof(PSU_TestMode_t)); // log_printf(LOG_INFO, "Test PSU: %d %d %d\n", PSU_TestMode.enable, PSU_TestMode.voltage, PSU_TestMode.current); // response_code = RESP_SUCCESS; // break; // } response_code = RESP_FAILED; break; case CMD_DEVICE_RESET: // 2. Отправляем SUCCESS (хост может успеть получить его перед ребутом) SC_SendPacket(NULL, 0, RESP_SUCCESS); while(huart2.gState == HAL_UART_STATE_BUSY_TX); // Ожидание завершения передачи HAL_Delay(10); // 3. Выполняем программный сброс NVIC_SystemReset(); return; // Сюда код уже не дойдет, но для компилятора нxужно case CMD_ISOLATION_STATUS: if (cmd->argument_length == sizeof(IsolationStatusPacket_t)) { memcpy(&ISO, cmd->argument, sizeof(IsolationStatusPacket_t)); // Для однонаправленного UART5 ответ не нужен if (g_sc_command_source == SC_SOURCE_UART5) { return; } response_code = RESP_SUCCESS; break; } response_code = RESP_FAILED; break; default: // Неизвестная команда response_code = RESP_FAILED; break; } // Отправляем финальный ответ (для команд без собственного ответа) SC_SendPacket(NULL, 0, response_code); } // Колбэк для заполнения данных мониторинга void monitoring_data_callback() { // Информация о зарядной сессии statusPacket.SOC = CONN.SOC; statusPacket.Energy = CONN.Energy; statusPacket.RequestedVoltage = CONN.RequestedVoltage; statusPacket.RequestedCurrent = CONN.WantedCurrent; statusPacket.MeasuredVoltage = CONN.MeasuredVoltage; statusPacket.MeasuredCurrent = CONN.MeasuredCurrent; statusPacket.outputEnabled = CONN.outputEnabled; statusPacket.chargingError = CONN.chargingError; statusPacket.connState = CONN.connState; statusPacket.chargingElapsedTimeMin = 0; statusPacket.chargingElapsedTimeSec = 0; statusPacket.estimatedRemainingChargingTime = 0; // состояние зарядной станции statusPacket.relayAC = RELAY_Read(RELAY_AC); statusPacket.relayDC = RELAY_Read(RELAY_DC); statusPacket.relayAUX = RELAY_Read(RELAY_AUX0); statusPacket.lockState = 0; statusPacket.stopButton = !IN_ReadInput(IN_ESTOP); statusPacket.logAvailable = (debug_buffer_available()>0)?1:0; statusPacket.evInfoAvailable = 0; statusPacket.psuOnline = PSU0.online; statusPacket.tempConnector0 = CONN_ReadTemp(0); // температура коннектора statusPacket.tempConnector1 = CONN_ReadTemp(1); statusPacket.tempAmbient = PSU0.tempAmbient; // температура окружающего воздуха statusPacket.tempBatteryMax = 0; statusPacket.tempBatteryMin = 0; statusPacket.highestVoltageOfBatteryCell = 0; statusPacket.batteryStatus = 0; statusPacket.phaseVoltageAB = PSU_06.VAB; statusPacket.phaseVoltageBC = PSU_06.VBC; statusPacket.phaseVoltageCA = PSU_06.VCA; // GBT TODO memset(statusPacket.VIN, 0, sizeof(statusPacket.VIN)); // GBT TODO statusPacket.batteryType = 0; statusPacket.batteryCapacity = 0; statusPacket.batteryVoltage = 0; memset(statusPacket.batteryVendor, 0, sizeof(statusPacket.batteryVendor)); statusPacket.batterySN = 0; statusPacket.batteryManuD = 0; statusPacket.batteryManuM = 0; statusPacket.batteryManuY = 0; statusPacket.batteryCycleCount = 0; statusPacket.ownAuto = 0; memset(statusPacket.EV_SW_VER, 0, sizeof(statusPacket.EV_SW_VER)); statusPacket.testMode = 0; statusPacket.testVoltage = 0; statusPacket.testCurrent = 0; // Информация о тачке // --- Информация об EV (из команды info2) --- // memcpy(statusPacket.version, GBT_EVInfo.version, sizeof(statusPacket.version)); // --- Состояние Hardware и GBT (различные команды) --- //statusPacket.lockState = GBT_LockGetState(); // Из команды lock_state //statusPacket.ccState = CONN_CC_GetState(); // Из команды cc_state //statusPacket.ccAdc = CONN_CC_GetAdc(); // Из команды adc // --- Поля, требующие внимания (неявные геттеры) --- // 1. Состояние соединения (ConnState) // В debug.c есть CONN_SetState, предполагаем наличие CONN_GetState() // Если такой функции нет, закомментируйте следующую строку: // statusPacket.connState = CONN_GetState(); } #endif