#include "common.h"
#include <stdlib.h>
#include "thread.h"
#include <pthread.h>
#include "msq.h"
#include "serial.h"
#include "ysp_debug.h"
#include "scl_shm.h"
#include "iec61850_process.h"

mqd_t iec61850_rx_mq;//
SCL_MSG_TYPE recv_iec_msg;
static char iec61850_rx_buf[1024];


static YSP_PRI_DATA ysp_pri_data;
//static YSP_IEC_DATA ysp_last_data;


int iec61850_send_msg(void *msg,int msg_len)
{
  static mqd_t iec61850_rx_slave_mq=(mqd_t)-1;
  if(iec61850_rx_slave_mq==-1)
   {
	 if((iec61850_rx_slave_mq= open_mq(IEC61850_RX_MQ))==((mqd_t)-1))
	    return -1;
   }
  if(mq_send(iec61850_rx_slave_mq,(const char *)msg,msg_len,IEC61850_RX_MQ_PRIO)==-1)
	 return -2;
 
  return 0;
}

int send_ysp_msg(YSP_PRI_DATA *ysp_pri)
{
static unsigned char ysp_msg_buf[512];
 unsigned int cmd;
 cmd=CMD_SEND_PRI_DATA;
 memcpy(ysp_msg_buf,&cmd,sizeof(cmd));
 memcpy(&ysp_msg_buf[4],(const void *)ysp_pri,sizeof(YSP_PRI_DATA));
 return iec61850_send_msg(ysp_msg_buf,sizeof(YSP_PRI_DATA)+4);	
}


void conv_pri2iec(YSP_PRI_DATA *ysp_pri,YSP_IEC_DATA *ysp_iec,unsigned int q,time_t smp_time)
{
time_t t;
if(smp_time!=0)
  t=smp_time;
else
  t=ysp_pri->SmpTm;
  
ysp_iec->H2ppm.v.f=ysp_pri->H2ppm;
ysp_iec->H2ppm.q=q;
ysp_iec->H2ppm.t.secs=t;

ysp_iec->COppm.v.f=ysp_pri->COppm;
ysp_iec->COppm.q=q;
ysp_iec->COppm.t.secs=t;

ysp_iec->CH4ppm.v.f=ysp_pri->CH4ppm;
ysp_iec->CH4ppm.q=q;
ysp_iec->CH4ppm.t.secs=t;

ysp_iec->C2H4ppm.v.f=ysp_pri->C2H4ppm;
ysp_iec->C2H4ppm.q=q;
ysp_iec->C2H4ppm.t.secs=t;

ysp_iec->C2H6ppm.v.f=ysp_pri->C2H6ppm;
ysp_iec->C2H6ppm.q=q;
ysp_iec->C2H6ppm.t.secs=t;

ysp_iec->C2H2ppm.v.f=ysp_pri->C2H2ppm;
ysp_iec->C2H2ppm.q=q;
ysp_iec->C2H2ppm.t.secs=t;

ysp_iec->TotHyd.v.f=ysp_pri->TotHyd;//(ysp_pri->CH4ppm)+(ysp_pri->C2H4ppm)+(ysp_pri->C2H6ppm)+(ysp_pri->C2H2ppm);
ysp_iec->TotHyd.q=q;
ysp_iec->TotHyd.t.secs=t;

ysp_iec->SmpTm.v.i=t;
ysp_iec->SmpTm.q=q;
ysp_iec->SmpTm.t.secs=t;

ysp_iec->CO2ppm.v.f=ysp_pri->CO2ppm;
if(co2_is_ok)
 {
   ysp_iec->CO2ppm.q=GOOD;	
 }
else
 {
   ysp_iec->CO2ppm.q=INVALID;	
 }
ysp_iec->CO2ppm.t.secs=t;	
}

