/*----------------------------------------------------------------------------*\
   Read method for the Modbus_TCP slave
\*----------------------------------------------------------------------------*/
static pwr_tStatus IoRackRead (
    io_tCtx	ctx,
    io_sAgent	*ap,
    io_sRack	*rp
)
{
    io_sRackLocal *local;
    pwr_sClass_Modbus_TCP_Slave *sp;
    pwr_tStatus sts;
    pwr_tTime now;
    pwr_tDeltaTime dt;

    local = rp->Local;

    sp = (pwr_sClass_Modbus_TCP_Slave *) rp->op;

    if (((sp->Status == MB__CONNDOWN) || (sp->Status == MB__CONNLOST)) && sp->DisableSlave != 1) {
        /* Reconnect */

        time_GetTimeMonotonic( &now);
        time_Adiff(&dt, &now, &local->last_try_connect_time);
        if (dt.tv_sec >= (1 << MIN(sp->ReconnectCount, 6))) {
            sts = connect_slave(local, rp);
            if (sts >= 0) {
                sp->ReconnectCount = 0;
                sp->Status = MB__NORMAL;
            } else {
                sp->ReconnectCount++;
                memset(&sp->Inputs, 0, local->input_size);
            }
        }
    }

    /* Receive data */
    if ((sp->Status == MB__NORMAL) && !sp->SingleOp) {
        sts = mb_recv_data(local, rp, sp);
    }

    if (sp->DisableSlave != 1) {

        if (sp->Status == MB__NORMAL) {
            sp->ErrorCount = 0;
        }
        else {
            sp->ErrorCount++;
        }

        if (sp->ErrorCount > sp->ErrorLimit) {
            memset(&sp->Inputs, 0, local->input_size);
        }
    }
    else {
        sp->ErrorCount = 0;
        sp->Status = MB__DISABLED;
    }

    return IO__SUCCESS;
}
Exemple #2
0
int main (int argc, char **argv)
{
  pwr_tStatus	    sts;
  pwr_tObjid	    ObjId;
  pwr_sClass_DsTrendConf *TConfP;
  pwr_tBoolean    InitOK;
  pwr_tTime		CurrentTime, LastScan, NextScan;
  pwr_tDeltaTime	ScanDeltaTime, WaitTime;
  qcom_sQid qini;
  qcom_sQattr qAttr;
  int tmo;
  char mp[2000];
  qcom_sQid qid = qcom_cNQid;
  qcom_sGet get;
  int swap = 0;
  trend_tCtx ctx;

  errh_Init("pwr_trend", errh_eAnix_trend);
  errh_SetStatus( PWR__SRVSTARTUP);

  sts = gdh_Init("ds_trend");
  If_Error_Log_Exit(sts, "gdh_Init");

  if (!qcom_Init(&sts, 0, "pwr_trend")) {
    errh_Fatal("qcom_Init, %m", sts);
    exit(sts);
  } 

  qAttr.type = qcom_eQtype_private;
  qAttr.quota = 100;
  if (!qcom_CreateQ(&sts, &qid, &qAttr, "events")) {
    errh_Fatal("qcom_CreateQ, %m", sts);
    exit(sts);
  } 

  qini = qcom_cQini;
  if (!qcom_Bind(&sts, &qid, &qini)) {
    errh_Fatal("qcom_Bind(Qini), %m", sts);
    exit(-1);
  }

  ctx = (trend_tCtx) calloc( 1, sizeof(trend_sCtx));

  /* Wait until local nethandler has started */
  while(EVEN(gdh_NethandlerRunning()))
    sleep(1);

  /* Fetch ScanTime */
  sts = gdh_GetClassList(pwr_cClass_DsTrendConf, &ObjId);
  if (EVEN(sts)) {
    errh_Info("Couldn't get the DsTrendConf object. Used ScanTime = 1 s");
    ctx->scantime = 1;
    ctx->scantime_tc = 1.0;
  } 
  else {
    gdh_ObjidToPointer(ObjId, (pwr_tAddress *)&TConfP);
    ctx->scantime = TConfP->ScanTime;
    if ( ctx->scantime > 3600)
      ctx->scantime = 3600;
    else if ( ctx->scantime < 1)
      ctx->scantime = 1;

    ctx->scantime_tc = TConfP->ScanTime;
    if ( ctx->scantime_tc > 3600)
      ctx->scantime_tc = 3600;
  }
  ctx->dstrend_multiple = (int) (ctx->scantime / ctx->scantime_tc + 0.5);

  aproc_RegisterObject( ObjId);

  InitOK = FALSE;
  sts = InitTrendList( ctx);
  if ( EVEN(sts)) { 
    /* This should be removed when we can wait for init messages. */
    errh_SetStatus(0);
    errh_Info("No DsTrend objects configured");
    exit(0);
  }

  /* If even sts, just wait for init message */

  time_GetTimeMonotonic(&LastScan);
  time_FloatToD( &ScanDeltaTime, ctx->scantime_tc);

  aproc_TimeStamp( ctx->scantime, 5.0);
  errh_SetStatus( PWR__SRUN);

  for (;;) {

    time_GetTimeMonotonic(&CurrentTime);
    time_Aadd(&NextScan, &LastScan, &ScanDeltaTime);
    if (time_Acomp(&CurrentTime, &NextScan) < 0) { 
      time_Adiff(&WaitTime, &NextScan, &CurrentTime);
      tmo = 1000 * time_DToFloat( 0, &WaitTime);

      get.maxSize = sizeof(mp);
      get.data = mp;
      qcom_Get( &sts, &qid, &get, tmo);
      if (sts == QCOM__TMO || sts == QCOM__QEMPTY) {
	if ( !swap)
	  StoreData( ctx);
      } 
      else {
	ini_mEvent  new_event;
	qcom_sEvent *ep = (qcom_sEvent*) get.data;

	new_event.m  = ep->mask;
	if (new_event.b.oldPlcStop && !swap) {
	  swap = 1;
	  errh_SetStatus( PWR__SRVRESTART);
	  CloseTrendList( ctx);
	} 
	else if (new_event.b.swapDone && swap) {
	  swap = 0;
	  sts = InitTrendList( ctx);
	  errh_SetStatus( PWR__SRUN);
	  errh_Info("Warm restart completed");
	}
	else if (new_event.b.terminate) {
	  exit(0);
	}
      }
    }
    else if ( !swap)
      StoreData( ctx);

    LastScan = NextScan;

    aproc_TimeStamp( ctx->scantime, 5.0);
  }

  return 1;
}
static int connect_slave( io_sRackLocal *local, io_sRack *rp)
{
    pwr_tStatus sts;
    pwr_sClass_Modbus_TCP_Slave *op;
    int buffsize = 10000;
    int flags;
    fd_set fdr;				/* For select call */
    fd_set fdw;				/* For select call */
    struct timeval tv;
    unsigned short port;

    time_GetTimeMonotonic( &local->last_try_connect_time);

    op = (pwr_sClass_Modbus_TCP_Slave *) rp->op;

    /* Create socket, store in local struct */
    port = op->Port == 0 ? 502 : op->Port;

    local->s = socket(AF_INET, SOCK_STREAM, 0);
    if (local->s < 0) {
        errh_Error( "Error creating socket for IO modbus tcp slave %s, %d", rp->Name, local->s);
        return local->s;
    }

    sts = setsockopt(local->s, SOL_SOCKET, SO_RCVBUF, &buffsize, sizeof(buffsize));

    if (sts < 0) {
        printf( "Error setting receive buffer size \n");
    }

    /* Initialize remote address structure */

    local->rem_addr.sin_family = AF_INET;
    local->rem_addr.sin_port = htons(port);
    // local->rem_addr.sin_addr.s_addr = inet_addr((char *) &(op->Address));
    sts = net_StringToAddr( op->Address, &local->rem_addr.sin_addr);
    if ( EVEN(sts)) {
        errh_Error( "Address error for IO modbus tcp slave %s %s", rp->Name, op->Address);
        return sts;
    }
    local->rem_addr.sin_addr.s_addr = ntohl(local->rem_addr.sin_addr.s_addr);

    /* Connect to remote address */

    fcntl(local->s, F_SETFL, (flags = fcntl(local->s, F_GETFL)) | O_NONBLOCK);

    sts = connect(local->s, (struct sockaddr *) &local->rem_addr, sizeof(local->rem_addr));

    if (sts < 0) {
        FD_ZERO(&fdr);
        FD_ZERO(&fdw);
        FD_SET(local->s, &fdr);
        FD_SET(local->s, &fdw);

        if (op->ReconnectLimit > 200) {
            tv.tv_sec = 0;
            tv.tv_usec = 1000 * op->ReconnectLimit;
        } else {
            tv.tv_sec = 0;
            tv.tv_usec = 200000;
        }

        sts = select((int)local->s+1, &fdr, &fdw, NULL, &tv);

        if (sts <= 0) {
            close(local->s);
            errh_Error( "Error connecting remote socket for IO modbus slave %s, %d", rp->Name, sts);
            return -1;
        }
    }

    fcntl(local->s, F_SETFL, (flags = fcntl(local->s, F_GETFL)) ^ O_NONBLOCK);

    return sts;
}
Exemple #4
0
int main (int argc, char **argv)
{
  pwr_tStatus sts = 1;
  io_tCtx io_ctx;
  io_tCtx io_ctx_swap;
  pwr_sClass_IOHandler *ihp;
  int swap_io;
  int close_io;
  int init_io;
  qcom_sQid qid = qcom_cNQid;
  int tmo;
  char mp[2000];
  qcom_sGet get;
  pwr_tTime now;
  pwr_tTime next;
  pwr_tTime after;
  pwr_tDeltaTime cycle;
  lst_sEntry *csup_lh;
  int delay_action = 0;
  pwr_sNode *nodep;
  pwr_tBoolean old_emergency_break = 0;

  if ( argc > 1) {
    if ( strcmp( argv[1], "-m") == 0) {
      io_methods_print();
      exit(0);
    }
    if ( strcmp( argv[1], "-h") == 0) {
      usage();
      exit(0);
    }
  }

  ihp = init(&qid, &csup_lh, &nodep);

  plc_UtlWaitForPlc();

  /* Prepare the swap context */
  sts = io_init_swap(io_mProcess_IoComm, pwr_cNObjid, &io_ctx_swap, 1, ihp->CycleTimeBus);

  for (close_io = swap_io = 0, init_io = 1;;) {

    if (init_io) {
      double f;
      
      sts = io_init(io_mProcess_IoComm, pwr_cNObjid, &io_ctx, 1, ihp->CycleTimeBus);
      if ( ODD(sts)) 
	errh_SetStatus( PWR__SRUN);
#if defined(OS_ELN)
      ker$clear_event( &sts, io_comm_terminate);
      io_dioc_init();
      io_dioc_start();
#endif
      init_io = 0;
      tmo = ihp->CycleTimeBus * 1000.;
      f = floor(ihp->CycleTimeBus);
      cycle.tv_sec = f;
      cycle.tv_nsec = (ihp->CycleTimeBus - f) * 1.0e9;
      cycle.tv_nsec++;
      time_GetTimeMonotonic(&next);
      time_Aadd(NULL, &next, &cycle);
    }

    get.maxSize = sizeof(mp);
    get.data = mp;
    qcom_Get(&sts,&qid, &get, tmo);
    if (sts == QCOM__TMO || sts == QCOM__QEMPTY) {

      if ( nodep->EmergBreakTrue && !old_emergency_break)
        sts = io_swap(io_ctx_swap, io_eEvent_IoCommEmergencyBreak);

      sts = io_read(io_ctx);
      if (EVEN(sts)) {
	ihp->IOReadWriteFlag = FALSE;
	errh_Error("IO read, %m", sts);
      }
      sts = io_write(io_ctx);
      if (EVEN(sts)) {
	ihp->IOReadWriteFlag = FALSE;
	errh_Error("IO write, %m", sts);
      }

      if ( nodep->EmergBreakTrue && !old_emergency_break)
        sts = io_swap(io_ctx, io_eEvent_EmergencyBreak);
      old_emergency_break = nodep->EmergBreakTrue;

      if (swap_io) 
      {
        sts = io_swap(io_ctx_swap, io_eEvent_IoCommSwap);
      }
      io_ScanSupLst( io_ctx->SupCtx);

      time_GetTime(&now);
      time_GetTimeMonotonic(&after);
      next = after;
      time_Aadd(NULL, &next, &cycle);
      delay_action = csup_Exec(&sts, csup_lh, (pwr_tDeltaTime *) &next,
                            (pwr_tDeltaTime *) &after, &now);
      if (delay_action == 2)
	ihp->IOReadWriteFlag = FALSE;

      aproc_TimeStamp(ihp->CycleTimeBus, 5);
    } else {
      ini_mEvent  new_event;
      qcom_sEvent *ep = (qcom_sEvent*) get.data;

      new_event.m  = ep->mask;
      if (new_event.b.oldPlcStop && !swap_io) {
        swap_io = 1;
	close_io = 1;
	errh_SetStatus(PWR__SRVRESTART);
      } else if (new_event.b.swapDone && swap_io) {
        swap_io = 0;
	init_io = 1;
      } else if (new_event.b.terminate) {
        exit(0);
      }
      if (close_io) {    
	io_close(io_ctx);
#if defined(OS_ELN)
	ker$signal( &sts, io_comm_terminate);
#endif
	close_io = 0;
      }
    }
  }
}