// // 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 *audioPlayerIO, 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->audioPlayerIO = audioPlayerIO; EraGlonassUveos_InvalidateSettings(env); env->fl_ecallState = false; env->fl_audioHids = true; } void EraGlonassUveos_setTelematicaChipState(tEraGlonassUveos *env, bool eValidCCID){ env->fl_telematicaCipReady = eValidCCID; } 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 < SystemGetMs()) { { env->timings.lastInMemTransmit = env->timings.lastInMemTransmit + (env->settings->INT_MEM_TRANSMIT_INTERVAL * 60 * 1000); return true; } } } return false; } // если установелнно время до которого мы должны находиться в сети // и это время меньше текущего говорим что сеть нужна bool EraGlonassUveos_IsStandby(tEraGlonassUveos *env) { if((env->timings.requireNetwork > 0 ) && (env->timings.requireNetwork > SystemGetMs()) ){ return true; } return false; } bool EraGlonassUveos_IsStandbyTestTimer(tEraGlonassUveos *env) { if ( env->timings.lastTestCall && ((env->timings.lastTestCall + (env->settings->TEST_REGISTRATION_PERIOD * 60 * 1000)) > SystemGetMs()) ) { return true; } else { 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; } bool statIsNetwork = EraGlonassUveos_IsStandby(env); // timings.requireNetwork bool statStandFulPower = EraGlonassUveos_IsAllowInCall(env); // timings.allowInCall bool statTestTimer = EraGlonassUveos_IsStandbyTestTimer(env); if ((statIsNetwork && statTestTimer) && (statStandFulPower) ) { return true; } return false; } bool EraGlonassUveos_IsVinCorrect(tEraGlonassUveos *env) { //todo похорошему нужно проверять vin на валидность, а так просто смотрим есть ли он вообще if (memcmp(&env->settings->VIN.data, "00000000000000000", sizeof("00000000000000000") - 1) == 0) return 0; 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, "Обнаружено не обработанное экстренное событие код 2") LoggerInfoStatic(LOGGER, LOG_SIGN, "Производится переотправка МНД") if (EraGlonassUveos_ResentMsdTry(env, item)) { LoggerInfoStatic(LOGGER, LOG_SIGN, "МНД успешно переотправлен") item->attemptsLeft = 0; EraGlonassUveosDumper_ForceDump(env->dumper); } else { item->attemptsLeft --; LoggerInfoStatic(LOGGER, LOG_SIGN, "Не удалось переотправить МНД, продолжаются попытки") } } } volatile uint16_t noSendMsdCount = EraGlonassMsdTable_GetNoSendDataCount(env->msdTable); if (noSendMsdCount == 0){ EraGlonassMsdTable_Init(env->msdTable); EraGlonassUveosDumper_ForceDump(env->dumper); 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); uint8_t isChekCount = 0; for(; isChekCount < noSendMsdCount; isChekCount++){ if(item != NULL) { LoggerInfoStatic(LOGGER, LOG_SIGN, "Обнаружено не обработанное экстренное событие код 1") tempAttemptsLeft = item->attemptsLeft; EraGlonassMsdSetDataEmergencySituationFlags(&item->msd, item->msd.MSD_Data.msgId, AUTOMATIC_ACTIVATION, EMERGENCY_CALL); LoggerInfoStatic(LOGGER, LOG_SIGN, "Производится переотправка МНД") if (EraGlonassUveos_ResentMsdTry(env, item)) { item->attemptsLeft = 0; LoggerInfoStatic(LOGGER, LOG_SIGN, "МНД отправлено по средствам СМС, количество попыток отправки текущего пакета установлено = 0") sendThisMSDFlag = true; EraGlonassUveosDumper_ForceDump(env->dumper); } else { item->attemptsLeft --; sendThisMSDFlag = false; LoggerInfoStatic(LOGGER, LOG_SIGN, "Не удалось отправить МНД по средствам СМС, количество попыток отправки снижено на 1") EraGlonassUveosDumper_ForceDump(env->dumper); } if (!sendThisMSDFlag) { item->attemptsLeft = tempAttemptsLeft; } } LoggerInfoStatic(LOGGER, LOG_SIGN, "Получение следующего не обработанного МНД...") item = EraGlonassMsdTable_GetNoSendData(env->msdTable, NULL); LoggerInfoStatic(LOGGER, LOG_SIGN, "Не обработанный МНД получен") } LoggerInfoStatic(LOGGER, LOG_SIGN, "Проверка итогов пересылки не обработанных МНД") volatile uint8_t noSendCn = EraGlonassMsdTable_GetNoSendDataCount(env->msdTable); if (noSendCn == 0){ LoggerInfoStatic(LOGGER, LOG_SIGN, "Не отправленные экстренные события обработаны полностью, данные из ПЗУ очищены") EraGlonassMsdTable_Init(env->msdTable); EraGlonassUveosDumper_ForceDump(env->dumper); } else { LoggerInfoStatic(LOGGER, LOG_SIGN, "Остались не обработанные МНД в хранилище") } LoggerInfoStatic(LOGGER, LOG_SIGN, "Обработка данных по не отправленным экстренным событиям выполнена") } 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); if(env->settings->notGost.ECALL_TEST_MODE){ env->timings.requireNetwork = SystemGetMs() + (env->settings->POST_TEST_REGISTRATION_TIME * 1000); } else { env->timings.requireNetwork = SystemGetMs() + (env->settings->NAD_DEREGISTRATION_TIME * 60 * 1000); } // env->timings.requireNetwork = SystemGetMs() + (env->settings->CALL_AUTO_ANSWER_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, env->settings->notGost.ECALL_DEBUG_MODE); LoggerInfoStatic(LOGGER, LOG_SIGN, "Обновляем время пребывания в сети и ожидания входящего вызова") return res; } eEraGlonassUveos_EcallProcessingResult EraGlonassUveos_ManualEmergencyCall(tEraGlonassUveos *env) { EraGlonassUveos_SetTimings(env); eEraGlonassUveos_EcallProcessingResult res; env->fl_ecallState = true; // 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; res = EraGlonassUveos_ProcessingEmergency(env, MANUAL_ACTIVATION, env->settings->notGost.ECALL_TEST_MODE, env->settings->notGost.ECALL_DEBUG_MODE); LoggerInfoStatic(LOGGER, LOG_SIGN, "Обновление времени пребывания в сети и ожидания входящего вызова") EraGlonassUveos_SetTimings(env); env->fl_ecallState = false; return res; } eEraGlonassUveos_EcallProcessingResult EraGlonassUveos_TestEmergencyCall( tEraGlonassUveos *env, tMSD_DiagnosticResult *diagnosticResult ) { if ( env->timings.lastTestCall && ((env->timings.lastTestCall + (env->settings->TEST_REGISTRATION_PERIOD * 60 * 1000)) > SystemGetMs()) ) { return ERA_GLONASS_UVEOS_TEST_CALL_NOT_ALLOWED; } 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, 0 ); 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); } }