#include "requester.h"

struct device CurrentDevice;
struct device Device_on_the_Network[8][16];
struct controlflags ControlFlags;

uint8_t CurrentStep = 0;
uint8_t LastStep = 0;
struct RXMsg rxMsg[CAN_RX_BUFFER_SIZE];

_Bool IsLeapYear(uint8_t year)
{
	year+=2000;
	return (year%400==0)||((year%4==0)&&(year%100!=0));
}

uint16_t AvailableCanRxMsg(void)
{
	return ((uint16_t)(CAN_RX_BUFFER_SIZE + LastStep - CurrentStep))%CAN_RX_BUFFER_SIZE;
}

/**
	* @brief Инициализация переферии
* @details Инициализация HAL, CAN, TIM7, RTC. 
* @note Фильтры CAN описаны в разделе REQUESTER_CAN_FILTERS().
*/
void REQUESTER_Init(void)
{
	HAL_Init();	
	MX_CAN_Init();
	HAL_CAN_Start(&_HCAN);
	REQUESTER_CAN_FILTERS();
	HAL_CAN_ActivateNotification(&_HCAN, CAN_IT_RX_FIFO0_MSG_PENDING);
	ControlFlags.IsPulse = 1;
	MX_TIM7_Init();
	MX_RTC_Init();
}

/**
* @brief Функция с обработкой полученных запросов
* @details В бесконечном цикле функция ожидает приёма сообщения. После этого сообщение распределяется в зависимости от DataType.
* Обработка запроса аналоговых значений - REQUESTER_AnalogProcessing().
*	Обработка широковещательных запросов - REQUESTER_BroadcastProcessing().
* Обработка запроса дискретных значений - REQUESTER_DiscreticProcessing().
* Обработка Modbus - REQUESTER_ModbusProcessing().
*/
void REQUESTER_MainWhile(void)
{
	HAL_TIM_Base_Start_IT(&htim7);
	unsigned currentAttemptCount;
	while(1)
	{
		if(AvailableCanRxMsg())
		{
			currentAttemptCount = 0;
				if(rxMsg[CurrentStep].eID.Fields.MsgType == DATA_TYPE_ANALOG)
				{
					REQUESTER_AnalogProcessing(rxMsg[CurrentStep]);
				}
				else if(rxMsg[CurrentStep].eID.Fields.MsgType == DATA_TYPE_BROADCAST)
				{
					REQUESTER_BroadcastProcessing(rxMsg[CurrentStep]);					
				}
				else if(rxMsg[CurrentStep].eID.Fields.MsgType == DATA_TYPE_DISCRETE)
				{
					REQUESTER_DiscreticProcessing(rxMsg[CurrentStep]);
				}
				else if(rxMsg[CurrentStep].eID.Fields.MsgType == DATA_TYPE_GENERAL_ADDRESS_SPACE)
				{
					
				}
				else if(rxMsg[CurrentStep].eID.Fields.MsgType == DATA_TYPE_MODBUS_COIL ||
					rxMsg[CurrentStep].eID.Fields.MsgType == DATA_TYPE_MODBUS_DISCRETE ||
					rxMsg[CurrentStep].eID.Fields.MsgType == DATA_TYPE_MODBUS_HOLDING ||
					rxMsg[CurrentStep].eID.Fields.MsgType == DATA_TYPE_MODBUS_INPUT)
				{
						REQUESTER_ModbusProcessing(rxMsg[CurrentStep]);
				}
			CurrentStep = (uint16_t)(CurrentStep + 1) % CAN_RX_BUFFER_SIZE;
		}
	}
}

/**
* @brief Функция обработки аналоговых запросов.
* @param struct RXMsg _rxMsg - структура для полученного сообщения.
* @details Функция, формирующая и отправляющая ответ на запросы. Типы запросов: Универсальный, Уставки, Напряжение, Ток, Температура.

*/
CRR_Status REQUESTER_AnalogProcessing(struct RXMsg _rxMsg)
{
	switch (_rxMsg.eID.Fields.Msg.Analog.SensorType)
	{
		case SENSOR_TYPE_ANALOG_UNIVERSAL:
		{
			return (CRR_Status)CanRequestToAnalogUniversal(_rxMsg);
			break;
		}
		case SENSOR_TYPE_ANALOG_USTAVKI:
		{
			return (CRR_Status)CanRequestToAnalogUSTAVKI(_rxMsg);
			break;
		}
		case SENSOR_TYPE_ANALOG_U:
		{
			return (CRR_Status)CanRequestToAnalogUSens(_rxMsg);
			break;
		}
		case SENSOR_TYPE_ANALOG_I:
		{
			return (CRR_Status)CanRequestToAnalogISens(_rxMsg);		
			break;
		}
		case SENSOR_TYPE_ANALOG_T:
		{
			return (CRR_Status)CanRequestToAnalogTSens(_rxMsg);
			break;
		}
		default:
			//RESERVE SENSOR TYPE
			return CRR_ERROR;
			break;
	}
	return CRR_ERROR;
}

