forked from PLCnext/CppExamples
-
Notifications
You must be signed in to change notification settings - Fork 0
/
DataAccessComponent.hpp
125 lines (106 loc) · 4.34 KB
/
DataAccessComponent.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
///////////////////////////////////////////////////////////////////////////////"
//
// Copyright PHOENIX CONTACT Electronics GmbH
//
///////////////////////////////////////////////////////////////////////////////
#pragma once
#include "Arp/System/Core/Arp.h"
#include "Arp/System/Acf/ComponentBase.hpp"
#include "Arp/System/Acf/IApplication.hpp"
#include "Arp/Plc/Commons/Meta/MetaComponentBase.hpp"
#include "Arp/System/Commons/Logging.h"
#include "Arp/System/Commons/Threading/WorkerThread.hpp"
#include "Arp/Plc/Gds/Services/IDataAccessService.hpp"
namespace DataAccess
{
using namespace Arp;
using namespace Arp::System::Acf;
using namespace Arp::Plc::Commons::Meta;
using namespace Arp::Plc::Gds::Services;
using namespace Arp::System::Commons::Threading;
/// <summary>
/// ###########################
/// Data Access example
/// ###########################
///
/// In this example the following Data Access methods are demonstrated:
///
/// - ReadSingle
/// - WriteSingle
/// - Read
/// - Write
///
/// Variables of both primitive and complex data types (including structs and arrays) are read and written.
///
/// It is assumed that all operations succeed, so return codes are ignored.
/// </summary>
//#acfcomponent
class DataAccessComponent : public ComponentBase, public MetaComponentBase, private Loggable<DataAccessComponent>
{
public: // typedefs
public: // construction/destruction
DataAccessComponent(IApplication& application, const String& name);
virtual ~DataAccessComponent() = default;
public: // IComponent operations
void Initialize() override;
void SubscribeServices()override;
void LoadSettings(const String& settingsPath)override;
void SetupSettings()override;
void PublishServices()override;
void LoadConfig() override;
void SetupConfig() override;
void ResetConfig() override;
void Dispose()override;
void PowerDown()override;
public: // MetaComponentBase operations
void RegisterComponentPorts() override;
private: // data access methods
void StartDataAccess(void);
void StopDataAccess(void);
void AccessData(void);
private: // Plc event handlers
void OnPlcLoaded(void);
void OnPlcStarted(void);
void OnPlcStopping(void);
void OnPlcUnloading(bool onError);
void OnPlcChanging(void);
void OnPlcChanged(bool success);
private: // methods
DataAccessComponent(const DataAccessComponent& arg) = delete;
DataAccessComponent& operator= (const DataAccessComponent& arg) = delete;
public: // static factory operations
static IComponent::Ptr Create(Arp::System::Acf::IApplication& application, const String& name);
private: // fields
// Service thread that reads and writes data and writes log messages
WorkerThread dataAccessThread;
IDataAccessService::Ptr dataAccessServicePtr = nullptr;
int16 Int_IN {0};
int16 Int_OUT {0};
public: /* Ports
=====
Component ports are defined in the following way:
//#attributes(Hidden)
struct Ports
{
//#name(NameOfPort)
//#attributes(Input|Retain|Opc)
Arp::boolean portField = false;
// The GDS name is "<componentName>/NameOfPort" if the struct is declared as Hidden
// otherwise the GDS name is "<componentName>/PORTS.NameOfPort"
};
//#port
Ports ports;
Create one (and only one) instance of this struct.
Apart from this single struct instance, there must be no other Component variables declared with the #port comment.
The only attribute that is allowed on the struct instance is "Hidden", and this is optional.
The struct can contain as many members as necessary.
The #name comment can be applied to each member of the struct, and is optional.
The #name comment defines the GDS name of an individual port element. If omitted, the member variable name is used as the GDS name.
The members of the struct can be declared with any of the attributes allowed for a Program port.
*/
};
inline IComponent::Ptr DataAccessComponent::Create(Arp::System::Acf::IApplication& application, const String& name)
{
return IComponent::Ptr(new DataAccessComponent(application, name));
}
} // end of namespace DataAccess