
/**
  ******************************************************************************
  * @file    BLV_485_Dev_SwitchFun.c
  * @author  BLW RCU  development Team
  * @version SongHan
  * @date    2022年03月06日
  * @brief  
	*    时间设备  有两个服务 1，当主机获取到时间后，同步给外设   
	                         2，当外设请求时间，主机发给外设
	*    输入：无
	*    输出：无
	* @log    增加时间下发功能
  ******************************************************************************
  */




#include "BLV_485_Dev_TimeFun.h"
#include <string.h>
#include "BLV_485_Protocol.h"
#include "SPI_SRAM.h"
#include "usart.h"
#include "CH57x_common.h"
#include "check_fun.h"
#include "rw_logging.h"
#include "SRAM_Variable_Address.h"
#include "DBG.h"
#include "rtc.h"
#include "Log_api.h"
/*时间同步驱动代码*/

#define TIME_REPEATSENDTIMEMAX			0x01  	//本设备重发次数上限
void BLW_TimeCtrl(Device_Public_Information_G *BUS_Public, RS485_TIME_INFO *Rs485TimeCtrlInfo);

/*******************************************************************************
* Fail Description	: 485设备 - 时间同步驱动文件
* 
*******************************************************************************/

void BLV_485_Dev_Time_Init(uint8_t devaddr)
{
	Device_Public_Information_G BUS_Public;
	RS485_TIME_INFO Rs485TimeCtrlInfo;       //时间同步局部变量
	
	memset(&BUS_Public,0,sizeof(Device_Public_Information_G));
	memset(&Rs485TimeCtrlInfo,0,sizeof(RS485_TIME_INFO));
	
	BUS_Public.addr = devaddr;			//设备地址
	BUS_Public.type = DEV_TIME_TYPE;		//设备类型
	BUS_Public.port = Active_Port;			//设备发送端口
	BUS_Public.baud = 9600;			//设备发送波特率
	BUS_Public.retry_num = TIME_REPEATSENDTIMEMAX;		//设备数据重发次数
	BUS_Public.wait_time = 0x0064;		//设备数据发送等待回复时间
	BUS_Public.polling_cf = (uint32_t)&BLV_Rs485_Dev_Time_CycleDis;
	BUS_Public.processing_cf = (uint32_t)&BLV_Rs485_Dev_Time_Check;
	
	Rs485TimeCtrlInfo.DevOffline = Rs485TimeCtrlInfo.DevOfflineLast = DEV_IS_LINEUNINIT;   //在线状态初始化
	Add_ACT_Device_To_List2(&BUS_Public, (uint8_t *)&Rs485TimeCtrlInfo, sizeof(RS485_TIME_INFO));
}
void BLV_485_Dev_Time_Logic_Init(LOGICFILE_DEVICE_INFO *dev_info,uint8_t *data,uint16_t data_len)
{
	Device_Public_Information_G BUS_Public;
	RS485_TIME_INFO Rs485TimeCtrlInfo;       //时间同步局部变量
	
	memset(&BUS_Public,0,sizeof(Device_Public_Information_G));
	memset(&Rs485TimeCtrlInfo,0,sizeof(RS485_TIME_INFO));
	
	BUS_Public.addr = dev_info->addr;			//设备地址
	BUS_Public.type = dev_info->type;		//设备类型
	BUS_Public.port = dev_info->port;			//设备发送端口 
	BUS_Public.baud = dev_info->baud;;			//设备发送波特率
	BUS_Public.retry_num = TIME_REPEATSENDTIMEMAX;		//设备数据重发次数
	BUS_Public.wait_time = 0x0064;		//设备数据发送等待回复时间
	BUS_Public.polling_cf = (uint32_t)&BLV_Rs485_Dev_Time_CycleDis;
	BUS_Public.processing_cf = (uint32_t)&BLV_Rs485_Dev_Time_Check;
	
	Rs485TimeCtrlInfo.DevOffline = Rs485TimeCtrlInfo.DevOfflineLast = DEV_IS_LINEUNINIT;   //在线状态初始化
	Add_ACT_Device_To_List2(&BUS_Public, (uint8_t *)&Rs485TimeCtrlInfo, sizeof(RS485_TIME_INFO));
}
/*******************************************************************************
* Function Name  : BLV_Rs485_Dev_Time_CycleDis 
* Description    : 时间同步485数据发送处理函数，包括重发

* Return         : 
	0x01：有数据需要发送
	0x00：没有数据需要发送
*******************************************************************************/
uint8_t BLV_Rs485_Dev_Time_CycleDis(uint32_t DevAdd)  
{
	RS485_TIME_INFO Rs485TimeCtrlInfo;       //时间同步局部变量
	Device_Public_Information_G BUS_Public;
	uint8_t Ret = RS485OCCUPYNOTIME;     

//	uint8_t temp;
//	uint8_t Ret = 0x00;
//	uint8_t val_check = 0;
//	uint16_t dev_datalen = 0x00;
	
	/*拷贝设备私有信息*/
	SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public,sizeof(Device_Public_Information_G),DevAdd);	//拷贝所有共有数据
	SRAM_DMA_Read_Buff((uint8_t *)&Rs485TimeCtrlInfo, sizeof(RS485_TIME_INFO), DevAdd+Dev_Privately);
	
	/*判断设备是否有数据需要发送*/
	
	if((Rs485TimeCtrlInfo.TimeGetFlag != DevActionGlobal.TimeGetFlag) && (RTC_Raw_Data.year >= 0x16))   //产生时间同步标记，且时间有效
	{
		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"产生C43时间同步标志");
		Dbg_Println(DBG_BIT_SYS_STATUS_bit,"当前RTC时间: 20%X-%X-%X %X:%X:%X 星期%X",RTC_Raw_Data.year,RTC_Raw_Data.month,RTC_Raw_Data.day,RTC_Raw_Data.hour,RTC_Raw_Data.minute,RTC_Raw_Data.second,RTC_Raw_Data.week);
		Rs485TimeCtrlInfo.TimeGetFlag = DevActionGlobal.TimeGetFlag; 
