EraGlonassUveos/Src/EraGlonassUveos.c

314 lines
13 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// 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);
}
}