__weak HAL_StatusTypeDef CanRequestToAnalogUniversal(struct RXMsg _rxMsg)
{
	CAN_TxHeaderTypeDef TxHeader;
	uint32_t TxMailBox = 0;
	uint8_t data[8];
	TxHeader.IDE = CAN_ID_EXT;
	TxHeader.TransmitGlobalTime = DISABLE;
	TxHeader.RTR = CAN_RTR_DATA;
	extID tmp_eID;
	tmp_eID.BitAll = _rxMsg.eID.BitAll;
	tmp_eID.Fields.Route = ROUTE_SLAVE;
	TxHeader.ExtId = tmp_eID.BitAll;
	TxHeader.DLC = 6;
	data[0] = 'U';
	data[1] = 'N';
	data[2] = 'I';
	data[3] = 'V';
	data[4] = 'E';
	data[5] = 'R';
	return HAL_CAN_AddTxMessage(&_HCAN, &TxHeader, data, &TxMailBox);
}

__weak HAL_StatusTypeDef CanRequestToAnalogUSTAVKI(struct RXMsg _rxMsg)
{
	CAN_TxHeaderTypeDef TxHeader;
	uint32_t TxMailBox = 0;
	uint8_t data[8];
	TxHeader.IDE = CAN_ID_EXT;
	TxHeader.TransmitGlobalTime = DISABLE;
	TxHeader.RTR = CAN_RTR_DATA;
	extID tmp_eID;
	tmp_eID.BitAll = _rxMsg.eID.BitAll;
	tmp_eID.Fields.Route = ROUTE_SLAVE;
	TxHeader.ExtId = tmp_eID.BitAll;
	TxHeader.DLC = 7;
	data[0] = 'U';
	data[1] = 'S';
	data[2] = 'T';
	data[3] = 'A';
	data[4] = 'V';
	data[5] = 'K';
	data[6] = 'I';
	return HAL_CAN_AddTxMessage(&_HCAN, &TxHeader, data, &TxMailBox);
}

__weak HAL_StatusTypeDef CanRequestToAnalogUSens(struct RXMsg _rxMsg)
{
	CAN_TxHeaderTypeDef TxHeader;
	uint32_t TxMailBox = 0;
	uint8_t data[8];
	TxHeader.IDE = CAN_ID_EXT;
	TxHeader.TransmitGlobalTime = DISABLE;
	TxHeader.RTR = CAN_RTR_DATA;
	extID tmp_eID;
	tmp_eID.BitAll = _rxMsg.eID.BitAll;
	tmp_eID.Fields.Route = ROUTE_SLAVE;
	TxHeader.ExtId = tmp_eID.BitAll;
	TxHeader.DLC = 6;
	data[0] = 'U';
	data[1] = 'S';
	data[2] = 47 + _rxMsg.eID.Fields.Msg.Analog.SensorID / 1000;
	data[3] = 47 + _rxMsg.eID.Fields.Msg.Analog.SensorID / 100 % 10;
	data[4] = 47 + _rxMsg.eID.Fields.Msg.Analog.SensorID / 10 % 10;
	data[5] = 47 + _rxMsg.eID.Fields.Msg.Analog.SensorID % 10;
	return HAL_CAN_AddTxMessage(&_HCAN, &TxHeader, data, &TxMailBox);
}

__weak HAL_StatusTypeDef CanRequestToAnalogISens(struct RXMsg _rxMsg)
{
	CAN_TxHeaderTypeDef TxHeader;
	uint32_t TxMailBox = 0;
	uint8_t data[8];
	TxHeader.IDE = CAN_ID_EXT;
	TxHeader.TransmitGlobalTime = DISABLE;
	TxHeader.RTR = CAN_RTR_DATA;
	extID tmp_eID;
	tmp_eID.BitAll = _rxMsg.eID.BitAll;
	tmp_eID.Fields.Route = ROUTE_SLAVE;
	TxHeader.ExtId = tmp_eID.BitAll;
	TxHeader.DLC = 6;
	data[0] = 'I';
	data[1] = 'S';
	data[2] = 47 + _rxMsg.eID.Fields.Msg.Analog.SensorID / 1000;
	data[3] = 47 + _rxMsg.eID.Fields.Msg.Analog.SensorID / 100 % 10;
	data[4] = 47 + _rxMsg.eID.Fields.Msg.Analog.SensorID / 10 % 10;
	data[5] = 47 + _rxMsg.eID.Fields.Msg.Analog.SensorID % 10;
	return HAL_CAN_AddTxMessage(&_HCAN, &TxHeader, data, &TxMailBox);
}

