Closed Benji1992-HU closed 4 years ago
Every class method has a "hidden" argument: the class instance. So you'll have to use std::bind to add the extra argument.
If you don't know how, let me know.
Sorry I am new in c++ programming, I dont know what you say.
Your example is lacking so much information that I can only guess what you're doing.
Anyway, suppose you have a class with a private variable esp32ModbusRTU myDevice
and a private function
class myClass {
// left out lot's of stuff
private:
void onData(uint8_t slaveId, esp32Modbus::FunctionCode fc, uint16_t addr, uint8_t* data, uint16_t len);
esp32ModbusRTU myDevice;
};
What you don't see is that there is -simply said- an extra argument in the _onData function which is the class instance. This is not part of the function signature that can be passed to myDevice.onData()
. To overcome this you can use std::bind
.
so somewhere in your class (perhaps a setup()
method) you have to do something like this:
myDevice.onData(std::bind(&myClass:_onData, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
The onData has only 4 argument, i corrected this. The code: .h file:
class parabolaCommunication
{
private:
int _modbusRxPin;
int _modbusTxPin;
int _modbusDePin;
const char* _mqttClientId;
const char* _wifiSsid;
const char* _wifiPassword;
bool _serviceMode;
const char* _mqttServerAddress;
uint16_t _mqttServerPort;
static int _modbusActualFuncCode;
static uint8_t _modbusActualSlaveAddr;
static uint16_t _modbusActualSlaveRegNum;
private:
void handleModbusData(uint8_t serverAddress, esp32Modbus::FunctionCode fc, uint8_t* data, uint16_t length);
static void identifyRecievedData(int senderAddress, long int recievedData);
//void onData(uint8_t slaveId, esp32Modbus::FunctionCode fc, uint16_t addr, uint8_t* data, uint16_t len);
public:
struct sensors
{
int deviceAddress;
int deviceRegisterNum;
};
public:
parabolaCommunication(int modbusRxPin, int modbusTxPin, int modbusDePin);
void setWifiSettings(const char* wifiSsid, const char* wifiPassword);
void setMqttSettings(const char* mqttServerIpAddress, uint16_t mqttServerPort, const char* mqttClientId);
bool init(String parabolaName, bool serviceMode);
bool wifiConnect();
void serialPrintln(int data);
void serialPrintln(float data);
void serialPrintln(long data);
void serialPrintln(byte data);
void serialPrintln(char data);
void serialPrintln(String data);
void modbusAction(uint8_t slaveAddress, int funcCode, uint16_t regNum, uint16_t regData);
void getSensorValue( struct sensors sensor );
};
.cpp file:
esp32ModbusRTU modbus(&Serial1);
SemaphoreHandle_t xSerialSemaphore;
SemaphoreHandle_t xModbusSemaphore;
bool parabolaCommunication::init(String parabolaName, bool serviceMode)
{
_serviceMode = serviceMode;
Serial.begin(115200);
if ( xSerialSemaphore == NULL )
{
xSerialSemaphore = xSemaphoreCreateMutex();
if ( ( xSerialSemaphore ) != NULL )
xSemaphoreGive( ( xSerialSemaphore ) );
}
if(_serviceMode == false)
{
wifiConnect();
client.setServer(_mqttServerAddress, _mqttServerPort);
}else
{ parabolaCommunication::serialPrintln("---- SERVICE MODE ----");
SerialBT.begin(parabolaName);
}
Serial1.begin(19200,SERIAL_8N1,_modbusRxPin,_modbusTxPin,true);
modbus.onData(std::bind(¶bolaCommunication::handleModbusData, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
modbus.onError([](esp32Modbus::Error error) {
if ( xSemaphoreTake( xSerialSemaphore, ( TickType_t ) 5 ) == pdTRUE )
{
Serial.printf("error: 0x%02x\n\n", static_cast<uint8_t>(error));
xSemaphoreGive( xSerialSemaphore );
}
});
modbus.begin();
if ( xModbusSemaphore == NULL )
{
xModbusSemaphore = xSemaphoreCreateMutex();
if ( ( xModbusSemaphore ) != NULL )
xSemaphoreGive( ( xModbusSemaphore ) );
}
//struct parabolaCommunication::sensors TEMP_1 = {1,0};
return 0;
}
void parabolaCommunication::handleModbusData(uint8_t serverAddress, esp32Modbus::FunctionCode fc, uint8_t* data, uint16_t length)
{
long int number = 0;
int deviceAddress = serverAddress;
number = (data[0] << 8) + data[1];
parabolaCommunication::serialPrintln(number);
identifyRecievedData(deviceAddress , number);
}
The compile with no error but when I send an request dont come back the answer. I think the onData function not working.
That's something completely different... but I still have no idea what you're doing without a main.cpp
file. But please, I'm not going to debug your entire code. I'm not interested in your WiFi or MQTT code.
I only sent the detail that concerns the library. The other part of code is work fine. In modbus slave PC tool I see the request is sent, and the slave is response to the request, but the onData handeler function is not called.
The code here is quite straightforward. There's not much that could be blocking, especially if you say your slave is receiving the request.
I don't have a clue about your program. Do all the semaphores get released? Is your debug printing code working? Does the onError method get called? Any object lifetime issues?
What about throwing in some debug print statements to see where is it blocking?
I tried without using semaphores. The result is the same. the onError is working, sometimes print 0xe0 error code.
Hy! I want to use the esp32ModbusRTU class in my own class, but i have this error message:
no suitable constructor exists to convert from "void (uint8_t serverAddress, esp32Modbus::FunctionCode fc, uint8_t *data, uint16_t length)" to "std::function<void (uint8_t, esp32Modbus::FunctionCode, uint8_t *, uint16_t)>"
My code:
.h
.cpp
Can you help me?
Thanks!