tool/CommandGraph.cpp
changeset 1422 d41e4537b75f
child 1425 c1322a8793c0
equal deleted inserted replaced
1421:043a518831b2 1422:d41e4537b75f
       
     1 /*****************************************************************************
       
     2  *
       
     3  *  $Id$
       
     4  *
       
     5  *  Copyright (C) 2006-2009  Florian Pose, Ingenieurgemeinschaft IgH
       
     6  *
       
     7  *  This file is part of the IgH EtherCAT Master.
       
     8  *
       
     9  *  The IgH EtherCAT Master is free software; you can redistribute it and/or
       
    10  *  modify it under the terms of the GNU General Public License version 2, as
       
    11  *  published by the Free Software Foundation.
       
    12  *
       
    13  *  The IgH EtherCAT Master is distributed in the hope that it will be useful,
       
    14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
       
    16  *  Public License for more details.
       
    17  *
       
    18  *  You should have received a copy of the GNU General Public License along
       
    19  *  with the IgH EtherCAT Master; if not, write to the Free Software
       
    20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
       
    21  *
       
    22  *  ---
       
    23  *
       
    24  *  The license mentioned above concerns the source code only. Using the
       
    25  *  EtherCAT technology and brand is only permitted in compliance with the
       
    26  *  industrial property and similar rights of Beckhoff Automation GmbH.
       
    27  *
       
    28  ****************************************************************************/
       
    29 
       
    30 #include <iostream>
       
    31 #include <map>
       
    32 using namespace std;
       
    33 
       
    34 #include "CommandGraph.h"
       
    35 
       
    36 /*****************************************************************************/
       
    37 
       
    38 CommandGraph::CommandGraph():
       
    39     Command("graph", "Output the bus topology as a graph.")
       
    40 {
       
    41 }
       
    42 
       
    43 /*****************************************************************************/
       
    44 
       
    45 string CommandGraph::helpString() const
       
    46 {
       
    47     stringstream str;
       
    48 
       
    49     str << getName() << " [OPTIONS]" << endl
       
    50         << endl
       
    51         << getBriefDescription() << endl
       
    52         << endl
       
    53         << "The bus is output in DOT language (see" << endl
       
    54         << "http://www.graphviz.org/doc/info/lang.html), which can" << endl
       
    55         << "be processed with the tools from the Graphviz" << endl
       
    56         << "package. Example:" << endl
       
    57         << endl
       
    58         << "  ethercat graph | dot -Tsvg > bus.svg" << endl
       
    59         << endl
       
    60         << "See 'man dot' for more information." << endl;
       
    61 
       
    62     return str.str();
       
    63 }
       
    64 
       
    65 /****************************************************************************/
       
    66 
       
    67 void CommandGraph::execute(MasterDevice &m, const StringVector &args)
       
    68 {
       
    69     ec_ioctl_master_t master;
       
    70     unsigned int i;
       
    71     typedef vector<ec_ioctl_slave_t> SlaveVector;
       
    72     SlaveVector slaves;
       
    73     ec_ioctl_slave_t slave;
       
    74     SlaveVector::const_iterator si;
       
    75     string font("fontname=\"Helvetica\"");
       
    76     map<int, string> portMedia;
       
    77     map<int, string>::const_iterator mi;
       
    78     map<int, int> mediaWeights;
       
    79     map<int, int>::const_iterator wi;
       
    80 
       
    81     portMedia[EC_PORT_MII] = "MII";
       
    82     mediaWeights[EC_PORT_MII] = 1;
       
    83 
       
    84     portMedia[EC_PORT_EBUS] = "EBUS";
       
    85     mediaWeights[EC_PORT_EBUS] = 5;
       
    86     
       
    87     if (args.size()) {
       
    88         stringstream err;
       
    89         err << "'" << getName() << "' takes no arguments!";
       
    90         throwInvalidUsageException(err);
       
    91     }
       
    92 
       
    93     m.open(MasterDevice::Read);
       
    94     m.getMaster(&master);
       
    95 
       
    96     for (i = 0; i < master.slave_count; i++) {
       
    97         m.getSlave(&slave, i);
       
    98         slaves.push_back(slave);
       
    99     }
       
   100 
       
   101     cout << "/* EtherCAT bus graph. Generated by 'ethercat graph'. */" << endl
       
   102         << endl
       
   103         << "strict graph bus {" << endl
       
   104         << "    rankdir=\"LR\"" << endl
       
   105         << endl
       
   106         << "    master [" << font << ",label=\"EtherCAT\\nMaster\"]" << endl;
       
   107 
       
   108     if (slaves.size()) {
       
   109         cout << "    master -- slave0 [" << font;
       
   110 
       
   111         mi = portMedia.find(slaves.front().port_descs[0]);
       
   112         if (mi != portMedia.end())
       
   113             cout << ",label=\"" << mi->second << "\"";
       
   114 
       
   115         cout << "]" << endl;
       
   116     }
       
   117     cout << endl;
       
   118 
       
   119     for (si = slaves.begin(); si != slaves.end(); si++) {
       
   120 	    cout << "    slave" << si->position << " [" << font <<
       
   121             ",shape=\"box\",label=\"" << si->position;
       
   122         if (string(si->order).size())
       
   123             cout << "\\n" << si->order;
       
   124         cout << "\"]" << endl;
       
   125 
       
   126         for (i = 1; i < EC_MAX_PORTS; i++) {
       
   127             if (si->next_slave[i] == 0xffff)
       
   128                 continue;
       
   129 
       
   130             cout << "    slave" << si->position << " -- "
       
   131                 << "slave" << si->next_slave[i] << " [" << font << ","
       
   132                 << "taillabel=\"" << i << "\"";
       
   133 
       
   134             mi = portMedia.find(si->port_descs[i]);
       
   135             if (mi == portMedia.end()) {
       
   136                 /* Try medium of next-hop slave. */
       
   137                 unsigned int pos = si->next_slave[i];
       
   138                 if (pos < slaves.size()) {
       
   139                     ec_ioctl_slave_t *next = &slaves[pos];
       
   140                     mi = portMedia.find(next->port_descs[0]);
       
   141                 } else {
       
   142                     cerr << "Invalid next slave pointer." << endl;
       
   143                 }
       
   144             }
       
   145             
       
   146             if (mi != portMedia.end())
       
   147                 cout << ",label=\"" << mi->second << "\"";
       
   148 
       
   149             wi = mediaWeights.find(si->port_descs[i]);
       
   150             if (wi != mediaWeights.end())
       
   151                 cout << ",weight=\"" << wi->second << "\"";
       
   152             
       
   153             cout << "]" << endl;
       
   154         }
       
   155 
       
   156         cout << endl;
       
   157     }
       
   158 
       
   159     cout << "}" << endl;
       
   160 }
       
   161 
       
   162 /*****************************************************************************/