__weak HAL_StatusTypeDef CanRequestToAnalogTSens(struct RXMsg _rxMsg)
{
	CAN_TxHeaderTypeDef TxHeader;
	uint32_t TxMailBox = 0;
	uint8_t data[8];
	TxHeader.IDE = CAN_ID_EXT;
	TxHeader.TransmitGlobalTime = DISABLE;
	TxHeader.RTR = CAN_RTR_DATA;
	extID tmp_eID;
	tmp_eID.BitAll = _rxMsg.eID.BitAll;
	tmp_eID.Fields.Route = ROUTE_SLAVE;
	TxHeader.ExtId = tmp_eID.BitAll;
	TxHeader.DLC = 6;
	data[0] = 'T';
	data[1] = 'S';
	data[2] = 47 + _rxMsg.eID.Fields.Msg.Analog.SensorID / 1000;
	data[3] = 47 + _rxMsg.eID.Fields.Msg.Analog.SensorID / 100 % 10;
	data[4] = 47 + _rxMsg.eID.Fields.Msg.Analog.SensorID / 10 % 10;
	data[5] = 47 + _rxMsg.eID.Fields.Msg.Analog.SensorID % 10;
	return HAL_CAN_AddTxMessage(&_HCAN, &TxHeader, data, &TxMailBox);
}

/**
* @brief Функция обработки широковещательных запросов.
* @param struct RXMsg _rxMsg - структура для полученного сообщения.
* @details Функция, выполняющая команды, переданные в широковещательном формате с головного (master) устройства. Типы команд: Запрос статуса, запрос на включение или выключение, рестарт устройств, установка времени.
*/
CRR_Status REQUESTER_BroadcastProcessing(struct RXMsg _rxMsg)
{	
	switch(_rxMsg.eID.Fields.Msg.Broadcast.BroadcastType)
	{
		case SENSOR_TYPE_BROADCAST_STATUS:
		{
			//Обработка запроса статуса устройства
			if(CanRequestToBroadcastStatus(_rxMsg)!=HAL_OK)
			{
				return CRR_ERROR;
			}
			break;
		}
		case SENSOR_TYPE_BROADCAST_ONOFF:
		{
			//Обработка запроса на вкл/выкл 
			CanRequestToBroadcastOnOff(_rxMsg);
			break;
		}
		case SENSOR_TYPE_BROADCAST_RESTARTDEVICE:
		{
			CanRequestToBroadcastRestart(_rxMsg);
			break;
		}
		case SENSOR_TYPE_BROADCAST_RTCSETUP:
		{
			//Обработка запроса на синхронизацию времени
			//С головным устройством
			CanRequestToBroadcastRtcSetup(_rxMsg);
			break;;
		}
		default:
			//RESERVE SENSOR TYPE.
			return CRR_ERROR;
			break;
	}
	return CRR_OK;
}

__weak HAL_StatusTypeDef CanRequestToBroadcastStatus(struct RXMsg _rxMsg)
{
	CAN_TxHeaderTypeDef TxHeader;
	uint32_t TxMailBox = 0;
	uint8_t data[8];	
	TxHeader.IDE = CAN_ID_EXT;
	TxHeader.DLC = 7;
	TxHeader.TransmitGlobalTime = DISABLE;
	TxHeader.RTR = CAN_RTR_DATA;
	extID tmp_eID;
	tmp_eID.BitAll = _rxMsg.eID.BitAll;
	tmp_eID.Fields.Route = ROUTE_SLAVE;
	tmp_eID.Fields.DeviceType = CURRENT_TYPE_DEVICE;
	tmp_eID.Fields.DeviceID = CURRENT_ID_DEVICE;
	TxHeader.ExtId = tmp_eID.BitAll;
	
	RTC_TimeTypeDef sTime = {0};
	HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
	data[0] = sTime.Hours;
	data[1] = sTime.Minutes;
	data[2] = sTime.Seconds;
	
	RTC_DateTypeDef DateToUpdate = {0};
	HAL_RTC_GetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BIN);
	data[3] = DateToUpdate.Year;
	data[4] = DateToUpdate.Month;
	data[5] = DateToUpdate.Date;
	data[6] = DateToUpdate.WeekDay;
	
	return HAL_CAN_AddTxMessage(&_HCAN, &TxHeader, data, &TxMailBox);
}

__weak void CanRequestToBroadcastOnOff(struct RXMsg _rxMsg)
{
	ControlFlags.IsPulse = !ControlFlags.IsPulse;
}

__weak void CanRequestToBroadcastRestart(struct RXMsg _rxMsg)
{
	if(_rxMsg.DLC == 0)
	{
		return;
	}
	if(_rxMsg.eID.Fields.Msg.Broadcast.Page == (CURRENT_ID_DEVICE / (_rxMsg.DLC*8)))
	{
		uint64_t page = 0;
		for(int i = 0; i < _rxMsg.DLC; i++)
		{
			page+=(_rxMsg.Data[i]<<(i*8));
		}
		if((page>>CURRENT_ID_DEVICE)&0b1)
		{
			NVIC_SystemReset();
		}
	}
	return;
}

