-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
1,037 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/** | ||
* @file | ||
* @author Philipp Jungkamp <[email protected]> | ||
* @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC | ||
* @license Apache 2.0 | ||
*********************************************************************************/ | ||
|
||
#pragma once | ||
|
||
#include <string> | ||
#include <optional> | ||
#include <villas/nodes/c37_118/parser.hpp> | ||
#include <villas/node/config.hpp> | ||
#include <villas/node.hpp> | ||
#include <villas/signal.hpp> | ||
|
||
namespace villas { | ||
namespace node { | ||
namespace c37_118 { | ||
|
||
class C37_118 : public Node { | ||
protected: | ||
struct Input { | ||
std::string address; | ||
} input; | ||
|
||
virtual | ||
int _read(struct Sample *smps[], unsigned cnt) override; | ||
|
||
public: | ||
C37_118(const std::string &name = ""); | ||
|
||
virtual | ||
~C37_118() override; | ||
|
||
virtual | ||
int parse(json_t *json, const uuid_t sn_uuid) override; | ||
|
||
virtual | ||
int start() override; | ||
|
||
virtual | ||
int stop() override; | ||
}; | ||
|
||
} /* namespace c37_118 */ | ||
} /* namespace node */ | ||
} /* namespace villas */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
/* Parser for C37-118. | ||
* | ||
* Author: Philipp Jungkamp <[email protected]> | ||
* SPDX-FileCopyrightText: 2014-2024 Institute for Automation of Complex Power Systems, RWTH Aachen University | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <cstring> | ||
#include <optional> | ||
#include <string> | ||
#include <villas/nodes/c37_118/types.hpp> | ||
|
||
namespace villas::node::c37_118::parser { | ||
using namespace villas::node::c37_118::types; | ||
|
||
class Parser { | ||
public: | ||
Parser(Config config = {}); | ||
void set_config(Config config); | ||
Config const *get_config() const; | ||
std::optional<Frame> deserialize(unsigned char const *buffer, | ||
std::size_t length); | ||
std::vector<unsigned char> serialize(Frame const &frame); | ||
|
||
private: | ||
uint16_t config_num_pmu() const; | ||
uint16_t config_format(uint16_t pmu) const; | ||
uint16_t config_phnmr(uint16_t pmu) const; | ||
uint16_t config_annmr(uint16_t pmu) const; | ||
uint16_t config_dgnmr(uint16_t pmu) const; | ||
|
||
template <typename T> void de_copy(T *value, std::size_t count = sizeof(T)) { | ||
if (de_cursor + count > de_end) | ||
throw RuntimeError{"c37_118: broken frame"}; | ||
|
||
std::memcpy((void *)value, de_cursor, count); | ||
de_cursor += count; | ||
} | ||
|
||
template <typename T> | ||
void se_copy(T const *value, std::size_t count = sizeof(T)) { | ||
auto index = se_buffer.size(); | ||
se_buffer.insert(se_buffer.end(), count, 0); | ||
std::memcpy(se_buffer.data() + index, (void const *)value, count); | ||
} | ||
|
||
uint16_t deserialize_uint16_t(); | ||
uint32_t deserialize_uint32_t(); | ||
int16_t deserialize_int16_t(); | ||
float deserialize_float(); | ||
std::string deserialize_name1(); | ||
Phasor deserialize_phasor(uint16_t pmu); | ||
Analog deserialize_analog(uint16_t pmu); | ||
Freq deserialize_freq(uint16_t pmu); | ||
PmuData deserialize_pmu_data(uint16_t pmu); | ||
PmuConfig deserialize_pmu_config_simple(); | ||
Config deserialize_config_simple(); | ||
Config1 deserialize_config1(); | ||
Config2 deserialize_config2(); | ||
Data deserialize_data(); | ||
Header deserialize_header(); | ||
Command deserialize_command(); | ||
std::optional<Frame> try_deserialize_frame(); | ||
|
||
void serialize_uint16_t(const uint16_t &value); | ||
void serialize_uint32_t(const uint32_t &value); | ||
void serialize_int16_t(const int16_t &value); | ||
void serialize_float(const float &value); | ||
void serialize_name1(const std::string &value); | ||
void serialize_phasor(const Phasor &value, uint16_t pmu); | ||
void serialize_analog(const Analog &value, uint16_t pmu); | ||
void serialize_freq(const Freq &value, uint16_t pmu); | ||
void serialize_pmu_data(const PmuData &value, uint16_t pmu); | ||
void serialize_pmu_config_simple(const PmuConfig &value); | ||
void serialize_config_simple(const Config &value); | ||
void serialize_config1(const Config1 &value); | ||
void serialize_config2(const Config2 &value); | ||
void serialize_data(const Data &value); | ||
void serialize_header(const Header &value); | ||
void serialize_command(const Command &value); | ||
void serialize_frame(const Frame &value); | ||
|
||
std::optional<Config> config; | ||
|
||
unsigned char const *de_cursor; | ||
unsigned char const *de_end; | ||
|
||
std::vector<unsigned char> se_buffer; | ||
}; | ||
|
||
uint16_t calculate_crc(unsigned char const *frame, uint16_t size); | ||
|
||
} // namespace villas::node::c37_118::parser |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
#include <array> | ||
#include <complex> | ||
#include <optional> | ||
#include <stdint.h> | ||
#include <type_traits> | ||
#include <variant> | ||
#include <vector> | ||
|
||
namespace villas::node::c37_118::types { | ||
|
||
class Phasor final { | ||
public: | ||
enum Notation { | ||
RectangularInt = 0, | ||
PolarInt, | ||
RectangularFloat, | ||
PolarFloat, | ||
}; | ||
using RectangularInt_t = std::tuple<int16_t, int16_t>; | ||
using PolarInt_t = std::tuple<uint16_t, int16_t>; | ||
using RectangularFloat_t = std::tuple<float, float>; | ||
using PolarFloat_t = std::tuple<float, float>; | ||
using Variant = std::variant<RectangularInt_t, PolarInt_t, RectangularFloat_t, | ||
PolarFloat_t>; | ||
|
||
Phasor() = default; | ||
|
||
Notation notation() const; | ||
std::complex<float> to_complex() const; | ||
static Phasor from_complex(std::complex<float> value, Notation notation); | ||
|
||
template <Notation N, typename Tuple = std::variant_alternative_t<N, Variant>, | ||
typename First = std::tuple_element<0, Tuple>, | ||
typename Second = std::tuple_element<1, Tuple>> | ||
static Phasor make(First first, Second second); | ||
|
||
template <Notation N, typename Tuple = std::variant_alternative_t<N, Variant>> | ||
Tuple get() const; | ||
|
||
private: | ||
Phasor(Variant variant) : variant{std::move(variant)} {} | ||
Variant variant; | ||
}; | ||
|
||
template <Phasor::Notation N, typename Tuple, typename First, typename Second> | ||
Phasor Phasor::make(First first, Second second) { | ||
return Variant{std::in_place_index<N>, first, second}; | ||
} | ||
|
||
template <Phasor::Notation N, typename Tuple> Tuple Phasor::get() const { | ||
return std::get<N>(this->variant); | ||
} | ||
|
||
class Number final { | ||
public: | ||
enum Notation { | ||
Int, | ||
Float, | ||
}; | ||
using Int_t = int16_t; | ||
using Float_t = float; | ||
using Variant = std::variant<Int_t, Float_t>; | ||
|
||
Number() = default; | ||
|
||
Notation notation() const; | ||
float to_float() const; | ||
static Number from_float(float value, Notation notation); | ||
|
||
template <Notation N, typename Value = std::variant_alternative_t<N, Variant>> | ||
static Number make(Value value); | ||
|
||
template <Notation N, typename Value = std::variant_alternative_t<N, Variant>> | ||
Value get() const; | ||
|
||
private: | ||
Number(Variant variant) : variant{std::move(variant)} {} | ||
Variant variant; | ||
}; | ||
|
||
using Analog = Number; | ||
using Freq = Number; | ||
|
||
struct PmuData final { | ||
uint16_t stat; | ||
std::vector<Phasor> phasor; | ||
Freq freq; | ||
Freq dfreq; | ||
std::vector<Analog> analog; | ||
std::vector<uint16_t> digital; | ||
}; | ||
|
||
template <Number::Notation N, typename Value> Number Number::make(Value value) { | ||
return Variant{std::in_place_index<N>, value}; | ||
} | ||
|
||
template <Number::Notation N, typename Value> Value Number::get() const { | ||
return std::get<N>(this->variant); | ||
} | ||
|
||
struct Data final { | ||
std::vector<PmuData> pmus; | ||
}; | ||
|
||
struct Header final { | ||
std::string data; | ||
}; | ||
|
||
struct ChannelInfo final { | ||
std::string nam; | ||
uint32_t unit; | ||
}; | ||
|
||
struct DigitalInfo final { | ||
std::array<std::string, 16> nam; | ||
uint32_t unit; | ||
}; | ||
|
||
struct PmuConfig final { | ||
std::string stn; | ||
uint16_t idcode; | ||
uint16_t format; | ||
std::vector<ChannelInfo> phinfo; | ||
std::vector<ChannelInfo> aninfo; | ||
std::vector<DigitalInfo> dginfo; | ||
uint16_t fnom; | ||
uint16_t cfgcnt; | ||
}; | ||
|
||
struct Config { | ||
uint32_t time_base; | ||
std::vector<PmuConfig> pmus; | ||
uint16_t data_rate; | ||
}; | ||
|
||
class Config1 { | ||
private: | ||
Config inner; | ||
|
||
public: | ||
Config1() = delete; | ||
Config1(Config config) noexcept : inner(config) {} | ||
operator Config&() noexcept {return inner;} | ||
operator Config const&() const noexcept {return inner;} | ||
Config* operator ->() { return &inner; } | ||
Config const* operator ->() const { return &inner; } | ||
}; | ||
|
||
class Config2 { | ||
private: | ||
Config inner; | ||
|
||
public: | ||
Config2() = delete; | ||
Config2(Config config) noexcept : inner(config) {} | ||
operator Config&() noexcept {return inner;} | ||
operator Config const&() const noexcept {return inner;} | ||
Config* operator ->() { return &inner; } | ||
Config const* operator ->() const { return &inner; } | ||
}; | ||
|
||
struct Command final { | ||
uint16_t cmd; | ||
std::vector<unsigned char> ext; | ||
|
||
static constexpr uint16_t DATA_START = 0x1; | ||
static constexpr uint16_t DATA_STOP = 0x2; | ||
static constexpr uint16_t GET_HEADER = 0x3; | ||
static constexpr uint16_t GET_CONFIG1 = 0x4; | ||
static constexpr uint16_t GET_CONFIG2 = 0x5; | ||
//static constexpr uint16_t GET_CONFIG3 = 0x6; | ||
}; | ||
|
||
struct Frame final { | ||
using Variant = std::variant<Data, Header, Config1, Config2, Command>; | ||
|
||
uint16_t version; | ||
uint16_t framesize; | ||
uint16_t idcode; | ||
uint32_t soc; | ||
uint32_t fracsec; | ||
Variant message; | ||
}; | ||
|
||
} // namespace villas::node::c37_118::types |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#include <villas/nodes/c37_118.hpp> | ||
|
||
using namespace villas::node::c37_118; |
Oops, something went wrong.