/* Modbus Library for Arduino Modbus public API implementation Copyright (C) 2014 Andr� Sarmento Barbosa 2017-2021 Alexander Emelianov (a.m.emelianov@gmail.com) */ #pragma once #include "Modbus.h" template class ModbusAPI : public T { public: // Alternative API template uint16_t read(TYPEID id, TAddress reg, uint16_t* value, uint16_t numregs = 1, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t read(TYPEID id, TAddress reg, bool* value, uint16_t numregs = 1, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t write(TYPEID id, TAddress reg, uint16_t value, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t write(TYPEID id, TAddress reg, bool value, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t write(TYPEID id, TAddress reg, uint16_t* value, uint16_t numregs = 1, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t write(TYPEID id, TAddress reg, bool* value, uint16_t numregs = 1, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); /* template uint16_t push(TYPEID id, TAddress to, TAddress from, uint16_t numregs = 1, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t pull(TYPEID id, TAddress from, TAddress to, uint16_t numregs = 1, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); */ // Classic API bool Hregs(uint16_t offset, uint16_t* value, uint16_t numregs = 1) {return this->Reg(HREG(offset), value);} bool Coils(uint16_t offset, bool* value, uint16_t numregs = 1) {return this->Reg(COIL(offset), value);} bool Istss(uint16_t offset, bool* value, uint16_t numregs = 1) {return this->Reg(ISTS(offset), value);} bool Iregs(uint16_t offset, uint16_t* value, uint16_t numregs = 1) {return this->Reg(IREG(offset), value);} //bool addHreg(uint16_t offset, uint16_t* value, uint16_t numregs = 1) {return this->addReg(HREG(offset), value);} //bool addCoil(uint16_t offset, bool* value, uint16_t numregs = 1) {return this->addReg(COIL(offset), value);} //bool addIsts(uint16_t offset, bool* value, uint16_t numregs = 1) {return this->addReg(ISTS(offset), value);} //bool addIreg(uint16_t offset, uint16_t* value, uint16_t numregs = 1) {return this->addReg(IREG(offset), value);} bool addHreg(uint16_t offset, uint16_t value = 0, uint16_t numregs = 1); bool addCoil(uint16_t offset, bool value = false, uint16_t numregs = 1); bool addIsts(uint16_t offset, bool value = false, uint16_t numregs = 1); bool addIreg(uint16_t offset, uint16_t value = 0, uint16_t numregs = 1); bool Hreg(uint16_t offset, uint16_t value); bool Coil(uint16_t offset, bool value); bool Ists(uint16_t offset, bool value); bool Ireg(uint16_t offset, uint16_t value); bool Coil(uint16_t offset); bool Ists(uint16_t offset); uint16_t Ireg(uint16_t offset); uint16_t Hreg(uint16_t offset); bool removeCoil(uint16_t offset, uint16_t numregs = 1); bool removeIsts(uint16_t offset, uint16_t numregs = 1); bool removeIreg(uint16_t offset, uint16_t numregs = 1); bool removeHreg(uint16_t offset, uint16_t numregs = 1); bool onGetCoil(uint16_t offset, cbModbus cb = nullptr, uint16_t numregs = 1); bool onSetCoil(uint16_t offset, cbModbus cb = nullptr, uint16_t numregs = 1); bool onGetHreg(uint16_t offset, cbModbus cb = nullptr, uint16_t numregs = 1); bool onSetHreg(uint16_t offset, cbModbus cb = nullptr, uint16_t numregs = 1); bool onGetIsts(uint16_t offset, cbModbus cb = nullptr, uint16_t numregs = 1); bool onSetIsts(uint16_t offset, cbModbus cb = nullptr, uint16_t numregs = 1); bool onGetIreg(uint16_t offset, cbModbus cb = nullptr, uint16_t numregs = 1); bool onSetIreg(uint16_t offset, cbModbus cb = nullptr, uint16_t numregs = 1); bool removeOnGetCoil(uint16_t offset, cbModbus cb = nullptr, uint16_t numregs = 1); bool removeOnSetCoil(uint16_t offset, cbModbus cb = nullptr, uint16_t numregs = 1); bool removeOnGetHreg(uint16_t offset, cbModbus cb = nullptr, uint16_t numregs = 1); bool removeOnSetHreg(uint16_t offset, cbModbus cb = nullptr, uint16_t numregs = 1); bool removeOnGetIsts(uint16_t offset, cbModbus cb = nullptr, uint16_t numregs = 1); bool removeOnSetIsts(uint16_t offset, cbModbus cb = nullptr, uint16_t numregs = 1); bool removeOnGetIreg(uint16_t offset, cbModbus cb = nullptr, uint16_t numregs = 1); bool removeOnSetIreg(uint16_t offset, cbModbus cb = nullptr, uint16_t numregs = 1); template uint16_t writeCoil(TYPEID id, uint16_t offset, bool value, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t writeCoil(TYPEID id, uint16_t offset, bool* value, uint16_t numregs = 1, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t readCoil(TYPEID id, uint16_t offset, bool* value, uint16_t numregs = 1, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t writeHreg(TYPEID id, uint16_t offset, uint16_t value, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t writeHreg(TYPEID id, uint16_t offset, uint16_t* value, uint16_t numregs = 1, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t readIsts(TYPEID id, uint16_t offset, bool* value, uint16_t numregs = 1, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t readHreg(TYPEID id, uint16_t offset, uint16_t* value, uint16_t numregs = 1, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t readIreg(TYPEID id, uint16_t offset, uint16_t* value, uint16_t numregs = 1, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t pushCoil(TYPEID id, uint16_t to, uint16_t from, uint16_t numregs = 1, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t pullCoil(TYPEID id, uint16_t from, uint16_t to, uint16_t numregs = 1, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t pullIsts(TYPEID id, uint16_t from, uint16_t to, uint16_t numregs = 1, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t pushHreg(TYPEID id, uint16_t to, uint16_t from, uint16_t numregs = 1, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t pullHreg(TYPEID id, uint16_t from, uint16_t to, uint16_t numregs = 1, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t pullIreg(TYPEID id, uint16_t from, uint16_t to, uint16_t numregs = 1, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t pullHregToIreg(TYPEID id, uint16_t offset, uint16_t startreg, uint16_t numregs = 1, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t pullCoilToIsts(TYPEID id, uint16_t offset, uint16_t startreg, uint16_t numregs = 1, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t pushIstsToCoil(TYPEID id, uint16_t to, uint16_t from, uint16_t numregs = 1, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t pushIregToHreg(TYPEID id, uint16_t to, uint16_t from, uint16_t numregs = 1, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t readFileRec(TYPEID slaveId, uint16_t fileNum, uint16_t startRec, uint16_t len, uint8_t* data, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t writeFileRec(TYPEID slaveId, uint16_t fileNum, uint16_t startRec, uint16_t len, uint8_t* data, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t maskHreg(TYPEID slaveId, uint16_t offset, uint16_t andMask, uint16_t orMask, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t readWriteHreg(TYPEID slaveId, uint16_t readOffset, uint16_t* readValue, uint16_t readNumregs, uint16_t writeOffset, uint16_t* writeValue, uint16_t writeNumregs, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t rawRequest(TYPEID ip, const uint8_t* data, uint16_t len, cbTransaction cb = nullptr, uint8_t unit = MODBUSIP_UNIT); template uint16_t rawResponce(TYPEID ip, const uint8_t* data, uint16_t len, uint8_t unit = MODBUSIP_UNIT); template uint16_t errorResponce(TYPEID ip, Modbus::FunctionCode fn, Modbus::ResultCode excode, uint8_t unit = MODBUSIP_UNIT); }; // FNAME writeCoil, writeIsts, writeHreg, writeIreg // REG COIL, ISTS, HREG, IREG // FUNC Modbus function // MAXNUM Register count limit // VALTYPE bool, uint16_t // VALUE #define IMPLEMENT_WRITEREG(FNAME, REG, FUNC, VALUE, VALTYPE) \ template \ template \ uint16_t ModbusAPI::FNAME(TYPEID ip, uint16_t offset, VALTYPE value, cbTransaction cb, uint8_t unit) { \ this->readSlave(offset, VALUE(value), Modbus::FUNC); \ return this->send(ip, REG(offset), cb, unit); \ } IMPLEMENT_WRITEREG(writeCoil, COIL, FC_WRITE_COIL, COIL_VAL, bool) IMPLEMENT_WRITEREG(writeHreg, HREG, FC_WRITE_REG, , uint16_t) #define IMPLEMENT_WRITEREGS(FNAME, REG, FUNC, VALUE, MAXNUM, VALTYPE) \ template \ template \ uint16_t ModbusAPI::FNAME(TYPEID ip, uint16_t offset, VALTYPE* value, uint16_t numregs, cbTransaction cb, uint8_t unit) { \ if (numregs < 0x0001 || numregs > MAXNUM) return false; \ this->VALUE(REG(offset), offset, numregs, Modbus::FUNC, value); \ return this->send(ip, REG(offset), cb, unit); \ } IMPLEMENT_WRITEREGS(writeCoil, COIL, FC_WRITE_COILS, writeSlaveBits, MODBUS_MAX_BITS, bool) IMPLEMENT_WRITEREGS(writeHreg, HREG, FC_WRITE_REGS, writeSlaveWords, MODBUS_MAX_WORDS, uint16_t) #define IMPLEMENT_READREGS(FNAME, REG, FUNC, MAXNUM, VALTYPE) \ template \ template \ uint16_t ModbusAPI::FNAME(TYPEID ip, uint16_t offset, VALTYPE* value, uint16_t numregs, cbTransaction cb, uint8_t unit) { \ if (numregs < 0x0001 || numregs > MAXNUM) return false; \ this->readSlave(offset, numregs, Modbus::FUNC); \ return this->send(ip, REG(offset), cb, unit, (uint8_t*)value); \ } IMPLEMENT_READREGS(readCoil, COIL, FC_READ_COILS, MODBUS_MAX_BITS, bool) IMPLEMENT_READREGS(readHreg, HREG, FC_READ_REGS, MODBUS_MAX_WORDS, uint16_t) IMPLEMENT_READREGS(readIsts, ISTS, FC_READ_INPUT_STAT, MODBUS_MAX_BITS, bool) IMPLEMENT_READREGS(readIreg, IREG, FC_READ_INPUT_REGS, MODBUS_MAX_WORDS, uint16_t) #if defined(MODBUS_ADD_REG) #define ADDREG(R) this->addReg(R(to), (uint16_t)0, numregs); #else #define ADDREG(R) ; #endif #define IMPLEMENT_PULL(FNAME, REG, FUNC, MAXNUM) \ template \ template \ uint16_t ModbusAPI::FNAME(TYPEID ip, uint16_t from, uint16_t to, uint16_t numregs, cbTransaction cb, uint8_t unit) { \ if (numregs < 0x0001 || numregs > MAXNUM) return false; \ ADDREG(REG) \ this->readSlave(from, numregs, Modbus::FUNC); \ return this->send(ip, REG(to), cb, unit); \ } IMPLEMENT_PULL(pullCoil, COIL, FC_READ_COILS, MODBUS_MAX_BITS) IMPLEMENT_PULL(pullIsts, ISTS, FC_READ_INPUT_STAT, MODBUS_MAX_BITS) IMPLEMENT_PULL(pullHreg, HREG, FC_READ_REGS, MODBUS_MAX_WORDS) IMPLEMENT_PULL(pullIreg, IREG, FC_READ_INPUT_REGS, MODBUS_MAX_WORDS) IMPLEMENT_PULL(pullHregToIreg, IREG, FC_READ_REGS, MODBUS_MAX_WORDS) IMPLEMENT_PULL(pullCoilToIsts, ISTS, FC_READ_COILS, MODBUS_MAX_BITS) #define IMPLEMENT_PUSH(FNAME, REG, FUNC, MAXNUM, FINT) \ template \ template \ uint16_t ModbusAPI::FNAME(TYPEID ip, uint16_t to, uint16_t from, uint16_t numregs, cbTransaction cb, uint8_t unit) { \ if (numregs < 0x0001 || numregs > MAXNUM) return false; \ if (!this->searchRegister(REG(from))) return false; \ this->FINT(REG(from), to, numregs, Modbus::FUNC); \ return this->send(ip, REG(from), cb, unit); \ } IMPLEMENT_PUSH(pushCoil, COIL, FC_WRITE_COILS, MODBUS_MAX_BITS, writeSlaveBits) IMPLEMENT_PUSH(pushHreg, HREG, FC_WRITE_REGS, MODBUS_MAX_WORDS, writeSlaveWords) IMPLEMENT_PUSH(pushIregToHreg, IREG, FC_WRITE_REGS, MODBUS_MAX_WORDS, writeSlaveWords) IMPLEMENT_PUSH(pushIstsToCoil, ISTS, FC_WRITE_COILS, MODBUS_MAX_BITS, writeSlaveBits) template template uint16_t ModbusAPI::read(TYPEID id, TAddress reg, uint16_t* value, uint16_t numregs, cbTransaction cb, uint8_t unit) { switch (reg.type) { case TAddress::HREG: return readHreg(id, reg.address, value, numregs, cb, unit); case TAddress::IREG: return readIreg(id, reg.address, value, numregs, cb, unit); default: return 0; } } template template uint16_t ModbusAPI::read(TYPEID id, TAddress reg, bool* value, uint16_t numregs, cbTransaction cb, uint8_t unit) { switch (reg.type) { case TAddress::COIL: return readCoil(id, reg.address, value, numregs, cb, unit); case TAddress::ISTS: return readIsts(id, reg.address, value, numregs, cb, unit); default: return 0; } } template template uint16_t ModbusAPI::write(TYPEID id, TAddress reg, uint16_t value, cbTransaction cb, uint8_t unit) { switch (reg.type) { case TAddress::COIL: return writeCoil(id, reg.address, value, cb, unit); case TAddress::HREG: return writeHreg(id, reg.address, value, cb, unit); default: return 0; } } template template uint16_t ModbusAPI::write(TYPEID id, TAddress reg, bool value, cbTransaction cb, uint8_t unit) { switch (reg.type) { case TAddress::COIL: return writeCoil(id, reg.address, value, cb, unit); default: return 0; } } template template uint16_t ModbusAPI::write(TYPEID id, TAddress reg, uint16_t* value, uint16_t numregs, cbTransaction cb, uint8_t unit) { switch (reg.type) { case TAddress::COIL: return writeCoil(id, reg.address, value, numregs, cb, unit); case TAddress::HREG: return writeHreg(id, reg.address, value, numregs, cb, unit); default: return 0; } } template template uint16_t ModbusAPI::write(TYPEID id, TAddress reg, bool* value, uint16_t numregs, cbTransaction cb, uint8_t unit) { switch (reg.type) { case TAddress::COIL: return writeCoil(id, reg.address, value, cb, numregs, unit); default: return 0; } } template \ bool ModbusAPI::addHreg(uint16_t offset, uint16_t value, uint16_t numregs) { return this->addReg(HREG(offset), value, numregs); } template \ bool ModbusAPI::Hreg(uint16_t offset, uint16_t value) { return this->Reg(HREG(offset), value); } template \ uint16_t ModbusAPI::Hreg(uint16_t offset) { return this->Reg(HREG(offset)); } template \ bool ModbusAPI::removeHreg(uint16_t offset, uint16_t numregs) { return this->removeReg(HREG(offset), numregs); } template \ bool ModbusAPI::addCoil(uint16_t offset, bool value, uint16_t numregs) { return this->addReg(COIL(offset), COIL_VAL(value), numregs); } template \ bool ModbusAPI::addIsts(uint16_t offset, bool value, uint16_t numregs) { return this->addReg(ISTS(offset), ISTS_VAL(value), numregs); } template \ bool ModbusAPI::addIreg(uint16_t offset, uint16_t value, uint16_t numregs) { return this->addReg(IREG(offset), value, numregs); } template \ bool ModbusAPI::Coil(uint16_t offset, bool value) { return this->Reg(COIL(offset), COIL_VAL(value)); } template \ bool ModbusAPI::Ists(uint16_t offset, bool value) { return this->Reg(ISTS(offset), ISTS_VAL(value)); } template \ bool ModbusAPI::Ireg(uint16_t offset, uint16_t value) { return this->Reg(IREG(offset), value); } template \ bool ModbusAPI::Coil(uint16_t offset) { return COIL_BOOL(this->Reg(COIL(offset))); } template \ bool ModbusAPI::Ists(uint16_t offset) { return ISTS_BOOL(this->Reg(ISTS(offset))); } template \ uint16_t ModbusAPI::Ireg(uint16_t offset) { return this->Reg(IREG(offset)); } template \ bool ModbusAPI::removeCoil(uint16_t offset, uint16_t numregs) { return this->removeReg(COIL(offset), numregs); } template \ bool ModbusAPI::removeIsts(uint16_t offset, uint16_t numregs) { return this->removeReg(ISTS(offset), numregs); } template \ bool ModbusAPI::removeIreg(uint16_t offset, uint16_t numregs) { return this->removeReg(IREG(offset), numregs); } template \ bool ModbusAPI::onGetCoil(uint16_t offset, cbModbus cb, uint16_t numregs) { return this->onGet(COIL(offset), cb, numregs); } template \ bool ModbusAPI::onSetCoil(uint16_t offset, cbModbus cb, uint16_t numregs) { return this->onSet(COIL(offset), cb, numregs); } template \ bool ModbusAPI::onGetHreg(uint16_t offset, cbModbus cb, uint16_t numregs) { return this->onGet(HREG(offset), cb, numregs); } template \ bool ModbusAPI::onSetHreg(uint16_t offset, cbModbus cb, uint16_t numregs) { return this->onSet(HREG(offset), cb, numregs); } template \ bool ModbusAPI::onGetIsts(uint16_t offset, cbModbus cb, uint16_t numregs) { return this->onGet(ISTS(offset), cb, numregs); } template \ bool ModbusAPI::onSetIsts(uint16_t offset, cbModbus cb, uint16_t numregs) { return this->onSet(ISTS(offset), cb, numregs); } template \ bool ModbusAPI::onGetIreg(uint16_t offset, cbModbus cb, uint16_t numregs) { return this->onGet(IREG(offset), cb, numregs); } template \ bool ModbusAPI::onSetIreg(uint16_t offset, cbModbus cb, uint16_t numregs) { return this->onSet(IREG(offset), cb, numregs); } template \ bool ModbusAPI::removeOnGetCoil(uint16_t offset, cbModbus cb, uint16_t numregs) { return this->removeOnGet(COIL(offset), cb, numregs); } template \ bool ModbusAPI::removeOnSetCoil(uint16_t offset, cbModbus cb, uint16_t numregs) { return this->removeOnSet(COIL(offset), cb, numregs); } template \ bool ModbusAPI::removeOnGetHreg(uint16_t offset, cbModbus cb, uint16_t numregs) { return this->removeOnGet(HREG(offset), cb, numregs); } template \ bool ModbusAPI::removeOnSetHreg(uint16_t offset, cbModbus cb, uint16_t numregs) { return this->removeOnSet(HREG(offset), cb, numregs); } template \ bool ModbusAPI::removeOnGetIsts(uint16_t offset, cbModbus cb, uint16_t numregs) { return this->removeOnGet(ISTS(offset), cb, numregs); } template \ bool ModbusAPI::removeOnSetIsts(uint16_t offset, cbModbus cb, uint16_t numregs) { return this->removeOnSet(ISTS(offset), cb, numregs); } template \ bool ModbusAPI::removeOnGetIreg(uint16_t offset, cbModbus cb, uint16_t numregs) { return this->removeOnGet(IREG(offset), cb, numregs); } template \ bool ModbusAPI::removeOnSetIreg(uint16_t offset, cbModbus cb, uint16_t numregs) { return this->removeOnSet(IREG(offset), cb, numregs); } template \ template \ uint16_t ModbusAPI::readFileRec(TYPEID slaveId, uint16_t fileNum, uint16_t startRec, uint16_t len, uint8_t* data, cbTransaction cb, uint8_t unit) { if (startRec > MODBUS_MAX_FILES) return 0; if (!this->readSlaveFile(&fileNum, &startRec, &len, 1, Modbus::FC_READ_FILE_REC)) return 0; return this->send(slaveId, NULLREG, cb, unit, data); }; template \ template \ uint16_t ModbusAPI::writeFileRec(TYPEID slaveId, uint16_t fileNum, uint16_t startRec, uint16_t len, uint8_t* data, cbTransaction cb, uint8_t unit) { if (startRec > MODBUS_MAX_FILES) return 0; if (!this->writeSlaveFile(&fileNum, &startRec, &len, 1, Modbus::FC_WRITE_FILE_REC, data)) return 0; return this->send(slaveId, NULLREG, cb, unit); }; template \ template \ uint16_t ModbusAPI::maskHreg(TYPEID slaveId, uint16_t offset, uint16_t andMask, uint16_t orMask, cbTransaction cb, uint8_t unit) { free(this->_frame); this->_len = 7; this->_frame = (uint8_t*) malloc(this->_len); this->_frame[0] = Modbus::FC_MASKWRITE_REG; this->_frame[1] = offset >> 8; this->_frame[2] = offset & 0x00FF; this->_frame[3] = andMask >> 8; this->_frame[4] = andMask & 0x00FF; this->_frame[5] = orMask >> 8; this->_frame[6] = orMask & 0x00FF; return this->send(slaveId, HREG(offset), cb, unit); }; template \ template \ uint16_t ModbusAPI::readWriteHreg(TYPEID ip, \ uint16_t readOffset, uint16_t* readValue, uint16_t readNumregs, \ uint16_t writeOffset, uint16_t* writeValue, uint16_t writeNumregs, \ cbTransaction cb, uint8_t unit) { const uint8_t _header = 10; if (readNumregs < 0x0001 || readNumregs > MODBUS_MAX_WORDS || writeNumregs < 0x0001 || writeNumregs > 0X0079 || !readValue || !writeValue) return 0; free(this->_frame); this->_len = _header + 2 * writeNumregs; this->_frame = (uint8_t*) malloc(this->_len); if (!this->_frame) { this->_reply = Modbus::REPLY_OFF; return 0; } this->_frame[0] = Modbus::FC_READWRITE_REGS; this->_frame[1] = readOffset >> 8; this->_frame[2] = readOffset & 0x00FF; this->_frame[3] = readNumregs >> 8; this->_frame[4] = readNumregs & 0x00FF; this->_frame[5] = writeOffset >> 8; this->_frame[6] = writeOffset & 0x00FF; this->_frame[7] = writeNumregs >> 8; this->_frame[8] = writeNumregs & 0x00FF; this->_frame[9] = this->_len - _header; uint16_t* frame = (uint16_t*)(this->_frame + _header); for (uint8_t i = 0; i < writeNumregs; i++) { frame[i] = __swap_16(writeValue[i]); } return this->send(ip, HREG(readOffset), cb, unit, (uint8_t*)readValue); }; template template uint16_t ModbusAPI::rawRequest(TYPEID ip, \ const uint8_t* data, uint16_t len, cbTransaction cb, uint8_t unit) { free(this->_frame); this->_frame = (uint8_t*)malloc(len); if (!this->_frame) return 0; this->_len = len; memcpy(this->_frame, data, len); return this->send(ip, NULLREG, cb, unit); }; template template uint16_t ModbusAPI::rawResponce(TYPEID ip, \ const uint8_t* data, uint16_t len, uint8_t unit) { free(this->_frame); this->_frame = (uint8_t*)malloc(len); if (!this->_frame) return 0; this->_len = len; memcpy(this->_frame, data, len); return this->send(ip, NULLREG, nullptr, unit, nullptr, false); }; template template uint16_t ModbusAPI::errorResponce(TYPEID ip, Modbus::FunctionCode fn, Modbus::ResultCode excode, uint8_t unit) { this->exceptionResponse(fn, excode); return this->send(ip, NULLREG, nullptr, unit, nullptr, false); }