Guest User

Untitled

a guest
Apr 9th, 2018
29
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.64 KB | None | 0 0
  1. #include <algorithm>
  2. #include <iomanip>
  3. #include <iostream>
  4. #include <stdexcept>
  5. #include <string>
  6. #include <string_view>
  7. #include <utility>
  8.  
  9. #include <boost/format.hpp>
  10.  
  11. #include "adsData.h"
  12. #ifdef _MSC_VER
  13. #    include <wtypes.h>
  14. using bytes_read_type = unsigned long;
  15. #else
  16. using bytes_read_type = std::uint32_t;
  17. #endif
  18. #include <TcAdsDef.h>
  19.  
  20. #include <TcAdsAPI.h>
  21.  
  22. using namespace std::literals::string_view_literals;
  23.  
  24. AdsData getPlcData(decltype(AmsAddr::port) port)
  25. {
  26.     auto adsPort = AdsPortOpenEx();
  27.     if (adsPort == 0)
  28.         throw std::runtime_error("cannot open ads port");
  29.  
  30.     auto                                     deleter = [=](auto) { AdsPortCloseEx(adsPort); };
  31.     std::unique_ptr<void, decltype(deleter)> portGuard(nullptr, deleter);
  32.  
  33.     AmsAddr ams_addr{};
  34.     if (auto err = AdsGetLocalAddressEx(adsPort, &ams_addr); err != ADSERR_NOERR)
  35.         throw std::runtime_error((boost::format("cannot get local ams address: %#4x") % err).str());
  36.     ams_addr.port = port;
  37.  
  38.     bytes_read_type bytes_read = 0;
  39.  
  40.     AdsSymbolUploadInfo2 info{};
  41.     if (auto err = AdsSyncReadReqEx2(adsPort, &ams_addr, ADSIGRP_SYM_UPLOADINFO2, 0, sizeof(info), &info, &bytes_read);
  42.         err != ADSERR_NOERR)
  43.         throw std::runtime_error((boost::format("cannot read symbol upload info: %#4x") % err).str());
  44.     if (bytes_read != sizeof(info))
  45.         throw std::runtime_error((boost::format("error reading sym_uploadinfo2: %1% bytes read") % bytes_read).str());
  46.  
  47.     std::vector<char> symData(info.nSymSize);
  48.     std::vector<char> dtData(info.nDatatypeSize);
  49.  
  50.     if (auto err =
  51.             AdsSyncReadReqEx2(adsPort, &ams_addr, ADSIGRP_SYM_UPLOAD, 0, info.nSymSize, &symData[0], &bytes_read);
  52.         err != ADSERR_NOERR)
  53.         throw std::runtime_error((boost::format("cannot read symbol info: %#4x") % err).str());
  54.     if (bytes_read != info.nSymSize)
  55.         throw std::runtime_error(
  56.             (boost::format("error reading symbols: %1% bytes read, %2% expected") % bytes_read % info.nSymSize).str());
  57.  
  58.     if (auto err = AdsSyncReadReqEx2(adsPort, &ams_addr, ADSIGRP_SYM_DT_UPLOAD, 0, info.nDatatypeSize, &dtData[0],
  59.                                      &bytes_read);
  60.         err != ADSERR_NOERR)
  61.         throw std::runtime_error((boost::format("cannot read datatype info: %#4x") % err).str());
  62.     if (bytes_read != info.nDatatypeSize)
  63.         throw std::runtime_error(
  64.             (boost::format("error reading datatypes: %1% bytes read, %2% expected") % bytes_read % info.nDatatypeSize)
  65.                 .str());
  66.  
  67.     portGuard.release();
  68.  
  69.     return AdsData(symData, dtData);
  70. }
  71.  
  72. std::ostream& operator<<(std::ostream& s, DatatypeId val)
  73. {
  74.     static constexpr std::pair<DatatypeId, std::string_view> typenames[] = {
  75.         {DatatypeId::void_, "void"sv},       {DatatypeId::int16_, "int16"sv},         {DatatypeId::int32_, "int32"sv},
  76.         {DatatypeId::float_, "float"sv},     {DatatypeId::double_, "double"sv},       {DatatypeId::int8_, "int8"sv},
  77.         {DatatypeId::uint8_, "uint8"sv},     {DatatypeId::uint16_, "uint16"sv},       {DatatypeId::uint32_, "uint32"sv},
  78.         {DatatypeId::int64_, "int64"sv},     {DatatypeId::uint64_, "uint64"sv},       {DatatypeId::string_, "string"sv},
  79.         {DatatypeId::wstring_, "wstring"sv}, {DatatypeId::ldouble_, "long double"sv}, {DatatypeId::bool_, "bool"sv},
  80.         {DatatypeId::blob_, "blob"sv},       {DatatypeId::maxtypes_, "max_types"sv}};
  81.     auto it =
  82.         std::lower_bound(std::begin(typenames), std::end(typenames), val, [](auto& x, auto& y) { return x.first < y; });
  83.     if (it == std::end(typenames) || it->first != val)
  84.         s << "unknown(" << static_cast<int>(val) << ')';
  85.     else
  86.         s << it->second << '(' << static_cast<int>(val) << ')';
  87.     return s;
  88. }
  89.  
  90. static bool ignoreTypeId = false;
  91. void        verify(std::int32_t adsPort, AmsAddr& amsAddr, const AdsVarData& var, std::string prefix = "")
  92. {
  93.     auto name = var.name(prefix);
  94.  
  95.     union
  96.     {
  97.         char           buffer[0xFFFF] = {};
  98.         AdsSymbolEntry entry;
  99.     };
  100.  
  101.     bytes_read_type bytes_read = 0;
  102.     if (auto err = AdsSyncReadWriteReqEx2(adsPort, &amsAddr, ADSIGRP_SYM_INFOBYNAMEEX, 0, sizeof(buffer), buffer,
  103.                                           static_cast<std::uint32_t>(name.size() + 1), name.data(), &bytes_read);
  104.         err != ADSERR_NOERR)
  105.     {
  106.         std::cout << boost::format("%1$-72s FAILED\n\tSYM_INFOBYNAMEEX %2$#4x\nparsed as:\n") % name % err
  107.                   << "\ttype: " << var.type() << '\n'
  108.                   << "\tcomment: " << var.comment() << '\n'
  109.                   << "\ttypeId: " << var.typeId() << '\n'
  110.                   << "\tgroup: " << var.group() << '\n'
  111.                   << "\toffset: " << var.offset() << '\n'
  112.                   << "\tsize: " << var.size() << '\n';
  113.         return;
  114.     }
  115.  
  116.     if (var.isReference())
  117.     {
  118.         std::cout << boost::format("%-71s SKIPPED\n") % name;
  119.         return;
  120.     }
  121.  
  122.     if (var.type() != PADSSYMBOLTYPE(&entry) || var.comment() != PADSSYMBOLCOMMENT(&entry)
  123.         || (var.typeId() != entry.dataType && !ignoreTypeId) || var.group() != entry.iGroup
  124.         || var.offset() != entry.iOffs || var.size() != entry.size)
  125.     {
  126.         std::cout << boost::format("%-72s FAILED\nSYM_INFOBYNAMEEX says:\n") % name
  127.                   << "\ttype: " << PADSSYMBOLTYPE(&entry) << '\n'
  128.                   << "\tcomment: " << PADSSYMBOLCOMMENT(&entry) << '\n'
  129.                   << "\ttypeId: " << DatatypeId(entry.dataType) << '\n'
  130.                   << "\tgroup: " << entry.iGroup << '\n'
  131.                   << "\toffset: " << entry.iOffs << '\n'
  132.                   << "\tsize: " << entry.size << "\nbut parsed as:\n"
  133.                   << "\ttype: " << var.type() << '\n'
  134.                   << "\tcomment: " << var.comment() << '\n'
  135.                   << "\ttypeId: " << var.typeId() << '\n'
  136.                   << "\tgroup: " << var.group() << '\n'
  137.                   << "\toffset: " << var.offset() << '\n'
  138.                   << "\tsize: " << var.size() << '\n';
  139.     }
  140.     else
  141.         std::cout << boost::format("%-76s OK\n") % name;
  142. }
  143.  
  144. void verifySubs(AdsData& plcData, std::int32_t adsPort, AmsAddr& amsAddr, const AdsVarData& var, std::string prefix)
  145. {
  146.     for (auto sub : var)
  147.     {
  148.         plcData[sub.name(prefix)];
  149.         verify(adsPort, amsAddr, sub, prefix);
  150.         verifySubs(plcData, adsPort, amsAddr, sub, sub.name(prefix));
  151.     }
  152. }
  153.  
  154. int main(int argc, char** argv)
  155. {
  156.     if (argc < 2)
  157.     {
  158.         std::cout << "usage: " << argv[0] << " <port> [options]\noptions:-i ignore typeId";
  159.         return 1;
  160.     }
  161.     auto port = static_cast<decltype(AmsAddr::port)>(std::stoul(argv[1]));
  162.     if (argc >= 3 && argv[2] == "-i"sv)
  163.         ignoreTypeId = true;
  164.     try
  165.     {
  166.         AdsData plcData = getPlcData(port);
  167.         auto    adsPort = AdsPortOpenEx();
  168.         if (adsPort == 0)
  169.             throw std::runtime_error("cannot open ads port");
  170.  
  171.         auto                                     deleter = [=](auto) { AdsPortCloseEx(adsPort); };
  172.         std::unique_ptr<void, decltype(deleter)> portGuard(nullptr, deleter);
  173.  
  174.         AmsAddr ams_addr{};
  175.         if (auto err = AdsGetLocalAddressEx(adsPort, &ams_addr); err != ADSERR_NOERR)
  176.             throw std::runtime_error((boost::format("cannot get local ams address: %#4x") % err).str());
  177.         ams_addr.port = port;
  178.  
  179.         for (auto var : plcData)
  180.         {
  181.             plcData[var.shortName()];
  182.             verify(adsPort, ams_addr, var);
  183.             verifySubs(plcData, adsPort, ams_addr, var, var.shortName());
  184.         }
  185.     }
  186.     catch (std::exception& e)
  187.     {
  188.         std::cout << e.what() << '\n';
  189.         return 1;
  190.     }
  191. }
Add Comment
Please, Sign In to add comment