144 lines
4.5 KiB
C++
144 lines
4.5 KiB
C++
![]() |
// SPDX-License-Identifier: MIT
|
||
|
/**
|
||
|
Copyright (c) 2015 - 2021 Beckhoff Automation GmbH & Co. KG
|
||
|
*/
|
||
|
|
||
|
#include "AdsLib.h"
|
||
|
#include "AdsNotificationOOI.h"
|
||
|
#include "AdsVariable.h"
|
||
|
|
||
|
#include <array>
|
||
|
#include <cstring>
|
||
|
#include <iostream>
|
||
|
#include <iomanip>
|
||
|
|
||
|
using ExampleDatatype = uint8_t;
|
||
|
|
||
|
static void NotifyCallback(const AmsAddr* pAddr, const AdsNotificationHeader* pNotification, uint32_t hUser)
|
||
|
{
|
||
|
ExampleDatatype data{};
|
||
|
std::memcpy(&data, pNotification + 1, std::min<size_t>(sizeof(data), pNotification->cbSampleSize));
|
||
|
std::cout << std::setfill('0') <<
|
||
|
"NetId: " << pAddr->netId <<
|
||
|
" hUser 0x" << std::hex << hUser <<
|
||
|
" sample time: " << std::dec << pNotification->nTimeStamp <<
|
||
|
" sample size: " << std::dec << pNotification->cbSampleSize <<
|
||
|
" value:" << " 0x" << std::hex << +data <<
|
||
|
'\n';
|
||
|
}
|
||
|
|
||
|
static void notificationExample(std::ostream& out, const AdsDevice& route)
|
||
|
{
|
||
|
const AdsNotificationAttrib attrib = {
|
||
|
sizeof(ExampleDatatype),
|
||
|
ADSTRANS_SERVERCYCLE,
|
||
|
0,
|
||
|
{4000000}
|
||
|
};
|
||
|
AdsNotification notification { route, 0x4020, 4, attrib, &NotifyCallback, 0xDEADBEEF };
|
||
|
|
||
|
out << "Hit ENTER to stop notifications\n";
|
||
|
std::cin.ignore();
|
||
|
}
|
||
|
|
||
|
static void notificationByNameExample(std::ostream& out, const AdsDevice& route)
|
||
|
{
|
||
|
const AdsNotificationAttrib attrib = {
|
||
|
sizeof(ExampleDatatype),
|
||
|
ADSTRANS_SERVERCYCLE,
|
||
|
0,
|
||
|
{4000000}
|
||
|
};
|
||
|
|
||
|
out << __FUNCTION__ << "():\n";
|
||
|
AdsNotification notification { route, "MAIN.byByte[4]", attrib, &NotifyCallback, 0xBEEFDEAD };
|
||
|
|
||
|
out << "Hit ENTER to stop by name notifications\n";
|
||
|
std::cin.ignore();
|
||
|
}
|
||
|
|
||
|
static void readExample(std::ostream& out, const AdsDevice& route)
|
||
|
{
|
||
|
AdsVariable<uint8_t> readVar {route, 0x4020, 0};
|
||
|
|
||
|
out << __FUNCTION__ << "():\n";
|
||
|
for (size_t i = 0; i < 8; ++i) {
|
||
|
out << "ADS read " << std::hex << (uint32_t)readVar << '\n';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void readByNameExample(std::ostream& out, const AdsDevice& route)
|
||
|
{
|
||
|
AdsVariable<uint8_t> readVar {route, "MAIN.byByte[4]"};
|
||
|
|
||
|
out << __FUNCTION__ << "():\n";
|
||
|
for (size_t i = 0; i < 8; ++i) {
|
||
|
out << "ADS read " << std::hex << (uint32_t)readVar << '\n';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void readWriteExample(std::ostream& out, const AdsDevice& route)
|
||
|
{
|
||
|
AdsVariable<uint8_t> simpleVar {route, "MAIN.byByte[0]"};
|
||
|
AdsVariable<uint8_t> validation {route, "MAIN.byByte[0]"};
|
||
|
|
||
|
out << __FUNCTION__ << "():\n";
|
||
|
simpleVar = 0xA5;
|
||
|
out << "Wrote " << 0xA5 << " to MAIN.byByte and read " << (uint32_t)validation << " back\n";
|
||
|
simpleVar = 0x5A;
|
||
|
out << "Wrote " << (uint32_t)simpleVar << " to MAIN.byByte and read " << (uint32_t)validation << " back\n";
|
||
|
}
|
||
|
|
||
|
static void readWriteArrayExample(std::ostream& out, const AdsDevice& route)
|
||
|
{
|
||
|
static const std::array<uint8_t, 4> arrayToWrite = { 1, 2, 3, 4 };
|
||
|
AdsVariable<std::array<uint8_t, 4> > arrayVar {route, "MAIN.byByte"};
|
||
|
arrayVar = arrayToWrite;
|
||
|
std::array<uint8_t, 4> readArray = arrayVar;
|
||
|
out << "Wrote array with first value " << (uint32_t)arrayToWrite[0] << " and last value " <<
|
||
|
(uint32_t)arrayToWrite[3] << "\n";
|
||
|
out << "Read back array with first value " << (uint32_t)readArray[0] << " and last value " <<
|
||
|
(uint32_t)readArray[3] << "\n";
|
||
|
}
|
||
|
|
||
|
static void readStateExample(std::ostream& out, const AdsDevice& route)
|
||
|
{
|
||
|
const auto state = route.GetState();
|
||
|
|
||
|
out << "ADS state: " << std::dec << (uint16_t)state.ads << " devState: " << std::dec << (uint16_t)state.device <<
|
||
|
'\n';
|
||
|
}
|
||
|
|
||
|
static void runExample(std::ostream& out)
|
||
|
{
|
||
|
static const AmsNetId remoteNetId { 192, 168, 129, 26, 1, 1 };
|
||
|
// static const char remoteIpV4[] = "ads-server";
|
||
|
static const char remoteIpV4[] = "192.168.129.26";
|
||
|
|
||
|
// uncomment and adjust if automatic AmsNetId deduction is not working as expected
|
||
|
bhf::ads::SetLocalAddress({192, 168, 112, 34, 1, 1});
|
||
|
|
||
|
AdsDevice route {remoteIpV4, remoteNetId, AMSPORT_R0_PLC_TC3};
|
||
|
notificationExample(out, route);
|
||
|
notificationByNameExample(out, route);
|
||
|
readExample(out, route);
|
||
|
readByNameExample(out, route);
|
||
|
readWriteExample(out, route);
|
||
|
readWriteArrayExample(out, route);
|
||
|
readStateExample(out, route);
|
||
|
}
|
||
|
|
||
|
int main()
|
||
|
{
|
||
|
try {
|
||
|
runExample(std::cout);
|
||
|
} catch (const AdsException& ex) {
|
||
|
std::cout << "Error: " << ex.errorCode << "\n";
|
||
|
std::cout << "AdsException message: " << ex.what() << "\n";
|
||
|
} catch (const std::runtime_error& ex) {
|
||
|
std::cout << ex.what() << '\n';
|
||
|
}
|
||
|
std::cout << "Hit ENTER to continue\n";
|
||
|
std::cin.ignore();
|
||
|
}
|