/* * Command line syntax: * * master2 --help * */ int main(int argc, char* argv[]) { // Check command line options cOptions options; options.set_master_defaults(); if( options.decode( argc, argv ) != 0 ) return 1; try { // Create a log object for the stack to use and configure it // with a subscriber that print alls messages to the stdout. EventLog log; log.AddLogSubscriber(LogToStdio::Inst()); // Specify a FilterLevel for the stack/physical layer to use. // Log statements with a lower priority will not be logged. const FilterLevel LOG_LEVEL = LEV_INFO; // Create our demo application that handles commands and // demonstrates how to publish data give it a logger with a // unique name and log level. MasterDemoApp app(log.GetLogger(LOG_LEVEL, "demoapp")); // This is the main point of interaction with the stack. The // AsyncStackManager object instantiates master/slave DNP // stacks, as well as their physical layers. AsyncStackManager mgr(log.GetLogger(LOG_LEVEL, "dnp")); if( ! options.flagcom ) { // Connect via a TCPClient socket to a slave. The server will // wait 3000 ms in between failed bind calls. mgr.AddTCPClient( options.PortName, PhysLayerSettings(LOG_LEVEL, 3000), options.ip.c_str(), options.port ); } else { // Con nect to slave over serial COM port mgr.AddSerial( options.PortName, PhysLayerSettings(LOG_LEVEL, 3000), options.serialsets ); } // The master config object for a master. The default are // useable, but understanding the options are important. MasterStackConfig stackConfig; // Override the default link addressing stackConfig.link.LocalAddr = options.local_dnp3; stackConfig.link.RemoteAddr = options.remote_dnp3; // Set the app instance as a callback for state change notices stackConfig.master.mpObserver = &app; // Create a new master on a previously declared port, with a // name, log level, command acceptor, and config info This // returns a thread-safe interface used for processing Master // messages. app.SetCommandAcceptor( mgr.AddMaster( options.PortName, // port name "master", // stack name LOG_LEVEL, // log filter level app.GetDataObserver(), // callback for data processing stackConfig // stack configuration ) ); // Configure signal handlers so we can exit gracefully SetDemo(&app); signal(SIGTERM, &Terminate); signal(SIGABRT, &Terminate); signal(SIGINT, &Terminate); app.Run(); SetDemo(NULL); } // sometime the dnp3 code will raise an exception // for example if you try to connect to a non-existent COM port // this catches the exception, preventing a crash, // and prints out a hint as to what went wrong catch ( Exception & e ) { printf("Exception raised by DNP3 code\n%s\n",e.GetErrorString().c_str()); } return 0; }
/* * Command line syntax: * * ./demo-slave-cpp [remote-dnp3] [local-dnp3] [local-ip] [local-port] * * Defaults: * * remote-dnp3 100 * local-dnp3 1 * local-ip 127.0.0.1 * local-port 4999 */ int main(int argc, char* argv[]) { // Default values unsigned remote_dnp3 = 100; unsigned local_dnp3 = 1; string local_ip = "127.0.0.1"; unsigned local_port = 4999; // Parse the command line arguments using a "fall-through" // switch statement. if (argc > 1 && std::strcmp("help", argv[1]) == 0) { cout << argv[0] << " [remote-dnp3] [local-dnp3] [local-ip] [local-port]" << endl; return -1; } switch (argc) { case 5: { istringstream iss(argv[4]); iss >> local_port; } case 4: local_ip = argv[3]; case 3: { istringstream iss(argv[2]); iss >> local_dnp3; } case 2: { istringstream iss(argv[1]); iss >> remote_dnp3; } } // Create a log object for the stack to use and configure it // with a subscriber that print alls messages to the stdout EventLog log; log.AddLogSubscriber(LogToStdio::Inst()); // Specify a FilterLevel for the stack/physical layer to use. // Log statements with a lower priority will not be logged. const FilterLevel LOG_LEVEL = LEV_INFO; // create our demo application that handles commands and // demonstrates how to publish data give it a loffer with a // unique name and log level SlaveDemoApp app(log.GetLogger(LOG_LEVEL, "demoapp")); // This is the main point of interaction with the stack. The // AsyncStackManager object instantiates master/slave DNP // stacks, as well as their physical layers AsyncStackManager mgr(log.GetLogger(LOG_LEVEL, "dnp")); // Add a TCPv4Server to the manager with the name "tcpserver". // The server will wait 3000 ms in between failed bind calls. mgr.AddTCPv4Server( "tcpserver", PhysLayerSettings(LOG_LEVEL, 3000), local_ip, local_port ); // The master config object for a slave. The default are // useable, but understanding the options are important. SlaveStackConfig stackConfig; // Override the default link addressing stackConfig.link.LocalAddr = local_dnp3; stackConfig.link.RemoteAddr = remote_dnp3; // The DeviceTemplate struct specifies the structure of the // slave's database, as well as the index range of controls and // setpoints it accepts. DeviceTemplate device(5, 5, 5, 5, 5, 5, 5); stackConfig.device = device; // Create a new slave on a previously declared port, with a // name, log level, command acceptor, and config info This // returns a thread-safe interface used for updating the slave's // database. IDataObserver* pDataObserver = mgr.AddSlave("tcpserver", "slave", LOG_LEVEL, app.GetCmdAcceptor(), stackConfig); // Tell the app where to write opdates app.SetDataObserver(pDataObserver); // Configure signal handlers so we can exit gracefully SetDemo(&app); signal(SIGTERM, &Terminate); signal(SIGABRT, &Terminate); signal(SIGINT, &Terminate); app.Run(); SetDemo(NULL); return 0; }
/* * Command line syntax: * * ./demo-master-cpp [local-dnp3] [remote-dnp3] [remote-ip] [remote-port] * * Defaults: * * local-dnp3 100 * remote-dnp3 1 * remote-ip 127.0.0.1 * remote-port 4999 */ int main(int argc, char* argv[]) { // Default values unsigned local_dnp3 = 100; unsigned remote_dnp3 = 1; string remote_ip = "127.0.0.1"; unsigned remote_port = 4999; // Parse the command line arguments using a "fall-through" // switch statement. if (argc > 1 && strcmp("help", argv[1]) == 0) { cout << argv[0] << " [local-dnp3] [remote-dnp3] [remote-ip] [remote-port]" << endl; return -1; } switch (argc) { case 5: { istringstream iss(argv[4]); iss >> remote_port; } case 4: remote_ip = argv[3]; case 3: { istringstream iss(argv[2]); iss >> remote_dnp3; } case 2: { istringstream iss(argv[1]); iss >> local_dnp3; } } // Create a log object for the stack to use and configure it // with a subscriber that print alls messages to the stdout. EventLog log; log.AddLogSubscriber(LogToStdio::Inst()); // Specify a FilterLevel for the stack/physical layer to use. // Log statements with a lower priority will not be logged. const FilterLevel LOG_LEVEL = LEV_INFO; // Create our demo application that handles commands and // demonstrates how to publish data give it a logger with a // unique name and log level. MasterDemoApp app(log.GetLogger(LOG_LEVEL, "demoapp")); // This is the main point of interaction with the stack. The // AsyncStackManager object instantiates master/slave DNP // stacks, as well as their physical layers. AsyncStackManager mgr(log.GetLogger(LOG_LEVEL, "dnp")); // Connect via a TCPv4Client socket to a slave. The server will // wait 3000 ms in between failed bind calls. mgr.AddTCPv4Client( "tcpclient", PhysLayerSettings(LOG_LEVEL, 3000), TcpSettings(remote_ip.c_str(), remote_port) ); // The master config object for a master. The default are // useable, but understanding the options are important. MasterStackConfig stackConfig; // Override the default link addressing stackConfig.link.LocalAddr = local_dnp3; stackConfig.link.RemoteAddr = remote_dnp3; // Set the app instance as a callback for state change notices stackConfig.master.mpObserver = &app; // Create a new master on a previously declared port, with a // name, log level, command acceptor, and config info This // returns a thread-safe interface used for processing Master // messages. app.SetCommandAcceptor( mgr.AddMaster( "tcpclient", // port name "master", // stack name LOG_LEVEL, // log filter level app.GetDataObserver(), // callback for data processing stackConfig // stack configuration ) ); // Configure signal handlers so we can exit gracefully SetDemo(&app); signal(SIGTERM, &Terminate); signal(SIGABRT, &Terminate); signal(SIGINT, &Terminate); app.Run(); SetDemo(NULL); return 0; }