Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using data streamed by agent. #4

Closed
nikhilbchilwant opened this issue May 28, 2014 · 5 comments
Closed

Using data streamed by agent. #4

nikhilbchilwant opened this issue May 28, 2014 · 5 comments
Assignees

Comments

@nikhilbchilwant
Copy link

I'm beginner in MTConnect and trying to make use of data/information (which is in MTConnect format) streamed by agent. My client doesn't understand MTconnect because its code is written for particular string format. So, I want to make a wrapper which will convert info. sent by agent (in MTConnect format) into the format that client will understand. So, first step is to get information from agent and the second is to convert into desired format. How do I receive information from agent? (Of course, not web browser because agent is an API).

To see output generated by agent, I was trying to do : 'telnet localhost 5000' in CMD but it wasn't showing anything.

What should I do?
Is there any wrapper for conversion of MTConnect to desired string format?

@shakthimaan
Copy link

The output of the agent is XML, and you will need to make a HTTP request to the agent to retrieve this information.

So, you will need to extract the content that you need from the XML and convert it into the desired string format.

@johnmichaloski
Copy link
Collaborator

You need to use an XML parser, e.g., MSXML or Xerces. (maybe others). Below is a MSXML parser, attached are some XERCES notes for parsing (FENT is a network analyzer using Wireshark on source forge) . I also have vb script to read and “tabelize” MTConnect xml (Will has ruby code). XMLspy will also generate C++ code that reads XML using MSXML or Xerces. You can also use Microsoft xsd.exe to generate an XML reader in C#.

You can view xml from webbrowser as http://ip:5000/current or http://ip:5000/probe But as you said this only displays output. (Telnet is for back end SHDR from controller).

John

//
// MTConnectStreamsParser.cpp – Example MSXML parsing of MTConnect XML
//
// DISCLAIMER:
// This software was developed by U.S. Government employees as part of
// their official duties and is not subject to copyright. No warranty implied
// or intended.

#include "StdAfx.h"
#include "MTConnectStreamsParser.h"

#pragma comment(lib, "comsuppw.lib")
#pragma comment(lib, "Ws2_32.lib")
#pragma comment(lib, "Iphlpapi.lib")

std::map<std::string, std::string> MTConnectStreamsParser::_TagRenames;
std::vectorstd::string MTConnectStreamsParser::_saveddata;
std::map<std::string, std::string> MTConnectStreamsParser::_valuerenames;

ptime GetDateTime(std::string s)
{
// parse 2012-02-03T17:31:51.0968Z
int Year, Month, Day, Hour, Minute, Second, Millisecond=0;
if(sscanf(s.c_str(), "%d-%d-%dT%d:%d:%d.%d", &Year, &Month, &Day, &Hour, &Minute,&Second, &Millisecond)==7){}
//12/2/2009 2:42:25 PM
else if(sscanf(s.c_str(), "%d-%d-%dT%d:%d:%d", &Year, &Month, &Day, &Hour, &Minute,&Second)==6){}
else if(sscanf(s.c_str(), "%d/%d/%4d%d:%d:%d", &Month, &Day, &Year, &Hour, &Minute,&Second)==6){}
else throw std::exception("Unrecognized date-time format\n");

   return ptime( date(Year,Month,Day),
              hours(Hour)  +
              minutes(Minute) +
              seconds(Second) +
              boost::posix_time::millisec(int(Millisecond)) );

   //return COleDateTime( Year, Month, Day, Hour, Minute, Second );

}

static _bstr_t checkParseError(MSXML2::IXMLDOMParseErrorPtr pError)
{
_bstr_t parseError =_bstr_t("At line ")+ _bstr_t(pError->Getline()) + _bstr_t("\n")+ _bstr_t(pError->Getreason());
//MessageBox(NULL,parseError, "Parse Error",MB_OK);
return parseError;

}

static void dump_com_error(_com_error &e)
{
::AtlTrace("Error\n");
//TRACE1("\a\tCode = %08lx\n", e.Error());
//TRACE1("\a\tCode meaning = %s", e.ErrorMessage());
_bstr_t bstrSource(e.Source());
_bstr_t bstrDescription(e.Description());
::AtlTrace("\a\tSource = %s\n", (LPCSTR) bstrSource);
::AtlTrace("\a\tDescription = %s\n", (LPCSTR) bstrDescription);
}

MTConnectStreamsParser::MTConnectStreamsParser(void)
{
}

MTConnectStreamsParser::~MTConnectStreamsParser(void)
{
}
void MTConnectStreamsParser::Release(void)
{
m_pSchemaCache=NULL;
m_pXSDDoc=NULL;
m_pXMLDoc=NULL;
}

