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

Attribute id 2 bytes #7

Open
wants to merge 4 commits into
base: indigo-devel
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions include/odva_ethernetip/path.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSI
#define ODVA_ETHERNETIP_PATH_H

#include <vector>
#include <iostream>
#include <iomanip>

#include "odva_ethernetip/eip_types.h"
#include "odva_ethernetip/serialization/reader.h"
Expand Down Expand Up @@ -69,6 +71,8 @@ class Path
*/
Path(EIP_USINT class_id, EIP_USINT instance_id, EIP_USINT attribute_id,
bool pad_after_length = false);
Path(EIP_USINT class_id, EIP_USINT instance_id, EIP_UINT attribute_id,
bool pad_after_length = false);

/**
* Shortcut to construct a path to the given logical class instance
Expand Down Expand Up @@ -107,6 +111,7 @@ class Path
* @param attribute_id ID Number of attribute to add to path
*/
void addLogicalAttribute(EIP_USINT attribute_id);
void addLogicalAttribute(EIP_UINT attribute_id);

/**
* Add a logical connection point segment
Expand Down Expand Up @@ -166,6 +171,23 @@ class Path
throw std::logic_error("Not implemented");
}

/**
* Prints path bytes to a given output stream
*/
friend std::ostream& operator<<(std::ostream& os, const Path& p)
{
os << "PATH: ";
os.setf(std::ios_base::hex , std::ios_base::basefield);
for (unsigned int ii=0; ii< p.path_buf_.size(); ii++)
{
os << std::setw(2) << std::setfill('0') << (unsigned short int)p.path_buf_.at(ii);
if ( (ii+1)%2 == 0 ) os << " ";
}
os << std::endl;
os.setf(std::ios_base::dec , std::ios_base::basefield);
return os;
}

private:
bool pad_after_length_;
vector<EIP_USINT> path_buf_;
Expand All @@ -176,6 +198,7 @@ class Path
* @param data Data to add to path
*/
void addSegment(EIP_USINT type, EIP_USINT data);
void addSegment(EIP_USINT type, EIP_UINT data);
};

} // namespace eip
Expand Down
19 changes: 19 additions & 0 deletions include/odva_ethernetip/session.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ class Session
*/
void getSingleAttributeSerializable(EIP_USINT class_id, EIP_USINT instance_id,
EIP_USINT attribute_id, Serializable& result);
void getSingleAttributeSerializable(EIP_USINT class_id, EIP_USINT instance_id,
EIP_UINT attribute_id, Serializable& result);

/**
* Shortcut to get a single attribute as a primitive type
Expand All @@ -120,6 +122,13 @@ class Session
getSingleAttributeSerializable(class_id, instance_id, attribute_id, data);
return data.data;
}
template <typename T>
T getSingleAttribute(EIP_USINT class_id, EIP_USINT instance_id, EIP_UINT attribute_id, T v)
{
SerializablePrimitive<T> data;
getSingleAttributeSerializable(class_id, instance_id, attribute_id, data);
return data.data;
}

/**
* Set a single attribute from the given class / instance / attribute path
Expand All @@ -130,6 +139,8 @@ class Session
*/
void setSingleAttributeSerializable(EIP_USINT class_id, EIP_USINT instance_id,
EIP_USINT attribute_id, shared_ptr<Serializable> data);
void setSingleAttributeSerializable(EIP_USINT class_id, EIP_USINT instance_id,
EIP_UINT attribute_id, shared_ptr<Serializable> data);

