Open FFBoard
Open source force feedback firmware
Loading...
Searching...
No Matches
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#include <span>
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#define CMDFLAG_EXTOVERRIDE 0x80000000
26
27#define CMDFLAG_STR_ONLY 0x100
28#define CMDFLAG_HID_ONLY 0x200 // Command not available for string based parsers
29
30enum class CMDtype : uint32_t{
31 none = 0,
32 set = CMDFLAG_SET,
33 setat = CMDFLAG_SETADR,
34 get = CMDFLAG_GET,
35 getat = CMDFLAG_GETADR,
36 info = CMDFLAG_INFOSTRING,
37 err = 0x1000
38};
39
42
44class CommandHandler; // defined lower
45
47{
48public:
49 CmdHandlerCommanddef(const char* cmd,const char* helpstring,const uint32_t cmdId,const uint32_t flags)
51 {};
52 const char* cmd = nullptr;
53 const char* helpstring = nullptr;
54 uint32_t cmdId;
55 uint32_t flags;
56};
57
59{
60 const char* clsname = nullptr;
61 const uint16_t clsTypeid;
62 uint8_t instance;
63 uint16_t commandHandlerID = 0;
64};
65
66
68{
69 uint32_t cmdId=0;
70 int64_t adr = 0;
71 int64_t val = 0;
72 uint8_t instance = 0xFF; // instance number. decided by the class. 0xFF if all instances are targeted
73 CommandHandler* target = nullptr; // Directly target a handler
76};
77
78
83public:
84 CommandReply(){}; // empty
89 CommandReply(const std::string& reply,int64_t val) : reply(reply),val(val), type(CommandReplyType::STRING_OR_INT){};
90 CommandReply(const std::string& reply,int64_t val,int64_t adr) : reply(reply),val(val),adr(adr), type(CommandReplyType::STRING_OR_DOUBLEINT){};
91 uint32_t size() const{
92 return reply.size() + sizeof(CommandReply);
93 }
94 std::string reply;
95 int64_t val = 0;
96 int64_t adr = 0;
98};
99
101 std::vector<CommandReply> reply;
103 uint16_t handlerId = 0;
104 //CommandInterface* originalInterface = nullptr;
107
108 uint32_t size() const{
109 uint32_t size_b = sizeof(CommandResult);
110 for(const CommandReply& r : reply){
111 size_b += r.size();
112 }
113 return size_b;
114 }
115};
116
117// All commands have the 0x80000000 but set! do no use anywhere else
118enum class CommandHandlerCommands : uint32_t{
119 id=0x80000001,name=0x80000002,help=0x80000003,instance=0x80000004,cmdhandleruid=0x80000005,selectionid=0x80000006,cmdinfo=0x80000007
120};
121
130public:
131 //static std::vector<CommandHandler*> cmdHandlers; //!< List of all registered command handlers to be called on commands
132 //static std::set<uint16_t> cmdHandlerIDs; //!< Reserves dynamic unique IDs to keep track of command handlers
133 //static cpp_freertos::MutexStandard cmdHandlerListMutex;
134 //static std::vector<uint16_t> cmdHandlerIDs;
139 virtual const ClassType getClassType(){return ClassType::NONE;};
140
141 CommandHandler(const char* clsname,uint16_t clsid,uint8_t instance = 0);
142 virtual ~CommandHandler();
143 virtual bool hasCommands();
144 virtual void setCommandsEnabled(bool enable);
145
146 virtual CommandStatus command(const ParsedCommand& cmd,std::vector<CommandReply>& replies);
147 void registerCommands(); // Function reserved to register commands in the command list.
148 virtual CommandStatus internalCommand(const ParsedCommand& cmd,std::vector<CommandReply>& replies);
149
150 virtual const ClassIdentifier getInfo() = 0;
151
152 virtual std::string getHelpstring(); // Returns a help string if "help" command is sent
153 virtual std::string getCommandsHelpstring(); // Returns a list of the commands helpstrings
154 virtual std::string getCsvHelpstring(); // Returns a list of the commands helpstrings formatted for csv
155
156 static void logSerial(std::string string);
157 static void logSerialDebug(std::string string);
158
159 virtual uint8_t getCommandHandlerInstance();
160
161 void broadcastCommandReply(CommandReply reply, uint32_t cmdId,CMDtype type);
162 void sendCommandReplyAsync(CommandReply reply, uint32_t cmdId,CMDtype type,CommandInterface* interface = nullptr);
163
164 static bool logEnabled;
165 static bool logsEnabled();
166 static void setLogsEnabled(bool enabled);
167 virtual uint16_t getCommandHandlerID(){return this->cmdHandlerInfo.commandHandlerID;}
168 //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
169
171
172
173
174 static uint32_t getClassIdFromName(const char* name);
175 static const char* getClassNameFromId(const uint32_t id);
176
177 static CommandHandler* getHandlerFromHandlerId(const uint16_t cmdhandlerID);
178 static CommandHandler* getHandlerFromId(const uint16_t id,const uint8_t instance=0xFF);
179 static CommandHandler* getHandlerFromClassName(const char* name,const uint8_t instance=0xFF);
180 static std::vector<CommandHandler*> getHandlersFromClassName(const char* name);
181 static std::vector<CommandHandler*> getHandlersFromId(const uint16_t id);
182 static bool isInHandlerList(CommandHandler* handler);
183
184 static std::string getAllHelpstrings();
185
186 virtual bool isValidCommandId(uint32_t cmdid,uint32_t ignoredFlags=0,uint32_t requiredFlag=0);
187
188 virtual CmdHandlerCommanddef* getCommandFromName(const std::string& cmd,uint32_t ignoredFlags=0);
189 virtual CmdHandlerCommanddef* getCommandFromId(const uint32_t id,uint32_t ignoredFlags=0);
190
191
192 static inline std::vector<CommandHandler*>& getCommandHandlers() {
193 static std::vector<CommandHandler*> commandhandlers{};
194 return commandhandlers;
195 }
196
197
201 template<typename TVal>
202 static CommandStatus handleGetSet(const ParsedCommand& cmd,std::vector<CommandReply>& replies,TVal& value){
203 if(cmd.type == CMDtype::set || cmd.type == CMDtype::setat){
204 value = static_cast<TVal>(cmd.val);
205 }else if(cmd.type == CMDtype::get || cmd.type == CMDtype::getat){
206 replies.emplace_back(value);
207 }else{
208 return CommandStatus::ERR;
209 }
210 return CommandStatus::OK;
211 }
212
215 template<typename TVal,class cls,class cls1>
216 static CommandStatus handleGetSetFunc(const ParsedCommand& cmd,std::vector<CommandReply>& replies,TVal& value,void (cls1::*setfunc)(TVal),cls* obj){
217 if(cmd.type == CMDtype::set || cmd.type == CMDtype::setat){
218 (obj->*setfunc)(cmd.val);
219 }else if(cmd.type == CMDtype::get || cmd.type == CMDtype::getat){
220 replies.emplace_back(value);
221 }else{
222 return CommandStatus::ERR;
223 }
224 return CommandStatus::OK;
225 }
226
229 template<typename TVal,class cls,class cls1,class cls2>
230 static CommandStatus handleGetFuncSetFunc(const ParsedCommand& cmd,std::vector<CommandReply>& replies,TVal (cls1::*getfunc)(),void (cls2::*setfunc)(TVal),cls* obj){
231 if(cmd.type == CMDtype::set || cmd.type == CMDtype::setat){
232 (obj->*setfunc)(cmd.val);
233 }else if(cmd.type == CMDtype::get || cmd.type == CMDtype::getat){
234 replies.emplace_back((obj->*getfunc)());
235 }else{
236 return CommandStatus::ERR;
237 }
238 return CommandStatus::OK;
239 }
240
243 template<typename TVal,class cls,class cls1>
244 static CommandStatus handleGetFuncSet(const ParsedCommand& cmd,std::vector<CommandReply>& replies,TVal& value,TVal (cls1::*getfunc)(),cls* obj){
245 if(cmd.type == CMDtype::set || cmd.type == CMDtype::setat){
246 value = static_cast<TVal>(cmd.val);
247 }else if(cmd.type == CMDtype::get || cmd.type == CMDtype::getat){
248 replies.emplace_back((obj->*getfunc)());
249 }else{
250 return CommandStatus::ERR;
251 }
252 return CommandStatus::OK;
253 }
254
262 template<typename ID>
263 void registerCommand(const char* cmd,const ID cmdid,const char* help=nullptr,uint32_t flags = 0){
264 registerCommand_INT(cmd, static_cast<uint32_t>(cmdid), help, flags);
265 }
266
267
268 virtual void postCmdhandlerInit(){}; // Can implement in external file to override command flags
269 template<typename ID>
273 void overrideCommandFlags(const ID cmdid,uint32_t flagmask = 0){
274 overrideCommandFlags_INT(static_cast<uint32_t>(cmdid), flagmask);
275 }
276
277
278
279
280protected:
281 void setInstance(uint8_t instance);
282 bool commandsEnabled = true;
283 virtual void addCommandHandler();
284 virtual void removeCommandHandler();
285
286 static inline std::vector<uint16_t>& getCommandHandlerIds() {
287 static std::vector<uint16_t> commandhandlerids{};
288 return commandhandlerids;
289 }
290
291
292 std::vector<CmdHandlerCommanddef> registeredCommands;
293
295
296 void registerCommand_INT(const char* cmd,const uint32_t cmdid,const char* help=nullptr,uint32_t flags = 0);
297 void overrideCommandFlags_INT(const uint32_t cmdid,uint32_t flagmask = CMDFLAG_GET | CMDFLAG_GETADR);
298
299};
300
301#endif /* COMMANDHANDLER_H_ */
ClassType
Definition ClassIDs.h:12
CommandHandlerCommands
CommandReplyType
CMDtype
CommandStatus
const char * helpstring
CmdHandlerCommanddef(const char *cmd, const char *helpstring, const uint32_t cmdId, 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 registerCommand_INT(const char *cmd, const uint32_t cmdid, const char *help=nullptr, uint32_t flags=0)
void overrideCommandFlags(const ID cmdid, uint32_t flagmask=0)
void overrideCommandFlags_INT(const uint32_t cmdid, uint32_t flagmask=CMDFLAG_GET|CMDFLAG_GETADR)
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)
virtual void postCmdhandlerInit()
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.
CommandHandler * target
CommandInterface * originalInterface
Command interface on which this command was received. nullptr indicates a broadcast.