#pragma once #include "Arp/System/Core/Arp.h" #include "Arp/System/Acf/ComponentBase.hpp" #include "Arp/System/Acf/IApplication.hpp" #include "Arp/Plc/Commons/Esm/ProgramComponentBase.hpp" #include "StorageDBComponentProgramProvider.hpp" #include "Arp/Plc/Commons/Meta/MetaLibraryBase.hpp" #include "Arp/System/Commons/Logging.h" #include "Arp/System/Acf/IControllerComponent.hpp" #include #include #include namespace StorageDB { using namespace Arp; using namespace Arp::System::Acf; using namespace Arp::Plc::Commons::Esm; using namespace Arp::Plc::Commons::Meta; //#component //class StorageDBComponent : public ComponentBase, public ProgramComponentBase, private Loggable class StorageDBComponent : public ComponentBase, public IControllerComponent, public ProgramComponentBase, private Loggable { public: // typedefs public: // construction/destruction StorageDBComponent(IApplication& application, const String& name); virtual ~StorageDBComponent() = default; public: // IComponent operations void Initialize() override; void LoadConfig() override; void SetupConfig() override; void ResetConfig() override; public: // IControllerComponent operations void Start(void) override; void Stop(void) override; public: // ProgramComponentBase operations void RegisterComponentPorts() override; void WriteToDB(); private: // methods StorageDBComponent(const StorageDBComponent& arg) = delete; StorageDBComponent& operator= (const StorageDBComponent& arg) = delete; public: // static factory operations static IComponent::Ptr Create(Arp::System::Acf::IApplication& application, const String& name); private: // fields StorageDBComponentProgramProvider programProvider; WorkerThread workerThread; private: // static fields static const int workerThreadIdleTime = 10; // 10 ms 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 "/NameOfPort" if the struct is declared as Hidden // otherwise the GDS name is "/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. */ //#port //#attributes(Input) int16 control = 0; //#port //#attributes(Input) int16 intArray[10] {}; // INT in PLCnext Engineer //#port //#attributes(Input) float32 floatArray[10] {}; // REAL in PLCnext Engineer //#port //#attributes(Output) int16 status = 0; }; inline IComponent::Ptr StorageDBComponent::Create(Arp::System::Acf::IApplication& application, const String& name) { return IComponent::Ptr(new StorageDBComponent(application, name)); } /////////////////////////////////////////////////////////////////////////////// // inline methods of class MyComponent inline StorageDBComponent::DBComponent(IApplication& application, const String& name) : ComponentBase(application, ::CppDB::CppDBLibrary::GetInstance(), name, ComponentCategory::Custom) , programProvider(*this) , workerThread(make_delegate(this, &StorageDBComponent::WriteToDB), workerThreadIdleTime, "MyProject.WriteToDatabase") // WorkerThread , ProgramComponentBase(::CppDB::CppDBLibrary::GetInstance().GetNamespace(), programProvider) {} } // end of namespace StorageDB