_bstr_t MTConnectStreamsParser::GetAttribute(MSXML2::IXMLDOMNodePtr node, _bstr_t attribute)
{
_bstr_t text= L"";;
CComPtrMSXML2::IXMLDOMNamedNodeMap attributes;
node->get_attributes( &attributes );
if( attributes )
{
MSXML2::IXMLDOMNodePtr attr = attributes->getNamedItem(attribute);
if(attr==NULL)
return text;
if(attr->nodeValue.vt == VT_BSTR)
return attr->nodeValue.bstrVal;
}

   return text;

}

std::string MTConnectStreamsParser::ParseXMLDocument(_bstr_t xmlfile, _bstr_t xsdfile, _bstr_t xsdname)
{
_bstr_t parseError(L"");
try{
IXMLDOMParseErrorPtr pError;

          // load the XML file
          // ****** you need to use IXMLDOMDocument2 interface *********
          HRESULT hr = m_pXMLDoc.CreateInstance(__uuidof(MSXML2::DOMDocument));
          m_pXMLDoc->async =  VARIANT_FALSE;

          hr = m_pXMLDoc->load(xmlfile);

          //check on the parser error
          if(hr!=VARIANT_TRUE)
          {
                 return (LPCSTR) checkParseError(m_pXMLDoc->parseError);
          }
   }
   catch(_com_error &e)
   {
          dump_com_error(e);
          return  e.ErrorMessage();
   }

   return (LPCSTR) parseError;

}
// Replace into data with newer from data
static DataDictionary Merge(DataDictionary &into, DataDictionary &from)
{
DataDictionary newdata = into;
for(DataDictionary::iterator it=from.begin(); it!=from.end(); it++)
{
into[(_it).first]=(_it).second;
}
return newdata;
}
std::string MTConnectStreamsParser::GetMTConnectUrl(std::string ippath)
{
std::string _devicesfilename = "http://" + ippath + "/current";
return _devicesfilename;
}

std::vector MTConnectStreamsParser::ReadStream(std::string filename)
{
DataDictionary data;
std::vector datums;
std::string ip;
ip = filename.substr( 0, filename.find_last_of( '/' ) );
ip = ip.substr( 0, ip.find_last_of( ':' ) );
//if(!TestPing(ip))
// return datums;

   _devicesfilename = "http://" + filename + "/current";

   // Not empty means error
   if(!ParseXMLDocument(_devicesfilename.c_str()).empty())
          return datums;

   data=ParseDataItems();

   datums.push_back(data);
   m_pXMLDoc=NULL;
   return datums;

}

DataDictionary MTConnectStreamsParser::ParseDataItems()
{
MSXML2::IXMLDOMNodePtr root = m_pXMLDoc->GetdocumentElement();
MSXML2::IXMLDOMNodeListPtr nodes = root->selectNodes(_bstr_t("//DeviceStream"));
DataDictionary data;
try
{
for(int i=0; i< nodes->length; i++)
{
MSXML2::IXMLDOMNodePtr pNode = NULL;
nodes->get_item(i, &pNode);

                 _bstr_t items[3] = {_bstr_t(".//Samples"), _bstr_t(".//Events") , _bstr_t(".//Condition") };
                 for(int ii=0; ii<3 ; ii++)
                 {
                       MSXML2::IXMLDOMNodeListPtr samples = pNode->selectNodes(items[ii]);
                       for(int j=0; j< samples->length; j++)
                       {
                              MSXML2::IXMLDOMNodePtr pSampleHive = NULL;
                              samples->get_item(j, &pSampleHive);

                              // Get each child
                              MSXML2::IXMLDOMNodeListPtr childs = pSampleHive->childNodes;
                              for(int k=0; k< childs->length; k++)
                              {
                                     MSXML2::IXMLDOMNodePtr pSample = NULL;
                                     ptime datetime;
                                     std::string name ;
                                     std::string value;
                                     std::string timestamp;
                                     std::string sequence;

                                     childs->get_item(k, &pSample);

                                     name = (LPCSTR)  GetAttribute(pSample, "name");

                                     if(name.empty())
                                            name = (LPCSTR)  GetAttribute(pSample, "dataItemId");


                                     if(name.empty())
                                            continue;

                                     // Lookup any name remapping to shorten - e.g., Frt or path_feedratefrt => Feed
                                     if(_TagRenames.find(name)!= _TagRenames.end())
                                     {
                                            name = _TagRenames[name];
                                     }

#if 0
// FIXME: is this necessary?
// Check to see if data item to be saved
if(std::find(_saveddata.begin(), _saveddata.end(), name) == _saveddata.end())
continue;
#endif

                                     value = (LPCSTR) pSample->Gettext();
                                     if(items[ii]== bstr_t(".//Condition") )
                                            value =  std::string((LPCSTR) pSample->nodeName) + "."  + value  ;

                                     if(_valuerenames.find(name+"."+value)!=_valuerenames.end())
                                            value=_valuerenames[name+"."+value];

                                     timestamp = (LPCSTR)  GetAttribute(pSample, "timestamp");
                                     sequence = (LPCSTR)  GetAttribute(pSample, "sequence");

                                     data[name]= value;

#if 0
if(!timestamp.empty())
{
datetime=GetDateTime(timestamp);
DataDictionary & dict(timeddata[datetime]) ;
dict[name]=data[name];
//for(DataDictionary::iterator it=dict.begin(); it!=dict.end(); it++)
//{
// OutputDebugString(StdStringFormat("%s %s=%s\n", timestamp.c_str(),
// (_it).first.c_str(), (_it).second.c_str()).c_str());
//}
}

                                     streamdata[name]=StreamData(name,data[name], timestamp, sequence);

#endif
}
}
}
}
}
catch(...)
{
std::cout<< "MTConnectStreamsParser::ParseDataItems() Exception\n";
}
return data;

}

