Skip to main content

C++ Класи Підтримки

У загальній бібліотеці, яка є частиною кожного плагіна Fledge, існує ряд класів підтримки.

Зчитування (Reading)

Клас Reading і пов’язані з ним класи Datapoint і DatapointValue забезпечують механізм у класах C++ для керування зчитаними даними активів. Загальнодоступна частина класу Reading наразі визначається наступним чином;

class Reading {
public:
Reading(const std::string& asset, Datapoint *value);
Reading(const std::string& asset, std::vector<Datapoint *> values);
Reading(const std::string& asset, std::vector<Datapoint *> values, const std::string& ts);
Reading(const Reading& orig);

~Reading();
void addDatapoint(Datapoint *value);
Datapoint *removeDatapoint(const std::string& name);
std::string toJSON(bool minimal = false) const;
std::string getDatapointsJSON() const;
// Return AssetName
const std::string& getAssetName() const { return m_asset; };
// Set AssetName
void setAssetName(std::string assetName) { m_asset = assetName; };
unsigned int getDatapointCount() { return m_values.size(); };
void removeAllDatapoints();
// Return Reading datapoints
const std::vector<Datapoint *> getReadingData() const { return m_values; };
// Return reference to Reading datapoints
std::vector<Datapoint *>& getReadingData() { return m_values; };
unsigned long getId() const { return m_id; };
unsigned long getTimestamp() const { return (unsigned long)m_timestamp.tv_sec; };
unsigned long getUserTimestamp() const { return (unsigned long)m_userTimestamp.tv_sec; };
void setId(unsigned long id) { m_id = id; };
void setTimestamp(unsigned long ts) { m_timestamp.tv_sec = (time_t)ts; };
void setTimestamp(struct timeval tm) { m_timestamp = tm; };
void setTimestamp(const std::string& timestamp);
void getTimestamp(struct timeval *tm) { *tm = m_timestamp; };
void setUserTimestamp(unsigned long uTs) { m_userTimestamp.tv_sec = (time_t)uTs; };
void setUserTimestamp(struct timeval tm) { m_userTimestamp = tm; };
void setUserTimestamp(const std::string& timestamp);
void getUserTimestamp(struct timeval *tm) { *tm = m_userTimestamp; };

typedef enum dateTimeFormat { FMT_DEFAULT, FMT_STANDARD, FMT_ISO8601 } readingTimeFormat;

// Return Reading asset time - ts time
const std::string getAssetDateTime(readingTimeFormat datetimeFmt = FMT_DEFAULT, bool addMs = true) const;
// Return Reading asset time - user_ts time
const std::string getAssetDateUserTime(readingTimeFormat datetimeFmt = FMT_DEFAULT, bool addMs = true) const;
}

Клас Reading містить ряд елементів, які відображаються в JSON-представлення даних, що надсилаються до сховища Fledge і використовуються різними сервісами та плагінами всередині Fledge.

  • Asset Name: Назва активу. Ім'я активу задається в конструкторі зчитування і отримується за допомогою методу getAssetName().
  • Timestamp: Мітка часу, коли читання було вперше побачено у Fledge.
  • User Timestamp: Мітка часу для фактичних даних у зчитуванні. Вона може відрізнятися від значення мітки часу, якщо пристрій сам може надавати значення мітки часу.
  • Datapoints: Фактичні дані зчитування, що зберігаються у класі Datapoint.

Клас Datapoint надає ім'я для кожної точки даних у межах Reading та дані тегованого типу для значення зчитування. Загальнодоступне визначення класу Datapoint є наступним;

class Datapoint {
public:
/**
* Construct with a data point value
*/
Datapoint(const std::string& name, DatapointValue& value) : m_name(name), m_value(value);
~Datapoint();
/**
* Return asset reading data point as a JSON
* property that can be included within a JSON
* document.
*/
std::string toJSONProperty();
const std::string getName() const;
void setName(std::string name);
const DatapointValue getData() const;
DatapointValue& getData();
}

Тісно пов'язаний з Datapoint є DatapointValue, який використовує об'єднання тегів для зберігання значень. Загальнодоступне визначення DatapointValue наступне;

class DatapointValue {
public:
/**
* Construct with a string
*/
DatapointValue(const std::string& value)
{
m_value.str = new std::string(value);
m_type = T_STRING;
};
/**
* Construct with an integer value
*/
DatapointValue(const long value)
{
m_value.i = value;
m_type = T_INTEGER;
};
/**
* Construct with a floating point value
*/
DatapointValue(const double value)
{
m_value.f = value;
m_type = T_FLOAT;
};
/**
* Construct with an array of floating point values
*/
DatapointValue(const std::vector<double>& values)
{
m_value.a = new std::vector<double>(values);
m_type = T_FLOAT_ARRAY;
};

/**
* Construct with an array of Datapoints
*/
DatapointValue(std::vector<Datapoint*>*& values, bool isDict)
{
m_value.dpa = values;
m_type = isDict? T_DP_DICT : T_DP_LIST;
}

/**
* Construct with an Image
*/
DatapointValue(const DPImage& value)
{
m_value.image = new DPImage(value);
m_type = T_IMAGE;
}

/**
* Construct with a DataBuffer
*/
DatapointValue(const DataBuffer& value)
{
m_value.dataBuffer = new DataBuffer(value);
m_type = T_DATABUFFER;
}

/**
* Construct with an Image Pointer, the
* image becomes owned by the datapointValue
*/
DatapointValue(DPImage *value)
{
m_value.image = value;
m_type = T_IMAGE;
}

/**
* Construct with a DataBuffer
*/
DatapointValue(DataBuffer *value)
{
m_value.dataBuffer = value;
m_type = T_DATABUFFER;
}

/**
* Construct with a 2 dimensional array of floating point values
*/
DatapointValue(const std::vector< std::vector<double> >& values)
{
m_value.a2d = new std::vector< std::vector<double> >();
for (auto row : values)
{
m_value.a2d->push_back(std::vector<double>(row));
}
m_type = T_2D_FLOAT_ARRAY;
};

/**
* Copy constructor
*/
DatapointValue(const DatapointValue& obj);

/**
* Assignment Operator
*/
DatapointValue& operator=(const DatapointValue& rhs);

/**
* Destructor
*/
~DatapointValue();


/**
* Set the value of a datapoint, this may
* also cause the type to be changed.
* @param value An integer value to set
*/
void setValue(long value)
{
m_value.i = value;
m_type = T_INTEGER;
}

/**
* Set the value of a datapoint, this may
* also cause the type to be changed.
* @param value A floating point value to set
*/
void setValue(double value)
{
m_value.f = value;
m_type = T_FLOAT;
}

/** Set the value of a datapoint to be an image
* @param value The image to set in the data point
*/
void setValue(const DPImage& value)
{
m_value.image = new DPImage(value);
m_type = T_IMAGE;
}

/**
* Return the value as a string
*/
std::string toString() const;

/**
* Return string value without trailing/leading quotes
*/
std::string toStringValue() const { return *m_value.str; };

/**
* Return long value
*/
long toInt() const { return m_value.i; };
/**
* Return double value
*/
double toDouble() const { return m_value.f; };

// Supported Data Tag Types
typedef enum DatapointTag
{
T_STRING,
T_INTEGER,
T_FLOAT,
T_FLOAT_ARRAY,
T_DP_DICT,
T_DP_LIST,
T_IMAGE,
T_DATABUFFER,
T_2D_FLOAT_ARRAY
} dataTagType;

/**
* Return the Tag type
*/
dataTagType getType() const
{
return m_type;
}

std::string getTypeStr() const
{
switch(m_type)
{
case T_STRING: return std::string("STRING");
case T_INTEGER: return std::string("INTEGER");
case T_FLOAT: return std::string("FLOAT");
case T_FLOAT_ARRAY: return std::string("FLOAT_ARRAY");
case T_DP_DICT: return std::string("DP_DICT");
case T_DP_LIST: return std::string("DP_LIST");
case T_IMAGE: return std::string("IMAGE");
case T_DATABUFFER: return std::string("DATABUFFER");
case T_2D_FLOAT_ARRAY: return std::string("2D_FLOAT_ARRAY");
default: return std::string("INVALID");
}
}

/**
* Return array of datapoints
*/
std::vector<Datapoint*>*& getDpVec()
{
return m_value.dpa;
}

/**
* Return array of float
*/
std::vector<double>*& getDpArr()
{
return m_value.a;
}

/**
* Return 2D array of float
*/
std::vector<std::vector<double> >*& getDp2DArr()
{
return m_value.a2d;
}

/**
* Return the Image
*/
DPImage *getImage()
{
return m_value.image;
}

/**
* Return the DataBuffer
*/
DataBuffer *getDataBuffer()
{
return m_value.dataBuffer;
}
};

DatapointValue може зберігати дані в кількох типах

TypeC++ Representation
T_STRINGPointer to std::string
T_INTEGERlong
T_FLOATdouble
T_FLOAT_ARRAYPointer to std::vector<double>
T_2D_FLOAT_ARRAYPointer to std::vector<std::vector<double>>
T_DP_DICTPointer to std::vector<Datapoint *>
T_DP_LISTPointer to std::vector<Datapoint *>
T_IMAGEPointer to DPImage
T_DATABUFFERPointer to DataBuffer

Configuration Category

Клас ConfigCategory є допоміжним класом для керування конфігураційною інформацією у плагіні і передається до точок входу плагіна. Загальнодоступне визначення класу наступне;

class ConfigCategory {
public:
enum ItemType {
UnknownType,
StringItem,
EnumerationItem,
JsonItem,
BoolItem,
NumberItem,
DoubleItem,
ScriptItem,
CategoryType,
CodeItem
};

ConfigCategory(const std::string& name, const std::string& json);
ConfigCategory() {};
ConfigCategory(const ConfigCategory& orig);
~ConfigCategory();
void addItem(const std::string& name, const std::string description,
const std::string& type, const std::string def,
const std::string& value);
void addItem(const std::string& name, const std::string description,
const std::string def, const std::string& value,
const std::vector<std::string> options);
void removeItems();
void removeItemsType(ItemType type);
void keepItemsType(ItemType type);
bool extractSubcategory(ConfigCategory &subCategories);
void setDescription(const std::string& description);
std::string getName() const;
std::string getDescription() const;
unsigned int getCount() const;
bool itemExists(const std::string& name) const;
bool setItemDisplayName(const std::string& name, const std::string& displayName);
std::string getValue(const std::string& name) const;
std::string getType(const std::string& name) const;
std::string getDescription(const std::string& name) const;
std::string getDefault(const std::string& name) const;
bool setDefault(const std::string& name, const std::string& value);
std::string getDisplayName(const std::string& name) const;
std::vector<std::string> getOptions(const std::string& name) const;
std::string getLength(const std::string& name) const;
std::string getMinimum(const std::string& name) const;
std::string getMaximum(const std::string& name) const;
bool isString(const std::string& name) const;
bool isEnumeration(const std::string& name) const;
bool isJSON(const std::string& name) const;
bool isBool(const std::string& name) const;
bool isNumber(const std::string& name) const;
bool isDouble(const std::string& name) const;
bool isDeprecated(const std::string& name) const;
std::string toJSON(const bool full=false) const;
std::string itemsToJSON(const bool full=false) const;
ConfigCategory& operator=(ConfigCategory const& rhs);
ConfigCategory& operator+=(ConfigCategory const& rhs);
void setItemsValueFromDefault();
void checkDefaultValuesOnly() const;
std::string itemToJSON(const std::string& itemName) const;
enum ItemAttribute { ORDER_ATTR, READONLY_ATTR, MANDATORY_ATTR, FILE_ATTR};
std::string getItemAttribute(const std::string& itemName,
ItemAttribute itemAttribute) const;
}

Хоча ConfigCategory є складним класом, лише деякі з методів зазвичай використовуються у плагіні

  • itemExists: - використовується для перевірки, чи існує очікуваний елемент конфігурації у категорії конфігурації.
  • getValue: - повертає значення елемента конфігурації з категорії конфігурації
  • isBool: - перевіряє, чи елемент конфігурації має логічний тип
  • isNumber: - перевіряє, чи елемент конфігурації є числом
  • isDouble: - перевіряє, чи елемент конфігурації допустимо представляти як double
  • isString: - перевіряє, чи елемент конфігурації є рядком

Logger

Клас Logger використовується для запису записів до системи syslog у Fledge. Існує єдиний екземпляр Logger, який можна отримати за допомогою наступного фрагмента коду;

Logger *logger = Logger::getLogger();
logger->error("An error has occurred within the plugin processing");

Після цього можна записувати повідомлення на одному з п'яти різних рівнів журналу: debug, info, warn, error або fatal. Повідомлення можна записувати за допомогою стандартних рядків форматування printf. Загальнодоступне визначення класу Logger наступне;

class Logger {
public:
Logger(const std::string& application);
~Logger();
static Logger *getLogger();
void debug(const std::string& msg, ...);
void printLongString(const std::string&);
void info(const std::string& msg, ...);
void warn(const std::string& msg, ...);
void error(const std::string& msg, ...);
void fatal(const std::string& msg, ...);
void setMinLevel(const std::string& level);
};

Різні рівні журналу слід використовувати наступним чином:

  • debug: слід використовувати для виведення повідомлень, які стосуються лише програміста, який налагоджує плагін.
  • info: слід використовувати для інформації, яка є важливою для кінцевих користувачів, але зазвичай не повинна записуватися до журналу.
  • warn: слід використовувати для попереджувальних повідомлень, які зазвичай записуються до журналу, але відображають стан, який не перешкоджає роботі плагіна.
  • error: слід використовувати для умов, які спричиняють тимчасовий збій в обробці у плагіні.
  • fatal: слід використовувати для умов, які спричиняють постійний збій у роботі плагіна, що може вимагати перезапуску мікросервісу для вирішення проблеми.