Open FFBoard
Open source force feedback firmware
CommandHandler.h
Go to the documentation of this file.
1/*
2 * CommandHandler.h
3 *
4 * Created on: 03.04.2020
5 * Author: Yannick
6 */
7
8#ifndef COMMANDHANDLER_H_
9#define COMMANDHANDLER_H_
10
11#include "ChoosableClass.h"
12#include <set>
13#include "mutex.hpp"
14#include "ClassIDs.h"
15#include <vector>
16
17
18#define CMDFLAG_GET 0x01
19#define CMDFLAG_SET 0x02
20#define CMDFLAG_INFOSTRING 0x08
21#define CMDFLAG_GETADR 0x10
22#define CMDFLAG_SETADR 0x20
23#define CMDFLAG_HIDDEN 0x40
24#define CMDFLAG_DEBUG 0x80
25
26#define CMDFLAG_STR_ONLY 0x100
27#define CMDFLAG_HID_ONLY 0x200 // Command not available for string based parsers
28
29enum class CMDtype : uint32_t{
30 none = 0,
31 set = CMDFLAG_SET,
32 setat = CMDFLAG_SETADR,
33 get = CMDFLAG_GET,
34 getat = CMDFLAG_GETADR,
35 info = CMDFLAG_INFOSTRING,
36 err = 0x1000
37};
38
41
43class CommandHandler; // defined lower
44
46{
47public:
48 CmdHandlerCommanddef(const char* cmd,const char* helpstring,const uint32_t cmdId,const uint32_t flags)
50 {};
51 const char* cmd = nullptr;
52 const char* helpstring = nullptr;
53 const uint32_t cmdId;
54 const uint32_t flags;
55};
56
58{
59 const char* clsname = nullptr;
60 const uint16_t clsTypeid;
61 uint8_t instance;
62 uint16_t commandHandlerID = 0;
63};
64
65
67{
68 uint32_t cmdId=0;
69 int64_t adr = 0;
70 int64_t val = 0;
71 uint8_t instance = 0xFF; // instance number. decided by the class. 0xFF if all instances are targeted
72 CommandHandler* target = nullptr; // Directly target a handler
75};
76
77
82public:
83 CommandReply(){}; // empty
88 CommandReply(const std::string& reply,int64_t val) : reply(reply),val(val), type(CommandReplyType::STRING_OR_INT){};
89 CommandReply(const std::string& reply,int64_t val,int64_t adr) : reply(reply),val(val),adr(adr), type(CommandReplyType::STRING_OR_DOUBLEINT){};
90 uint32_t size() const{
91 return reply.size() + sizeof(CommandReply);
92 }
93 std::string reply;
94 int64_t val = 0;
95 int64_t adr = 0;
97};
98
100 std::vector<CommandReply> reply;
102 uint16_t handlerId = 0;
103 //CommandInterface* originalInterface = nullptr;
106
107 uint32_t size() const{
108 uint32_t size_b = sizeof(CommandResult);
109 for(const CommandReply& r : reply){
110 size_b += r.size();
111 }
112 return size_b;
113 }
114};
115
116// All commands have the 0x80000000 but set! do no use anywhere else
117enum class CommandHandlerCommands : uint32_t{
118 id=0x80000001,name=0x80000002,help=0x80000003,instance=0x80000004,cmdhandleruid=0x80000005,selectionid=0x80000006,cmdinfo=0x80000007
119};
120
129public:
130 //static std::vector<CommandHandler*> cmdHandlers; //!< List of all registered command handlers to be called on commands
131 //static std::set<uint16_t> cmdHandlerIDs; //!< Reserves dynamic unique IDs to keep track of command handlers
132 //static cpp_freertos::MutexStandard cmdHandlerListMutex;
133 //static std::vector<uint16_t> cmdHandlerIDs;
138 virtual const ClassType getClassType(){return ClassType::NONE;};
139
140 CommandHandler(const char* clsname,uint16_t clsid,uint8_t instance = 0);
141 virtual ~CommandHandler();
142 virtual bool hasCommands();
143 virtual void setCommandsEnabled(bool enable);
144
145 virtual CommandStatus command(const ParsedCommand& cmd,std::vector<CommandReply>& replies);
146 void registerCommands(); // Function reserved to register commands in the command list.
147 virtual CommandStatus internalCommand(const ParsedCommand& cmd,std::vector<CommandReply>& replies);
148
149 virtual const ClassIdentifier getInfo() = 0;
150
151 virtual std::string getHelpstring(); // Returns a help string if "help" command is sent
152 virtual std::string getCommandsHelpstring(); // Returns a list of the commands helpstrings
153 virtual std::string getCsvHelpstring(); // Returns a list of the commands helpstrings formatted for csv
154
155 static void logSerial(std::string string);
156 static void logSerialDebug(std::string string);
157
158 virtual uint8_t getCommandHandlerInstance();
159
160 void broadcastCommandReply(CommandReply reply, uint32_t cmdId,CMDtype type);
161 void sendCommandReplyAsync(CommandReply reply, uint32_t cmdId,CMDtype type,CommandInterface* interface = nullptr);
162
163 static bool logEnabled;
164 static bool logsEnabled();
165 static void setLogsEnabled(bool enabled);
166 virtual uint16_t getCommandHandlerID(){return this->cmdHandlerInfo.commandHandlerID;}
167 //virtual uint16_t getSelectionID(){return this->getInfo().id;} //!< normally returns class id but for choosable classes this can be the id used to create the class
168
170
171
172
173 static uint32_t getClassIdFromName(const char* name);
174 static const char* getClassNameFromId(const uint32_t id);
175
176 static CommandHandler* getHandlerFromHandlerId(const uint16_t cmdhandlerID);
177 static CommandHandler* getHandlerFromId(const uint16_t id,const uint8_t instance=0xFF);
178 static CommandHandler* getHandlerFromClassName(const char* name,const uint8_t instance=0xFF);
179 static std::vector<CommandHandler*> getHandlersFromClassName(const char* name);
180 static std::vector<CommandHandler*> getHandlersFromId(const uint16_t id);
181 static bool isInHandlerList(CommandHandler* handler);
182
183 static std::string getAllHelpstrings();
184
185 virtual bool isValidCommandId(uint32_t cmdid,uint32_t ignoredFlags=0,uint32_t requiredFlag=0);
186
187 virtual CmdHandlerCommanddef* getCommandFromName(const std::string& cmd,uint32_t ignoredFlags=0);
188 virtual CmdHandlerCommanddef* getCommandFromId(const uint32_t id,uint32_t ignoredFlags=0);
189
190
191 static inline std::vector<CommandHandler*>& getCommandHandlers() {
192 static std::vector<CommandHandler*> commandhandlers{};
193 return commandhandlers;
194 }
195
196
200 template<typename TVal>
201 static CommandStatus handleGetSet(const ParsedCommand& cmd,std::vector<CommandReply>& replies,TVal& value){
202 if(cmd.type == CMDtype::set || cmd.type == CMDtype::setat){
203 value = static_cast<TVal>(cmd.val);
204 }else if(cmd.type == CMDtype::get || cmd.type == CMDtype::getat){
205 replies.emplace_back(value);
206 }else{
207 return CommandStatus::ERR;
208 }
209 return CommandStatus::OK;
210 }
214 template<typename TVal,class cls,class cls1>
215 static CommandStatus handleGetSetFunc(const ParsedCommand& cmd,std::vector<CommandReply>& replies,TVal& value,void (cls1::*setfunc)(TVal),cls* obj){
216 if(cmd.type == CMDtype::set || cmd.type == CMDtype::setat){
217 (obj->*setfunc)(cmd.val);
218 }else if(cmd.type == CMDtype::get || cmd.type == CMDtype::getat){
219 replies.emplace_back(value);
220 }else{
221 return CommandStatus::ERR;
222 }
223 return CommandStatus::OK;
224 }
228 template<typename TVal,class cls,class cls1,class cls2>
229 static CommandStatus handleGetFuncSetFunc(const ParsedCommand& cmd,std::vector<CommandReply>& replies,TVal (cls1::*getfunc)(),void (cls2::*setfunc)(TVal),cls* obj){
230 if(cmd.type == CMDtype::set || cmd.type == CMDtype::setat){
231 (obj->*setfunc)(cmd.val);
232 }else if(cmd.type == CMDtype::get || cmd.type == CMDtype::getat){
233 replies.emplace_back((obj->*getfunc)());
234 }else{
235 return CommandStatus::ERR;
236 }
237 return CommandStatus::OK;
238 }
242 template<typename TVal,class cls,class cls1>
243 static CommandStatus handleGetFuncSet(const ParsedCommand& cmd,std::vector<CommandReply>& replies,TVal& value,TVal (cls1::*getfunc)(),cls* obj){
244 if(cmd.type == CMDtype::set || cmd.type == CMDtype::setat){
245 value = static_cast<TVal>(cmd.val);
246 }else if(cmd.type == CMDtype::get || cmd.type == CMDtype::getat){
247 replies.emplace_back((obj->*getfunc)());
248 }else{
249 return CommandStatus::ERR;
250 }
251 return CommandStatus::OK;
252 }
253
261 template<typename ID>
262 void registerCommand(const char* cmd,const ID cmdid,const char* help=nullptr,uint32_t flags = 0){
264 if(cmdDef.cmdId == static_cast<uint32_t>(cmdid))
265 return; //already present
266 }
267
268 this->registeredCommands.emplace_back(cmd, help,static_cast<uint32_t>(cmdid),flags);
269 this->registeredCommands.shrink_to_fit();
270 }
271
272
273
274protected:
275 void setInstance(uint8_t instance);
276 bool commandsEnabled = true;
277 virtual void addCommandHandler();
278 virtual void removeCommandHandler();
279
280 static inline std::vector<uint16_t>& getCommandHandlerIds() {
281 static std::vector<uint16_t> commandhandlerids{};
282 return commandhandlerids;
283 }
284
285
286 std::vector<CmdHandlerCommanddef> registeredCommands;
287
289
290};
291
292#endif /* COMMANDHANDLER_H_ */
ClassType
Definition: ClassIDs.h:12
CommandHandlerCommands
CommandReplyType
CMDtype
CommandStatus
const char * helpstring
const uint32_t cmdId
CmdHandlerCommanddef(const char *cmd, const char *helpstring, const uint32_t cmdId, const uint32_t flags)
const uint32_t flags
static CommandStatus handleGetFuncSetFunc(const ParsedCommand &cmd, std::vector< CommandReply > &replies, TVal(cls1::*getfunc)(), void(cls2::*setfunc)(TVal), cls *obj)
virtual std::string getHelpstring()
static bool logsEnabled()
static std::vector< CommandHandler * > getHandlersFromClassName(const char *name)
static std::vector< uint16_t > & getCommandHandlerIds()
virtual uint8_t getCommandHandlerInstance()
void registerCommand(const char *cmd, const ID cmdid, const char *help=nullptr, uint32_t flags=0)
static void logSerial(std::string string)
Send a log formatted sequence.
virtual void addCommandHandler()
std::vector< CmdHandlerCommanddef > registeredCommands
virtual CmdHandlerCommanddef * getCommandFromId(const uint32_t id, uint32_t ignoredFlags=0)
virtual void setCommandsEnabled(bool enable)
static void setLogsEnabled(bool enabled)
static const char * getClassNameFromId(const uint32_t id)
static bool isInHandlerList(CommandHandler *handler)
virtual const ClassType getClassType()
virtual bool hasCommands()
virtual uint16_t getCommandHandlerID()
static CommandStatus handleGetSet(const ParsedCommand &cmd, std::vector< CommandReply > &replies, TVal &value)
virtual CommandStatus internalCommand(const ParsedCommand &cmd, std::vector< CommandReply > &replies)
void setInstance(uint8_t instance)
virtual const ClassIdentifier getInfo()=0
Command handlers always have class infos. Works well with ChoosableClass.
static CommandHandler * getHandlerFromClassName(const char *name, const uint8_t instance=0xFF)
CmdHandlerInfo cmdHandlerInfo
virtual ~CommandHandler()
static void logSerialDebug(std::string string)
Send a log formatted sequence if debug is on.
virtual CommandStatus command(const ParsedCommand &cmd, std::vector< CommandReply > &replies)
static bool logEnabled
static CommandHandler * getHandlerFromHandlerId(const uint16_t cmdhandlerID)
void sendCommandReplyAsync(CommandReply reply, uint32_t cmdId, CMDtype type, CommandInterface *interface=nullptr)
virtual CmdHandlerCommanddef * getCommandFromName(const std::string &cmd, uint32_t ignoredFlags=0)
virtual std::string getCommandsHelpstring()
static CommandStatus handleGetSetFunc(const ParsedCommand &cmd, std::vector< CommandReply > &replies, TVal &value, void(cls1::*setfunc)(TVal), cls *obj)
void broadcastCommandReply(CommandReply reply, uint32_t cmdId, CMDtype type)
virtual CmdHandlerInfo * getCommandHandlerInfo()
static std::string getAllHelpstrings()
virtual void removeCommandHandler()
static CommandHandler * getHandlerFromId(const uint16_t id, const uint8_t instance=0xFF)
static CommandStatus handleGetFuncSet(const ParsedCommand &cmd, std::vector< CommandReply > &replies, TVal &value, TVal(cls1::*getfunc)(), cls *obj)
static std::vector< CommandHandler * > getHandlersFromId(const uint16_t id)
static uint32_t getClassIdFromName(const char *name)
CommandHandler(const char *clsname, uint16_t clsid, uint8_t instance=0)
static std::vector< CommandHandler * > & getCommandHandlers()
virtual bool isValidCommandId(uint32_t cmdid, uint32_t ignoredFlags=0, uint32_t requiredFlag=0)
virtual std::string getCsvHelpstring()
std::string reply
uint32_t size() const
CommandReply(const std::string &reply, int64_t val)
CommandReply(CommandReplyType type)
CommandReply(const std::string &reply, int64_t val, int64_t adr)
CommandReply(int64_t val, int64_t adr)
CommandReply(int64_t val)
CommandReplyType type
CommandReply(const std::string &reply)
const char * clsname
uint16_t commandHandlerID
const uint16_t clsTypeid
uint32_t size() const
ParsedCommand originalCommand
CommandStatus type
CommandHandler * commandHandler
std::vector< CommandReply > reply
uint16_t handlerId
ID of the command handler responding to the command.
uint8_t instance
CommandHandler * target
uint32_t cmdId
CommandInterface * originalInterface
Command interface on which this command was received. nullptr indicates a broadcast.