/** * \file ipc_send.h * \brief definition de classe * \author { * Sébastien Ambroziak * Paul Sauvage * } * \version 0.1 * \date 5 novembre 2020 * * Definitions de la classe IpcSender ainsi que ses méthodes. * Cette classe permet d'envoyer des structures ou des liste de structure par ipc * * La classe IpcSender utilise une template à 2 paramètres, T et N * le paramètre T correspond au type de donnée que le sender doit pouvoir envoyer * le paramètre N correspond au nombre d'élément du tableau d'élément de type T à envoyer * si N = 0 la fonction send() prend en paramètre et envoi une structure de type T * si N > 0 la fonction send() prend en paramètre et envoi un tableau de N éléments de type T * * Le constructeur utilise 2 paramètres: * Une chaîne de caractère contenant le nom du fichier ipc vers lequel écrire les données * Un entier correspond au numéro de canal Ipc * */ #ifndef IPC_SEND #define IPC_SEND #include "ipc_base.h" #include #include #include #include #include #include #include #include #include using namespace std; using namespace ipc::type; class IpcSenderBase { public: IpcSenderBase(const char* ipc_name, int proj_id=65) { cout << "IpcReceiver on " << ipc_name << endl; system("mkdir -p /tmp/ipc"); system("chmod 777 /tmp/ipc"); string pathname = string("/tmp/ipc/") + string(ipc_name); string command = string("> ") + pathname; system(command.c_str()); command = string("chmod 666 ") + pathname; system(command.c_str()); key_t ipc_key = ftok(pathname.c_str(), proj_id); //crete unique key cout << "ipc key " << ipc_key << endl << endl; _queue_id = msgget(ipc_key, 0666 | IPC_CREAT); //create message queue and return id } ~IpcSenderBase() { msgctl(_queue_id, IPC_RMID, NULL); //destroy the message queue. } protected: int _queue_id; }; template class IpcSender : IpcSenderBase { public: IpcSender(const char* ipc_name, int proj_id=65, bool auto_refresh = true): IpcSenderBase(ipc_name, proj_id), _auto_refresh(auto_refresh) {} ~IpcSender() = default; void send(){ if(_auto_refresh) refreshTime(); if (msgsnd(_queue_id, &_message, sizeof(_message.data), IPC_NOWAIT) < 0) //send message { //std::cout << "Erreur envoi message" << std::endl; } } void send(T value) { _message.data.value = value; send(); } timestamp getTimestamp(){ return _message.data.stamp; } timestamp refreshTime(){ _message.time_now(); return _message.data.stamp; } T getValue(){return _message.data.value;} void setValue(T value){_message.data.value = value;} void setTimestamp(timestamp stamp){_message.data.stamp = stamp;} void setTimestamp(int32_t sec, uint32_t nanosec){ _message.data.stamp.sec = sec; _message.data.stamp.nanosec = nanosec; } protected: bool _auto_refresh; ipc_message _message; }; template class IpcSenderTab : IpcSenderBase { public: IpcSenderTab(size_t N, const char* ipc_name, int proj_id=65, bool auto_refresh = true): IpcSenderBase(ipc_name, proj_id), _N(N), _auto_refresh(auto_refresh){ _message = (ipc_tab*) malloc(sizeof(ipc_tab) + sizeof(T)*(N-1)); _message->msg_type = 1; } ~IpcSenderTab() = default; void send(T* values){ memcpy(_message->data.values, values, sizeof(T)*_N); send(); } void send(){ if(_auto_refresh) refreshTime(); if (msgsnd(_queue_id, _message, sizeof(T)*_N + sizeof(_message->data), IPC_NOWAIT) < 0) //send message { //cout << errno << endl; } } void setTimestamp(timestamp stamp){_message->data.stamp = stamp;} void setTimestamp(int32_t sec, uint32_t nanosec){ _message->data.stamp.sec = sec; _message->data.stamp.nanosec = nanosec; } timestamp getTimestamp(){ return _message->data.stamp; } timestamp refreshTime(){ _message->time_now(); return _message->data.stamp; } void setValue(T value, size_t index){ if(index < _N){ _message->data.values[index] = value; } } void setAll(T value) { for (size_t i = 0; i < _N; i++) { _message->data.values[i] = value; } } size_t getN() const {return _N;} protected: size_t _N; bool _auto_refresh; ipc_tab* _message; }; #endif