#include "../config.h"
#include <locale.h>
#include <libintl.h>
#define _(x) gettext(x)
#ifdef MODULE
#include <linux/string.h>
#else
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#endif
#include "hal.h"
#include "classicladder.h"
#include "global.h"
#include "files_project.h"
#include "calc.h"
#include "vars_access.h"
#include "manager.h"
#include "calc_sequential.h"
#include "files_sequential.h"
#include "config.h"
#include "socket_server.h"
#include "socket_modbus_master.h"
#if !defined( MODULE )
#include "classicladder_gtk.h"
#include "manager_gtk.h"
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <signal.h>
#include <getopt.h>
#ifdef __WIN32__
#include <windows.h>
#else
#include <pthread.h>
#endif
#ifdef __XENO__
#include <sys/mman.h>
#endif
#endif
#ifdef GTK_INTERFACE
#include <gtk/gtk.h>
#endif
#ifdef MAT_CONNECTION
#include "../../lib/plc.h"
#endif
int cl_remote;
int nogui = 0,modmaster=0,modslave=0,pathswitch=0;;
int ModbusServerPort = 9502; int CyclicThreadRunning = 0;
char *NewPath;
void ClassicLadderEndOfAppli( void )
{
CyclicThreadRunning = 0;
if(modmaster) { CloseSocketModbusMaster( ); }
if(modslave) { CloseSocketServer( ); }
}
void display_help (void)
{
printf("\nClassicLadder v"CL_RELEASE_VER_STRING"\n"CL_RELEASE_DATE_STRING"\n"
"Copyright (C) 2001-2004 Marc Le Douarain\nmavati@club-internet.fr\n"
"Adapted to EMC\n"
"\n"
"ClassicLadder comes with NO WARRANTY\n"
"to the extent permitted by law.\n"
"\n"
"You may redistribute copies of ClassicLadder\n"
"under the terms of the GNU Lesser General Public Licence.\n"
"See the file `lesserGPL.txt' for more information.\n");
printf("This version of Classicladder is adapted for use with EMC and HAL\n"
"\nUsage: classicladder [OPTIONS] [PATH]\n"
"eg: loadusr -w classicladder ladtest.clp\n"
"eg: loadusr -w classicladder --nogui ladtest.clp\n"
"eg: loadusr -w classicladder --modmaster ladtest.clp\n"
"\n"
" --nogui do not create a GUI, only load a configuration\n"
" --config=filename initialize modbus master I/O & load config file-( deprecated- use --modmaster)\n"
" --modmaster initialize modbus master I/O ( modbus config is loaded with other objects )\n"
" --modslave initialize modbus slave I/O (TCP only- B and W variables accesable\n"
" --modbus_port=portnumber used for modbus slave using TCP ( ethernet )\n"
" --debug sets the RTAPI debuglevel for printing debug messages\n"
"Please also note that the classicladder realtime module must be loaded first\n"
"eg: loadrt classicladder_rt for default number of ladder objects\n"
);
hal_exit(compId); exit(0);
}
void process_options (int argc, char *argv[])
{
int error = 0;
for (;;)
{
int option_index = 0;
static const char *short_options = "c:";
static const struct option long_options[] = {
{"nogui", no_argument, 0, 'n'},
{"config", required_argument, 0, 'c'},
{"modmaster",no_argument,0,'m'},
{"modslave",no_argument,0,'s'},
{"debug",no_argument,0,'d'},
{"modbus_port", required_argument, 0, 'p'},
{"newpath", required_argument, 0, 'f'},
{0, 0, 0, 0},
};
int c = getopt_long(argc, argv, short_options,
long_options, &option_index);
if (c == EOF)
break;
switch (c)
{
case 'n':
nogui = 1;
break;
case 'c':
read_config (optarg);
modmaster=1;
break;
case 'm':
modmaster=1;
break;
case 's':
modslave=1;
break;
case 'd':
rtapi_set_msg_level(RTAPI_MSG_ALL);
break;
case 'p':
ModbusServerPort = atoi( optarg );
break;
case 'f':
NewPath = ( optarg );
pathswitch=1;
break;
case '?':
error = 1;
break;
}
}
if (error)
display_help ();
if ((argc - optind) != 0)
VerifyDirectorySelected (argv[optind]);
}
static void do_exit(int unused) {
hal_exit(compId);
printf(_("ERROR CLASSICLADDER- Error initializing classicladder user module.\n"));
exit(0);
}
void DoPauseMilliSecs( int Time )
{
struct timespec time;
time.tv_sec = 0;
if (Time>=1000)
{
time.tv_sec=Time/1000;
Time=Time%1000;
}
time.tv_nsec = Time*1000000;
nanosleep( &time, NULL );
}
void StopRunIfRunning( void )
{
if (InfosGene->LadderState==STATE_RUN)
{
InfosGene->LadderStoppedToRunBack = TRUE;
InfosGene->LadderState = STATE_STOP;
while( InfosGene->UnderCalculationPleaseWait==TRUE )
{
DoPauseMilliSecs( 100 );
}
}
}
void RunBackIfStopped( void )
{
if ( InfosGene->LadderStoppedToRunBack )
{
InfosGene->LadderState = STATE_RUN;
InfosGene->LadderStoppedToRunBack = FALSE;
}
}
int main( int argc, char *argv[] )
{
int used=0, NumRung;
static int old_level ;
bindtextdomain("linuxcnc", EMC2_PO_DIR);
setlocale(LC_MESSAGES,"");
setlocale(LC_CTYPE,"");
textdomain("linuxcnc");
old_level = rtapi_get_msg_level();
compId=hal_init("classicladder"); if (compId<0) return -1; signal(SIGTERM,do_exit); InitModbusMasterBeforeReadConf( );
if (ClassicLadder_AllocAll())
{
char ProjectLoadedOk=TRUE;
process_options (argc, argv);
if (nogui==TRUE)
{
rtapi_print(_("INFO CLASSICLADDER- No ladder GUI requested-Realtime runs till HAL closes.\n"));
ClassicLadder_InitAllDatas( );
ProjectLoadedOk = LoadProjectFiles( InfosGene->CurrentProjectFileName );
if (pathswitch){ strcpy( InfosGene->CurrentProjectFileName, NewPath ); }
InfosGene->LadderState = STATE_RUN;
ClassicLadder_FreeAll(TRUE);
hal_ready(compId);
hal_exit(compId);
return 0;
} else {
for(NumRung=0;NumRung<NBR_RUNGS;NumRung++) { if ( RungArray[NumRung].Used ) used++; }
if((used==0) || ( (argc - optind) != 0) )
{
ClassicLadder_InitAllDatas( );
ProjectLoadedOk = LoadProjectFiles( InfosGene->CurrentProjectFileName );
InitGtkWindows( argc, argv );
UpdateAllGtkWindows();
if (pathswitch){ strcpy( InfosGene->CurrentProjectFileName, NewPath ); }
UpdateWindowTitleWithProjectName( );
MessageInStatusBar( ProjectLoadedOk?_("Project loaded and running"):_("Project failed to load..."));
if (!ProjectLoadedOk)
{
ClassicLadder_InitAllDatas( );
if (modmaster) { PrepareModbusMaster( ); }
}
}else{
InitGtkWindows( argc, argv );
UpdateAllGtkWindows();
if (pathswitch){ strcpy( InfosGene->CurrentProjectFileName, NewPath ); }
UpdateWindowTitleWithProjectName( );
MessageInStatusBar(_("GUI reloaded with existing ladder program"));
if (modmaster) { PrepareModbusMaster( ); }
}
if (modslave) { InitSocketServer( 0, ModbusServerPort); }
InfosGene->LadderState = STATE_RUN;
hal_ready(compId);
gtk_main();
rtapi_print(_("INFO CLASSICLADDER- Ladder GUI closed. Realtime runs till HAL closes\n"));
ClassicLadder_FreeAll(TRUE);
hal_exit(compId);
return 0;
}
}
rtapi_print(_("ERROR CLASSICLADDER- Ladder memory allocation error\n"));
ClassicLadder_FreeAll(TRUE);
rtapi_set_msg_level(old_level);
hal_exit(compId);
return 0;
}