From: Nikhil [mailto:notifications@github.com]
Sent: Wednesday, May 28, 2014 5:32 AM
To: mtconnect/cppagent
Subject: [cppagent] Using data streamed by agent. (#4)

I'm beginner in MTConnect and trying to make use of data/information (which is in MTConnect format) streamed by agent. My client doesn't understand MTconnect because its code is written for particular string format. So, I want to make a wrapper which will convert info. sent by agent (in MTConnect format) into the format that client will understand. So, first step is to get information from agent and the second is to convert into desired format. How do I receive information from agent? (Of course, not web browser because agent is an API).

To see output generated by agent, I was trying to do : 'telnet localhost 5000' in CMD but it wasn't showing anything.

What should I do?
Is there any wrapper for conversion of MTConnect to desired string format?


Reply to this email directly or view it on GitHubhttps://github.com//issues/4.

@wsobel
Copy link
Member

wsobel commented May 28, 2014

Nikhil,

The easiest way to dump the data into an file is the curl command line application: http://curl.haxx.se

This utility is very capable and will work on almost any platform.

curl http://localhost:5000/probe
curl http://localhost:5000/current  
etc…

The output will go to std out and you can process it with your favorite XML parser. There are better ways to handle the data from an application, but that is a longer discussion.

On May 28, 2014, at 2:31 AM, Nikhil notifications@github.com wrote:

I'm beginner in MTConnect and trying to make use of data/information (which is in MTConnect format) streamed by agent. My client doesn't understand MTconnect because its code is written for particular string format. So, I want to make a wrapper which will convert info. sent by agent (in MTConnect format) into the format that client will understand. So, first step is to get information from agent and the second is to convert into desired format. How do I receive information from agent? (Of course, not web browser because agent is an API).

To see output generated by agent, I was trying to do : 'telnet localhost 5000' in CMD but it wasn't showing anything.

What should I do?
Is there any wrapper for conversion of MTConnect to desired string format?


Reply to this email directly or view it on GitHub.

@nikhilbchilwant
Copy link
Author

Thank you @wsobel shakthimaan johnmichaloski for your response.
I forgot to mentioned that I'm working in C#. I have found a way to access data from agent using HttpWebRequest in C#. You just need to give required URI to retrieve data. @wsobel How curl is better than this?

@wsobel
Copy link
Member

wsobel commented May 29, 2014

Since you mentioned telnet, I made the assumption you were working from the command line.

For a r/t streaming example in c# - check out the app lab: github.com/mtconnect/mc2-app-lab

Sent from my iPhone

On May 28, 2014, at 23:16, Nikhil notifications@github.com wrote:

Thank you @wsobel shakthimaan johnmichaloski for your response.
I forgot to mentioned that I'm working in C#. I have found a way to access data from agent using HttpWebRequest in C#. You just need to give required URI to retrieve data. @wsobel How curl is better than this?


Reply to this email directly or view it on GitHub.

@wsobel wsobel self-assigned this Sep 29, 2014
wsobel pushed a commit that referenced this issue Dec 10, 2019
* Removed dlib::unit64 and replaced with uint64_t

* This addresses issue #4
* Part of the larger epic of removing dlib (#3)
* Removed redundant #includes
* Whitespace changes for coding consistency
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants