EraGlonassUveos/Src/EraGlonassUveos.c

351 lines
15 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 *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);
}
}