Beckhoff / ADS

Beckhoff protocol to communicate with TwinCAT devices.
MIT License
491 stars 193 forks source link

How can I get address of Variable in plc by ads(indexgroup and index offset)? #189

Closed syz007110 closed 10 months ago

syz007110 commented 1 year ago

How can I get address of variable in plc by ads(indexgroup and index offset)? which functionality I want to implement is get address of variable by variable's symbol name , we can get indexgroup and index offset by symbol name , so can we get address of variable in plc by indexgroup and index offset?

pbruenn commented 1 year ago

What is the difference between "symbol name" and "variable"?

syz007110 commented 1 year ago

sorry , i want to use this way to get the address of variable in twincat plc AdsVariable(const AdsDevice& route, const std::string& symbolName) : m_Route(route), m_IndexGroup(ADSIGRP_SYM_VALBYHND), m_Handle(route.GetHandle(symbolName)) {} image

syz007110 commented 1 year ago

how to finde Mapping relationships bewteen variable pointer with indexgroup.indexoffset

pbruenn commented 1 year ago

You can use SymbolAccess

auto device = bhf::ads::SymbolAccess{ gw, netid, port };
const auto map =  device.FetchSymbolEntries();
const auto entry = map.at("bTest");
auto IndexGroup = entry.header.iGroup;
auto IndexOffset = entry.header.iOffs;
syz007110 commented 1 year ago

Thanks, Can I get the pointer of "bTest" ADR(bTest) by IndexGroup and IndexOffset?

You can use SymbolAccess

auto device = bhf::ads::SymbolAccess{ gw, netid, port };
const auto map =  device.FetchSymbolEntries();
const auto entry = map.at("bTest");
auto IndexGroup = entry.header.iGroup;
auto IndexOffset = entry.header.iOffs;
pbruenn commented 1 year ago

I don't know. I just hope TwinCAT has no support for it built in.

If you really want to shoot yourself in the foot just query the value of pTest1 via ADS

syz007110 commented 1 year ago

Many thanks,but i think there are some clues in "AdsLib.cpp " sendto Method use destination address to read by socket; Ads is non-real-time, and I want to improve the efficiency of obtaining variables without using variable binding so i want to get the pointer of variable;

long AdsSyncReadReqEx2(long           port,
                       const AmsAddr* pAddr,
                       uint32_t       indexGroup,
                       uint32_t       indexOffset,
                       uint32_t       bufferLength,
                       void*          buffer,
                       uint32_t*      bytesRead)
{
    ASSERT_PORT_AND_AMSADDR(port, pAddr);
    if (!buffer) {
        return ADSERR_CLIENT_INVALIDPARM;
    }
    try {
        AmsRequest request {
            *pAddr,
            (uint16_t)port,
            AoEHeader::READ,
            bufferLength,
            buffer,
            bytesRead,
            sizeof(AoERequestHeader)
        };
        request.frame.prepend(AoERequestHeader {
            indexGroup,
            indexOffset,
            bufferLength
        });
        return GetRouter().AdsRequest(request);
    } catch (const std::bad_alloc&) {
        return GLOBALERR_NO_MEMORY;
    }
}
size_t Socket::write(const Frame& frame) const
{
    if (frame.size() > std::numeric_limits<int>::max()) {
        LOG_ERROR("frame length: " << frame.size() << " exceeds maximum length for sockets");
        return 0;
    }

    const int bufferLength = static_cast<int>(frame.size());
    const char* const buffer = reinterpret_cast<const char*>(frame.data());
    const int status = **sendto**(m_Socket, buffer, bufferLength, 0, m_DestAddr, m_DestAddrLen);

    if (SOCKET_ERROR == status) {
        LOG_ERROR("write frame failed with error: " << std::strerror(WSAGetLastError()));
        return 0;
    }
    return status;
}

Thanks for your answer again !