__weak void CanRequestToBroadcastRtcSetup(struct RXMsg _rxMsg)
{
	if(_rxMsg.DLC > 7)
		{
			//ERROR
		}
		else
		{
			int DaysCount_Normal[2][12] = {{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 
																			{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
			if (_rxMsg.Data[0]>23 ||
					_rxMsg.Data[1]>59 ||
					_rxMsg.Data[2]>59 ||
					_rxMsg.Data[3]>99 ||
					_rxMsg.Data[4]>12 ||
					_rxMsg.Data[5] > DaysCount_Normal[IsLeapYear(_rxMsg.Data[3])][_rxMsg.Data[4]] ||
					_rxMsg.Data[6]>6)
			{
				//ERROR
			}
			else
			{
				REQUESTER_RTC_SYNC(_rxMsg.Data);
			}
		}
}

/**
* @brief Функция обработки дискретных запросов.
* @param struct RXMsg _rxMsg - структура для полученного сообщения.
* @details Функция, формирующая и отправляющая ответ на запросы. Типы запросов: Аварии, Предупреждения, Управляющие сигналы, Флаги, Рестарт устройства, Изменение режима работы устройства, Запрос на устройство.
* @note Запрос на устройство. Головное (master) устройство запрашивает некоторое колличество параметров. В Data - 64 битовых адресса параметров, тип которых задаётся в Sensor ID. Имеется возможность запрашивать непоследовательные параметры.
*/
CRR_Status REQUESTER_DiscreticProcessing(struct RXMsg _rxMsg)
{
	switch(_rxMsg.eID.Fields.Msg.Discrete.Type){
		case SENSOR_TYPE_DISCRETE_ACCIDENT:
		{
			CanRequestToDiscreteAccident(_rxMsg);
			break;
		}
		case SENSOR_TYPE_DISCRETE_WARNING:
		{
			CanRequestToDiscreteWarning(_rxMsg);
			break;
		}
		case SENSOR_TYPE_DISCRETE_CONTROL_SIGNALS:
		{
			CanRequestToDiscreteControlSignals(_rxMsg);
			break;
		}
		case SENSOR_TYPE_DISCRETE_FLAGS:
		{
			CanRequestToDiscreteFlags(_rxMsg);
			break;
		}
		case SENSOR_TYPE_DISCRETE_RESET:
		{
			CanRequestToDiscreteReset(_rxMsg);
			break;
		}
		case SENSOR_TYPE_DISCRETE_CHANGE_MODE:
		{
			CanRequestToDiscreteChangeMode(_rxMsg);
			break;
		}
		case SENSOR_TYPE_DISCRETE_REQUEST_LIST_OF_PARAMETERS:
		{
			CanRequestToDiscreteRequestListOfParameters(_rxMsg);
			break;
		}
		default:
			//RESERVE SENSOR TYPE.
			return CRR_ERROR;
			break;
	}
	return CRR_OK;
}

__weak void CanRequestToDiscreteAccident(struct RXMsg _rxMsg)
{
	return;
}

__weak void CanRequestToDiscreteWarning(struct RXMsg _rxMsg)
{
	return;
}

__weak void CanRequestToDiscreteControlSignals(struct RXMsg _rxMsg)
{
	return;
}

__weak void CanRequestToDiscreteFlags(struct RXMsg _rxMsg)
{
	return;
}

__weak void CanRequestToDiscreteReset(struct RXMsg _rxMsg)
{
	NVIC_SystemReset();
}

__weak void CanRequestToDiscreteChangeMode(struct RXMsg _rxMsg)
{
	return;
}
__weak void CanRequestToDiscreteRequestListOfParameters(struct RXMsg _rxMsg)
{
	return;
}

/**
* @brief Функция обработки Modbus запросов.
* @param struct RXMsg _rxMsg - структура для полученного сообщения.
* @details Функция, формирующая и отправляющая ответ на запросы.
*/
CRR_Status REQUESTER_ModbusProcessing(struct RXMsg _rxMsg)
{
	switch(_rxMsg.eID.Fields.MsgType)
	{
		case DATA_TYPE_MODBUS_COIL:
		{
			return (CRR_Status)CanRequestToModbusCoil(_rxMsg);
			break;
		}
		case DATA_TYPE_MODBUS_DISCRETE:
		{
			return (CRR_Status)CanRequestToModbusDiscrete(_rxMsg);
			break;
		}
		case DATA_TYPE_MODBUS_HOLDING:
		{	
			return (CRR_Status)CanRequestToModbusHolding(_rxMsg);
			break;
		}
		case DATA_TYPE_MODBUS_INPUT:
		{
			return (CRR_Status)CanRequestToModbusInput(_rxMsg);
			break;
		}
		default:
			//ERROR
			return CRR_ERROR;
			break;
	}
	return CRR_ERROR;
}

__weak HAL_StatusTypeDef CanRequestToModbusCoil(struct RXMsg _rxMsg)
{
	CAN_TxHeaderTypeDef TxHeader;
	uint32_t TxMailBox = 0;
	uint8_t data[8];
	TxHeader.IDE = CAN_ID_EXT;
	TxHeader.TransmitGlobalTime = DISABLE;
	TxHeader.RTR = CAN_RTR_DATA;
	extID tmp_eID;
	tmp_eID.BitAll = _rxMsg.eID.BitAll;
	tmp_eID.Fields.Route = ROUTE_SLAVE;
	TxHeader.ExtId = tmp_eID.BitAll;
	TxHeader.DLC = 8;
	data[0] = 'M';
	data[1] = 'C';
	data[2] = ' ';
	data[3] = 'S';
	data[4] = _rxMsg.eID.Fields.Msg.Modbus.StrAdr;
	data[5] = ' ';
	data[6] = 'C';
	data[7] = _rxMsg.eID.Fields.Msg.Modbus.RegCount;
	return HAL_CAN_AddTxMessage(&_HCAN, &TxHeader, data, &TxMailBox);
}
__weak HAL_StatusTypeDef CanRequestToModbusDiscrete(struct RXMsg _rxMsg)
{
	CAN_TxHeaderTypeDef TxHeader;
	uint32_t TxMailBox = 0;
	uint8_t data[8];
	TxHeader.IDE = CAN_ID_EXT;
	TxHeader.TransmitGlobalTime = DISABLE;
	TxHeader.RTR = CAN_RTR_DATA;
	extID tmp_eID;
	tmp_eID.BitAll = _rxMsg.eID.BitAll;
	tmp_eID.Fields.Route = ROUTE_SLAVE;
	TxHeader.ExtId = tmp_eID.BitAll;
	TxHeader.DLC = 8;
	data[0] = 'M';
	data[1] = 'D';
	data[2] = ' ';
	data[3] = 'S';
	data[4] = _rxMsg.eID.Fields.Msg.Modbus.StrAdr;
	data[5] = ' ';
	data[6] = 'C';
	data[7] = _rxMsg.eID.Fields.Msg.Modbus.RegCount;
	return HAL_CAN_AddTxMessage(&_HCAN, &TxHeader, data, &TxMailBox);
}
__weak HAL_StatusTypeDef CanRequestToModbusHolding(struct RXMsg _rxMsg)
{
	CAN_TxHeaderTypeDef TxHeader;
	uint32_t TxMailBox = 0;
	uint8_t data[8];
	TxHeader.IDE = CAN_ID_EXT;
	TxHeader.TransmitGlobalTime = DISABLE;
	TxHeader.RTR = CAN_RTR_DATA;
	extID tmp_eID;
	tmp_eID.BitAll = _rxMsg.eID.BitAll;
	tmp_eID.Fields.Route = ROUTE_SLAVE;
	TxHeader.ExtId = tmp_eID.BitAll;
	TxHeader.DLC = 8;
	data[0] = 'M';
	data[1] = 'H';
	data[2] = ' ';
	data[3] = 'S';
	data[4] = _rxMsg.eID.Fields.Msg.Modbus.StrAdr;
	data[5] = ' ';
	data[6] = 'C';
	data[7] = _rxMsg.eID.Fields.Msg.Modbus.RegCount;
	return HAL_CAN_AddTxMessage(&_HCAN, &TxHeader, data, &TxMailBox);
}
__weak HAL_StatusTypeDef CanRequestToModbusInput(struct RXMsg _rxMsg)
{
	CAN_TxHeaderTypeDef TxHeader;
	uint32_t TxMailBox = 0;
	uint8_t data[8];
	TxHeader.IDE = CAN_ID_EXT;
	TxHeader.TransmitGlobalTime = DISABLE;
	TxHeader.RTR = CAN_RTR_DATA;
	extID tmp_eID;
	tmp_eID.BitAll = _rxMsg.eID.BitAll;
	tmp_eID.Fields.Route = ROUTE_SLAVE;
	TxHeader.ExtId = tmp_eID.BitAll;
	TxHeader.DLC = 8;
	data[0] = 'M';
	data[1] = 'I';
	data[2] = ' ';
	data[3] = 'S';
	data[4] = _rxMsg.eID.Fields.Msg.Modbus.StrAdr;
	data[5] = ' ';
	data[6] = 'C';
	data[7] = _rxMsg.eID.Fields.Msg.Modbus.RegCount;
	return HAL_CAN_AddTxMessage(&_HCAN, &TxHeader, data, &TxMailBox);
}

/**
* @brief
* @param extID tmp_eID
* @param uint32_t tmp_IDE
* @param uint32_t tmp_RTR
* @param uint32_t tmp_DLC
* @param uint8_t *tmp_DATA
* @param uint16_t tmp_LastStep
* @details
*/
void TakeRxMsgToBuffer(extID tmp_eID, uint32_t tmp_IDE, uint32_t tmp_RTR, uint32_t tmp_DLC, uint8_t *tmp_DATA, uint16_t tmp_LastStep)
{
	rxMsg[tmp_LastStep].eID.BitAll = tmp_eID.BitAll;
	rxMsg[tmp_LastStep].info.EXT = tmp_IDE;
	rxMsg[tmp_LastStep].info.RTR = tmp_RTR;
	rxMsg[tmp_LastStep].DLC = tmp_DLC;
	for(int i = 0; i < tmp_DLC; i++)
	{
		rxMsg[tmp_LastStep].Data[i] = tmp_DATA[i];
	}
	LastStep = tmp_LastStep;
}

/**
* @brief Callback-Функция обработки приёма.
* @details Функция, сигнализирующая через флаги в бесконечный цикл REQUESTER_MainWhile о приёме запроса.
*/
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
	CAN_RxHeaderTypeDef RxHeader;
	uint8_t RCAN_Data[8];
	HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RCAN_Data);
	//Расширенный ID
	if(RxHeader.IDE == CAN_ID_EXT)
	{
		uint16_t tmp_LastStep = (uint16_t)(LastStep + 1) % CAN_RX_BUFFER_SIZE;

		if(tmp_LastStep == CurrentStep)
		{
			//Буффер переполнен
			return;
		}
		extID ExtID_Of_RX_MSG;
		ExtID_Of_RX_MSG.BitAll = RxHeader.ExtId;
		//Полученное сообщение - широковещательное
		if (ExtID_Of_RX_MSG.Fields.MsgType == DATA_TYPE_BROADCAST)
		{
			TakeRxMsgToBuffer(ExtID_Of_RX_MSG, RxHeader.IDE, RxHeader.RTR, RxHeader.DLC, RCAN_Data, tmp_LastStep);
			return;
		}
		//Если ID запроса соответствует ID устройства
		if((ExtID_Of_RX_MSG.Fields.DeviceType == CURRENT_TYPE_DEVICE) && (ExtID_Of_RX_MSG.Fields.DeviceID == CURRENT_ID_DEVICE))
		{
			if(ExtID_Of_RX_MSG.Fields.MsgType == DATA_TYPE_DISCRETE)
			{
				TakeRxMsgToBuffer(ExtID_Of_RX_MSG, RxHeader.IDE, RxHeader.RTR, RxHeader.DLC, RCAN_Data, tmp_LastStep);
				return;
			}
			if(ExtID_Of_RX_MSG.Fields.MsgType == DATA_TYPE_ANALOG)
			{
				//Является ли полученное сообщение - запросом
				if(RxHeader.RTR)
				{
					TakeRxMsgToBuffer(ExtID_Of_RX_MSG, RxHeader.IDE, RxHeader.RTR, RxHeader.DLC, RCAN_Data, tmp_LastStep);
					return;
				}
			}
			if(ExtID_Of_RX_MSG.Fields.MsgType == DATA_TYPE_MODBUS_COIL ||
				ExtID_Of_RX_MSG.Fields.MsgType == DATA_TYPE_MODBUS_DISCRETE ||
				ExtID_Of_RX_MSG.Fields.MsgType == DATA_TYPE_MODBUS_HOLDING ||
				ExtID_Of_RX_MSG.Fields.MsgType == DATA_TYPE_MODBUS_INPUT)
			{
				TakeRxMsgToBuffer(ExtID_Of_RX_MSG, RxHeader.IDE, RxHeader.RTR, RxHeader.DLC, RCAN_Data, tmp_LastStep);
				return;
			}
		}
		//Полученное сообщение - пульс устройств в сети
		if (ExtID_Of_RX_MSG.Fields.MsgType == DATA_TYPE_PULSE)
		{
			Device_on_the_Network[ExtID_Of_RX_MSG.Fields.DeviceType][ExtID_Of_RX_MSG.Fields.DeviceID].Status = ONLINE;
			Device_on_the_Network[ExtID_Of_RX_MSG.Fields.DeviceType][ExtID_Of_RX_MSG.Fields.DeviceID].TimeFromLastPulse = 0;
		}
	}
}

/**
* @brief Функция отправки пульса устройства.
* @details Пульс устройства. Есть возможность отключить пульс по запросу.
*/
void REQUESTER_Pulse_TIM_Handler()
{
	if(ControlFlags.IsPulse)
	{
		static unsigned PulseStage = 0;
		CAN_TxHeaderTypeDef TxHeader;
		uint32_t TxMailBox = 0;
		extID currentID;
		currentID.BitAll = 0;
		currentID.Fields.DeviceID = CURRENT_ID_DEVICE;
		currentID.Fields.DeviceType = CURRENT_TYPE_DEVICE;
		currentID.Fields.MsgType = DATA_TYPE_PULSE;
		currentID.Fields.Route = ROUTE_SLAVE;
		currentID.Fields.Priority = PRIORITY_STANDARD;
		TxHeader.ExtId = currentID.BitAll;
		uint8_t data[8];
		TxHeader.IDE = CAN_ID_EXT;
		TxHeader.TransmitGlobalTime = DISABLE;
		TxHeader.RTR = CAN_RTR_DATA;
		TxHeader.DLC = 1;
		if(PulseStage > 0xFF)
		{
			PulseStage = 0;
		}
		data[0] = PulseStage++;
		HAL_CAN_AddTxMessage(&_HCAN, &TxHeader, data, &TxMailBox);
	}
}

/**
* @brief Функция установки в RTC полученной даты/время из запроса.
* @param uint8_t *data - Байтовый массив, 7 элементов. [0] - Часы. [1] - Минуты. [2] - Секунды. [3] - Год. [4] - Месяц. [5] - Дата. [6] - День недели.
*/
void REQUESTER_RTC_SYNC(uint8_t *data)
{
	__HAL_RTC_WRITEPROTECTION_DISABLE(&hrtc);
	RTC_TimeTypeDef sTime = {0};
  RTC_DateTypeDef DateToUpdate = {0};
	
	sTime.Hours = data[0];
  sTime.Minutes = data[1];
  sTime.Seconds = data[2];
	
  if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK)
  {
    Error_Handler();
  }

  DateToUpdate.Year = data[3];
  DateToUpdate.Month = data[4];
  DateToUpdate.Date = data[5];
  DateToUpdate.WeekDay = data[6];
  if (HAL_RTC_SetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BIN) != HAL_OK)
  {
    Error_Handler();
  }
	__HAL_RTC_WRITEPROTECTION_ENABLE(&hrtc);
}

/**
* @brief Функция настройки фильтров CAN.
* @details Настройка фильтров. Фильр для приёма сообщений с главного устройства. Фильтр для приёма на текущее устройство. Фильтр для приёма пульса других устройств в сети.
*/

void CONFIG_CAN_FILTER(uint8_t filterBank, uint32_t idFilter, uint32_t idMask)
{
    CAN_FilterTypeDef canFilterConfig;
    canFilterConfig.FilterBank = filterBank;
    canFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
    canFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
    canFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
    canFilterConfig.FilterActivation = ENABLE;
    canFilterConfig.SlaveStartFilterBank = 14;

    // Разбиваем 32-битный ID и маску для фильтрации на High и Low 16 бит
    canFilterConfig.FilterIdHigh = (uint16_t)( ((idFilter & 0xFFFF) >> 13) );       // верхние 16 бит
    canFilterConfig.FilterIdLow  = (uint16_t)( (((idFilter & 0x1FFF) << 3) ) | CAN_IDE_32 );  // низкие 16 бит,
    canFilterConfig.FilterMaskIdHigh = (uint16_t)(((idMask & 0xFFFF) >> 13) );
    canFilterConfig.FilterMaskIdLow  = (uint16_t)( (((idMask & 0x1FFF) << 3) ) | CAN_IDE_32 );

    if(HAL_CAN_ConfigFilter(&_HCAN, &canFilterConfig) != HAL_OK)
    {
        Error_Handler();
    }
}

