Hoymiles Lib: Remove hard coded Serial output

The serial port for output of debug information can now changed during runtime
This commit is contained in:
Thomas Basler 2022-12-19 20:52:12 +01:00
parent 3421c9a0b1
commit f689fedf4e
10 changed files with 72 additions and 51 deletions

View File

@ -35,8 +35,8 @@ void HoymilesClass::loop()
if (_radio->isIdle()) { if (_radio->isIdle()) {
std::shared_ptr<InverterAbstract> iv = getInverterByPos(inverterPos); std::shared_ptr<InverterAbstract> iv = getInverterByPos(inverterPos);
if (iv != nullptr) { if (iv != nullptr) {
Serial.print(F("Fetch inverter: ")); _messageOutput->print(F("Fetch inverter: "));
Serial.println(iv->serial(), HEX); _messageOutput->println(iv->serial(), HEX);
iv->sendStatsRequest(_radio.get()); iv->sendStatsRequest(_radio.get());
@ -48,25 +48,25 @@ void HoymilesClass::loop()
if ((iv->SystemConfigPara()->getLastLimitRequestSuccess() == CMD_NOK) if ((iv->SystemConfigPara()->getLastLimitRequestSuccess() == CMD_NOK)
|| ((millis() - iv->SystemConfigPara()->getLastUpdateRequest() > HOY_SYSTEM_CONFIG_PARA_POLL_INTERVAL) || ((millis() - iv->SystemConfigPara()->getLastUpdateRequest() > HOY_SYSTEM_CONFIG_PARA_POLL_INTERVAL)
&& (millis() - iv->SystemConfigPara()->getLastUpdateCommand() > HOY_SYSTEM_CONFIG_PARA_POLL_MIN_DURATION))) { && (millis() - iv->SystemConfigPara()->getLastUpdateCommand() > HOY_SYSTEM_CONFIG_PARA_POLL_MIN_DURATION))) {
Serial.println("Request SystemConfigPara"); _messageOutput->println("Request SystemConfigPara");
iv->sendSystemConfigParaRequest(_radio.get()); iv->sendSystemConfigParaRequest(_radio.get());
} }
// Set limit if required // Set limit if required
if (iv->SystemConfigPara()->getLastLimitCommandSuccess() == CMD_NOK) { if (iv->SystemConfigPara()->getLastLimitCommandSuccess() == CMD_NOK) {
Serial.println(F("Resend ActivePowerControl")); _messageOutput->println(F("Resend ActivePowerControl"));
iv->resendActivePowerControlRequest(_radio.get()); iv->resendActivePowerControlRequest(_radio.get());
} }
// Set power status if required // Set power status if required
if (iv->PowerCommand()->getLastPowerCommandSuccess() == CMD_NOK) { if (iv->PowerCommand()->getLastPowerCommandSuccess() == CMD_NOK) {
Serial.println(F("Resend PowerCommand")); _messageOutput->println(F("Resend PowerCommand"));
iv->resendPowerControlRequest(_radio.get()); iv->resendPowerControlRequest(_radio.get());
} }
// Fetch dev info (but first fetch stats) // Fetch dev info (but first fetch stats)
if (iv->Statistics()->getLastUpdate() > 0 && (iv->DevInfo()->getLastUpdateAll() == 0 || iv->DevInfo()->getLastUpdateSimple() == 0)) { if (iv->Statistics()->getLastUpdate() > 0 && (iv->DevInfo()->getLastUpdateAll() == 0 || iv->DevInfo()->getLastUpdateSimple() == 0)) {
Serial.println(F("Request device info")); _messageOutput->println(F("Request device info"));
iv->sendDevInfoRequest(_radio.get()); iv->sendDevInfoRequest(_radio.get());
} }
} }
@ -176,3 +176,13 @@ void HoymilesClass::setPollInterval(uint32_t interval)
{ {
_pollInterval = interval; _pollInterval = interval;
} }
void HoymilesClass::setMessageOutput(Print* output)
{
_messageOutput = output;
}
Print* HoymilesClass::getMessageOutput()
{
return _messageOutput;
}

View File

@ -4,6 +4,7 @@
#include "HoymilesRadio.h" #include "HoymilesRadio.h"
#include "inverters/InverterAbstract.h" #include "inverters/InverterAbstract.h"
#include "types.h" #include "types.h"
#include <Print.h>
#include <SPI.h> #include <SPI.h>
#include <memory> #include <memory>
#include <vector> #include <vector>
@ -16,6 +17,9 @@ public:
void init(SPIClass* initialisedSpiBus, uint8_t pinCE, uint8_t pinIRQ); void init(SPIClass* initialisedSpiBus, uint8_t pinCE, uint8_t pinIRQ);
void loop(); void loop();
void setMessageOutput(Print* output);
Print* getMessageOutput();
std::shared_ptr<InverterAbstract> addInverter(const char* name, uint64_t serial); std::shared_ptr<InverterAbstract> addInverter(const char* name, uint64_t serial);
std::shared_ptr<InverterAbstract> getInverterByPos(uint8_t pos); std::shared_ptr<InverterAbstract> getInverterByPos(uint8_t pos);
std::shared_ptr<InverterAbstract> getInverterBySerial(uint64_t serial); std::shared_ptr<InverterAbstract> getInverterBySerial(uint64_t serial);
@ -36,6 +40,8 @@ private:
uint32_t _pollInterval = 0; uint32_t _pollInterval = 0;
uint32_t _lastPoll = 0; uint32_t _lastPoll = 0;
Print* _messageOutput = &Serial;
}; };
extern HoymilesClass Hoymiles; extern HoymilesClass Hoymiles;

