yaacov / ArduinoModbusSlave

Modbus slave library for Arduino
ISC License
205 stars 75 forks source link

Added posibility for applying "context" of modbus callback #97

Closed ValentiWorkLearning closed 1 year ago

ValentiWorkLearning commented 1 year ago

I've decided to use the library for adding Modbus support for fun-project and faced with the issue that it's impossible to set up callback for read/write as a class member. For fixing this I've added the possibility to apply "context" for callback context, which can be later user for forwaring handling procedure into the corresponding instance.

  1. Setup callbackContext:

    m_slave.setCallbackContext(this);
  2. Add callbacks to the multiplexer:

    
    etl::flat_map<u16, ModbusRegisterHandler, modbus::address::kModbusRegistersCount> m_modbusRequestsMultiplexer;
    
        m_modbusRequestsMultiplexer[modbus::address::kTargetTemperatureAddr] =
            ModbusRegisterHandler{
                .readHandler = etl::delegate<u16()>::create<ModbusServer::ModbusServerImpl, &ModbusServerImpl::getTargetTemperature>(*this),
                .writeHandler = etl::delegate<void(u16)>::create<ModbusServer::ModbusServerImpl, &ModbusServerImpl::setTargetTemperature>(*this)};
4. Implement basic callbacks:
```cpp

u8 writeDigitalOutCb(u8 fc, u16 address, u16 length, void *callbackContext) noexcept
{
    const bool isAddrValid = (address == modbus::LED_COIL_ADDR);
    if (!isAddrValid)
    {
        return STATUS_ILLEGAL_DATA_ADDRESS;
    }

    auto modbusServerImpl = reinterpret_cast<ModbusServer::ModbusServerImpl *>(callbackContext);
    modbusServerImpl->handleCoilsWrite();
    return STATUS_OK;
}

u8 readHoldingRegistersCb(u8 fc, u16 address, u16 length, void *callbackContext) noexcept
{
    auto modbusServerImpl = reinterpret_cast<ModbusServer::ModbusServerImpl *>(callbackContext);
    return modbusServerImpl->handleReadHoldingRequest(address, length);
}

u8 writeHoldingRegistersCb(u8 fc, u16 address, u16 length, void *callbackContext) noexcept
{
    auto modbusServerImpl = reinterpret_cast<ModbusServer::ModbusServerImpl *>(callbackContext);
    return modbusServerImpl->handleWriteHoldingRegisterRequest(address, length);

}

The full code is available here: https://github.com/ValentiWorkLearning/ReflowTableModbusController/blob/master/src/modbus_server_task.cpp