/***************************************************************************** * * $Id$ * * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH * * This file is part of the IgH EtherCAT Master. * * The IgH EtherCAT Master is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. * * The IgH EtherCAT Master is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * You should have received a copy of the GNU General Public License along * with the IgH EtherCAT Master; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * --- * * The license mentioned above concerns the source code only. Using the * EtherCAT technology and brand is only permitted in compliance with the * industrial property and similar rights of Beckhoff Automation GmbH. * ****************************************************************************/ #include #include using namespace std; #include "CommandGraph.h" /*****************************************************************************/ CommandGraph::CommandGraph(): Command("graph", "Output the bus topology as a graph.") { } /*****************************************************************************/ string CommandGraph::helpString() const { stringstream str; str << getName() << " [OPTIONS]" << endl << endl << getBriefDescription() << endl << endl << "The bus is output in DOT language (see" << endl << "http://www.graphviz.org/doc/info/lang.html), which can" << endl << "be processed with the tools from the Graphviz" << endl << "package. Example:" << endl << endl << " ethercat graph | dot -Tsvg > bus.svg" << endl << endl << "See 'man dot' for more information." << endl; return str.str(); } /****************************************************************************/ void CommandGraph::execute(MasterDevice &m, const StringVector &args) { ec_ioctl_master_t master; unsigned int i; typedef vector SlaveVector; SlaveVector slaves; ec_ioctl_slave_t slave; SlaveVector::const_iterator si; string font("fontname=\"Helvetica\""); map portMedia; map::const_iterator mi; map mediaWeights; map::const_iterator wi; portMedia[EC_PORT_MII] = "MII"; mediaWeights[EC_PORT_MII] = 1; portMedia[EC_PORT_EBUS] = "EBUS"; mediaWeights[EC_PORT_EBUS] = 5; if (args.size()) { stringstream err; err << "'" << getName() << "' takes no arguments!"; throwInvalidUsageException(err); } m.open(MasterDevice::Read); m.getMaster(&master); for (i = 0; i < master.slave_count; i++) { m.getSlave(&slave, i); slaves.push_back(slave); } cout << "/* EtherCAT bus graph. Generated by 'ethercat graph'. */" << endl << endl << "strict graph bus {" << endl << " rankdir=\"LR\"" << endl << endl << " master [" << font << ",label=\"EtherCAT\\nMaster\"]" << endl; if (slaves.size()) { cout << " master -- slave0 [" << font; mi = portMedia.find(slaves.front().port_descs[0]); if (mi != portMedia.end()) cout << ",label=\"" << mi->second << "\""; cout << "]" << endl; } cout << endl; for (si = slaves.begin(); si != slaves.end(); si++) { cout << " slave" << si->position << " [" << font << ",shape=\"box\",label=\"" << si->position; if (string(si->order).size()) cout << "\\n" << si->order; cout << "\"]" << endl; for (i = 1; i < EC_MAX_PORTS; i++) { if (si->next_slave[i] == 0xffff) continue; cout << " slave" << si->position << " -- " << "slave" << si->next_slave[i] << " [" << font << "," << "taillabel=\"" << i << "\""; mi = portMedia.find(si->port_descs[i]); if (mi == portMedia.end()) { /* Try medium of next-hop slave. */ unsigned int pos = si->next_slave[i]; if (pos < slaves.size()) { ec_ioctl_slave_t *next = &slaves[pos]; mi = portMedia.find(next->port_descs[0]); } else { cerr << "Invalid next slave pointer." << endl; } } if (mi != portMedia.end()) cout << ",label=\"" << mi->second << "\""; wi = mediaWeights.find(si->port_descs[i]); if (wi != mediaWeights.end()) cout << ",weight=\"" << wi->second << "\""; cout << "]" << endl; } cout << endl; } cout << "}" << endl; } /*****************************************************************************/