This sample is a console application with a mini visualisation for the current data point values and configuration. Every time a datapoint value indication is received the view is updated and shows the new value. For it to work properly the complete view must be visible inside the console windows without scrolling. Scrolling or resizing the console window will mess up the writing of the updated datapoint values on the correct position. This sample heavilly relies on the ANSI Escape sequences to move the cursor in the console, if those are not available in your console, this sample will not work as expected.
#include "Helper.h"
#include <iostream>
#include <memory>
using namespace wz::baos::ip;
namespace
{
std::string formatFlags(const protocol::DatapointConfigFlags& flags)
{
std::string result;
result += flags.communication ? "C " : "- ";
result += flags.readFromBus ? "R " : "- ";
result += flags.writeFromBus ? "W " : "- ";
result += flags.transmitToBus ? "T " : "- ";
result += flags.updateResponse ? "U " : "- ";
result += flags.readOnInit ? "I " : "- ";
return result;
}
enum ColumnWidths
{
Id = 6,
DescriptionString = 30,
Flags = 13,
Data = 25
};
class BaosView
{
public:
BaosView(const std::string& ip4Address, std::uint16_t port = 12004)
: device_(ip4Address, port)
{
loadInitialDeviceInfo();
}
public:
void print()
{
std::cout <<
"|" << std::string(ColumnWidths::Id,
'-') <<
"|" << std::string(
ColumnWidths::DPT,
'-') <<
"|"
<< std::string(ColumnWidths::DescriptionString, '-') << "|" << std::string(ColumnWidths::Flags, '-')
<< "|" << std::string(ColumnWidths::Data, '-') << "|" << std::endl;
std::cout << "|" << std::setfill(' ') << std::setw(ColumnWidths::Id) << "Id "
<< "|" << std::setfill(' ') << std::setw(ColumnWidths::DescriptionString) << "Description "
<< "|" << std::setfill(' ') << std::setw(ColumnWidths::Flags) << "Flags "
<< "|" << std::setfill(' ') << std::setw(ColumnWidths::Data) << "Data "
<< "|" << std::endl;
std::cout << "|" << std::setfill(' ') << std::setw(ColumnWidths::Id) << ""
<< "|" << std::setfill(' ') << std::setw(ColumnWidths::DescriptionString) << ""
<< "|" << std::setfill(' ') << std::setw(ColumnWidths::Flags) << "C R W T U I "
<< "|" << std::setfill(' ') << std::setw(ColumnWidths::Data) << "(in hex) "
<< "|" << std::endl;
std::cout <<
"|" << std::string(ColumnWidths::Id,
'-') <<
"|" << std::string(
ColumnWidths::DPT,
'-') <<
"|"
<< std::string(ColumnWidths::DescriptionString, '-') << "|" << std::string(ColumnWidths::Flags, '-')
<< "|" << std::string(ColumnWidths::Data, '-') << "|" << std::endl;
if(dp_configs_.empty())
{
std::cout << "No datapoints configured" << std::endl;
return;
}
for (const auto& item : limitedDps)
{
const std::uint16_t dpId = item.first;
const DatapointConfig& desc = item.second;
lastDpId_ = dpId;
std::string formatedValue = "-- ";
auto iter = values.find(dpId);
if (iter != values.end())
{
formatedValue = wzcpp::rangeToHex(iter->second);
}
std::cout << "|" << std::setfill(' ') << std::setw(ColumnWidths::Id) << dpId << "|" << std::setfill(' ')
<< std::setw(ColumnWidths::DescriptionString) << desc.desc << "|" << std::setfill(' ')
<< std::setw(ColumnWidths::Flags) << formatFlags(desc.flags) << "|" << std::setfill(' ')
<< std::setw(ColumnWidths::Data-1) << formatedValue << " |" << std::endl;
std::cout <<
"|" << std::string(ColumnWidths::Id,
'-') <<
"|" << std::string(
ColumnWidths::DPT,
'-') <<
"|"
<< std::string(ColumnWidths::DescriptionString, '-') << "|" << std::string(ColumnWidths::Flags, '-')
<< "|" << std::string(ColumnWidths::Data, '-') << "|" << std::endl;
}
std::cout << "\u001b[s";
auto omitted = dp_configs_.size() - limitedDps.size();
if(omitted > 0)
{
std::cout << omitted << " Datapoints omitted" << std::endl;
}
}
void watchForIndications()
{
device_.registerDPValueCallback(
{
try
{
for (const auto& item : values)
{
std::uint16_t id = item.first;
this->updateView(id, value);
}
}
catch (const std::exception&)
{
}
});
}
private:
{
auto endDpIter = std::begin(dp_configs_);
if(dp_limit < dp_configs_.size())
{
std::advance(endDpIter, dp_limit);
}
else
{
endDpIter = std::end(dp_configs_);
}
}
void loadInitialDeviceInfo()
{
device_.getStaticInfo();
dp_configs_ = device_.getAllDpConfigurations();
}
std::uint32_t getReverseRowIndexForDpId(std::uint16_t dpId)
{
auto endDpIter = std::begin(dp_configs_);
auto iter = cutConfigs.find(dpId);
return std::distance(iter, cutConfigs.end());
}
{
std::string formatedValue = wzcpp::rangeToHex(value);
std::uint32_t rowIndex = getReverseRowIndexForDpId(dpId);
std::uint32_t cursorUp = (rowIndex * 2);
std::uint32_t cursorRight = 1 + ColumnWidths::Id + 1 +
ColumnWidths::DPT + 1 + ColumnWidths::DescriptionString + 1 +
ColumnWidths::Flags + 1 + 1;
std::cout << "\u001b[u";
std::cout << "\u001b[3B";
if(dpId > lastDpId_)
{
std::cout << "+ Skipped updating: datapoint id(" << dpId <<"): " << wzcpp::rangeToHex(value) << " ";
std::cout << "\u001b[u";
}
else
{
std::cout << "+ Updating the view: datapoint id(" << dpId <<"): " << wzcpp::rangeToHex(value) << " ";
std::cout << "\u001b[u";
std::cout << "\u001b["<< cursorUp << "A";
std::cout << "\u001b[" << cursorRight << "G";
std::cout << "\u001b[0K";
std::cout << "\u001b[36m" << std::setfill(' ') << std::setw(ColumnWidths::Data-1) << formatedValue << "\u001b[39m" << " |";
std::cout << "\u001b[u";
}
}
private:
BaosIp4Device device_;
std::uint16_t lastDpId_{0};
const std::uint32_t dp_limit{5};
};
}
int main(int argc, char* argv[])
{
try
{
std::cout << "\u001b[2J";
std::cout << "\u001b[H";
std::cout << "******************************************" << std::endl;
std::cout << "09_BaosView sample" << std::endl;
std::cout << "******************************************" << std::endl;
std::cout << std::endl;
CommandLineOptions options;
options.parse(argc, argv);
if (options.wasHelpdisplayed())
{
return 0;
}
const std::string ipAddress = options.getIpAddress();
std::cout << " Connection requested for " << ipAddress << std::endl;
BaosView baosView{ipAddress};
BaosIp4Device baosDevice(ipAddress);
baosView.print();
baosView.watchForIndications();
std::cout << "Press [Enter] to exit the application ..." << std::endl;
std::getchar();
std::cout << "\u001b[3B";
std::cout << "Bye ..." << std::endl;
}
catch (const std::exception& e)
{
std::cerr << "Failed: " << e.what() << std::endl;
return -1;
}
return 0;
}
Specialization for a IP v4 BAOSDevice.
Specialization for a TCP IP v4 BAOSConnection.
Global BAOS protocol defines and types.
Global BAOS SDK function and options.
Groups BAOS binary protocol specific types , defines and classes for Indications, Responses etc.
Definition: Defines.h:32
std::map< std::uint16_t, DatapointValue > DatapointValues
A map with datapoint ids as keys and DatapointValue as values.
Definition: Defines.h:35
BAOSLIB_EXPORT std::string dptToString(DPT dpt)
Convert the enum value to a human readable string.
DPT
Enumeration value for the supported datapoint types( DPTs )
Definition: Defines.h:172
wz::baos::Buffer DatapointValue
An type for the DatapointValues.
Definition: Defines.h:33
Global BAOS sdk namespace.
Definition: config.h:62
std::map< std::uint16_t, DatapointConfig > DatapointConfigurations
Definition: BaosDeviceDataTypes.h:212
void setBaosLogLevel(wzcpp::LogLevel level)