Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lang/el.lang.json
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@
"RxFailNothing": "Αποτυχημένα RX: Δεν λαμβάνετε τίποτα",
"RxFailPartial": "Αποτυχημένα RX: Μερική λήψη",
"RxFailCorrupt": "Αποτυχημένα RX: Λήψη κατεστραμμένου",
"RxLastFrequency": "RX frequency of the latest package received",
"MHz": "{mhz} MHz",
"TxReRequest": "TX Επαναίτηση Fragment",
"StatsReset": "Επαναφορά Στατιστικών",
"StatsResetting": "Επαναφορά...",
Expand Down
2 changes: 2 additions & 0 deletions lang/es.lang.json
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@
"RxFailNothing": "RX Fail: Receive Nothing",
"RxFailPartial": "RX Fail: Receive Partial",
"RxFailCorrupt": "RX Fail: Receive Corrupt",
"RxLastFrequency": "RX frequency of the latest package received",
"MHz": "{mhz} MHz",
"TxReRequest": "TX Re-Request Fragment",
"StatsReset": "Reset Statistics",
"StatsResetting": "Resetting...",
Expand Down
2 changes: 2 additions & 0 deletions lang/it.lang.json
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@
"RxFailNothing": "RX Fail: Receive Nothing",
"RxFailPartial": "RX Fail: Receive Partial",
"RxFailCorrupt": "RX Fail: Receive Corrupt",
"RxLastFrequency": "RX frequency of the latest package received",
"MHz": "{mhz} MHz",
"TxReRequest": "TX Re-Request Fragment",
"StatsReset": "Reset Statistics",
"StatsResetting": "Resetting...",
Expand Down
4 changes: 3 additions & 1 deletion lib/Hoymiles/src/Hoymiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ void HoymilesClass::loop()
_messageOutput->print("Fetch inverter: ");
_messageOutput->println(iv->serial(), HEX);