void iec61850_rx_routine(void *arg)
{  
  int i;
  time_t now;
  float f=0;
  int update_flg=0;
  USR_MV rdre[2];

  start_scl_mem();
  if((iec61850_rx_mq=create_mq(IEC61850_RX_MQ,IEC61850_RX_MAX_MESSAGE,IEC61850_RX_MESSAGE_SIZE))<0)
   {
   	 LOG_DEBUG(ERROR_DEBUG,"create iec61850 rx message queue failed\n");
   	 exit(1);
   }
   
  while(1)
   {
     if(recv_mq_wait(iec61850_rx_mq,(void *)iec61850_rx_buf,sizeof(iec61850_rx_buf),1000000)>0)
	   {
         memcpy(&recv_iec_msg,iec61850_rx_buf,sizeof(recv_iec_msg));        
         switch(recv_iec_msg.cmd)
         {
		  case CMD_SEND_PRI_DATA:
		      LOG_DEBUG(IEC61850_TRACE_DEBUG,"receive CMD_SEND_PRI_DATA\n");
			  now=time(NULL);

			  lock_input_data(); 
        //更新油温和微水含量到ysp_glb_data
        ysp_glb_data.Tmp.v.f=my_input_data.temp;//油温
        ysp_glb_data.Mst.v.f=my_input_data.water;//微水
        if(my_input_data.com_flg)
          {
            ysp_glb_data.Tmp.q=INVALID;//油温品质
           	ysp_glb_data.Mst.q=INVALID;//微水品质
          }
        else
          {
       	    ysp_glb_data.Mst.q=GOOD;
            ysp_glb_data.Tmp.q=GOOD;
          }
			  ysp_glb_data.Mst.t.secs=now;//微水时标
        ysp_glb_data.Tmp.t.secs=now;//温度时标
        unlock_input_data();	

        //更新载气压力到ysp_glb_data
        get_presure(PRES_PA1,&ysp_glb_data.GasPres.v.f); //载气压力 	
        ysp_glb_data.GasPres.t.secs=now;//压力时标
        ysp_glb_data.GasPres.q=GOOD;

        if(ysp_glb_data.MoDevConf.v.stVal)
   	    {
       	  ysp_glb_data.MoDevConf.q=INVALID; 
       	}
        else
        {
          ysp_glb_data.MoDevConf.q=GOOD; 
        }  

		    memcpy(&ysp_pri_data,&iec61850_rx_buf[4],sizeof(YSP_PRI_DATA));	      
			  conv_pri2iec(&ysp_pri_data,&ysp_glb_data,0,0);//从ysp_pri_data拷贝数据到ysp_glb_data
        
        rdre[0].v.stVal=1;//rcd_made
        rdre[0].q=GOOD;
        rdre[0].t.secs=now;

        rdre[1].v.i++;//file_num
        rdre[1].q=GOOD;
        rdre[1].t.secs=now;

        //发送ysp_glb_data到iec61850;
			  lock_scl_mem();
        put_mv_data(0,0,(USR_MV *)&ysp_glb_data,sizeof(ysp_glb_data)/sizeof(USR_MV));
        put_mv_data(0,20,(USR_MV *)&rdre[0],sizeof(rdre)/sizeof(USR_MV));
   	    unlock_scl_mem();	 
        sleep(3);
        rdre[0].v.stVal=0;//rcd_made  
        lock_scl_mem();
         put_mv_data(0,20,(USR_MV *)&rdre[0],1);
   	     unlock_scl_mem();	   
		      break;
    	  default:
    	      break;
         }
	   }
	 else
	   {
        if(update_flg==0)
        {
	        now=time(NULL);
          lock_input_data(); 
          ysp_glb_data.Tmp.v.f=my_input_data.temp;//油温
          ysp_glb_data.Mst.v.f=my_input_data.water;//微水
          if(my_input_data.com_flg)
          {
           	 ysp_glb_data.Tmp.q=INVALID;//油温品质
           	 ysp_glb_data.Mst.q=INVALID;
          }
          else
          {
      	     ysp_glb_data.Tmp.q=GOOD;
       	     ysp_glb_data.Mst.q=GOOD;
          }
          unlock_input_data();  

          ysp_glb_data.Tmp.t.secs=now;//温度时标

   	      get_presure(PRES_PA1,&ysp_glb_data.GasPres.v.f); //载气压力 
          ysp_glb_data.GasPres.t.secs=now;//压力时标
   	      if(ysp_glb_data.MoDevConf.v.stVal)
   	       {
       	   	 ysp_glb_data.MoDevConf.q=INVALID; 
       	   }
          else
           {
           	 ysp_glb_data.MoDevConf.q=GOOD; 
           }  	 
          update_flg++;
        }
 
   	     conv_pri2iec(&ysp_pri_data,&ysp_glb_data,0,0); //从ysp_pri_data赋值给ysp_glb_data 	     

   	   	 lock_scl_mem(); 
         put_mv_data(0,0,(USR_MV *)&ysp_glb_data,sizeof(ysp_glb_data)/sizeof(USR_MV)); //将ysp_glb_data发送给iec61850服务    	     
   	     unlock_scl_mem();
      }
   }
  stop_scl_mem();
}


int iec61850_rx_init(void)
{
  pthread_t iec61850_rx_thread;
  if((iec61850_rx_thread=task_create(iec61850_rx_routine,NULL,0,0))==-1)
   {
	 LOG_DEBUG(ERROR_DEBUG,"create iec61850_rx_routine failed\n");
	 return 1;
   }
  return 0;
}