View File

@ -25,9 +25,9 @@ void HoymilesRadio::init(SPIClass* initialisedSpiBus, uint8_t pinCE, uint8_t pin
_radio->setRetries(0, 0); _radio->setRetries(0, 0);
_radio->maskIRQ(true, true, false); // enable only receiving interrupts _radio->maskIRQ(true, true, false); // enable only receiving interrupts
if (_radio->isChipConnected()) { if (_radio->isChipConnected()) {
Serial.println(F("Connection successfull")); Hoymiles.getMessageOutput()->println(F("Connection successfull"));
} else { } else {
Serial.println(F("Connection error!!")); Hoymiles.getMessageOutput()->println(F("Connection error!!"));
} }
attachInterrupt(digitalPinToInterrupt(pinIRQ), std::bind(&HoymilesRadio::handleIntr, this), FALLING); attachInterrupt(digitalPinToInterrupt(pinIRQ), std::bind(&HoymilesRadio::handleIntr, this), FALLING);
@ -44,7 +44,7 @@ void HoymilesRadio::loop()
} }
if (_packetReceived) { if (_packetReceived) {
Serial.println(F("Interrupt received")); Hoymiles.getMessageOutput()->println(F("Interrupt received"));
while (_radio->available()) { while (_radio->available()) {
if (!(_rxBuffer.size() > FRAGMENT_BUFFER_SIZE)) { if (!(_rxBuffer.size() > FRAGMENT_BUFFER_SIZE)) {
fragment_t f; fragment_t f;
@ -56,7 +56,7 @@ void HoymilesRadio::loop()
_radio->read(f.fragment, f.len); _radio->read(f.fragment, f.len);
_rxBuffer.push(f); _rxBuffer.push(f);
} else { } else {
Serial.println(F("Buffer full")); Hoymiles.getMessageOutput()->println(F("Buffer full"));
_radio->flush_rx(); _radio->flush_rx();
} }
} }
@ -76,11 +76,11 @@ void HoymilesRadio::loop()
dumpBuf(buf, f.fragment, f.len); dumpBuf(buf, f.fragment, f.len);
inv->addRxFragment(f.fragment, f.len); inv->addRxFragment(f.fragment, f.len);
} else { } else {
Serial.println(F("Inverter Not found!")); Hoymiles.getMessageOutput()->println(F("Inverter Not found!"));
} }
} else { } else {
Serial.println(F("Frame kaputt")); Hoymiles.getMessageOutput()->println(F("Frame kaputt"));
} }
// Remove paket from buffer even it was corrupted // Remove paket from buffer even it was corrupted
@ -89,46 +89,46 @@ void HoymilesRadio::loop()
} }
if (_busyFlag && _rxTimeout.occured()) { if (_busyFlag && _rxTimeout.occured()) {
Serial.println(F("RX Period End")); Hoymiles.getMessageOutput()->println(F("RX Period End"));
std::shared_ptr<InverterAbstract> inv = Hoymiles.getInverterBySerial(_commandQueue.front().get()->getTargetAddress()); std::shared_ptr<InverterAbstract> inv = Hoymiles.getInverterBySerial(_commandQueue.front().get()->getTargetAddress());
if (nullptr != inv) { if (nullptr != inv) {
CommandAbstract* cmd = _commandQueue.front().get(); CommandAbstract* cmd = _commandQueue.front().get();
uint8_t verifyResult = inv->verifyAllFragments(cmd); uint8_t verifyResult = inv->verifyAllFragments(cmd);
if (verifyResult == FRAGMENT_ALL_MISSING_RESEND) { if (verifyResult == FRAGMENT_ALL_MISSING_RESEND) {
Serial.println(F("Nothing received, resend whole request")); Hoymiles.getMessageOutput()->println(F("Nothing received, resend whole request"));
sendLastPacketAgain(); sendLastPacketAgain();
} else if (verifyResult == FRAGMENT_ALL_MISSING_TIMEOUT) { } else if (verifyResult == FRAGMENT_ALL_MISSING_TIMEOUT) {
Serial.println(F("Nothing received, resend count exeeded")); Hoymiles.getMessageOutput()->println(F("Nothing received, resend count exeeded"));
_commandQueue.pop(); _commandQueue.pop();
_busyFlag = false; _busyFlag = false;
} else if (verifyResult == FRAGMENT_RETRANSMIT_TIMEOUT) { } else if (verifyResult == FRAGMENT_RETRANSMIT_TIMEOUT) {
Serial.println(F("Retransmit timeout")); Hoymiles.getMessageOutput()->println(F("Retransmit timeout"));
_commandQueue.pop(); _commandQueue.pop();
_busyFlag = false; _busyFlag = false;
} else if (verifyResult == FRAGMENT_HANDLE_ERROR) { } else if (verifyResult == FRAGMENT_HANDLE_ERROR) {
Serial.println(F("Packet handling error")); Hoymiles.getMessageOutput()->println(F("Packet handling error"));
_commandQueue.pop(); _commandQueue.pop();
_busyFlag = false; _busyFlag = false;
} else if (verifyResult > 0) { } else if (verifyResult > 0) {
// Perform Retransmit // Perform Retransmit
Serial.print(F("Request retransmit: ")); Hoymiles.getMessageOutput()->print(F("Request retransmit: "));
Serial.println(verifyResult); Hoymiles.getMessageOutput()->println(verifyResult);
sendRetransmitPacket(verifyResult); sendRetransmitPacket(verifyResult);
} else { } else {
// Successfull received all packages // Successfull received all packages
Serial.println(F("Success")); Hoymiles.getMessageOutput()->println(F("Success"));
_commandQueue.pop(); _commandQueue.pop();
_busyFlag = false; _busyFlag = false;
} }
} else { } else {
// If inverter was not found, assume the command is invalid // If inverter was not found, assume the command is invalid
Serial.println(F("RX: Invalid inverter found")); Hoymiles.getMessageOutput()->println(F("RX: Invalid inverter found"));
_commandQueue.pop(); _commandQueue.pop();
_busyFlag = false; _busyFlag = false;
} }
@ -142,7 +142,7 @@ void HoymilesRadio::loop()
inv->clearRxFragmentBuffer(); inv->clearRxFragmentBuffer();
sendEsbPacket(cmd); sendEsbPacket(cmd);
} else { } else {
Serial.println(F("TX: Invalid inverter found")); Hoymiles.getMessageOutput()->println(F("TX: Invalid inverter found"));
_commandQueue.pop(); _commandQueue.pop();
} }
} }
@ -252,12 +252,12 @@ void HoymilesRadio::sendEsbPacket(CommandAbstract* cmd)
openWritingPipe(s); openWritingPipe(s);
_radio->setRetries(3, 15); _radio->setRetries(3, 15);
Serial.print(F("TX ")); Hoymiles.getMessageOutput()->print(F("TX "));
Serial.print(cmd->getCommandName()); Hoymiles.getMessageOutput()->print(cmd->getCommandName());
Serial.print(F(" Channel: ")); Hoymiles.getMessageOutput()->print(F(" Channel: "));
Serial.print(_radio->getChannel()); Hoymiles.getMessageOutput()->print(_radio->getChannel());
Serial.print(F(" --> ")); Hoymiles.getMessageOutput()->print(F(" --> "));
cmd->dumpDataPayload(Serial); cmd->dumpDataPayload(Hoymiles.getMessageOutput());
_radio->write(cmd->getDataPayload(), cmd->getDataSize()); _radio->write(cmd->getDataPayload(), cmd->getDataSize());
_radio->setRetries(0, 0); _radio->setRetries(0, 0);
@ -289,10 +289,10 @@ void HoymilesRadio::dumpBuf(const char* info, uint8_t buf[], uint8_t len)
{ {
if (NULL != info) if (NULL != info)
Serial.print(String(info)); Hoymiles.getMessageOutput()->print(String(info));
for (uint8_t i = 0; i < len; i++) { for (uint8_t i = 0; i < len; i++) {
Serial.printf("%02X ", buf[i]); Hoymiles.getMessageOutput()->printf("%02X ", buf[i]);
} }
Serial.println(F("")); Hoymiles.getMessageOutput()->println(F(""));
} }

