/* nutclient.h - definitions for nutclient C/C++ library Copyright (C) 2012 Emilien Kia This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef NUTCLIENT_HPP_SEEN #define NUTCLIENT_HPP_SEEN /* Begin of C++ nutclient library declaration */ #ifdef __cplusplus #include #include #include #include #include namespace nut { namespace internal { class Socket; } /* namespace internal */ class Client; class TcpClient; class Device; class Variable; class Command; /** * Basic nut exception. */ class NutException : public std::exception { public: NutException(const std::string& msg):_msg(msg){} virtual ~NutException() throw() {} virtual const char * what() const throw() {return this->_msg.c_str();} virtual std::string str() const throw() {return this->_msg;} private: std::string _msg; }; /** * System error. */ class SystemException : public NutException { public: SystemException(); virtual ~SystemException() throw() {} private: static std::string err(); }; /** * IO oriented nut exception. */ class IOException : public NutException { public: IOException(const std::string& msg):NutException(msg){} virtual ~IOException() throw() {} }; /** * IO oriented nut exception specialized for unknown host */ class UnknownHostException : public IOException { public: UnknownHostException():IOException("Unknown host"){} virtual ~UnknownHostException() throw() {} }; /** * IO oriented nut exception when client is not connected */ class NotConnectedException : public IOException { public: NotConnectedException():IOException("Not connected"){} virtual ~NotConnectedException() throw() {} }; /** * IO oriented nut exception when there is no response. */ class TimeoutException : public IOException { public: TimeoutException():IOException("Timeout"){} virtual ~TimeoutException() throw() {} }; /** * A nut client is the starting point to dialog to NUTD. * It can connect to an NUTD then retrieve its device list. * Use a specific client class to connect to a NUTD. */ class Client { friend class Device; friend class Variable; friend class Command; public: ~Client(); /** * Intend to authenticate to a NUTD server. * Set the username and password associated to the connection. * \param user User name. * \param passwd Password. * \todo Is his method is global to all connection protocol or is it specific to TCP ? * \note Actually, authentication fails only if already set, not if bad values are sent. */ virtual void authenticate(const std::string& user, const std::string& passwd)throw(NutException)=0; /** * Disconnect from the NUTD server. * \todo Is his method is global to all connection protocol or is it specific to TCP ? */ virtual void logout()throw(NutException)=0; /** * Device manipulations. * \see nut::Device * \{ */ /** * Retrieve a device from its name. * If the device does not exist, a bad (not ok) device is returned. * \param name Name of the device. * \return The device. */ virtual Device getDevice(const std::string& name)throw(NutException); /** * Retrieve the list of all devices supported by UPSD server. * \return The set of supported devices. */ virtual std::set getDevices()throw(NutException); /** * Test if a device is supported by the NUTD server. * \param dev Device name. * \return true if supported, false otherwise. */ virtual bool hasDevice(const std::string& dev)throw(NutException); /** * Retrieve names of devices supported by NUTD server. * \return The set of names of supported devices. */ virtual std::set getDeviceNames()throw(NutException)=0; /** * Retrieve the description of a device. * \param name Device name. * \return Device description. */ virtual std::string getDeviceDescription(const std::string& name)throw(NutException)=0; /** \} */ /** * Variable manipulations. * \see nut::Variable * \{ */ /** * Retrieve names of all variables supported by a device. * \param dev Device name * \return Variable names */ virtual std::set getDeviceVariableNames(const std::string& dev)throw(NutException)=0; /** * Retrieve names of read/write variables supported by a device. * \param dev Device name * \return RW variable names */ virtual std::set getDeviceRWVariableNames(const std::string& dev)throw(NutException)=0; /** * Test if a variable is supported by a device. * \param dev Device name * \param name Variable name * \return true if the variable is supported. */ virtual bool hasDeviceVariable(const std::string& dev, const std::string& name)throw(NutException); /** * Retrieve the description of a variable. * \param dev Device name * \param name Variable name * \return Variable description if provided. */ virtual std::string getDeviceVariableDescription(const std::string& dev, const std::string& name)throw(NutException)=0; /** * Retrieve values of a variable. * \param dev Device name * \param name Variable name * \return Variable values (usually one) if available. */ virtual std::vector getDeviceVariableValue(const std::string& dev, const std::string& name)throw(NutException)=0; /** * Retrieve values of all variables of a device. * \param dev Device name * \return Variable values indexed by variable names. */ virtual std::map > getDeviceVariableValues(const std::string& dev)throw(NutException); /** * Intend to set the value of a variable. * \param dev Device name * \param name Variable name * \param value Variable value */ virtual void setDeviceVariable(const std::string& dev, const std::string& name, const std::string& value)throw(NutException)=0; /** * Intend to set the value of a variable. * \param dev Device name * \param name Variable name * \param value Variable value */ virtual void setDeviceVariable(const std::string& dev, const std::string& name, const std::vector& values)throw(NutException)=0; /** \} */ /** * Instant command manipulations. * \see nut::Command * \{ */ /** * Retrieve names of all commands supported by a device. * \param dev Device name * \return Command names */ virtual std::set getDeviceCommandNames(const std::string& dev)throw(NutException)=0; /** * Test if a command is supported by a device. * \param dev Device name * \param name Command name * \return true if the command is supported. */ virtual bool hasDeviceCommand(const std::string& dev, const std::string& name)throw(NutException); /** * Retrieve the description of a command. * \param dev Device name * \param name Command name * \return Command description if provided. */ virtual std::string getDeviceCommandDescription(const std::string& dev, const std::string& name)throw(NutException)=0; /** * Intend to execute a command. * \param dev Device name * \param name Command name */ virtual void executeDeviceCommand(const std::string& dev, const std::string& name)throw(NutException)=0; /** \} */ /** * Device specific commands. * \{ */ /** * Log the current user (if authenticated) for a device. * \param dev Device name. */ virtual void deviceLogin(const std::string& dev)throw(NutException)=0; /** * Retrieve the number of user longged in the specified device. * \param dev Device name. * \return Number of logged-in users. */ virtual int deviceGetNumLogins(const std::string& dev)throw(NutException)=0; virtual void deviceMaster(const std::string& dev)throw(NutException)=0; virtual void deviceForcedShutdown(const std::string& dev)throw(NutException)=0; protected: Client(); }; /** * TCP NUTD client. * It connect to NUTD with a TCP socket. */ class TcpClient : public Client { public: /** * Construct a nut TcpClient object. * You must call one of TcpClient::connect() after. */ TcpClient(); /** * Construct a nut TcpClient object then connect it to the specified server. * \param host Server host name. * \param port Server port. */ TcpClient(const std::string& host, int port = 3493)throw(nut::IOException); ~TcpClient(); /** * Connect it to the specified server. * \param host Server host name. * \param port Server port. */ void connect(const std::string& host, int port = 3493)throw(nut::IOException); /** * Connect to the server. * Host name and ports must have already set (usefull for reconnection). */ void connect()throw(nut::IOException); /** * Test if the connection is active. * \return tru if the connection is active. */ bool isConnected()const; /** * Force the deconnection. */ void disconnect(); /** * Set the timeout in seconds. * \param timeout Timeout n seconds, negative to block operations. */ void setTimeout(long timeout); /** * Retrieve the timeout. * \returns Current timeout in seconds. */ long getTimeout()const; /** * Retriueve the host name of the server the client is connected to. * \return Server host name */ std::string getHost()const; /** * Retriueve the port of host of the server the client is connected to. * \return Server port */ int getPort()const; virtual void authenticate(const std::string& user, const std::string& passwd)throw(NutException); virtual void logout()throw(NutException); virtual Device getDevice(const std::string& name)throw(NutException); virtual std::set getDeviceNames()throw(NutException); virtual std::string getDeviceDescription(const std::string& name)throw(NutException); virtual std::set getDeviceVariableNames(const std::string& dev)throw(NutException); virtual std::set getDeviceRWVariableNames(const std::string& dev)throw(NutException); virtual std::string getDeviceVariableDescription(const std::string& dev, const std::string& name)throw(NutException); virtual std::vector getDeviceVariableValue(const std::string& dev, const std::string& name)throw(NutException); virtual std::map > getDeviceVariableValues(const std::string& dev)throw(NutException); virtual void setDeviceVariable(const std::string& dev, const std::string& name, const std::string& value)throw(NutException); virtual void setDeviceVariable(const std::string& dev, const std::string& name, const std::vector& values)throw(NutException); virtual std::set getDeviceCommandNames(const std::string& dev)throw(NutException); virtual std::string getDeviceCommandDescription(const std::string& dev, const std::string& name)throw(NutException); virtual void executeDeviceCommand(const std::string& dev, const std::string& name)throw(NutException); virtual void deviceLogin(const std::string& dev)throw(NutException); virtual void deviceMaster(const std::string& dev)throw(NutException); virtual void deviceForcedShutdown(const std::string& dev)throw(NutException); virtual int deviceGetNumLogins(const std::string& dev)throw(NutException); protected: std::string sendQuery(const std::string& req)throw(nut::IOException); static void detectError(const std::string& req)throw(nut::NutException); std::vector get(const std::string& subcmd, const std::string& params = "") throw(nut::NutException); std::vector > list(const std::string& subcmd, const std::string& params = "") throw(nut::NutException); static std::vector explode(const std::string& str, size_t begin=0); static std::string escape(const std::string& str); private: std::string _host; int _port; long _timeout; internal::Socket* _socket; }; /** * Device attached to a client. * Device is a lightweight class which can be copied easily. */ class Device { friend class Client; friend class TcpClient; public: ~Device(); Device(const Device& dev); /** * Retrieve the name of the device. * The name is the unique id under which NUTD known the device. */ std::string getName()const; /** * Retrieve the client to which the device is attached. */ const Client* getClient()const; /** * Retrieve the client to which the device is attached. */ Client* getClient(); /** * Test if the device is valid (has a name and is attached to a client). */ bool isOk()const; /** * Test if the device is valid (has a name and is attached to a client). * @see Device::isOk() */ operator bool()const; /** * Test if the device is not valid (has no name or is not attached to any client). * @see Device::isOk() */ bool operator!()const; /** * Test if the two devices are sames (same name ad same client attached to). */ bool operator==(const Device& dev)const; /** * Comparison operator. */ bool operator<(const Device& dev)const; /** * Retrieve the description of the devce if specified. */ std::string getDescription()throw(NutException); /** * Intend to retrieve the value of a variable of the device. * \param name Name of the variable to get. * \return Value of the variable, if available. */ std::vector getVariableValue(const std::string& name)throw(NutException); /** * Intend to retrieve values of all variables of the devices. * \return Map of all variables values indexed by their names. */ std::map > getVariableValues()throw(NutException); /** * Retrieve all variables names supported by the device. * \return Set of available variable names. */ std::set getVariableNames()throw(NutException); /** * Retrieve all Read/Write variables names supported by the device. * \return Set of available Read/Write variable names. */ std::set getRWVariableNames()throw(NutException); /** * Intend to set the value of a variable of the device. * \param name Variable name. * \param value New variable value. */ void setVariable(const std::string& name, const std::string& value)throw(NutException); /** * Intend to set values of a variable of the device. * \param name Variable name. * \param value New variable values. */ void setVariable(const std::string& name, const std::vector& values)throw(NutException); /** * Retrieve a Variable object representing the specified variable. * \param name Variable name. * \return Variable object. */ Variable getVariable(const std::string& name)throw(NutException); /** * Retrieve Variable objects representing all variables available for the device. * \return Set of Variable objects. */ std::set getVariables()throw(NutException); /** * Retrieve Variable objects representing all Read/Write variables available for the device. * \return Set of Variable objects. */ std::set getRWVariables()throw(NutException); /** * Retrieve names of all commands supported by the device. * \return Set of available command names. */ std::set getCommandNames()throw(NutException); /** * Retrieve objects for all commands supported by the device. * \return Set of available Command objects. */ std::set getCommands()throw(NutException); /** * Retrieve an object representing a command of the device. * \param name Command name. * \return Command object. */ Command getCommand(const std::string& name)throw(NutException); /** * Intend to execute a command on the device. * \param name Command name. */ void executeCommand(const std::string& name)throw(NutException); /** * Login current client's user for the device. */ void login()throw(NutException); void master()throw(NutException); void forcedShutdown()throw(NutException); /** * Retrieve the number of logged user for the device. * \return Number of users. */ int getNumLogins()throw(NutException); protected: Device(Client* client, const std::string& name); private: Client* _client; std::string _name; }; /** * Variable attached to a device. * Variable is a lightweight class which can be copied easily. */ class Variable { friend class Device; friend class TcpClient; public: ~Variable(); Variable(const Variable& var); /** * Retrieve variable name. */ std::string getName()const; /** * Retrieve the device to which the variable is attached to. */ const Device* getDevice()const; /** * Retrieve the device to which the variable is attached to. */ Device* getDevice(); /** * Test if the variable is valid (has a name and is attached to a device). */ bool isOk()const; /** * Test if the variable is valid (has a name and is attached to a device). * @see Variable::isOk() */ operator bool()const; /** * Test if the variable is not valid (has no name or is not attached to any device). * @see Variable::isOk() */ bool operator!()const; /** * Test if the two variables are sames (same name ad same device attached to). */ bool operator==(const Variable& var)const; /** * Less-than operator (based on variable name) to allow variable sorting. */ bool operator<(const Variable& var)const; /** * Intend to retrieve variable value. * \return Value of the variable. */ std::vector getValue()throw(NutException); /** * Intend to retireve variable description. * \return Variable description if provided. */ std::string getDescription()throw(NutException); /** * Intend to set a value to the variable. * \param value New variable value. */ void setValue(const std::string& value)throw(NutException); /** * Intend to set (multiple) values to the variable. * \param value New variable values. */ void setValues(const std::vector& values)throw(NutException); protected: Variable(Device* dev, const std::string& name); private: Device* _device; std::string _name; }; /** * Command attached to a device. * Command is a lightweight class which can be copied easily. */ class Command { friend class Device; friend class TcpClient; public: ~Command(); Command(const Command& cmd); /** * Retrieve command name. */ std::string getName()const; /** * Retrieve the device to which the command is attached to. */ const Device* getDevice()const; /** * Retrieve the device to which the command is attached to. */ Device* getDevice(); /** * Test if the command is valid (has a name and is attached to a device). */ bool isOk()const; /** * Test if the command is valid (has a name and is attached to a device). * @see Command::isOk() */ operator bool()const; /** * Test if the command is not valid (has no name or is not attached to any device). * @see Command::isOk() */ bool operator!()const; /** * Test if the two commands are sames (same name ad same device attached to). */ bool operator==(const Command& var)const; /** * Less-than operator (based on command name) to allow comand sorting. */ bool operator<(const Command& var)const; /** * Intend to retireve command description. * \return Command description if provided. */ std::string getDescription()throw(NutException); /** * Intend to retrieve command description. * \return Command description if provided. */ void execute()throw(NutException); protected: Command(Device* dev, const std::string& name); private: Device* _device; std::string _name; }; } /* namespace nut */ #endif /* __cplusplus */ /* End of C++ nutclient library declaration */ /* Begin of C nutclient library declaration */ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /** * Array of string manipulation functions. * \{ */ /** Array of string.*/ typedef char** strarr; /** * Alloc an array of string. */ strarr strarr_alloc(unsigned short count); /** * Free an array of string. */ void strarr_free(strarr arr); /** * Nut general client types and functions. * \{ */ /** Hidden structure representing a connection to NUTD. */ typedef void* NUTCLIENT_t; /** * Destroy a client. * \param client Nut client handle. */ void nutclient_destroy(NUTCLIENT_t client); /** * Authenticate into the server. * \param client Nut client handle. * \param login User name. * \param passwd Password. */ void nutclient_authenticate(NUTCLIENT_t client, const char* login, const char* passwd); /** * Log out from server. * \param client Nut client handle. */ void nutclient_logout(NUTCLIENT_t client); /** * Register current user on the device. * \param client Nut client handle. * \param dev Device name to test. */ void nutclient_device_login(NUTCLIENT_t client, const char* dev); /** * Retrieve the number of users registered on a device. * \param client Nut client handle. * \param dev Device name to test. */ int nutclient_get_device_num_logins(NUTCLIENT_t client, const char* dev); /** * Set current user as master user of the device. * \param client Nut client handle. * \param dev Device name to test. */ void nutclient_device_master(NUTCLIENT_t client, const char* dev); /** * Set the FSD flag for the device. * \param client Nut client handle. * \param dev Device name to test. */ void nutclient_device_forced_shutdown(NUTCLIENT_t client, const char* dev); /** * Retrieve the list of devices of a client. * \param client Nut client handle. * \return Array of string containing device names. Must be freed with strarr_free(strarr). */ strarr nutclient_get_devices(NUTCLIENT_t client); /** * Test if a device is supported by the client. * \param client Nut client handle. * \param dev Device name to test. * \return 1 if supported, 0 otherwise. */ int nutclient_has_device(NUTCLIENT_t client, const char* dev); /** * Intend to retrieve device description. * \param client Nut client handle. * \param dev Device name to test. * \return Description of device. Must be freed after use. */ char* nutclient_get_device_description(NUTCLIENT_t client, const char* dev); /** * Intend to retrieve device variable names. * \param client Nut client handle. * \param dev Device name. * \return Array of string containing variable names. Must be freed with strarr_free(strarr). */ strarr nutclient_get_device_variables(NUTCLIENT_t client, const char* dev); /** * Intend to retrieve device read/write variable names. * \param client Nut client handle. * \param dev Device name. * \return Array of string containing read/write variable names. Must be freed with strarr_free(strarr). */ strarr nutclient_get_device_rw_variables(NUTCLIENT_t client, const char* dev); /** * Test if a variable is supported by the device and the client. * \param client Nut client handle. * \param dev Device name. * \param var Variable name. * \return 1 if supported, 0 otherwise. */ int nutclient_has_device_variable(NUTCLIENT_t client, const char* dev, const char* var); /** * Intend to retrieve device variable description. * \param client Nut client handle. * \param dev Device name. * \param var Variable name. * \return Description of device variable. Must be freed after use. */ char* nutclient_get_device_variable_description(NUTCLIENT_t client, const char* dev, const char* var); /** * Intend to retrieve device variable values. * \param client Nut client handle. * \param dev Device name. * \param var Variable name. * \return Array of string containing variable values. Must be freed with strarr_free(strarr). */ strarr nutclient_get_device_variable_values(NUTCLIENT_t client, const char* dev, const char* var); /** * Intend to set device variable value. * \param client Nut client handle. * \param dev Device name. * \param var Variable name. * \param value Value to set. */ void nutclient_set_device_variable_value(NUTCLIENT_t client, const char* dev, const char* var, const char* value); /** * Intend to set device variable multiple values. * \param client Nut client handle. * \param dev Device name. * \param var Variable name. * \param values Values to set. The cller is responsible to free it after call. */ void nutclient_set_device_variable_values(NUTCLIENT_t client, const char* dev, const char* var, const strarr values); /** * Intend to retrieve device command names. * \param client Nut client handle. * \param dev Device name. * \return Array of string containing command names. Must be freed with strarr_free(strarr). */ strarr nutclient_get_device_commands(NUTCLIENT_t client, const char* dev); /** * Test if a command is supported by the device and the client. * \param client Nut client handle. * \param dev Device name. * \param cmd Command name. * \return 1 if supported, 0 otherwise. */ int nutclient_has_device_command(NUTCLIENT_t client, const char* dev, const char* cmd); /** * Intend to retrieve device command description. * \param client Nut client handle. * \param dev Device name. * \param cmd Command name. * \return Description of device command. Must be freed after use. */ char* nutclient_get_device_command_description(NUTCLIENT_t client, const char* dev, const char* cmd); /** * Intend to execute device command. * \param client Nut client handle. * \param dev Device name. * \param cmd Command name. */ void nutclient_execute_device_command(NUTCLIENT_t client, const char* dev, const char* cmd); /** \} */ /** * Nut TCP client dedicated types and functions * \{ */ /** * Hidden structure representing a TCP connection to NUTD. * NUTCLIENT_TCP_t is back compatible to NUTCLIENT_t. */ typedef NUTCLIENT_t NUTCLIENT_TCP_t; /** * Create a client to NUTD using a TCP connection. * \param host Host name to connect to. * \param port Host port. * \return New client or NULL if failed. */ NUTCLIENT_TCP_t nutclient_tcp_create_client(const char* host, unsigned short port); /** * Test if a nut TCP client is connected. * \param client Nut TCP client handle. * \return 1 if connected, 0 otherwise. */ int nutclient_tcp_is_connected(NUTCLIENT_TCP_t client); /** * Disconnect a nut TCP client. * \param client Nut TCP client handle. */ void nutclient_tcp_disconnect(NUTCLIENT_TCP_t client); /** * Intend to reconnect a nut TCP client. * \param client Nut TCP client handle. * \return 0 if correctly connected. * \todo Implement different error codes. */ int nutclient_tcp_reconnect(NUTCLIENT_TCP_t client); /** * Set the timeout value for the TCP connection. * \param timeout Timeout in seconds, negative for blocking. */ void nutclient_tcp_set_timeout(NUTCLIENT_TCP_t client, long timeout); /** * Retrieve the timeout value for the TCP connection. * \return Timeout value in seconds. */ long nutclient_tcp_get_timeout(NUTCLIENT_TCP_t client); /** \} */ #ifdef __cplusplus } #endif /* __cplusplus */ /* End of C nutclient library declaration */ #endif /* NUTCLIENT_HPP_SEEN */