Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <algorithm>
- #include <iomanip>
- #include <iostream>
- #include <stdexcept>
- #include <string>
- #include <string_view>
- #include <utility>
- #include <boost/format.hpp>
- #include "adsData.h"
- #ifdef _MSC_VER
- # include <wtypes.h>
- using bytes_read_type = unsigned long;
- #else
- using bytes_read_type = std::uint32_t;
- #endif
- #include <TcAdsDef.h>
- #include <TcAdsAPI.h>
- using namespace std::literals::string_view_literals;
- AdsData getPlcData(decltype(AmsAddr::port) port)
- {
- auto adsPort = AdsPortOpenEx();
- if (adsPort == 0)
- throw std::runtime_error("cannot open ads port");
- auto deleter = [=](auto) { AdsPortCloseEx(adsPort); };
- std::unique_ptr<void, decltype(deleter)> portGuard(nullptr, deleter);
- AmsAddr ams_addr{};
- if (auto err = AdsGetLocalAddressEx(adsPort, &ams_addr); err != ADSERR_NOERR)
- throw std::runtime_error((boost::format("cannot get local ams address: %#4x") % err).str());
- ams_addr.port = port;
- bytes_read_type bytes_read = 0;
- AdsSymbolUploadInfo2 info{};
- if (auto err = AdsSyncReadReqEx2(adsPort, &ams_addr, ADSIGRP_SYM_UPLOADINFO2, 0, sizeof(info), &info, &bytes_read);
- err != ADSERR_NOERR)
- throw std::runtime_error((boost::format("cannot read symbol upload info: %#4x") % err).str());
- if (bytes_read != sizeof(info))
- throw std::runtime_error((boost::format("error reading sym_uploadinfo2: %1% bytes read") % bytes_read).str());
- std::vector<char> symData(info.nSymSize);
- std::vector<char> dtData(info.nDatatypeSize);
- if (auto err =
- AdsSyncReadReqEx2(adsPort, &ams_addr, ADSIGRP_SYM_UPLOAD, 0, info.nSymSize, &symData[0], &bytes_read);
- err != ADSERR_NOERR)
- throw std::runtime_error((boost::format("cannot read symbol info: %#4x") % err).str());
- if (bytes_read != info.nSymSize)
- throw std::runtime_error(
- (boost::format("error reading symbols: %1% bytes read, %2% expected") % bytes_read % info.nSymSize).str());
- if (auto err = AdsSyncReadReqEx2(adsPort, &ams_addr, ADSIGRP_SYM_DT_UPLOAD, 0, info.nDatatypeSize, &dtData[0],
- &bytes_read);
- err != ADSERR_NOERR)
- throw std::runtime_error((boost::format("cannot read datatype info: %#4x") % err).str());
- if (bytes_read != info.nDatatypeSize)
- throw std::runtime_error(
- (boost::format("error reading datatypes: %1% bytes read, %2% expected") % bytes_read % info.nDatatypeSize)
- .str());
- portGuard.release();
- return AdsData(symData, dtData);
- }
- std::ostream& operator<<(std::ostream& s, DatatypeId val)
- {
- static constexpr std::pair<DatatypeId, std::string_view> typenames[] = {
- {DatatypeId::void_, "void"sv}, {DatatypeId::int16_, "int16"sv}, {DatatypeId::int32_, "int32"sv},
- {DatatypeId::float_, "float"sv}, {DatatypeId::double_, "double"sv}, {DatatypeId::int8_, "int8"sv},
- {DatatypeId::uint8_, "uint8"sv}, {DatatypeId::uint16_, "uint16"sv}, {DatatypeId::uint32_, "uint32"sv},
- {DatatypeId::int64_, "int64"sv}, {DatatypeId::uint64_, "uint64"sv}, {DatatypeId::string_, "string"sv},
- {DatatypeId::wstring_, "wstring"sv}, {DatatypeId::ldouble_, "long double"sv}, {DatatypeId::bool_, "bool"sv},
- {DatatypeId::blob_, "blob"sv}, {DatatypeId::maxtypes_, "max_types"sv}};
- auto it =
- std::lower_bound(std::begin(typenames), std::end(typenames), val, [](auto& x, auto& y) { return x.first < y; });
- if (it == std::end(typenames) || it->first != val)
- s << "unknown(" << static_cast<int>(val) << ')';
- else
- s << it->second << '(' << static_cast<int>(val) << ')';
- return s;
- }
- static bool ignoreTypeId = false;
- void verify(std::int32_t adsPort, AmsAddr& amsAddr, const AdsVarData& var, std::string prefix = "")
- {
- auto name = var.name(prefix);
- union
- {
- char buffer[0xFFFF] = {};
- AdsSymbolEntry entry;
- };
- bytes_read_type bytes_read = 0;
- if (auto err = AdsSyncReadWriteReqEx2(adsPort, &amsAddr, ADSIGRP_SYM_INFOBYNAMEEX, 0, sizeof(buffer), buffer,
- static_cast<std::uint32_t>(name.size() + 1), name.data(), &bytes_read);
- err != ADSERR_NOERR)
- {
- std::cout << boost::format("%1$-72s FAILED\n\tSYM_INFOBYNAMEEX %2$#4x\nparsed as:\n") % name % err
- << "\ttype: " << var.type() << '\n'
- << "\tcomment: " << var.comment() << '\n'
- << "\ttypeId: " << var.typeId() << '\n'
- << "\tgroup: " << var.group() << '\n'
- << "\toffset: " << var.offset() << '\n'
- << "\tsize: " << var.size() << '\n';
- return;
- }
- if (var.isReference())
- {
- std::cout << boost::format("%-71s SKIPPED\n") % name;
- return;
- }
- if (var.type() != PADSSYMBOLTYPE(&entry) || var.comment() != PADSSYMBOLCOMMENT(&entry)
- || (var.typeId() != entry.dataType && !ignoreTypeId) || var.group() != entry.iGroup
- || var.offset() != entry.iOffs || var.size() != entry.size)
- {
- std::cout << boost::format("%-72s FAILED\nSYM_INFOBYNAMEEX says:\n") % name
- << "\ttype: " << PADSSYMBOLTYPE(&entry) << '\n'
- << "\tcomment: " << PADSSYMBOLCOMMENT(&entry) << '\n'
- << "\ttypeId: " << DatatypeId(entry.dataType) << '\n'
- << "\tgroup: " << entry.iGroup << '\n'
- << "\toffset: " << entry.iOffs << '\n'
- << "\tsize: " << entry.size << "\nbut parsed as:\n"
- << "\ttype: " << var.type() << '\n'
- << "\tcomment: " << var.comment() << '\n'
- << "\ttypeId: " << var.typeId() << '\n'
- << "\tgroup: " << var.group() << '\n'
- << "\toffset: " << var.offset() << '\n'
- << "\tsize: " << var.size() << '\n';
- }
- else
- std::cout << boost::format("%-76s OK\n") % name;
- }
- void verifySubs(AdsData& plcData, std::int32_t adsPort, AmsAddr& amsAddr, const AdsVarData& var, std::string prefix)
- {
- for (auto sub : var)
- {
- plcData[sub.name(prefix)];
- verify(adsPort, amsAddr, sub, prefix);
- verifySubs(plcData, adsPort, amsAddr, sub, sub.name(prefix));
- }
- }
- int main(int argc, char** argv)
- {
- if (argc < 2)
- {
- std::cout << "usage: " << argv[0] << " <port> [options]\noptions:-i ignore typeId";
- return 1;
- }
- auto port = static_cast<decltype(AmsAddr::port)>(std::stoul(argv[1]));
- if (argc >= 3 && argv[2] == "-i"sv)
- ignoreTypeId = true;
- try
- {
- AdsData plcData = getPlcData(port);
- auto adsPort = AdsPortOpenEx();
- if (adsPort == 0)
- throw std::runtime_error("cannot open ads port");
- auto deleter = [=](auto) { AdsPortCloseEx(adsPort); };
- std::unique_ptr<void, decltype(deleter)> portGuard(nullptr, deleter);
- AmsAddr ams_addr{};
- if (auto err = AdsGetLocalAddressEx(adsPort, &ams_addr); err != ADSERR_NOERR)
- throw std::runtime_error((boost::format("cannot get local ams address: %#4x") % err).str());
- ams_addr.port = port;
- for (auto var : plcData)
- {
- plcData[var.shortName()];
- verify(adsPort, ams_addr, var);
- verifySubs(plcData, adsPort, ams_addr, var, var.shortName());
- }
- }
- catch (std::exception& e)
- {
- std::cout << e.what() << '\n';
- return 1;
- }
- }
Add Comment
Please, Sign In to add comment