// // Created by xemon on 21.10.22. // #include "EraGlonassUveos_Private.h" #define LOGGER env->logger #define LOG_SIGN "УВЭОС" void EraGlonassUveos_Init( tEraGlonassUveos *env, tLoggerInterface *logger, tEraGlonassMsdTable *msdTable, tUveosGostSettings *settings, tEraGlonassUveosDumperInterface *dumper, tNavDataProvider *navDataProvider, tEraGlonassEcallProvider *ecallProvider, tEraGlonassSmsProvider *smsProvider, tEraGlonassUveosIndicator *indicator, tUserButtonsInterface *buttons, uint16_t addButtonId, tAudioPlayerInterface *audioPlayer, tRtcIO *Rtc, uint32_t stopLimitTime ) { env->timings.rtcIo = Rtc; env->buttons = buttons; env->buttonsIds.additional = addButtonId; env->dumper = dumper; env->ecallProvider = ecallProvider; env->logger = logger; env->settings = settings; env->navDataProvider = navDataProvider; env->msdTable = msdTable; env->doNothing.mode = UVEOS_DO_NOTHING_DISABLED; env->doNothing.stopLimitTime = stopLimitTime; env->smsProvider = smsProvider; env->indicator = indicator; env->currentMsd = EraGlonassMsdTable_GetNextFree(env->msdTable); EraGlonassMsdInit(&env->currentMsd->msd); env->timings.lastInMemTransmit = 0; env->timings.lastTestCall = 0; env->timings.allowInCall = 0; env->timings.lastNetworkRequest = 0; env->timings.requireNetwork = 0; env->timings.powerOfDelay = 0; env->audioPlayer = audioPlayer; EraGlonassUveos_InvalidateSettings(env); } void EraGlonassUveos_InvalidateSettings(tEraGlonassUveos *env) { LoggerInfoStatic(LOGGER, LOG_SIGN, "Обновляем параметры из настроек...") EraGlonassMsdSetPassengersNumber(&env->currentMsd->msd, env->settings->VEHICLE_PASSENGERS_NUMBER); EraGlonassMsdSetVehicleType(&env->currentMsd->msd, env->settings->VEHICLE_TYPE); EraGlonassMsdSetVIN(&env->currentMsd->msd, env->settings->VIN.data, env->settings->VIN.length); EraGlonassMsdSetPropulsionStorageType(&env->currentMsd->msd, env->settings->VEHICLE_PROPULSION_STORAGE_TYPE); } bool EraGlonassUveos_RequiredInMemTransmit(tEraGlonassUveos *env) { tEraGlonassMsdTableItem *first = EraGlonassMsdTable_GetNoSendData(env->msdTable, NULL); if (first) { return true; } return false; } bool EraGlonassUveos_IsAllowInCall(tEraGlonassUveos *env) { if (env->timings.allowInCall > SystemGetMs()) { return true; } else { return false; } } static const uint32_t NETWORK_REQ_DELAY = 3000; //запрос необходимости передачи мнд из памяти //для предварительного срабатывания заранее за вермя T до реального срабатывания необходиммо задать //праметр timeOffset = T, в таком случае функция вернет true на T милисикунд раньше bool EraGlonassUveos_InMemTransmitNow(tEraGlonassUveos *env, uint32_t timeOffset) { if (EraGlonassUveos_RequiredInMemTransmit(env)) { if (env->timings.lastInMemTransmit) { uint32_t nextTransmit = env->timings.lastInMemTransmit + (env->settings->INT_MEM_TRANSMIT_INTERVAL * 60 * 1000); if (nextTransmit < timeOffset) { return true; } else { return ((nextTransmit - timeOffset) < SystemGetMs()); } } else { return true; } } return false; } // если установелнно время до которого мы должны находиться в сети // и это время меньше текущего говорим что сеть нужна bool EraGlonassUveos_IsStandby(tEraGlonassUveos *env) { if((env->timings.requireNetwork > 0 ) && (env->timings.requireNetwork > SystemGetMs()) ){ return true; } return false; } bool EraGlonassUveos_IsPowerOffDelay(tEraGlonassUveos *env) { if(env->timings.powerOfDelay > SystemGetMs() ){ return true; } return false; } bool EraGlonassUveos_IsRequireNetwork(tEraGlonassUveos *env) { if (EraGlonassUveos_InMemTransmitNow(env, NETWORK_REQ_DELAY)) { return true; } return EraGlonassUveos_IsStandby(env); } bool EraGlonassUveos_IsVinCorrect(tEraGlonassUveos *env) { //todo похорошему нужно проверять vin на валидность, а так просто смотрим есть ли он вообще return env->settings->VIN.length; } bool EraGlonassUveos_IsEraAllowed(tEraGlonassUveos *env) { return EraGlonassUveos_IsVinCorrect(env); } void EraGlonassUveos_ProcessingInMemTransmit(tEraGlonassUveos *env) { if (EraGlonassUveos_InMemTransmitNow(env, 0)) { tEraGlonassMsdTableItem *item = NULL; //Достаем из таблицы неотправленное МНД while ((item = EraGlonassMsdTable_GetNextUnsent(env->msdTable, item)) != NULL) { //остались ли у нас попытки переотправки и валидный ли id в таблице if (item->attemptsLeft > 0) { LoggerInfoStatic(LOGGER, LOG_SIGN, "Обнаружено не обработанное экстренное событие") LoggerInfoStatic(LOGGER, LOG_SIGN, "Производится переотправка МНД") if (EraGlonassUveos_ResentMsdTry(env, item)) { LoggerInfoStatic(LOGGER, LOG_SIGN, "МНД успешно переотправлен") EraGlonassMsdTable_Init(env->msdTable); EraGlonassUveosDumper_ForceDump(env->dumper); } else { LoggerInfoStatic(LOGGER, LOG_SIGN, "Не удалось переотправить МНД, продолжаются попытки") } } } env->timings.lastInMemTransmit += (env->settings->INT_MEM_TRANSMIT_INTERVAL * 60 * 1000); } } void EraGlonassUveos_ProcessingCheckNoSendMSD(tEraGlonassUveos *env) { tEraGlonassMsdTableItem *item = NULL; volatile bool sendThisMSDFlag = false; volatile uint8_t tempAttemptsLeft = 0; volatile uint8_t noSendMsdCount = EraGlonassMsdTable_GetNoSendDataCount(env->msdTable); item = EraGlonassMsdTable_GetNoSendData(env->msdTable, NULL); volatile uint8_t isChekCount = 0; volatile uint8_t isSendCount = 0; for(; isChekCount < noSendMsdCount; isChekCount++){ if(item!= NULL) { LoggerInfoStatic(LOGGER, LOG_SIGN, "Обнаружено не обработанное экстренное событие") tempAttemptsLeft = item->attemptsLeft; EraGlonassMsdSetDataEmergencySituationFlags(&item->msd, item->msd.MSD_Data.msgId, AUTOMATIC_ACTIVATION, EMERGENCY_CALL); LoggerInfoStatic(LOGGER, LOG_SIGN, "Производится переотправка МНД") if (EraGlonassUveos_ResentMsdTry(env, item)) { LoggerInfoStatic(LOGGER, LOG_SIGN, "МНД успешно переотправлен") sendThisMSDFlag = true; } else { item->attemptsLeft--; sendThisMSDFlag = false; LoggerInfoStatic(LOGGER, LOG_SIGN, "Не удалось переотправить МНД, продолжаются попытки") } if (!sendThisMSDFlag) { item->attemptsLeft = tempAttemptsLeft; } EraGlonassUveosDumper_ForceDump(env->dumper); } item = EraGlonassMsdTable_GetNoSendData(env->msdTable, NULL); } LoggerInfoStatic(LOGGER, LOG_SIGN, "Обработка данных по не отправленным экстренным событиям выполнена") if (isSendCount == noSendMsdCount){ EraGlonassMsdTable_Init(env->msdTable); EraGlonassUveosDumper_ForceDump(env->dumper); } } void EraGlonassUveos_ProcessingEra(tEraGlonassUveos *env) { EraGlonassUveos_ProcessingInMemTransmit(env); } void EraGlonassUveos_SetTimings(tEraGlonassUveos *env) { env->timings.allowInCall = SystemGetMs() + (env->settings->CALL_AUTO_ANSWER_TIME * 60 * 1000); env->timings.requireNetwork = SystemGetMs() + (env->settings->NAD_DEREGISTRATION_TIME * 60 * 1000); env->timings.powerOfDelay = SystemGetMs() + (env->settings->notGost.FULL_POWER_OFF_TIME * 60 * 1000); env->timings.lastInMemTransmit = SystemGetMs() + (env->settings->INT_MEM_TRANSMIT_INTERVAL * 60 * 1000); } eEraGlonassUveos_EcallProcessingResult EraGlonassUveos_ProcessingEmergencyEvent(tEraGlonassUveos *env, tUveosEmergencyEvent *event) { EraGlonassUveos_Indicate(env, UVEOS_STATUS_AUTOMATIC_BEGIN); LoggerInfoStatic(LOGGER, LOG_SIGN, "Экстренное событие, автоматический вызов") LoggerInfoStatic(LOGGER, LOG_SIGN, "Заполняем дополнительную информацию в МНД о обстаятельствах события") tEraGlonassMsd_DataTypedef *msd = &env->currentMsd->msd.MSD_Data; msd->additionalDataPresent = true; msd->additionalData.diagnosticResult = NULL; env->currentMsd->msd.MSD_Data.msgId = 1; if (event->isImpact) { msd->additionalData.asi15Present = true; //todo проверить значение типа данных asi15 в мнд msd->additionalData.asi15 = (uint16_t) (event->impactValue * 1000); } if (event->isFlip) { msd->additionalData.crashInfoPresent = true; EraGlonassMsd_CrashInfoClear(&msd->additionalData.crashInfo); EraGlonassMsd_OptionalFlagSet(msd->additionalData.crashInfo.CrashWithRollover, true); } eEraGlonassUveos_EcallProcessingResult res; res = EraGlonassUveos_ProcessingEmergency(env, AUTOMATIC_ACTIVATION, env->settings->notGost.ECALL_TEST_MODE, false); LoggerInfoStatic(LOGGER, LOG_SIGN, "Обновляем время пребывания в сети и ожидания входящего вызова") uint32_t t = SystemGetMs() + 250; while (t > SystemGetMs()){} EraGlonassUveos_Indicate(env, UVEOS_STATUS_DIALING); t = SystemGetMs() + 10; while (t > SystemGetMs()){} EraGlonassUveos_SetTimings(env); return res; } void EraGlonassUveos_ManualEmergencyCall(tEraGlonassUveos *env, bool fl_blocRegNet) { EraGlonassUveos_Indicate(env, UVEOS_STATUS_MANUAL_BEGIN); LoggerInfoStatic(LOGGER, LOG_SIGN, "Экстренный вызов инициирован вручную") LoggerInfoStatic(LOGGER, LOG_SIGN, "Убираем дополнительную информацию в МНД") tEraGlonassMsd_DataTypedef *msd = &env->currentMsd->msd.MSD_Data; msd->additionalDataPresent = false; msd->additionalData.diagnosticResult = NULL; EraGlonassUveos_ProcessingEmergency(env, MANUAL_ACTIVATION, env->settings->notGost.ECALL_TEST_MODE, fl_blocRegNet); LoggerInfoStatic(LOGGER, LOG_SIGN, "Обновляем время пребывания в сети и ожидания входящего вызова") uint32_t t = SystemGetMs() + 250; while (t > SystemGetMs()){} EraGlonassUveos_Indicate(env, UVEOS_STATUS_DIALING); t = SystemGetMs() + 10; while (t > SystemGetMs()){} EraGlonassUveos_SetTimings(env); } eEraGlonassUveos_EcallProcessingResult EraGlonassUveos_TestEmergencyCall( tEraGlonassUveos *env, tMSD_DiagnosticResult *diagnosticResult, bool blocReg ) { if (env->timings.lastTestCall && ((env->timings.lastTestCall + (env->settings->TEST_REGISTRATION_PERIOD * 60 * 1000)) > SystemGetMs())) { return ERA_GLONASS_UVEOS_TEST_CALL_NOT_ALLOWED; } // EraGlonassUveos_Indicate(env, UVEOS_STATUS_TESTING_BEGIN); LoggerInfoStatic(LOGGER, LOG_SIGN, "Тестовый экстренный вызов инициирован") LoggerInfoStatic(LOGGER, LOG_SIGN, "Заполняем дополнительную информацию в МНД резульатами тестирования") tEraGlonassMsd_DataTypedef *msd = &env->currentMsd->msd.MSD_Data; // msd->additionalDataPresent = true; msd->additionalData.asi15Present = false; msd->additionalData.crashInfoPresent = false; // env->currentMsd->msd.MSD_Data.additionalData.diagnosticResult = diagnosticResult; env->currentMsd->msd.MSD_Data.msgId = 1; eEraGlonassUveos_EcallProcessingResult result = EraGlonassUveos_ProcessingEmergency( env, MANUAL_ACTIVATION, TEST_CALL, blocReg ); LoggerInfoStatic(LOGGER, LOG_SIGN, "Обновляем время пребывания в сети") env->timings.requireNetwork = SystemGetMs() + (env->settings->POST_TEST_REGISTRATION_TIME * 1000); env->timings.lastTestCall = SystemGetMs(); return result; } void EraGlonassUveos_Indicate(tEraGlonassUveos *env, tEraGlonassUveosStatus status) { if (env->indicator) { EraGlonassUveosIndicator_Show(env->indicator, status); } }