OpcUaCanOpen
CANopen OPC-UA server
servermain.cpp
Go to the documentation of this file.
1 /******************************************************************************
2 ** Copyright (C) 2006-2008 Unified Automation GmbH. All Rights Reserved.
3 ** Web: http://www.unifiedautomation.com
4 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
5 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
6 **
7 ** Project: OPC sample server
8 **
9 ** Description: Main entry for the application.
10 ******************************************************************************/
11 #include "OpcServer.h"
12 #include "uaplatformlayer.h"
13 #include "uathread.h"
15 
16 #include "UaCanTrace.h"
17 
18 #include "Version.h"
19 
20 using namespace AddressSpace;
21 
22 #include "xmldocument.h"
23 
24 #include "shutdown.h"
25 
26 #include <stdio.h>
27 #include <string.h>
28 #include <iostream>
29 #include <boost/program_options.hpp>
30 
31 #ifndef WIN32
32 # include <unistd.h>
33 # include <limits.h>
34 #endif
36 bool noExit;
37 
38 unique_ptr<UserDevice::ControlInterface> createControlInterface(void);
39 //unique_ptr<OpcServer> pServer;
41 
42 using namespace boost::program_options;
43 
44 int OpcServerMain(const char* szAppPath, const char *p_sServerConfig,const char *p_sDeviceConfig)
45 {
46  int ret = 0;
47  UaString sDeviceConfig;
48 
49  //- Initialize the environment --------------
50  // Initialize the XML Parser
51  UaXmlDocument::initParser();
52  // Initialize the UA Stack platform layer
53  ret = UaPlatformLayer::init();
54  //-------------------------------------------
55 // CanOpen::UaCanTrace *m_Trace = new CanOpen::UaCanTrace();
56 
57  if (ret == 0)
58  {
59  UaString sConfigFileName;
60 
61  // Create configuration file name
62  if (p_sServerConfig) {
63 
64  sConfigFileName = "";
65  sConfigFileName = p_sServerConfig;
66  }
67  else {
68  sConfigFileName = szAppPath;
69  sConfigFileName += "/ServerConfig.xml";
70  }
71 
72  if (p_sDeviceConfig) {
73 
74  sDeviceConfig = p_sDeviceConfig;
75  }
76  else {
77  sDeviceConfig = "";
78  sDeviceConfig = szAppPath;
79  sDeviceConfig += "/OPCUACANOpenServer.xml";
80  }
81 
82 
83  //- Start up OPC server ---------------------
84  // This code can be integrated into a start up
85  // sequence of the application where the
86  // OPC server should be integrated
87  //-------------------------------------------
88  // Create and initialize server object
89 
90 // OpcServer* pServer = new OpcServer;
91 // pServer = unique_ptr<OpcServer>(new OpcServer());
92  pServer = new OpcServer();
93  pServer->setServerConfig(sConfigFileName, szAppPath);
95  pServer->setDeviceConfig(sDeviceConfig);
96 
98 
100  {
101  cout << "Load Configuration" << endl;
102 
103  cout << "Config file " << sDeviceConfig.toUtf8() << endl;
104 
105  cout << "Set Server Config " << sConfigFileName.toUtf8() << endl;
106  cout << "Create Interface" << endl;
107  shared_ptr<UserDevice::ControlInterface> pControlInterface = createControlInterface();
108  pServer->setControlInterface(pControlInterface);
109 
110  if (pControlInterface->CreateXmlParser(sDeviceConfig/*,devicelog*/).isBad())
111  {
112  cout << "Parser error" << endl;
113  return OpcUa_Bad;
114  }
115  // XML UANodeSet file to load
116  UaString sNodesetFile(UaString("%1/AddressSpace.xml").arg(szAppPath));
117  // We create our own BaseNode factory to create the user data from XML
118  UaBase::BaseNodeFactory* pBaseNodeFactory = new UaBase::BaseNodeFactory;
119  // We create our own NodeManager creator to instantiate our own NodeManager
121  UaNodeSetXmlParserUaNode* pXmlParser = new UaNodeSetXmlParserUaNode(sNodesetFile, pNodeManagerCreator, pBaseNodeFactory, NULL);
122  // Add UANodeSet XML parser as module
123  pServer->addModule(pXmlParser);
124  pServer->setTypeCreator(pNodeManagerCreator);
125 
126  NmBuildingAutomation *pMyNodeManager = new NmBuildingAutomation(pControlInterface, "OpcUaCanOpenServer");
127  if (pMyNodeManager == 0)
128  {
129  cout << "Could not Create Node Manager" << endl;
130  return OpcUa_Bad;
131  }
132  ret = pServer->addNodeManager(pMyNodeManager);
133  if (ret != 0)
134  {
135  cout << "Could not Create Node Manager" << endl;
136  return ret;
137  }
138  pServer->setAutomationNode(pMyNodeManager);
139  // Start server object
140  cout << "Start Server" << endl;
141  }
142 
143  ret = pServer->start();
144 
145  if (ret != 0)
146  {
147  cout << "Server Could not start" << endl;
148  }
149  else
150  {
151  //-------------------------------------------
152 
153  cout << "***************************************************" << endl;
154  cout << " Press " << SHUTDOWN_SEQUENCE << " to shutdown server" << endl;
155  cout << "***************************************************" << endl;
156  // Wait for user command to terminate the server thread.
157  while (ShutDownFlag() == 0)
158  {
159  UaThread::msleep(1000);
160  }
161  cout << "***************************************************" << endl;
162 // LOG(Log::INF) << " Shutting down server";
163  cout << " Shutting down server" << endl;
164  cout << "***************************************************" << endl;
165  }
166 
167  //- Stop OPC server -------------------------
168  // This code can be integrated into a shut down
169  // sequence of the application where the
170  // OPC server should be integrated
171  //-------------------------------------------
172  // Stop the server and wait three seconds if clients are connected
173  // to allow them to disconnect after they received the shutdown signal
175 // pServer->stop(3, UaLocalizedText("", "User shut down"));
176 // delete pServer;
177 // pServer = NULL;
178  //-------------------------------------------
179  }
180 
181  cout << "Server stopped" << endl;
182 // exit(0);
183  // Cleanup the XML Parser
184  UaXmlDocument::cleanupParser();
185 
186  //- Cleanup the environment --------------
187  //-------------------------------------------
188 
189 
190  return ret;
191 }
192 
193 
194 int main(int argc, char* argv[])
195 {
196 
197  int ret = 0;
198  char *pszFind;
199  const char *pDeviceConfig = 0;
200  const char *pServerConfig = 0;
201 
202 // const char *pLogFile = 0;
203 
205 
206  // Extract application path
207 #ifdef _WIN32
208  char szAppPath[MAX_PATH];
209  memset(szAppPath, 0, sizeof szAppPath);
210  GetModuleFileNameA(NULL, szAppPath, MAX_PATH);
211  szAppPath[MAX_PATH-1] = 0;
212  pszFind = strrchr(szAppPath, '\\');
213 #else
214  char szAppPath[PATH_MAX];
215  memset( szAppPath, 0, sizeof szAppPath );
216  readlink("/proc/self/exe", szAppPath, sizeof(szAppPath));
217  szAppPath[PATH_MAX-1] = 0;
218  pszFind = strrchr(szAppPath, '/');
219 #endif
220  if (pszFind)
221  {
222  *pszFind = 0; // cut off appname
223  }
224 
225  createCertificateOnly = false;
226  noExit = false;
227  bool printVersion = false;
228  string logFile;
229  options_description desc ("Allowed options");
230  // boost::program_options::value< vector<string> >(),
231  desc.add_options()
232  ("config_file", "A path to the config file")
233  ("server_config", "server config files")
234  ("cs", bool_switch(&createCertificateOnly), "Create new certificate and exit" )
235  ("help", "Print help")
236  ("noex", bool_switch(&noExit), "no Exit if cannot open canbus")
237 // ("l", value< string > (&logFile), "Logfile to print to")
238  ("version", bool_switch(&printVersion), "Print version and exit")
239  ;
240  positional_options_description p;
241  p.add("config_file", 1);
242  p.add("server_config", 2);
243 
244  variables_map vm;
245  try
246  {
247  store(command_line_parser(argc,argv)
248  .options(desc)
249  .style(command_line_style::allow_long_disguise | command_line_style::unix_style)
250  .positional(p)
251  .run(),
252  vm);
253  }
254  catch (boost::exception &e)
255  {
256  cout << "Couldn't interpret command line, please run with -help " << endl ;
257  return 1;
258  }
259  notify(vm);
260  if (vm.count("help"))
261  {
262  cout << desc << endl;
263  return 0;
264  }
265 
266  if (printVersion)
267  {
268  std::cout << VERSION_STR << std::endl;
269  return 0;
270  }
271  else
272  {
273 
274  if (vm.count("config_file") > 0)
275  pDeviceConfig = vm["config_file"].as< string > ().c_str();
276  if (vm.count("server_config") > 0)
277  pServerConfig = vm["server_config"].as< string >().c_str();
278 
279  //-------------------------------------------
280  // Call the OPC server main method
281 
282  OpcServerMain(szAppPath,pServerConfig,pDeviceConfig);
283 
284  //-------------------------------------------
285  // Cleanup the UA Stack platform layer
286  UaPlatformLayer::cleanup();
287 
288  }
289 
290 // return ret;
291 }