//		Rs485WxLockInfo.WeixinLockWriteTime = RTC_Conversion_To_Unix(&RTC_Raw_Data);   //拿到当前主机运行的时间戳
		Rs485TimeCtrlInfo.TimeCtrlFlag = 0x01;    //时间设置标志置位
		Rs485TimeCtrlInfo.TimeCtrlCnt = TIME_REPEATSENDTIMEMAX;   //
	}
	
	
	if(0x01 == Rs485TimeCtrlInfo.TimeCtrlFlag)       //时间同步标志
	{
		if(0x00 != Rs485TimeCtrlInfo.TimeCtrlCnt)
		{
			Rs485TimeCtrlInfo.TimeCtrlCnt--;
		}
		else
		{
			Rs485TimeCtrlInfo.TimeCtrlFlag = 0x00;
		}
		BLW_TimeCtrl(&BUS_Public, &Rs485TimeCtrlInfo);  //时间同步函数
		Ret = RS485OCCUPYTIME;
	}	
	
	if(RS485OCCUPYTIME == Ret)
	{
		if(Rs485TimeCtrlInfo.DevSendCnt > TIME_REPEATSENDTIMEMAX)
		{
			if(Rs485TimeCtrlInfo.DevOffline != DEV_IS_OFFLINE)
			{
				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"Rs485_time LogInfo_Device_Offline...........");
				LOG_Device_Online_Record(DEV_TIME_TYPE,SRAM_Read_Byte(DevAdd+Dev_Addr),LogInfo_Device_Offline);	//记录设备离线
			}
			Rs485TimeCtrlInfo.DevOffline = DEV_IS_OFFLINE;		//判为离线
			if(Rs485TimeCtrlInfo.DevOffline != Rs485TimeCtrlInfo.DevOfflineLast)	//当前在线状态不等于上一次在线状态
			{
				Rs485TimeCtrlInfo.DevOfflineLast = Rs485TimeCtrlInfo.DevOffline;	//更新上一次在线状态
				Write_Device_Fault_State(BUS_Public.type,BUS_Public.addr,In_ErrFun_LineState,DEV_IS_OFFLINE);	//保存设备在线状态到SRAM
			}
		}
		else 
		{
			Rs485TimeCtrlInfo.DevSendCnt++;   				//发送次数累计

		}
		BLV_Communication_Record(&Rs485TimeCtrlInfo.comm_record,0x01,0x00);
		Rs485TimeCtrlInfo.inquire_tick = SysTick_1ms;

		BUS_Public.check = 0x00;
		BUS_Public.check = DoubleData_CheckSum((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), (uint8_t *)&Rs485TimeCtrlInfo, sizeof(RS485_TIME_INFO));
		SRAM_DMA_Write_Buff((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G),DevAdd);/*将数据保存*/
		SRAM_DMA_Write_Buff((uint8_t *)&Rs485TimeCtrlInfo,sizeof(RS485_TIME_INFO),DevAdd+Dev_Privately);
				
	}

	
	return Ret;
}

/*宝来威时间控制函数*/
void BLW_TimeCtrl(Device_Public_Information_G *BUS_Public, RS485_TIME_INFO *Rs485TimeCtrlInfo)
{
	uint8_t sendbuff[8];  // = {0};
//			temp = SRAM_Read_Byte(DevAdd+ Dev_port);
	
	sendbuff[0] = BUS_Public->addr;//SRAM_Read_Byte(DevAdd+ Dev_Addr);    //地址
	sendbuff[1] = TIME_ISSUE_CMD;    //下发时间命令
	uint32_t time = RTC_Conversion_To_Unix(&RTC_Raw_Data) + 8*3600;    //UTC时间
	sendbuff[2] = time;    //时间戳
	sendbuff[3] = time>>8;    //时间戳
	sendbuff[4] = time>>16;    //时间戳
	sendbuff[5] = time>>24;    //时间戳
	sendbuff[6] = ~CheckSum(sendbuff, 6);    //和校验
	MCU485_SendString(BUS_Public->port, sendbuff, 7);   //发送
	/*日志记录*/
	LOG_Device_COMM_Send_Control_Record2(BUS_Public->port,BUS_Public->baud,sendbuff,7);

}

#define IsMyData     0x00
#define IsNotMyData  0x01
/*******************************************************************************
* Function Name  : BLV_Rs485_Dev_Time_Check 
* Description    : 时间同步485接收处理函数

* Return         : 
	0x01：数据处理失败
	0x00：数据处理成功
*******************************************************************************/
uint8_t BLV_Rs485_Dev_Time_Check(uint32_t DevAdd ,uint32_t Data_addr, uint16_t DataLen) 
{
	uint8_t temp = 0;
	uint8_t ret = IsNotMyData;
	uint8_t receive[8]	= {0};
	RS485_TIME_INFO Rs485TimeCtrlInfo;       //时间同步局部变量
	Device_Public_Information_G BUS_Public;			
	
	if(DataLen != 7)
	{
		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"Time len err!");
		return ret;    //时间同步7个字节
	}
	/*拷贝设备私有信息*/
	SRAM_DMA_Read_Buff((uint8_t *)&Rs485TimeCtrlInfo,sizeof(RS485_TIME_INFO),DevAdd+Dev_Privately);
	SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public,sizeof(Device_Public_Information_G),DevAdd);		
	SRAM_DMA_Read_Buff(receive, DataLen, Data_addr);
	
	if(receive[0] != BUS_Public.addr)    //SRAM_Read_Byte(DevAdd+ Dev_Addr)
	{
		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"Time addr err!");
		return ret;    //地址不对
	}
	if((TIME_READ_CMD != receive[1]) && (TIME_ISSUE_CMD != receive[1]))
	{
		Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"Time CMD err!");
		return ret;
	}
	
	if(receive[DataLen-1] == (uint8_t)(~CheckSum(receive, 6)))   //和校验正确
	{
		ret = 0x00;
		Rs485TimeCtrlInfo.DevSendCnt = 0;        //重发计数清零
		Rs485TimeCtrlInfo.DevOffline = DEV_IS_ONLINE;		//判为在线		
		if(Rs485TimeCtrlInfo.DevOffline != DEV_IS_ONLINE)
		{
			Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"Rs485_time LogInfo_Device_Online....");
			LOG_Device_Online_Record(DEV_TIME_TYPE,SRAM_Read_Byte(DevAdd+Dev_Addr),LogInfo_Device_Online);	//记录设备在线
		}	
		if(Rs485TimeCtrlInfo.DevOffline != Rs485TimeCtrlInfo.DevOfflineLast)	//当前在线状态不等于上一次在线状态
		{
			Rs485TimeCtrlInfo.DevOfflineLast = Rs485TimeCtrlInfo.DevOffline;	//更新上一次在线状态
			Write_Device_Fault_State(BUS_Public.type,BUS_Public.addr,In_ErrFun_LineState,DEV_IS_ONLINE);	//保存设备在线状态到SRAM
		}
		switch(receive[1])    
		{
			case TIME_READ_CMD:     //读取时间
				temp++;
				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"接收到时间同步请求报文");
				
				Rs485TimeCtrlInfo.TimeCtrlFlag = 0x01;    //时间设置标志置位
				Rs485TimeCtrlInfo.TimeCtrlCnt = TIME_REPEATSENDTIMEMAX;   //				
				break;
			case TIME_ISSUE_CMD:    //下发时间回复
				temp++;
				Dbg_Println(DBG_BIT_DEVICE_STATUS_bit,"接收到C43时间确认报文");
				Rs485TimeCtrlInfo.TimeCtrlFlag = 0x00;
				break;
		}

		
		BLV_Communication_Record(&Rs485TimeCtrlInfo.comm_record,0x02,0x01);		//记录通讯成功
		LOG_Device_COMM_Control_Reply_Record(BUS_Public.port,BUS_Public.baud,receive,DataLen);/*日志记录*/

	}
	
	if(temp)
	{

		BUS_Public.check = 0x00;
		BUS_Public.check = DoubleData_CheckSum((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), (uint8_t *)&Rs485TimeCtrlInfo, sizeof(RS485_TIME_INFO));
		SRAM_DMA_Write_Buff((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G),DevAdd);/*将数据保存*/
		SRAM_DMA_Write_Buff((uint8_t *)&Rs485TimeCtrlInfo,sizeof(RS485_TIME_INFO),DevAdd+Dev_Privately);
						
		
		
	}
	
	return ret;
}

/*******************************************************************************
* Function Name  : BLV_Time_Control_Update 
* Description    : 开启时间同步
* Input          : 
	dev_addr	:设备地址
	loop		:控制开关回路
	mode		:模式
	dir			：方向
	num     : 步进值
*******************************************************************************/
//void BLV_Time_Control_Update(uint32_t dev_addr)
//{
//	uint8_t val_check = 0;
//	uint16_t dev_datalen = 0x00;
//	RS485_TIME_INFO Rs485TimeCtrlInfo;       //时间同步局部变量
//	
//	/*拷贝设备私有信息*/
//	SRAM_DMA_Read_Buff((uint8_t *)&Rs485TimeCtrlInfo,sizeof(RS485_TIME_INFO),dev_addr+Dev_Privately);
//	
////	Rs485TimeCtrlInfo.DevCtrlFlag = 1;
//	Rs485TimeCtrlInfo.DevSendCnt = 0;
//	
//	/*将数据保存，重新计算校验值 注意：一般数据有变动时，才重新计算校验值*/
//	SRAM_DMA_Write_Buff((uint8_t *)&Rs485TimeCtrlInfo,sizeof(RS485_TIME_INFO),dev_addr+Dev_Privately);
//	
//	SRAM_Write_Byte(0x00,dev_addr+Dev_Check);				//校验值清零
//	dev_datalen = sizeof(RS485_TIME_INFO) + Dev_Privately;
//	val_check = Dev_CheckSum(dev_addr,dev_datalen);
//	
//	SRAM_Write_Byte(val_check,dev_addr+Dev_Check);		//校验值重新写入
//}
