rosaria/Legacy/Aria/ArNetworking/include/ArServerHandlerConfig.h

322 lines
14 KiB
C
Raw Permalink Normal View History

2021-12-16 15:07:59 +01:00
#ifndef ARSERVERCONFIGHANDLER_H
#define ARSERVERCONFIGHANDLER_H
#include "Aria.h"
#include "ArServerBase.h"
class ArServerClient;
/// Class for sending and receiving ArConfig data via ArNetworking.
/**
* ArServerHandlerConfig defines the network packet handlers used to transmit
* ArConfig objects to a client, and to modify them based on information
* received from the client. Since the packet structure for the ArConfig is
* rather complex, this class is best used in conjunction with the
* ArClientHandlerConfig.
*
* This class handles the following requests:
* <ul>
* <li>getConfigBySections/getConfigBySectionsV2: Replies with multiple
* packets, one for each ArConfig section plus an empty packet that
* terminates the reply. Each packet contains the following header
* information:
* <ol>
* <li>Section Indicator: Always set to 'S' (byte)</li>
* <li>Section Name: (string)</li>
* <li>Section Comment: (string) </li>
* <li>Section Category Name: (string) Only for getConfigBySectionsV2 </li>
* </ol>
* For each parameter in the section, the packet then contains a
* a Parameter Indicator (always set to 'P' (byte)) followed by a
* complete description of the parameter (display hints are included).
* See ArClientArgUtils for more information.
* </li>
* <li>getConfig: This request has been superceded by getConfigBySections. (It
* replies with a single packet containing all of the ArConfig
* sections as described above. If the ArConfig is large, then it
* may not be sent successfully. In addition, it contains no parameter
* display hints.)
* </li>
* <li>setConfig: Parses the received packet and updates the robot's
* ArConfig (and saves it to the file). For each modified section,
* the received packet is expected to contain:
* <ol>
* <li>Section Indicator: Always set to "Section" (string)</li>
* <li>Section Name: (string) </li>
* </ol>
* Followed by a brief "text" description of each modified parameter.
* This is the parameter name (string) followed by the parameter value
* formatted as text (string). See ArClientArgUtils for more information.
*
* A reply packet containing a string is sent to the client. If the
* string is empty, then the config was successfully updated. Otherwise,
* the string contains the name of the first parameter that caused an
* error during the update handling.
* </li>
* <li>reloadConfig: Reloads the ArConfig from the text file.
* </li>
* <li>configUpdated: An empty packet is broadcast to all interested clients
* after setConfig or reloadConfig has been completed. The clients may
* then request the modified ArConfig data with getConfigBySections
* (or getConfig).
* </li>
* <li>getConfigDefaults: If a "default" configuration file is available,
* then this command can be used to send the preferred default values
* to the client. The received packet should contain a single string,
* which is the name of the section to be retrieved, or an empty string
* to indicate all sections.
*
* For each requested section, the reply packet contains:
* <ol>
* <li>Section Indicator: Always set to "Section" (string)</li>
* <li>Section Name: (string) </li>
* </ol>
* Followed by a brief "text" description of each default parameter value.
* This is the parameter name (string) followed by the parameter value
* formatted as text (string). See ArClientArgUtils for more information.
* </li>
* </ul>
*
* If you are using this class with the default file option you'll
* want to make it AFTER you're done adding things to the config, ie
* last, so that the default code can work correctly (it needs to know
* about all the info).
**/
class ArServerHandlerConfig
{
public:
/// Constructor
/**
* @param server the ArServerBase * used to send and receive network packets;
* must be non-NULL
* @param config the ArConfig * that is maintained by this server handler
* @param defaultFile the char * name of the file that contains the default
* values for the ArConfig; if NULL, then getConfigDefaults will not be
* supported
* @param defaultFileBaseDirectory the char * name of the directory that
* contains the default file
**/
AREXPORT ArServerHandlerConfig(ArServerBase *server,
ArConfig *config,
const char *defaultFile = NULL,
const char *defaultFileBaseDirectory = NULL,
bool allowFactory = true,
const char *robotName = NULL,
bool preventChanges = false,
const char *preventChangesString = NULL);
/// Destructor
AREXPORT virtual ~ArServerHandlerConfig();
// ---------------------------------------------------------------------------
// Network Packet Handlers
// ---------------------------------------------------------------------------
/// Handles the "reloadConfig" request.
AREXPORT void reloadConfig(ArServerClient *client, ArNetPacket *packet);
/// Handles the "getConfigBySections" request.
AREXPORT void getConfigBySections(ArServerClient *client, ArNetPacket *packet);
/// Handles the "getConfigBySectionsV2" request.
AREXPORT void getConfigBySectionsV2(ArServerClient *client, ArNetPacket *packet);
/// Handles the "getConfigBySectionsV3" request.
AREXPORT void getConfigBySectionsV3(ArServerClient *client, ArNetPacket *packet);
/// Handles the (deprecated) "getConfig" request.
AREXPORT void getConfig(ArServerClient *client, ArNetPacket *packet);
/// Handles the "setConfig" request.
AREXPORT void setConfig(ArServerClient *client, ArNetPacket *packet);
AREXPORT void setConfigBySections(ArServerClient *client, ArNetPacket *packet);
AREXPORT void setConfigBySectionsV2(ArServerClient *client, ArNetPacket *packet);
/// Handles the "getConfigDefaults" request.
AREXPORT void getConfigDefaults(ArServerClient *client, ArNetPacket *packet);
/// Handles the "getConfigSectionFlags" request.
AREXPORT void getConfigSectionFlags(ArServerClient *client,
ArNetPacket *packet);
/// Handles the "getLastEditablePriority" request.
AREXPORT void getLastEditablePriority(ArServerClient *client,
ArNetPacket *packet);
// ---------------------------------------------------------------------------
// Callback Methods
// ---------------------------------------------------------------------------
/// Adds a callback to be called before writing to disk
AREXPORT void addPreWriteCallback(ArFunctor *functor,
ArListPos::Pos position = ArListPos::LAST);
/// Removes a callback to be called before writing to disk
AREXPORT void remPreWriteCallback(ArFunctor *functor);
/// Adds a callback to be called after writing to disk
AREXPORT void addPostWriteCallback(ArFunctor *functor,
ArListPos::Pos position = ArListPos::LAST);
/// Removes a callback to be called after writing to disk
AREXPORT void remPostWriteCallback(ArFunctor *functor);
/// Adds a callback to be called when the config is updated
AREXPORT void addConfigUpdatedCallback(ArFunctor *functor,
ArListPos::Pos position = ArListPos::LAST);
/// Removes a callback to be called when the config is updated
AREXPORT void remConfigUpdatedCallback(ArFunctor *functor);
/// Restarts the IO manually (mostly for because of a config change)
void restartIO(const char *reason);
/// Restarts the software manually (mostly for because of a config change)
void restartSoftware(const char *reason);
/// Restarts the hardware manually (mostly for because of a config change)
void restartHardware(const char *reason);
/// Adds a callback for when the IO is changed
void addRestartIOCB(ArFunctor *functor, int position = 50)
{ myRestartIOCBList.addCallback(functor, position); }
/// Adds a callback for when the IO is changed
void remRestartIOCB(ArFunctor *functor)
{ myRestartIOCBList.remCallback(functor); }
/// Sets a callback for when a RESTART_SERVER config param is changed
AREXPORT void setRestartSoftwareCB(ArFunctor *restartServerCB);
/// Gets the callback for when a RESTART_SERVER config param is changed
AREXPORT ArFunctor *getRestartSoftwareCB(void);
/// Sets a callback for when a RESTART_ROBOT config param is changed
AREXPORT void setRestartHardwareCB(ArFunctor *restartRobotCB);
/// Gets the callback for when a RESTART_ROBOT config param is changed
AREXPORT ArFunctor *getRestartHardwareCB(void);
/// Locks the config so we don't do anything with it
AREXPORT int lockConfig(void) { return myConfigMutex.lock(); }
/// Tries to lock the config so we don't do anything with it
AREXPORT int tryLockConfig(void) { return myConfigMutex.tryLock(); }
/// Unlocks the config so we can use it again
AREXPORT int unlockConfig(void) { return myConfigMutex.unlock(); }
/// Writes the config out
AREXPORT bool writeConfig(void);
/// Notifies the clients that the config was updated
AREXPORT bool configUpdated(ArServerClient *client = NULL);
/// Changes the variables that prevent changes
void setPreventChanges(bool preventChanges = false,
const char *preventChangesString = NULL);
/// loads the whole of a default file (for internal use)
AREXPORT bool loadDefaultsFromFile(void);
/// Parses a line of the default config (for internal use)
AREXPORT bool loadDefaultsFromPacket(ArNetPacket *packet);
/// Creates an empty default config...
AREXPORT void createEmptyConfigDefaults(void);
/// Changes if factory is allowed... this is internal, only for when
/// that decision is deferred
void setAllowFactory(bool allowFactory)
{ myPermissionAllowFactory = allowFactory; }
/// Changes if factory is allowed... this is internal, only for when
/// that decision is deferred
bool getAllowFactory(void)
{ return myPermissionAllowFactory; }
protected:
AREXPORT void doGetConfigBySections(ArServerClient *client,
ArNetPacket *packet,
int version);
/// Helper method for the get config callbacks (e.g. getConfigBySections, getConfig, ...).
AREXPORT void handleGetConfig(ArServerClient *client,
ArNetPacket *packet,
bool isMultiplePackets,
ArPriority::Priority lastPriority,
bool isSendIneditablePriorities,
int version);
/// Helper method for the get config callbacks (e.g. getConfigBySections, getConfig, ...).
AREXPORT bool handleGetConfigSection(ArNetPacket &sending,
ArServerClient *client,
ArNetPacket *packet,
bool isMultiplePackets,
ArPriority::Priority lastPriority,
bool isSendIneditablePriorities,
int version,
ArConfigSection *section,
int startIndex,
int paramCount,
int sectionIndex,
std::set<std::string> &sentParams);
/// Internal method that handles a setConfig packet for myConfig or
/// myDefaults
bool internalSetConfig(ArServerClient *client,
ArNetPacket *packet,
int version,
bool isMultiplePackets = false);
/// just creates the default config... (internal, don't use)
void createDefaultConfig(const char *defaultFileBaseDir);
/// Adds the default config callbacks;
void addDefaultServerCommands(void);
/// Determines the last editable priority based on the input flags
ArPriority::Priority findLastEditablePriority();
ArPriority::Priority convertToPriority(int priorityVal,
ArPriority::Priority defaultPriority);
protected:
std::string myRobotName;
std::string myLogPrefix;
ArServerBase *myServer;
ArConfig *myConfig;
ArConfig *myDefault;
std::string myDefaultFile;
std::string myDefaultFileBaseDir;
ArMutex myDefaultConfigMutex;
bool myAddedDefaultServerCommands;
bool myPermissionAllowFactory;
bool myPreventChanges;
std::string myPreventChangesString;
ArMutex myConfigMutex;
std::list<ArFunctor *> myPreWriteCallbacks;
std::list<ArFunctor *> myPostWriteCallbacks;
std::list<ArFunctor *> myConfigUpdatedCallbacks;
ArCallbackList myRestartIOCBList;
ArFunctor *myRestartSoftwareCB;
bool myRestartSoftwareCBSet;
ArFunctor *myRestartHardwareCB;
bool myRestartHardwareCBSet;
ArFunctor2C<ArServerHandlerConfig, ArServerClient*, ArNetPacket *> myGetConfigBySectionsCB;
ArFunctor2C<ArServerHandlerConfig, ArServerClient*, ArNetPacket *> myGetConfigBySectionsV2CB;
ArFunctor2C<ArServerHandlerConfig, ArServerClient*, ArNetPacket *> myGetConfigBySectionsV3CB;
ArFunctor2C<ArServerHandlerConfig, ArServerClient*, ArNetPacket *> myGetConfigCB;
ArFunctor2C<ArServerHandlerConfig, ArServerClient*, ArNetPacket *> mySetConfigCB;
ArFunctor2C<ArServerHandlerConfig, ArServerClient*, ArNetPacket *> mySetConfigBySectionsCB;
ArFunctor2C<ArServerHandlerConfig, ArServerClient*, ArNetPacket *> mySetConfigBySectionsV2CB;
ArFunctor2C<ArServerHandlerConfig, ArServerClient*, ArNetPacket *> myReloadConfigCB;
ArFunctor2C<ArServerHandlerConfig, ArServerClient*, ArNetPacket *> myGetConfigDefaultsCB;
ArFunctor2C<ArServerHandlerConfig, ArServerClient*, ArNetPacket *> myGetConfigSectionFlagsCB;
ArFunctor2C<ArServerHandlerConfig, ArServerClient*, ArNetPacket *> myGetLastEditablePriorityCB;
};
#endif