Open MENIER opened 1 year ago
This is the good way? Is there an other solution with non inherit class tMsgHandler?:
#include "Arduino.h"
#include <NMEA2000_CAN.h>
#include <NMEA2000.h>
class Derived : public tNMEA2000::tMsgHandler{
public:
tNMEA2000 *pNMEA2000=0;
const unsigned long ReceiveMessages[16] PROGMEM = {/*126992L,*/ // System time
130306L, // Wind
127245L,// Rudder
0
};
virtual void HandleMsg(const tN2kMsg &N2kMsg)
{
}
Derived(tNMEA2000 *_pNMEA2000):tNMEA2000::tMsgHandler(0, _pNMEA2000)
{
_pNMEA2000->ExtendReceiveMessages(ReceiveMessages);
this->pNMEA2000=_pNMEA2000;
}
};
Derived derived(&NMEA2000);
void setup()
{
// Add your initialization code here
}
// The loop function is called in an endless loop
void loop()
{
//Add your repeated code here
}
pNMEA2000->SetMsgHandler(&handleNMEA2000Msg); This is naturally impossible, since you try to point object function without object.
You have to either use functional way: void MsgHandler(const tN2kMsg &N2kMsg) { ... } pNMEA2000->SetMsgHandler(MsgHandler);
or class way class Derived : public tNMEA2000::tMsgHandler { ... };
Derived MyHandler(130306L,pNMEA2000);
pNMEA2000->AttachMsgHandler(MyHandler);
Note also that your class structure is wrong. In your sample you derive Derived from tNMEA2000::tMsgHandler and have public object tNMEA2000 *pNMEA2000, which is already private inside tNMEA2000::tMsgHandler, so not sure what would actually happen.
I do not see at your point you are trying to do.
Thanks for your fast reply! 1)Derived MyHandler(130306L,pNMEA2000); mean the class can't parse array of PGN? 2) No way to SetMsgHandler (from class ) without inherit from class tMsgHandler? 3) I haven't see the member NMEA2000 in subclass tMsgHandler I correct the code:
class Derived : public tNMEA2000::tMsgHandler{
private:
tNMEA2000 *pNMEA20001;
public:
const unsigned long ReceiveMessages[16] PROGMEM = {/*126992L,*/ // System time
130306L, // Wind
127245L,// Rudder
0
};
virtual void HandleMsg(const tN2kMsg &N2kMsg)
{
}
Derived(unsigned long _PGN=0,tNMEA2000 *_pNMEA2000=0):tNMEA2000::tMsgHandler(_PGN=0, _pNMEA2000=0)
{
_pNMEA2000->ExtendReceiveMessages(ReceiveMessages);
//_pNMEA2000->AttachMsgHandler(this); in constructor tMsgHandler it's done???
pNMEA20001=GetNMEA2000();
}
};
Derived MyHandler(130306L,&NMEA2000);
1) No. Class is designed to make inherited handler for each PGN. If you want to use class for multiple PGN, you set PGN=0, but then you need to check from message, what PGN it has. 2) No. Why it should? There is functional way for that purpose. 3) But why do you have now pNMEA20001? It is unnecessary, since you can always use GetNMEA2000() inside your class.
Note that your constructor is also wrong:
Derived(unsigned long _PGN=0,tNMEA2000 *_pNMEA2000=0):tNMEA2000::tMsgHandler(_PGN=0, _pNMEA2000=0)...
For your derived class you define _PGN default value to 0 and _pNMEA2000 to 0, but then it calls parent constructor with _PGN=0, _pNMEA2000=0 causing that both _PGN and _pNMEA2000 will be set to 0 and actually call tNMEA2000::tMsgHandler(0,0). So now parent handler can not link to tNMEA2000 object and newer handle the messages. Naturally if you later call NMEA2000.AttachHandler(MyHandler), it will be attached and does handle all PGNs. The proper way to use class is something like:
class tWindhandler : public tNMEA2000::tMsgHandler {
public:
Windhandler (tNMEA2000 *_pNMEA2000=0):tNMEA2000::tMsgHandler(130306L, _pNMEA2000) {}
virtual void HandleMsg(const tN2kMsg &N2kMsg); // Write your handler function some where
};
tWindhandler Windhandler(&NMEA2000);
...
Note also that library currently does not handle dynamic PGN handling lists. So you just do on your setup NMEA2000.ExtendReceiveMessages(ReceiveMessages);
I have still the problem use functional way from a class:
class MyClass {
public:
static void HandleMsgStatic(const tN2kMsg &N2kMsg){;}
void HandleMsg(const tN2kMsg &N2kMsg){;}
MyClass(tNMEA2000 *_pNMEA2000)
{
_pNMEA2000->SetMsgHandler(HandleMsgStatic);//OK
//_pNMEA2000->SetMsgHandler(HandleMsg);//Error
}
};
MyClass myClass(&NMEA2000);
void HandleMsgC(const tN2kMsg &N2kMsg){myClass.HandleMsg(N2kMsg);}
void setup()
{
NMEA2000.SetMsgHandler(HandleMsgC);//OK
}
You can not call class method without class object except if you define method static. But static method is almost same as function. The difference is it has access to protected class functions and variables. But even then you need somehow provide class object for that method.
There is no other way to use class as message handler except inherit it from tMsgHandler, since that base class is declared for tNMEA2000. E.g., in javascript it would be possible to just provide object for tNMEA2000 kind object, which would then call HandlerObject.HandleMgs(...) and it would work fine, if HandlerObject has method HandleMgs. But C++ is very strict typed language and requires that things has been declared before use.
I prefer you to study bit more about C++ classes. Why do you e.g., should use class for message handling. In most cases it is enough and easiest to just write message handler function.
I'm agree with you i must study more about about C++ classes. Sorry for that. I have used lambda and std::bind in cpp with success but i don#t find the right syntax for your code:
` auto lambda = [&] (
AsyncWebSocket *server,
AsyncWebSocketClient *client,
AwsEventType type,
void *arg,
uint8_t *data,
size_t len)
{
return this->onEventDerived(
server,
client,
type,
arg,
data,
len);
};
this->onEvent(lambda);
this->onEvent(std::bind(&Derived::onEventDerived, this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3,
std::placeholders::_4,
std::placeholders::_5,
std::placeholders::_6));`
I'm working with little bit complex project communicate between websocket en NMEA2000 many callback between them read write from html page to NMEA2000 via websocket....
With binding you can like rewrite call function argument list. In library case you are not doing callback so there is no use for it.
Hello every body;I have tested std::bind and lambda with no success my code: