////////////////////////////////////////////////////////////////////////////////

/// 共同资源模块
///
///
/// 包含设备层和代理层共同资源 
/// @file    comm_queue.c 
/// @author  gkl 
/// @date    2017-06-15创建
/// @version v0.1 

////////////////////////////////////////////////////////////////////////////////

#include  "pdebug.h"
#include  "includes.h"
#include  "app_cfg.h"
#include  "uart_recv.h" 
#include  "comm_resource.h" 
#include  "pdebug.h"

/// 最大消息数
#define MAX_MESSAGES 6
/// 上行消息队列指针,device->agent
OS_EVENT *p_queue_up;
/// 上行消息指针数组
void *queue_up_grp[MAX_MESSAGES];

/// 下行消息队列指针,agent->device
OS_EVENT *p_queue_down;
/// 下行消息指针数组
void *queue_down_grp[MAX_MESSAGES];

BSP_OS_SEM sem_hy_collect_o2;
BSP_OS_SEM sem_hy_collect_co;
BSP_OS_SEM sem_hy_collect_water;
BSP_OS_SEM sem_hy_collect_current;
BSP_OS_SEM sem_hy_collect_well;
BSP_OS_SEM sem_hy_collect_ch4;
BSP_OS_SEM sem_hy_collect_h2s;
BSP_OS_SEM sem_hy_collect_temphumi;

BSP_OS_SEM rs485_mutex;//485操作共享资源锁
static  u_int8_t rs485_in_buff[RS485_BUFF_SIZE];
/// 初始化rs485串口相关GPIO
/// @param  none   
/// @param  none
/// @return none 
/// @note   修改日志
///         jjj于2017-06-07
void init_rs485_gpio()
{
 /*   //weather-power
    drv_gpio_open(PORTD,9,OUTPUT,1);
    J26_POWER_OFF;
           
   //RD485
    drv_gpio_open(PORTC,9,OUTPUT,1);
    RD485_RECEIVE;
    
    //CS485
    drv_gpio_open(PORTC,5,OUTPUT,1);
    CS_RS485_BAT_DISABLE;
    drv_gpio_open(PORTC,6,OUTPUT,1);
    CS_485_J27_DISABLE;
    drv_gpio_open(PORTC,7,OUTPUT,1);
    CS_485_J28_DISABLE;
    drv_gpio_open(PORTC,8,OUTPUT,1);
    CS_485_J26_DISABLE;   */
  
    drv_gpio_open(PORTD,11,OUTPUT,1);
    SENSOR_POWER_OFF;
           
   //RD485
    drv_gpio_open(PORTC,5,OUTPUT,1);
    RD485_RECEIVE;
}
/// 485发送数据
/// @param  none   
/// @param  none
/// @return none 
/// @note   修改日志
///         jjj于2017-05-31
void send_rs485_data(device_handle dev,const void *data, int len)
{       
       RD485_SEND;
       BSP_OS_TimeDlyMs(150); 
       uart_dev_write(dev,(u_int8_t *)data,len);
       BSP_OS_TimeDlyMs(3); 
       RD485_RECEIVE;
}
/// 初始化rs485串口设备
/// @param  none   
/// @param  none
/// @return none 
/// @note   修改日志
///         jjj于2017-05-31
void init_rs485_uart() 
{
      g_rs485_uart_handle = uart_dev_init(RS485_INDEX, RS485_BAUD,rs485_in_buff, sizeof(rs485_in_buff));
      BSP_OS_SemCreate(&rs485_mutex,1u,"rs485_mutex");
}
void send_up_fault_queue_pack(char *type,u_int8_t code,char *fault_message)
{
    char  send_buff[PACK_BUFF_SIZE];
    memset(send_buff,0,sizeof(send_buff));
    sprintf(send_buff,"%s,%d,%s",type,code,fault_message);
    if(memcmp(type,"o2",sizeof(type)) == 0)
    {
        pdebug(DEBUG_LEVEL_ERROR,"send o2 fault pack: %s\n\r",send_buff);
    }
    if(memcmp(type,"water",sizeof(type)) == 0)
    {
        pdebug(DEBUG_LEVEL_ERROR,"send water fault pack: %s\n\r",send_buff);
    }    
    if(memcmp(type,"current",sizeof(type)) == 0)
    {
        pdebug(DEBUG_LEVEL_ERROR,"send current fault pack: %s\n\r",send_buff);
    } 
    if(memcmp(type,"co",sizeof(type)) == 0)
    {
        pdebug(DEBUG_LEVEL_ERROR,"send co fault pack: %s\n\r",send_buff);  
    }  
    if(memcmp(type,"h2s",sizeof(type)) == 0)
    {
        pdebug(DEBUG_LEVEL_ERROR,"send h2s fault pack: %s\n\r",send_buff);  
    }  
    if(memcmp(type,"ch4",sizeof(type)) == 0)
    {
        pdebug(DEBUG_LEVEL_ERROR,"send ch4 fault pack: %s\n\r",send_buff);  
    }      
    OSQPostOpt(p_queue_up,send_buff, OS_POST_OPT_BROADCAST);   
}

/// 创建信号量 
///
/// 用于设备层直接通信
/// @param  none   
/// @param  none
/// @return none 
/// @note   修改日志
///         jjj于2017-05-31
static void sem_create_device_module()
{
#if CFG_MODULE_O2
    if (!BSP_OS_SemCreate(&sem_hy_collect_o2,0u,"sem_hy_collect_o2")) {
		pdebug(DEBUG_LEVEL_FATAL,"create sem_hy_collect_o2 failed\n\r");
    }    
#endif    
#if CFG_MODULE_CO
	if (!BSP_OS_SemCreate(&sem_hy_collect_co,0u,"sem_hy_collect_co")) {
        pdebug(DEBUG_LEVEL_FATAL,"create sem_hy_collect_co failed\n\r");
    }
#endif     
#if CFG_MODULE_WATER    
	if (!BSP_OS_SemCreate(&sem_hy_collect_water,0u,"sem_hy_collect_water")) {
        pdebug(DEBUG_LEVEL_FATAL,"create sem_hy_collect_water failed\n\r");
    }  
#endif     
#if CFG_MODULE_WELL     
	if (!BSP_OS_SemCreate(&sem_hy_collect_well,0u,"sem_hy_collect_well")) {
        pdebug(DEBUG_LEVEL_FATAL,"create sem_hy_collect_well failed\n\r");
    }
#endif     
#if CFG_MODULE_CURRENT     
	if (!BSP_OS_SemCreate(&sem_hy_collect_current,0u,"sem_hy_collect_current")) {
        pdebug(DEBUG_LEVEL_FATAL,"create sem_hy_collect_current failed\n\r");
    }
#endif     
#if CFG_MODULE_CH4     
	if (!BSP_OS_SemCreate(&sem_hy_collect_ch4,0u,"sem_hy_collect_ch4")) {
        pdebug(DEBUG_LEVEL_FATAL,"create sem_hy_collect_ch4 failed\n\r");
    } 
#endif     
#if CFG_MODULE_H2S     
	if (!BSP_OS_SemCreate(&sem_hy_collect_h2s,0u,"sem_hy_collect_h2s")) {
        pdebug(DEBUG_LEVEL_FATAL,"create sem_hy_collect_h2s failed\n\r");
    } 
#endif     
#if CFG_MODULE_TEMPHUMI     
	if (!BSP_OS_SemCreate(&sem_hy_collect_temphumi,0u,"sem_hy_collect_temphumi")) {
        pdebug(DEBUG_LEVEL_FATAL,"create sem_hy_collect_temphumi failed\n\r");
    }     
#endif    
}

/// 接收下行消息队列任务 
///
/// 收到并解析消息队列,以信号量型式通知其他模块
/// 设备层使用 
/// @param  none   
/// @param  none
/// @return none 
/// @note   修改日志
///         jjj于2017-05-31
static  void task_listen_queue_down (void        *p_arg)
{
    p_arg = p_arg;
    char *s_recv_down;
    unsigned char err;
    char type[20];
    char code[20];
    char message[20];     
    while(1){
          s_recv_down = OSQPend(p_queue_down,0,&err);     //请求消息队列
          if (err) {
              pdebug(DEBUG_LEVEL_ERROR,"recv queue down error: %s\n", err);
          }else { 
              pdebug(DEBUG_LEVEL_INFO,"recv queue down messages: %s\n", s_recv_down);
          }
          sscanf(s_recv_down,"%[^,],%[^,],%s",type,code,message);       
          if(memcmp("o2",type,strlen(type)) == 0) 
          {
              if(memcmp("get data",code,strlen(code)) == 0)    
              {
                  BSP_OS_SemPost(&sem_hy_collect_o2);               
              }            
          }
          if(memcmp("co",type,strlen(type)) == 0) 
          {
              if(memcmp("get data",code,strlen(code)) == 0)    
              {
                  BSP_OS_SemPost(&sem_hy_collect_co);               
              }            
          }
          if(memcmp("water",type,strlen(type)) == 0) 
          {
              if(memcmp("get data",code,strlen(code)) == 0)    
              {
                   BSP_OS_SemPost(&sem_hy_collect_water); 
              }            
          } 
          if(memcmp("current",type,strlen(type)) == 0) 
          {
              if(memcmp("get data",code,strlen(code)) == 0)    
              {
                   BSP_OS_SemPost(&sem_hy_collect_current); 
              }            
          } 
          if(memcmp("well",type,strlen(type)) == 0) 
          {
              if(memcmp("get data",code,strlen(code)) == 0)    
              {
                   BSP_OS_SemPost(&sem_hy_collect_well); 
              }            
          }

          if(memcmp("ch4",type,strlen(type)) == 0) 
          {
              if(memcmp("get data",code,strlen(code)) == 0)    
              {
                   BSP_OS_SemPost(&sem_hy_collect_ch4); 
              }            
          }

          if(memcmp("h2s",type,strlen(type)) == 0) 
          {
              if(memcmp("get data",code,strlen(code)) == 0)    
              {
                   BSP_OS_SemPost(&sem_hy_collect_h2s); 
              }            
          }          
     }              
}

/// 创建接收下行消息队列任务 
///
/// @param  none   
/// @param  none
/// @return none 
/// @note   修改日志
///         jjj于2017-05-31

static OS_STK  task_listen_queue_down_stk[TASK_LISTEN_QUEUE_DOWN_STK_SIZE];
static  void  task_create_listen_queue_down (void)
{ 
   CPU_INT08U  task_err;   
   CPU_INT08U  name_err;
   
   task_err = OSTaskCreateExt((void (*)(void *)) task_listen_queue_down,           
		   (void           *) 0,
		   (OS_STK         *)&task_listen_queue_down_stk[TASK_LISTEN_QUEUE_DOWN_STK_SIZE - 1],
		   (INT8U           ) TASK_LISTEN_QUEUE_DOWN_PRIO,                   
		   (INT16U          ) TASK_LISTEN_QUEUE_DOWN_PRIO,
		   (OS_STK         *)&task_listen_queue_down_stk[0],
		   (INT32U          ) TASK_LISTEN_QUEUE_DOWN_STK_SIZE,
		   (void           *) 0,
		   (INT16U          )(OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR));     
    #if (OS_TASK_NAME_EN > 0)
    OSTaskNameSet(TASK_LISTEN_QUEUE_DOWN_PRIO, "task_listen_queue_down", &name_err);
    #endif
       
    if ((task_err == OS_ERR_NONE) && (name_err == OS_ERR_NONE)) {
        pdebug(DEBUG_LEVEL_INFO,"create task_listen_queue_down success...\n\r");
	} else { 
        pdebug(DEBUG_LEVEL_FATAL,"create task_listen_queue_down failed...\n\r");
	}
}

/// 消息队列模块初始化 
///
/// 创建上行、下行消息队列，创建设备层共享资源
/// @param  none   
/// @param  none
/// @return none 
/// @note   修改日志
///         gkl与2017-06-02创建
void init_comm_queue_module()
{   
    pdebug(DEBUG_LEVEL_INFO,"init common queue module\n\r"); 
	
    // 创建上行消息队列
    pdebug(DEBUG_LEVEL_INFO,"create queue up\n\r"); 
    p_queue_up = OSQCreate(&queue_up_grp[0], MAX_MESSAGES); 

    // 创建下行消息队列
    pdebug(DEBUG_LEVEL_INFO,"create queue down\n\r"); 
    p_queue_down = OSQCreate(&queue_down_grp[0], MAX_MESSAGES); 
	
	// 创建设备层通信用信号量
	pdebug(DEBUG_LEVEL_INFO,"create sem device\n\r"); 
	sem_create_device_module();
	
	// 创建设备层模块，监听下行数据，并将解析结果告知其他设备层模块
	pdebug(DEBUG_LEVEL_INFO,"create task listen queue down\n\r"); 
	task_create_listen_queue_down();
	
	pdebug(DEBUG_LEVEL_INFO,"init common queue module finished\n\r");     
}






