/*----------------------------------------------------------------------------*\ 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; }
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; }
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; } } } }