Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PMP2-348 : New path connection states #109

Merged
merged 20 commits into from
Feb 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
1d72341
refs #PMP2-277 : Deletion of redundant variable m_connected
Ineo-JFA Dec 4, 2024
9a85307
refs #PMP2-277 Rework of connection states as a finite state automaton
Ineo-JFA Dec 11, 2024
4f1ea72
refs #PMP2-277 : Fix protocol state transitions
Ineo-JFA Dec 13, 2024
bbf39ca
refs #PMP2-277 : Fix BULLE not sent in OUTPUT_CONNECTED
Ineo-JFA Dec 16, 2024
98c7d7e
refs #PMP2-277 : Unit test for new protocol states
Ineo-JFA Dec 17, 2024
297c5f2
refs #PMP2-277 : Moved audit fail triggers
Ineo-JFA Dec 17, 2024
132ed9c
refs #PMP2-277 : Consolidation of protocol states for edge cases
Ineo-JFA Dec 19, 2024
58fb822
refs #PMP2-277 : Updated tests to fit new state transitions
Ineo-JFA Dec 19, 2024
571e307
refs #PMP2-277 : Updated connectionEvent2str
Ineo-JFA Dec 19, 2024
e40cec1
refs #PMP2-277 : Setting invalid timestamps of TSCE in state INPUT_CO…
Ineo-JFA Jan 15, 2025
557a29e
refs #PMP2-277 : Add tempo for init messages
Ineo-JFA Jan 17, 2025
68d7564
refs #PMP2-277 : Unit tests adaptation
Ineo-JFA Jan 24, 2025
fa1bd01
refs #PMP2-277 : Sonarqube quality fixes
Ineo-JFA Feb 3, 2025
e8f3d39
refs #PMP2-277 : Add tempo to ConnectionLossTwoPath
Ineo-JFA Feb 3, 2025
7635f8b
refs #PMP2-277 : Adding a flag for init messages
Ineo-JFA Feb 4, 2025
82816d4
refs #PMP2-277 : Discard un-acknowledged BULLEs
Ineo-JFA Feb 4, 2025
8fecc38
refs PMP2-348 : Move UT specific code
Ineo-JFA Jan 29, 2025
45fefdf
refs #PMP2-348 : New path connection management
Ineo-JFA Jan 31, 2025
c67946b
refs #PMP2-348 : Unit test adaptations
Ineo-JFA Jan 31, 2025
c8195bd
refs #PMP2-348 : Fix double ack in specific case
Ineo-JFA Feb 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion include/hnz.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,11 +179,13 @@ class HNZ {
*/
inline void setDaySection(unsigned char daySection) { m_daySection = daySection; }

#ifdef UNIT_TEST
protected:
/**
* Sends a CG request (reset counters if any was already in progress)
*/
void sendInitialGI();
#endif

private:
// Tells if the plugin is currently running
Expand Down Expand Up @@ -224,7 +226,7 @@ class HNZ {
/**
* Waits for new messages and processes them
*/
void receive(std::shared_ptr<HNZPath> hnz_path_in_use);
void receive(HNZPath* hnz_path_in_use);

/**
* Handle a message: translate the message and send it to Fledge.
Expand Down Expand Up @@ -288,6 +290,7 @@ class HNZ {
unsigned int ts_iv = 0;
unsigned int ts_c = 0;
unsigned int ts_s = 0;
bool empty_timestamp = false; // TSCE with no timestamp, the module HNZtoPivot will fill it artificially
// TS only
bool cg = false;
// TM only
Expand Down
48 changes: 13 additions & 35 deletions include/hnzconf.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include <memory>
#include "rapidjson/document.h"

#define MAXPATHS 2

// Local definition of make_unique as it is only available since C++14 and right now fledge-south-hnz is built with C++11
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
Expand Down Expand Up @@ -149,32 +151,18 @@ class HNZConf {
unsigned int getLastTSAddress() const;

/**
* Get the IP address to remote IEC 104 server (A path)
* Get paths ips as an array of string
*
* @return string
* @return Array of string containing paths ip
*/
string get_ip_address_A() const { return m_ip_A; }
std::array<string, MAXPATHS> get_paths_ip() const { return m_paths_ip; }

/**
* Get the port number to remote IEC 104 server (A path)
* Get paths ports as an array of unsigned int
*
* @return unsigned int
* @return Array of int containing paths ip
*/
unsigned int get_port_A() const { return m_port_A; }

/**
* Get the IP address to remote IEC 104 server (B path)
*
* @return string
*/
string get_ip_address_B() const { return m_ip_B; }

/**
* Get the port number to remote IEC 104 server (B path)
*
* @return unsigned int
*/
unsigned int get_port_B() const { return m_port_B; }
std::array<unsigned int, MAXPATHS> get_paths_port() const { return m_paths_port; }

/**
* Get the remote server station address
Expand All @@ -199,18 +187,10 @@ class HNZConf {
unsigned int get_max_sarm() const { return m_max_sarm; }

/**
* Get the max number of authorized repeats for path A
*
* @return unsigned int
*/
unsigned int get_repeat_path_A() const { return m_repeat_path_A; }

/**
* Get the max number of authorized repeats for path B
*
* Get the max number of authorized repeats for all paths
* @return unsigned int
*/
unsigned int get_repeat_path_B() const { return m_repeat_path_B; }
std::array<unsigned int, MAXPATHS> get_paths_repeat() const { return m_paths_repeat; }

/**
* Get the time in ms allowed for the receiver to acknowledge a frame, after this
Expand Down Expand Up @@ -323,14 +303,12 @@ class HNZConf {
*/
bool m_importDatapoint(const Value &msg);

string m_ip_A, m_ip_B = "";
unsigned int m_port_A = 0;
unsigned int m_port_B = 0;
std::array<string, MAXPATHS> m_paths_ip = {"", ""};
std::array<unsigned int, MAXPATHS> m_paths_port = {0, 0};
std::array<unsigned int, MAXPATHS> m_paths_repeat = {0, 0};
unsigned int m_remote_station_addr = 0;
unsigned int m_inacc_timeout = 0;
unsigned int m_max_sarm = 0;
unsigned int m_repeat_path_A = 0;
unsigned int m_repeat_path_B = 0;
unsigned int m_repeat_timeout = 0;
unsigned int m_anticipation_ratio = 0;
BulleFormat m_test_msg_send;
Expand Down
63 changes: 44 additions & 19 deletions include/hnzconnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,39 +61,44 @@ class HNZConnection {
* commands).
* @return the active path
*/
std::shared_ptr<HNZPath> getActivePath() {
HNZPath* getActivePath() {
std::lock_guard<std::recursive_mutex> lock(m_path_mutex);
return m_active_path;
};

/**
* Get the path in stand-by.
* @return the active path
* Get a pointer to the first passive path found, if any.
* @return a passive path or nullptr
*/
std::shared_ptr<HNZPath> getPassivePath() {
HNZPath* getPassivePath() {
std::lock_guard<std::recursive_mutex> lock(m_path_mutex);
return m_passive_path;
for (HNZPath* path: m_paths)
{
if(path != nullptr && path != m_active_path) return path;
}
return nullptr;
};

/**
* Get both active and passive path (with a single lock)
* @return a path pair (active_path, passive_path)
* Get both active and passive path as an array of pointers (with a single lock)
* @return array of existing paths
*/
std::pair<std::shared_ptr<HNZPath>, std::shared_ptr<HNZPath>> getBothPath() {
std::array<HNZPath*, MAXPATHS> getPaths() {
std::lock_guard<std::recursive_mutex> lock(m_path_mutex);
return std::make_pair(m_active_path, m_passive_path);
return m_paths;
};

/**
* Switch between the active path and passive path. Must be called in case of
* connection problem on the active path.
* Manages the connection state of the different paths.
*/
void switchPath();
void pathConnectionChanged(HNZPath* path, bool isReady);

#ifdef UNIT_TEST
/**
* Send the initial GI message (reset retry counter if it was in progress)
*/
void sendInitialGI();
#endif

/**
* Called to update the current connection status
Expand Down Expand Up @@ -124,6 +129,17 @@ class HNZConnection {
*/
bool isRunning() const { return m_is_running; };

/**
* A running path can extract messages only if it is active, or has at least its input connected.
* */
bool canPathExtractMessage(HNZPath* path){
if(path == nullptr) return false;
if(path == m_active_path){
return true;
}
return path == m_first_input_connected && m_active_path == nullptr;
}

/**
* Returns the name of the Fledge service instanciating this plugin
*/
Expand All @@ -135,20 +151,29 @@ class HNZConnection {
*/
inline void setDaySection(unsigned char daySection) { m_hnz_fledge->setDaySection(daySection); }

/**
* Allows a path to notify that a GI request has been sent
*/
void notifyGIsent();

private:
std::shared_ptr<HNZPath> m_active_path;
std::shared_ptr<HNZPath> m_passive_path;
HNZPath* m_active_path = nullptr;
// First path in protocol state INPUT_CONNECTED, covers edge cases of the protocol
HNZPath* m_first_input_connected = nullptr;
std::array<HNZPath*, MAXPATHS> m_paths = {nullptr, nullptr};
std::recursive_mutex m_path_mutex;
std::shared_ptr<std::thread> m_messages_thread; // Main thread that monitors messages
std::atomic<bool> m_is_running{false}; // If false, the connection thread will stop
uint64_t m_current = 0; // Store the last time requested
uint64_t m_elapsedTimeMs = 0; // Store elapsed time in milliseconds every time m_current is updated
uint64_t m_days_since_epoch = 0;
bool m_sendInitNexConnection = true; // The init messages (time/date/GI) have to be sent

int m_gi_repeat = 0;
long m_gi_start_time = 0;
// Plugin configuration
int gi_repeat_count_max = 0; // time to wait for GI completion
int gi_time_max = 0; // repeat GI for this number of times in case it is
// incomplete
int m_gi_repeat_count_max = 0; // time to wait for GI completion
int m_gi_time_max = 0; // repeat GI for this number of times in case it is incomplete
GIScheduleFormat m_gi_schedule;

int m_repeat_timeout = 0; // time allowed for the receiver to acknowledge a frame
Expand All @@ -169,7 +194,7 @@ class HNZConnection {
* If a message is not acknowledged, then a retransmission request is sent.
* @param path the related path
*/
void m_check_timer(std::shared_ptr<HNZPath> path) const;
void m_check_timer(HNZPath* path);

/**
* Check the state of ongoing GI (General Interrogation) and manage scheduled
Expand All @@ -181,7 +206,7 @@ class HNZConnection {
* Checks that sent command messages have been acknowledged and removes them
* from the sent queue.
*/
void m_check_command_timer();
void m_check_command_timer(HNZPath* path);

/**
* Update the current time and time elapsed since last call to this function
Expand Down
Loading
Loading