View File

@ -23,13 +23,13 @@ const uint8_t* CommandAbstract::getDataPayload()
return _payload; return _payload;
} }
void CommandAbstract::dumpDataPayload(Stream& stream) void CommandAbstract::dumpDataPayload(Print* stream)
{ {
const uint8_t* payload = getDataPayload(); const uint8_t* payload = getDataPayload();
for (uint8_t i = 0; i < getDataSize(); i++) { for (uint8_t i = 0; i < getDataSize(); i++) {
stream.printf("%02X ", payload[i]); stream->printf("%02X ", payload[i]);
} }
stream.println(""); stream->println("");
} }
uint8_t CommandAbstract::getDataSize() uint8_t CommandAbstract::getDataSize()

View File

@ -15,7 +15,7 @@ public:
virtual ~CommandAbstract() {}; virtual ~CommandAbstract() {};
const uint8_t* getDataPayload(); const uint8_t* getDataPayload();
void dumpDataPayload(Stream& stream); void dumpDataPayload(Print* stream);
uint8_t getDataSize(); uint8_t getDataSize();

View File

@ -3,6 +3,7 @@
* Copyright (C) 2022 Thomas Basler and others * Copyright (C) 2022 Thomas Basler and others
*/ */
#include "InverterAbstract.h" #include "InverterAbstract.h"
#include "../Hoymiles.h"
#include "crc.h" #include "crc.h"
#include <cstring> #include <cstring>
@ -107,18 +108,18 @@ void InverterAbstract::clearRxFragmentBuffer()
void InverterAbstract::addRxFragment(uint8_t fragment[], uint8_t len) void InverterAbstract::addRxFragment(uint8_t fragment[], uint8_t len)
{ {
if (len < 11) { if (len < 11) {
Serial.printf("FATAL: (%s, %d) fragment too short\n", __FILE__, __LINE__); Hoymiles.getMessageOutput()->printf("FATAL: (%s, %d) fragment too short\n", __FILE__, __LINE__);
return; return;
} }
if (len - 11 > MAX_RF_PAYLOAD_SIZE) { if (len - 11 > MAX_RF_PAYLOAD_SIZE) {
Serial.printf("FATAL: (%s, %d) fragment too large\n", __FILE__, __LINE__); Hoymiles.getMessageOutput()->printf("FATAL: (%s, %d) fragment too large\n", __FILE__, __LINE__);
return; return;
} }
uint8_t fragmentCount = fragment[9]; uint8_t fragmentCount = fragment[9];
if (fragmentCount == 0) { if (fragmentCount == 0) {
Serial.println("ERROR: fragment number zero received and ignored"); Hoymiles.getMessageOutput()->println("ERROR: fragment number zero received and ignored");
return; return;
} }
@ -145,7 +146,7 @@ uint8_t InverterAbstract::verifyAllFragments(CommandAbstract* cmd)
{ {
// All missing // All missing
if (_rxFragmentLastPacketId == 0) { if (_rxFragmentLastPacketId == 0) {
Serial.println(F("All missing")); Hoymiles.getMessageOutput()->println(F("All missing"));
if (cmd->getSendCount() <= MAX_RESEND_COUNT) { if (cmd->getSendCount() <= MAX_RESEND_COUNT) {
return FRAGMENT_ALL_MISSING_RESEND; return FRAGMENT_ALL_MISSING_RESEND;
} else { } else {
@ -156,7 +157,7 @@ uint8_t InverterAbstract::verifyAllFragments(CommandAbstract* cmd)
// Last fragment is missing (thte one with 0x80) // Last fragment is missing (thte one with 0x80)
if (_rxFragmentMaxPacketId == 0) { if (_rxFragmentMaxPacketId == 0) {
Serial.println(F("Last missing")); Hoymiles.getMessageOutput()->println(F("Last missing"));
if (_rxFragmentRetransmitCnt++ < MAX_RETRANSMIT_COUNT) { if (_rxFragmentRetransmitCnt++ < MAX_RETRANSMIT_COUNT) {
return _rxFragmentLastPacketId + 1; return _rxFragmentLastPacketId + 1;
} else { } else {
@ -168,7 +169,7 @@ uint8_t InverterAbstract::verifyAllFragments(CommandAbstract* cmd)
// Middle fragment is missing // Middle fragment is missing
for (uint8_t i = 0; i < _rxFragmentMaxPacketId - 1; i++) { for (uint8_t i = 0; i < _rxFragmentMaxPacketId - 1; i++) {
if (!_rxFragmentBuffer[i].wasReceived) { if (!_rxFragmentBuffer[i].wasReceived) {
Serial.println(F("Middle missing")); Hoymiles.getMessageOutput()->println(F("Middle missing"));
if (_rxFragmentRetransmitCnt++ < MAX_RETRANSMIT_COUNT) { if (_rxFragmentRetransmitCnt++ < MAX_RETRANSMIT_COUNT) {
return i + 1; return i + 1;
} else { } else {

View File

@ -3,6 +3,7 @@
* Copyright (C) 2022 Thomas Basler and others * Copyright (C) 2022 Thomas Basler and others
*/ */
#include "AlarmLogParser.h" #include "AlarmLogParser.h"
#include "../Hoymiles.h"
#include <cstring> #include <cstring>
void AlarmLogParser::clearBuffer() void AlarmLogParser::clearBuffer()
@ -14,7 +15,7 @@ void AlarmLogParser::clearBuffer()
void AlarmLogParser::appendFragment(uint8_t offset, uint8_t* payload, uint8_t len) void AlarmLogParser::appendFragment(uint8_t offset, uint8_t* payload, uint8_t len)
{ {
if (offset + len > ALARM_LOG_PAYLOAD_SIZE) { if (offset + len > ALARM_LOG_PAYLOAD_SIZE) {
Serial.printf("FATAL: (%s, %d) stats packet too large for buffer (%d > %d)\n", __FILE__, __LINE__, offset + len, ALARM_LOG_PAYLOAD_SIZE); Hoymiles.getMessageOutput()->printf("FATAL: (%s, %d) stats packet too large for buffer (%d > %d)\n", __FILE__, __LINE__, offset + len, ALARM_LOG_PAYLOAD_SIZE);
return; return;
} }
memcpy(&_payloadAlarmLog[offset], payload, len); memcpy(&_payloadAlarmLog[offset], payload, len);

View File

@ -3,6 +3,7 @@
* Copyright (C) 2022 Thomas Basler and others * Copyright (C) 2022 Thomas Basler and others
*/ */
#include "DevInfoParser.h" #include "DevInfoParser.h"
#include "../Hoymiles.h"
#include <cstring> #include <cstring>
#define ALL 0xff #define ALL 0xff
@ -36,7 +37,7 @@ void DevInfoParser::clearBufferAll()
void DevInfoParser::appendFragmentAll(uint8_t offset, uint8_t* payload, uint8_t len) void DevInfoParser::appendFragmentAll(uint8_t offset, uint8_t* payload, uint8_t len)
{ {
if (offset + len > DEV_INFO_SIZE) { if (offset + len > DEV_INFO_SIZE) {
Serial.printf("FATAL: (%s, %d) dev info all packet too large for buffer\n", __FILE__, __LINE__); Hoymiles.getMessageOutput()->printf("FATAL: (%s, %d) dev info all packet too large for buffer\n", __FILE__, __LINE__);
return; return;
} }
memcpy(&_payloadDevInfoAll[offset], payload, len); memcpy(&_payloadDevInfoAll[offset], payload, len);
@ -52,7 +53,7 @@ void DevInfoParser::clearBufferSimple()
void DevInfoParser::appendFragmentSimple(uint8_t offset, uint8_t* payload, uint8_t len) void DevInfoParser::appendFragmentSimple(uint8_t offset, uint8_t* payload, uint8_t len)
{ {
if (offset + len > DEV_INFO_SIZE) { if (offset + len > DEV_INFO_SIZE) {
Serial.printf("FATAL: (%s, %d) dev info Simple packet too large for buffer\n", __FILE__, __LINE__); Hoymiles.getMessageOutput()->printf("FATAL: (%s, %d) dev info Simple packet too large for buffer\n", __FILE__, __LINE__);
return; return;
} }
memcpy(&_payloadDevInfoSimple[offset], payload, len); memcpy(&_payloadDevInfoSimple[offset], payload, len);
@ -88,7 +89,7 @@ uint16_t DevInfoParser::getFwBuildVersion()
time_t DevInfoParser::getFwBuildDateTime() time_t DevInfoParser::getFwBuildDateTime()
{ {
struct tm timeinfo = { }; struct tm timeinfo = {};
timeinfo.tm_year = ((((uint16_t)_payloadDevInfoAll[2]) << 8) | _payloadDevInfoAll[3]) - 1900; timeinfo.tm_year = ((((uint16_t)_payloadDevInfoAll[2]) << 8) | _payloadDevInfoAll[3]) - 1900;
timeinfo.tm_mon = ((((uint16_t)_payloadDevInfoAll[4]) << 8) | _payloadDevInfoAll[5]) / 100 - 1; timeinfo.tm_mon = ((((uint16_t)_payloadDevInfoAll[4]) << 8) | _payloadDevInfoAll[5]) / 100 - 1;

View File

@ -3,6 +3,7 @@
* Copyright (C) 2022 Thomas Basler and others * Copyright (C) 2022 Thomas Basler and others
*/ */
#include "StatisticsParser.h" #include "StatisticsParser.h"
#include "../Hoymiles.h"
static float calcYieldTotalCh0(StatisticsParser* iv, uint8_t arg0); static float calcYieldTotalCh0(StatisticsParser* iv, uint8_t arg0);
static float calcYieldDayCh0(StatisticsParser* iv, uint8_t arg0); static float calcYieldDayCh0(StatisticsParser* iv, uint8_t arg0);
@ -42,7 +43,7 @@ void StatisticsParser::clearBuffer()
void StatisticsParser::appendFragment(uint8_t offset, uint8_t* payload, uint8_t len) void StatisticsParser::appendFragment(uint8_t offset, uint8_t* payload, uint8_t len)
{ {
if (offset + len > STATISTIC_PACKET_SIZE) { if (offset + len > STATISTIC_PACKET_SIZE) {
Serial.printf("FATAL: (%s, %d) stats packet too large for buffer\n", __FILE__, __LINE__); Hoymiles.getMessageOutput()->printf("FATAL: (%s, %d) stats packet too large for buffer\n", __FILE__, __LINE__);
return; return;
} }
memcpy(&_payloadStatistic[offset], payload, len); memcpy(&_payloadStatistic[offset], payload, len);

View File

@ -3,6 +3,7 @@
* Copyright (C) 2022 Thomas Basler and others * Copyright (C) 2022 Thomas Basler and others
*/ */
#include "SystemConfigParaParser.h" #include "SystemConfigParaParser.h"
#include "../Hoymiles.h"
#include <cstring> #include <cstring>
void SystemConfigParaParser::clearBuffer() void SystemConfigParaParser::clearBuffer()
@ -14,7 +15,7 @@ void SystemConfigParaParser::clearBuffer()
void SystemConfigParaParser::appendFragment(uint8_t offset, uint8_t* payload, uint8_t len) void SystemConfigParaParser::appendFragment(uint8_t offset, uint8_t* payload, uint8_t len)
{ {
if (offset + len > (SYSTEM_CONFIG_PARA_SIZE)) { if (offset + len > (SYSTEM_CONFIG_PARA_SIZE)) {
Serial.printf("FATAL: (%s, %d) stats packet too large for buffer\n", __FILE__, __LINE__); Hoymiles.getMessageOutput()->printf("FATAL: (%s, %d) stats packet too large for buffer\n", __FILE__, __LINE__);
return; return;
} }
memcpy(&_payload[offset], payload, len); memcpy(&_payload[offset], payload, len);