edouard@3937: /*
edouard@3937:     Copyright Edouard TISSERANT 2024
edouard@3937:     See COPYING for details
edouard@3937: */
edouard@3937: 
edouard@3937: #if !defined(_PLCObject_hpp_)
edouard@3937: #define _PLCObject_hpp_
edouard@3937: 
edouard@3940: #include <map>
edouard@3940: #include <vector>
edouard@3945: #include <mutex>
edouard@3945: #include <thread>
edouard@3949: 
edouard@3940: #include "blob.hpp"
edouard@3940: 
edouard@3937: #include "erpc_PLCObject_interface.hpp"
edouard@3937: 
edouard@3937: using namespace erpcShim;
edouard@3937: 
edouard@3940: #define FOR_EACH_PLC_SYMBOLS_DO(ACTION) \
edouard@3940:     ACTION(PLC_ID)\
edouard@3940:     ACTION(startPLC)\
edouard@3940:     ACTION(stopPLC)\
edouard@3940:     ACTION(ResetDebugVariables)\
edouard@3940:     ACTION(RegisterDebugVariable)\
edouard@3940:     ACTION(FreeDebugData)\
edouard@3940:     ACTION(GetDebugData)\
edouard@3940:     ACTION(suspendDebug)\
edouard@3949:     ACTION(resumeDebug)\
edouard@3940:     ACTION(ResetLogCount)\
edouard@3940:     ACTION(GetLogCount)\
edouard@3940:     ACTION(LogMessage)\
edouard@3940:     ACTION(GetLogMessage)
edouard@3940: 
edouard@3949: extern "C" {   
edouard@3949:     typedef struct s_PLCSyms{
edouard@3949:         uint8_t *PLC_ID;
edouard@3949:         int (*startPLC)(int argc,char **argv);
edouard@3949:         int (*stopPLC)(void);
edouard@3949:         void (*ResetDebugVariables)(void);
edouard@3949:         int (*RegisterDebugVariable)(unsigned int idx, void* force, size_t force_size);
edouard@3949:         void (*FreeDebugData)(void);
edouard@3949:         int (*GetDebugData)(unsigned int *tick, unsigned int *size, void **buffer);
edouard@3949:         int (*suspendDebug)(int disable);
edouard@3949:         void (*resumeDebug)(void);
edouard@3949:         void (*ResetLogCount)(void);
edouard@3949:         uint32_t (*GetLogCount)(uint8_t level);
edouard@3949:         int (*LogMessage)(uint8_t level, char* buf, uint32_t size);
edouard@3949:         uint32_t (*GetLogMessage)(uint8_t level, uint32_t msgidx, char* buf, uint32_t max_size, uint32_t* tick, uint32_t* tv_sec, uint32_t* tv_nsec);
edouard@3949:     } PLCSyms;
edouard@3949: }
edouard@3937: class PLCObject : public BeremizPLCObjectService_interface
edouard@3937: {
edouard@3937:     public:
edouard@3937: 
edouard@3940:         PLCObject(void);
edouard@3937:         ~PLCObject(void);
edouard@3937: 
edouard@3940:         // ERPC interface
edouard@3940:         uint32_t AppendChunkToBlob(const binary_t * data, const binary_t * blobID, binary_t * newBlobID);
edouard@3940:         uint32_t GetLogMessage(uint8_t level, uint32_t msgID, log_message * message);
edouard@3940:         uint32_t GetPLCID(PSKID * plcID);
edouard@3940:         uint32_t GetPLCstatus(PLCstatus * status);
edouard@3940:         uint32_t GetTraceVariables(uint32_t debugToken, TraceVariables * traces);
edouard@3940:         uint32_t MatchMD5(const char * MD5, bool * match);
edouard@3940:         uint32_t NewPLC(const char * md5sum, const binary_t * plcObjectBlobID, const list_extra_file_1_t * extrafiles, bool * success);
edouard@3940:         uint32_t PurgeBlobs(void);
edouard@3940:         uint32_t RepairPLC(void);
edouard@3940:         uint32_t ResetLogCount(void);
edouard@3940:         uint32_t SeedBlob(const binary_t * seed, binary_t * blobID);
edouard@3945:         uint32_t SetTraceVariablesList(const list_trace_order_1_t * orders, int32_t * debugtoken);
edouard@3940:         uint32_t StartPLC(void);
edouard@3940:         uint32_t StopPLC(bool * success);
edouard@4032:         uint32_t ExtendedCall(const char * method, const binary_t * argument, binary_t * answer);
edouard@3940: 
edouard@3977:         // Public interface used by runtime
edouard@3977:         uint32_t AutoLoad();
edouard@3977:         uint32_t LogMessage(uint8_t level, std::string message);
edouard@3977: 
edouard@3940:     private:
edouard@3940:         // A map of all the blobs
edouard@3940:         std::map<std::vector<uint8_t>, Blob*> m_mapBlobIDToBlob;
edouard@3940: 
edouard@3940:         // PLC object library handle
edouard@3940:         void * m_handle;
edouard@3940: 
edouard@3945:         // Shared object mutex
edouard@3945:         std::mutex m_PLClibMutex;
edouard@3945: 
edouard@3940:         // Symbols resolved from the PLC object
edouard@3940:         PLCSyms m_PLCSyms;
edouard@3940: 
edouard@3940:         // argc and argv for the PLC object
edouard@3940:         int m_argc;
edouard@3940:         char ** m_argv;
edouard@3940: 
edouard@3940:         // PLC status
edouard@3940:         PLCstatus m_status;
edouard@3940: 
edouard@3949:         // PSK
edouard@3949:         std::string m_PSK_ID;
edouard@3949:         std::string m_PSK_secret;
edouard@3940: 
edouard@3945:         // Debug token, used for consistency check of traces
edouard@3945:         uint32_t m_debugToken;
edouard@3945: 
edouard@3945:         // Trace thread
edouard@3945:         std::thread m_traceThread;
edouard@3945: 
edouard@3945:         // Trace thread mutex
edouard@3945:         std::mutex m_tracesMutex;
edouard@3945: 
edouard@3945:         // Trace double buffer
edouard@3945:         std::vector<trace_sample> m_traces;
edouard@3945: 
edouard@3940:         uint32_t BlobAsFile(const binary_t * BlobID, std::filesystem::path filename);
edouard@3940:         uint32_t LoadPLC(void);
edouard@3940:         uint32_t UnLoadPLC(void);
edouard@3945:         uint32_t PurgePLC(void);
edouard@3949:         void PurgeTraceBuffer(void);
edouard@3945:         void TraceThreadProc(void);
edouard@3937: };
edouard@3937: 
edouard@3977: #endif