if (!iv->isReachable()) {
iv->getFrequencyManager()->startNextFetch();

if (!iv->isReachable() || iv->getFrequencyManager()->shouldSendChangeChannelCommand()) {
iv->sendChangeChannelRequest();
}

Expand Down
16 changes: 9 additions & 7 deletions lib/Hoymiles/src/HoymilesRadio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "HoymilesRadio.h"
#include "Hoymiles.h"
#include "crc.h"
#include "frequencymanagers/FrequencyManagerAbstract.h"

serial_u HoymilesRadio::DtuSerial() const
{
Expand Down Expand Up @@ -34,21 +35,21 @@ bool HoymilesRadio::checkFragmentCrc(const fragment_t& fragment) const
return (crc == fragment.fragment[fragment.len - 1]);
}

void HoymilesRadio::sendRetransmitPacket(const uint8_t fragment_id)
void HoymilesRadio::sendRetransmitPacket(const uint8_t fragment_id, FrequencyManagerAbstract& freq_mgr)
{
CommandAbstract* cmd = _commandQueue.front().get();

CommandAbstract* requestCmd = cmd->getRequestFrameCommand(fragment_id);

if (requestCmd != nullptr) {
sendEsbPacket(*requestCmd);
sendEsbPacket(*requestCmd, freq_mgr);
}
}

void HoymilesRadio::sendLastPacketAgain()
void HoymilesRadio::sendLastPacketAgain(FrequencyManagerAbstract &freq_mgr)
{
CommandAbstract* cmd = _commandQueue.front().get();
sendEsbPacket(*cmd);
sendEsbPacket(*cmd, freq_mgr);
}

void HoymilesRadio::handleReceivedPackage()
Expand All @@ -60,9 +61,10 @@ void HoymilesRadio::handleReceivedPackage()
if (nullptr != inv) {
CommandAbstract* cmd = _commandQueue.front().get();
uint8_t verifyResult = inv->verifyAllFragments(*cmd);
inv->getFrequencyManager()->processRXResult(cmd, verifyResult);
if (verifyResult == FRAGMENT_ALL_MISSING_RESEND) {
Hoymiles.getMessageOutput()->println("Nothing received, resend whole request");
sendLastPacketAgain();
sendLastPacketAgain(*inv->getFrequencyManager());

} else if (verifyResult == FRAGMENT_ALL_MISSING_TIMEOUT) {
Hoymiles.getMessageOutput()->println("Nothing received, resend count exeeded");
Expand Down Expand Up @@ -101,7 +103,7 @@ void HoymilesRadio::handleReceivedPackage()
// Statistics: Count TX Re-Request Fragment
inv->RadioStats.TxReRequestFragment++;

sendRetransmitPacket(verifyResult);
sendRetransmitPacket(verifyResult, *inv->getFrequencyManager());

} else {
// Successful received all packages
Expand Down Expand Up @@ -132,7 +134,7 @@ void HoymilesRadio::handleReceivedPackage()
// Statistics: TX Requests
inv->RadioStats.TxRequestData++;

sendEsbPacket(*cmd);
sendEsbPacket(*cmd, *inv->getFrequencyManager());
} else {
Hoymiles.getMessageOutput()->println("TX: Invalid inverter found");
_commandQueue.pop();
Expand Down
7 changes: 4 additions & 3 deletions lib/Hoymiles/src/HoymilesRadio.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "Arduino.h"
#include "commands/CommandAbstract.h"
#include "frequencymanagers/FrequencyManagerAbstract.h"
#include "queue/CommandQueue.h"
#include "types.h"
#include <TimeoutHelper.h>
Expand Down Expand Up @@ -75,9 +76,9 @@ class HoymilesRadio {
static void dumpBuf(const uint8_t buf[], const uint8_t len, const bool appendNewline = true);

bool checkFragmentCrc(const fragment_t& fragment) const;
virtual void sendEsbPacket(CommandAbstract& cmd) = 0;
void sendRetransmitPacket(const uint8_t fragment_id);
void sendLastPacketAgain();
virtual void sendEsbPacket(CommandAbstract& cmd, FrequencyManagerAbstract& freq_mgr) = 0;
void sendRetransmitPacket(const uint8_t fragment_id, FrequencyManagerAbstract& freq_mgr);
void sendLastPacketAgain(FrequencyManagerAbstract& freq_mgr);
void handleReceivedPackage();

serial_u _dtuSerial;
Expand Down
48 changes: 42 additions & 6 deletions lib/Hoymiles/src/HoymilesRadio_CMT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "crc.h"
#include <FunctionalInterrupt.h>
#include <frozen/map.h>
#include "frequencymanagers/FrequencyManagerAbstract.h"

constexpr CountryFrequencyDefinition_t make_value(FrequencyBand_t Band, uint32_t Freq_Legal_Min, uint32_t Freq_Legal_Max, uint32_t Freq_Default, uint32_t Freq_StartUp)
{
Expand Down Expand Up @@ -192,6 +193,7 @@ void HoymilesRadio_CMT::setPALevel(const int8_t paLevel)
if (!_isInitialized) {
return;
}
this->_pa_level = paLevel;

if (_radio->setPALevel(paLevel)) {
Hoymiles.getMessageOutput()->printf("CMT TX power set to %" PRId8 " dBm\r\n", paLevel);
Expand Down Expand Up @@ -232,6 +234,16 @@ uint32_t HoymilesRadio_CMT::getMaxFrequency() const
return countryDefinition.at(_countryMode).Freq_Max;
}

uint32_t HoymilesRadio_CMT::getLegalMinFrequency() const
{
return countryDefinition.at(_countryMode).Freq_Legal_Min;
}

uint32_t HoymilesRadio_CMT::getLegalMaxFrequency() const
{
return countryDefinition.at(_countryMode).Freq_Legal_Max;
}

CountryModeId_t HoymilesRadio_CMT::getCountryMode() const
{
return _countryMode;
Expand Down Expand Up @@ -262,26 +274,50 @@ void ARDUINO_ISR_ATTR HoymilesRadio_CMT::handleInt2()
_packetReceived = true;
}

void HoymilesRadio_CMT::sendEsbPacket(CommandAbstract& cmd)
void HoymilesRadio_CMT::handleTxError(bool is_error) {
if(!is_error) {
this->_tx_error_counter = 0;
return;
}
this->_tx_error_counter++;
if(_tx_error_counter==5 || _tx_error_counter == 10 || _tx_error_counter == 15) {
Hoymiles.getMessageOutput()->println("TX recovery: Re-applying PA level");
this->setPALevel(this->_pa_level);
return;
}
if(_tx_error_counter==20 || _tx_error_counter == 25) {
Hoymiles.getMessageOutput()->println("TX recovery: Re-initializing radio");
this->_radio->begin();
}
if(_tx_error_counter >= 30) {
Hoymiles.getMessageOutput()->println("TX recovery: Giving up");
this->_isInitialized = false;
}

}

void HoymilesRadio_CMT::sendEsbPacket(CommandAbstract& cmd, FrequencyManagerAbstract &freq_mgr)
{
cmd.incrementSendCount();

cmd.setRouterAddress(DtuSerial().u64);

_radio->stopListening();

if (cmd.getDataPayload()[0] == 0x56) { // @todo(tbnobody) Bad hack to identify ChannelChange Command
cmtSwitchDtuFreq(getInvBootFrequency());
}
cmtSwitchDtuFreq(freq_mgr.getTXFrequency(cmd));

Hoymiles.getMessageOutput()->printf("TX %s %.2f MHz --> ",
cmd.getCommandName().c_str(), getFrequencyFromChannel(_radio->getChannel()) / 1000000.0);
cmd.dumpDataPayload(Hoymiles.getMessageOutput());

if (!_radio->write(cmd.getDataPayload(), cmd.getDataSize())) {
bool tx_worked = _radio->write(cmd.getDataPayload(), cmd.getDataSize());
if (!tx_worked) {
Hoymiles.getMessageOutput()->println("TX SPI Timeout");
}
cmtSwitchDtuFreq(_inverterTargetFrequency);
this->handleTxError(!tx_worked);


cmtSwitchDtuFreq(freq_mgr.getRXFrequency(cmd));
_radio->startListening();
_busyFlag = true;
_rxTimeout.set(cmd.getTimeout());
Expand Down
8 changes: 7 additions & 1 deletion lib/Hoymiles/src/HoymilesRadio_CMT.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ class HoymilesRadio_CMT : public HoymilesRadio {

uint32_t getMinFrequency() const;
uint32_t getMaxFrequency() const;
uint32_t getLegalMinFrequency() const;
uint32_t getLegalMaxFrequency() const;
static constexpr uint32_t getChannelWidth()
{
return FH_OFFSET * CMT2300A_ONE_STEP_SIZE;
Expand All @@ -70,7 +72,7 @@ class HoymilesRadio_CMT : public HoymilesRadio {
void ARDUINO_ISR_ATTR handleInt1();
void ARDUINO_ISR_ATTR handleInt2();

void sendEsbPacket(CommandAbstract& cmd);
void sendEsbPacket(CommandAbstract& cmd, FrequencyManagerAbstract &freq_mgr);

std::unique_ptr<CMT2300A> _radio;

Expand All @@ -79,6 +81,7 @@ class HoymilesRadio_CMT : public HoymilesRadio {

bool _gpio2_configured = false;
bool _gpio3_configured = false;
int8_t _pa_level = 0;

std::queue<fragment_t> _rxBuffer;
TimeoutHelper _txTimeout;
Expand All @@ -88,4 +91,7 @@ class HoymilesRadio_CMT : public HoymilesRadio {
bool cmtSwitchDtuFreq(const uint32_t to_frequency);

CountryModeId_t _countryMode;

int _tx_error_counter = 0;
void handleTxError(bool is_error);
};
4 changes: 3 additions & 1 deletion lib/Hoymiles/src/HoymilesRadio_NRF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,10 @@ void HoymilesRadio_NRF::switchRxCh()
_radio->startListening();
}

void HoymilesRadio_NRF::sendEsbPacket(CommandAbstract& cmd)
void HoymilesRadio_NRF::sendEsbPacket(CommandAbstract& cmd, FrequencyManagerAbstract& freq_mgr)
{
(void) freq_mgr;

cmd.incrementSendCount();

cmd.setRouterAddress(DtuSerial().u64);
Expand Down
2 changes: 1 addition & 1 deletion lib/Hoymiles/src/HoymilesRadio_NRF.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class HoymilesRadio_NRF : public HoymilesRadio {
void openReadingPipe();
void openWritingPipe(const serial_u serial);

void sendEsbPacket(CommandAbstract& cmd);
void sendEsbPacket(CommandAbstract& cmd, FrequencyManagerAbstract &freq_mgr);

std::unique_ptr<SPIClass> _spiPtr;
std::unique_ptr<RF24> _radio;
Expand Down
6 changes: 3 additions & 3 deletions lib/Hoymiles/src/commands/ChannelChangeCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ bool ChannelChangeCommand::handleResponse(const fragment_t fragment[], const uin
return true;
}

uint8_t ChannelChangeCommand::getMaxResendCount()
uint8_t ChannelChangeCommand::getMaxResendCount() const
{
// This command will never retrieve an answer. Therefor it's not required to repeat it
return 0;
// This command will never retrieve an answer. Repeat anyway to allow FrequencyManager to send it on a few different frequencies.
return MAX_RESEND_COUNT;
}
2 changes: 1 addition & 1 deletion lib/Hoymiles/src/commands/ChannelChangeCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ class ChannelChangeCommand : public CommandAbstract {

virtual bool handleResponse(const fragment_t fragment[], const uint8_t max_fragment_id);

virtual uint8_t getMaxResendCount();
virtual uint8_t getMaxResendCount() const;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: GPL-2.0-or-later

#include "FrequencyManagerAbstract.h"
#include "inverters/InverterAbstract.h"
#include "commands/CommandAbstract.h"

FrequencyManagerAbstract::FrequencyManagerAbstract(InverterAbstract* inv) {
this->_inv = inv;
}
24 changes: 24 additions & 0 deletions lib/Hoymiles/src/frequencymanagers/FrequencyManagerAbstract.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once

#include "Arduino.h"
#include "types.h"

class InverterAbstract;
class CommandAbstract;

class FrequencyManagerAbstract {
public:
explicit FrequencyManagerAbstract(InverterAbstract* inv);
virtual ~FrequencyManagerAbstract() {};

virtual uint32_t getTXFrequency(CommandAbstract& cmd) = 0;
virtual uint32_t getRXFrequency(CommandAbstract& cmd) = 0;

virtual void processRXResult(CommandAbstract *cmd, uint8_t verify_fragments_result) = 0;
virtual bool shouldSendChangeChannelCommand() = 0;
virtual void startNextFetch() = 0;
protected:

InverterAbstract* _inv;
};
Loading