/**
* Shortcut to set a single attribute from a primitive type
Expand All @@ -146,6 +157,14 @@ class Session
make_shared< SerializablePrimitive<T> > (v);
setSingleAttributeSerializable(class_id, instance_id, attribute_id, data);
}
template <typename T>
void setSingleAttribute(EIP_USINT class_id, EIP_USINT instance_id,
EIP_UINT attribute_id, T v)
{
shared_ptr< SerializablePrimitive<T> > data =
make_shared< SerializablePrimitive<T> > (v);
setSingleAttributeSerializable(class_id, instance_id, attribute_id, data);
}

/**
* Create an Ethernet/IP Connection for sending implicit messages
Expand Down
22 changes: 22 additions & 0 deletions src/path.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ Path::Path(EIP_USINT class_id, EIP_USINT instance_id, EIP_USINT attribute_id,
addLogicalAttribute(attribute_id);
}

Path::Path(EIP_USINT class_id, EIP_USINT instance_id, EIP_UINT attribute_id,
bool pad_after_length) : pad_after_length_(pad_after_length)
{
path_buf_.reserve(7);
addLogicalClass(class_id);
addLogicalInstance(instance_id);
addLogicalAttribute(attribute_id);
}


Path::Path(EIP_USINT class_id, EIP_USINT instance_id) : pad_after_length_(false)
{
path_buf_.reserve(4);
Expand All @@ -56,6 +66,13 @@ void Path::addSegment(EIP_USINT type, EIP_USINT data)
path_buf_.push_back(data);
}

void Path::addSegment(EIP_USINT type, EIP_UINT data)
{
path_buf_.push_back(type);
path_buf_.push_back( (EIP_USINT)(data&0xff) );
path_buf_.push_back( (EIP_USINT)((data&0xff00)>>8) );
}

void Path::addLogicalClass(EIP_USINT class_id)
{
addSegment(0x20, class_id);
Expand All @@ -71,6 +88,11 @@ void Path::addLogicalAttribute(EIP_USINT attribute_id)
addSegment(0x30, attribute_id);
}

void Path::addLogicalAttribute(EIP_UINT attribute_id)
{
addSegment(0x31, attribute_id);
}

void Path::addLogicalConnectionPoint(EIP_USINT connection_id)
{
addSegment(0x2C, connection_id);
Expand Down
34 changes: 25 additions & 9 deletions src/session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ Session::Session(shared_ptr<Socket> socket, shared_ptr<Socket> io_socket,
boost::random::uniform_int_distribution<> dist(0, 0xFFFF);
next_connection_id_ = gen();
next_connection_sn_ = dist(gen);
cout << "Generated starting connection ID " << next_connection_id_
<< " and SN " << next_connection_sn_ << endl;;
//cout << "Generated starting connection ID " << next_connection_id_ << " and SN " << next_connection_sn_ << endl;;
}

Session::~Session()
Expand All @@ -81,12 +80,12 @@ Session::~Session()

void Session::open(string hostname, string port, string io_port)
{
cout << "Resolving hostname and connecting socket" << endl;
//cout << "Resolving hostname and connecting socket" << endl;
socket_->open(hostname, port);
io_socket_->open(hostname, io_port);

// create the registration message
cout << "Creating and sending the registration message" << endl;
//cout << "Creating and sending the registration message" << endl;
shared_ptr<RegisterSessionData> reg_data = make_shared<RegisterSessionData>();
EncapPacket reg_msg(EIP_CMD_REGISTER_SESSION, 0, reg_data);

Expand Down Expand Up @@ -149,7 +148,7 @@ void Session::open(string hostname, string port, string io_port)
}

session_id_ = response.getHeader().session_handle;
cout << "Successfully opened session ID " << session_id_ << endl;
//cout << "Successfully opened session ID " << session_id_ << endl;
}

void Session::close()
Expand All @@ -170,12 +169,12 @@ void Session::close()

EncapPacket Session::sendCommand(EncapPacket& req)
{
cout << "Sending Command" << endl;
//cout << "Sending Command" << endl;
socket_->send(req);

cout << "Waiting for response" << endl;
//cout << "Waiting for response" << endl;
size_t n = socket_->receive(buffer(recv_buffer_));
cout << "Received response of " << n << " bytes" << endl;
//cout << "Received response of " << n << " bytes" << endl;

BufferReader reader(buffer(recv_buffer_, n));
EncapPacket result;
Expand Down Expand Up @@ -237,17 +236,34 @@ void Session::getSingleAttributeSerializable(EIP_USINT class_id, EIP_USINT insta
resp_data.getResponseDataAs(result);
}

void Session::getSingleAttributeSerializable(EIP_USINT class_id, EIP_USINT instance_id,
EIP_UINT attribute_id, Serializable& result)
{
shared_ptr<Serializable> no_data;
RRDataResponse resp_data = sendRRDataCommand(0x0E,
Path(class_id, instance_id, attribute_id), no_data);

resp_data.getResponseDataAs(result);
}


void Session::setSingleAttributeSerializable(EIP_USINT class_id,
EIP_USINT instance_id, EIP_USINT attribute_id, shared_ptr<Serializable> data)
{
RRDataResponse resp_data = sendRRDataCommand(0x10,
Path(class_id, instance_id, attribute_id), data);
}
void Session::setSingleAttributeSerializable(EIP_USINT class_id,
EIP_USINT instance_id, EIP_UINT attribute_id, shared_ptr<Serializable> data)
{
RRDataResponse resp_data = sendRRDataCommand(0x10,
Path(class_id, instance_id, attribute_id), data);
}

RRDataResponse Session::sendRRDataCommand(EIP_USINT service, const Path& path,
shared_ptr<Serializable> data)
{
cout << "Creating RR Data Request" << endl;
//cout << "Creating RR Data Request" << endl;
shared_ptr<RRDataRequest> req_data =
make_shared<RRDataRequest> (service, path, data);
EncapPacket encap_pkt(EIP_CMD_SEND_RR_DATA, session_id_, req_data);
Expand Down