forked from PLCnext/CppExamples
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSubscriptionsComponent3.hpp
148 lines (124 loc) · 5.57 KB
/
SubscriptionsComponent3.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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
///////////////////////////////////////////////////////////////////////////////"
//
// 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/ISubscriptionService.hpp"
namespace Subscriptions
{
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>
/// ###########################################
/// Read complex variable subscription example
/// ###########################################
///
/// This example focuses on how to read complex variable data (structures and arrays) from a subscription.
///
/// Therefore one complex variable ('Arp.Plc.Eclr/DataProducer100ms.counter') is added to the subscription.
/// Afterwards the read values including the time stamps are printed to the system log.
/// The complex variable has the following type:
///
/// struct SampleStruct
/// {
/// uint16 varUInt16 = false;
/// bool varBool = false;
/// uint16 varUInt16Array_5[5];
/// };
///
/// It is assumed that all operations succeed, so related return codes are ignored.
///
/// Take a look at the other examples or the subscription SDK reference for more information.
/// </summary>
//#acfcomponent
class SubscriptionsComponent3 : public ComponentBase, public MetaComponentBase, private Loggable<SubscriptionsComponent3>
{
public: // typedefs
public: // construction/destruction
SubscriptionsComponent3(IApplication& application, const String& name);
virtual ~SubscriptionsComponent3() = 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: // subscription methods
void SetupSubscription(void);
void ResetSubscription(void);
void StartSubscription(void);
void StopSubscription(void);
void LogSubscription(void)const;
void LogValues(IRscReadEnumerator<RscVariant<512>>& readEnumerator);
void LogVariant(const RscVariant<512>& value, std::ostream& os)const;
void LogValue(const RscVariant<512>& variant, std::ostream& os)const;
void LogArray(RscArrayReader& arrayReader, std::ostream& os)const;
void LogStruct(RscStructReader<512>& structReader, std::ostream& os)const;
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
SubscriptionsComponent3(const SubscriptionsComponent3& arg) = delete;
SubscriptionsComponent3& operator= (const SubscriptionsComponent3& arg) = delete;
public: // static factory operations
static IComponent::Ptr Create(Arp::System::Acf::IApplication& application, const String& name);
private: // fields
// Service thread that reads the data from the subscription and writes it to the system log
WorkerThread subscriptionThread;
ISubscriptionService::Ptr subscriptionServicePtr = nullptr;
// The 'subscriptionId' is the ID of a created subscription.
// A valid value is greater than 0, so the member variable is initialized with 0, meaning uninitialized.
uint32 subscriptionId = 0;
// Delegate function which reads the data and writes it to the system log.
ISubscriptionService::ReadValuesValuesDelegate readSubscriptionValuesDelegate;
private: // static fields
static const String complexVarName;
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 SubscriptionsComponent3::Create(Arp::System::Acf::IApplication& application, const String& name)
{
return IComponent::Ptr(new SubscriptionsComponent3(application, name));
}
} // end of namespace Subscriptions