#define BIT27 (1UL << 27)
#define BITS_20_23_MASK (0xFUL << 20)       // 4 бита (20..23)
#define BITS_24_26_MASK (0x7UL << 24)       // 3 бита (24..26)

uint32_t filter1_id = BIT27 | CURRENT_TYPE_DEVICE | CURRENT_ID_DEVICE;
uint32_t filter1_mask = BIT27 | BITS_24_26_MASK | BITS_20_23_MASK; // все проверяемые биты

#define BITS_16_19_MASK (0xFUL << 16)

uint32_t filter2_id = DATA_TYPE_BROADCAST;
uint32_t filter2_mask = BITS_16_19_MASK;

uint32_t filter3_id = DATA_TYPE_PULSE;
uint32_t filter3_mask = BITS_16_19_MASK;

void REQUESTER_CAN_FILTERS()
{
    // Первый фильтр: проверяем 20-27 биты, где 27-й всегда 1
    CONFIG_CAN_FILTER(0, filter1_id, filter1_mask);

    // Второй фильтр: проверяем 16-19 биты, равны DATA_TYPE_BROADCASTE
    CONFIG_CAN_FILTER(1, filter2_id, filter2_mask);

    // Третий фильтр: проверяем 16-19 биты, равны DATA_TYPE_PULSE
    CONFIG_CAN_FILTER(2, filter3_id, filter3_mask);
}

//void REQUESTER_CAN_FILTERS()
//{
//	//MAIN DEVICE
//	CAN_FilterTypeDef canFilterConfig;
//	canFilterConfig.FilterBank = 0;
//	canFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
//	canFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
//	/*Для ID устройства используются восемь младших битов.
//	Макс значение 0 устройство - 0x000, 1 - 0x002, 2 - 0x004, 3 - 0x006*/
//	canFilterConfig.FilterIdHigh = (uint16_t)(ID_MAIN_DEVICE>>13);
//	canFilterConfig.FilterIdLow = (uint16_t)(ID_MAIN_DEVICE<<5) | CAN_IDE_32;
//	/*Маска 1.1111.1110.<...>. Нули - любые символы. Единицы - точное соответствие фильтру выше.*/
//	canFilterConfig.FilterMaskIdHigh = (uint16_t)(CAN_DEVICE_ID_FILTER>>13);
//	canFilterConfig.FilterMaskIdLow = (uint16_t)(CAN_DEVICE_ID_FILTER<<3) | CAN_IDE_32;
//	canFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
//	canFilterConfig.FilterActivation = ENABLE;
//	canFilterConfig.SlaveStartFilterBank = 14;
//	if(HAL_CAN_ConfigFilter(&_HCAN, &canFilterConfig) != HAL_OK)
//	{
//    Error_Handler();
//	}
//	
//	//CURRENT DEVICE
//	canFilterConfig.FilterBank = 1;
//	/*Для ID устройства используются восемь младших битов.
//	Макс значение 0 устройство - 0x000, 1 - 0x002, 2 - 0x004, 3 - 0x006*/
//	canFilterConfig.FilterIdHigh = (uint16_t)(CURRENT_ID_DEVICE>>13);
//	canFilterConfig.FilterIdLow = (uint16_t)(CURRENT_ID_DEVICE<<5) | CAN_IDE_32;
//	/*Маска 1.1111.1110.<...>. Нули - любые символы. Единицы - точное соответствие фильтру выше.*/
//	canFilterConfig.FilterMaskIdHigh = (uint16_t)(CAN_DEVICE_ID_FILTER>>13);
//	canFilterConfig.FilterMaskIdLow = (uint16_t)(CAN_DEVICE_ID_FILTER<<3) | CAN_IDE_32;
//	if(HAL_CAN_ConfigFilter(&_HCAN, &canFilterConfig) != HAL_OK)
//	{
//    Error_Handler();
//	}
//	
//	//MODBUS
//	canFilterConfig.FilterBank = 2;
//	canFilterConfig.FilterIdHigh = (uint16_t)(0x03000000>>13);
//	canFilterConfig.FilterIdLow = (uint16_t)(0x03000000<<5) | CAN_IDE_32;
//	canFilterConfig.FilterMaskIdHigh = 	(uint16_t)(CAN_DATA_TYPE_FILTER>>13); // we're checking only high 13 bits, that contained "key"
//	canFilterConfig.FilterMaskIdLow = 	(uint16_t)(CAN_DATA_TYPE_FILTER<<3) | CAN_IDE_32; // 1<<2 - set IDE bit
//	if(HAL_CAN_ConfigFilter(&_HCAN, &canFilterConfig) != HAL_OK)
//	{
//		Error_Handler();
//	}
//	
//	//PULSE
//	canFilterConfig.FilterBank = 3;
//	canFilterConfig.FilterIdHigh = (uint16_t)(HighIdFilter(DATA_TYPE_PULSE)>>13);
//	canFilterConfig.FilterIdLow = (uint16_t)(HighIdFilter(DATA_TYPE_PULSE)<<5) | CAN_IDE_32;
//	canFilterConfig.FilterMaskIdHigh = 	(uint16_t)(CAN_DATA_TYPE_FILTER>>13); // we're checking only high 13 bits, that contained "key"
//	canFilterConfig.FilterMaskIdLow = 	(uint16_t)(CAN_DATA_TYPE_FILTER<<3) | CAN_IDE_32; // 1<<2 - set IDE bit
//	if(HAL_CAN_ConfigFilter(&_HCAN, &canFilterConfig) != HAL_OK)
//	{
//		Error_Handler();
//	}
//	
//	//DEBUG FILTER "ALL IDE WELCOME"
//	canFilterConfig.FilterBank = 4;
//	canFilterConfig.FilterIdHigh = (uint16_t)(HighIdFilter(0)>>13);
//	canFilterConfig.FilterIdLow = (uint16_t)(HighIdFilter(0)<<5) | CAN_IDE_32;
//	canFilterConfig.FilterMaskIdHigh = 	(uint16_t)(0>>13); // we're checking only high 13 bits, that contained "key"
//	canFilterConfig.FilterMaskIdLow = 	(uint16_t)(0<<3) | CAN_IDE_32; // 1<<2 - set IDE bit
//	if(HAL_CAN_ConfigFilter(&_HCAN, &canFilterConfig) != HAL_OK)
//	{
//		Error_Handler();
//	}
//}
