Browse Source

sns: flush does not mean reset for both tx and rx

* clean-up useless stream read() / flush(), rely on timer and internal state
  avoids wdt reset with sensors looping on available()
* fix some instances of `available()` in boolean context to use `>0`
  (not everything returns sign, but if it does - we are in trouble)
* util func to read available bytes from the stream using buffered
  interface instead of 1 byte at a time
pull/2558/head
Maxim Prokhorov 1 year ago
parent
commit
a3d8582a70
5 changed files with 68 additions and 48 deletions
  1. +0
    -1
      code/espurna/sensors/CSE7766Sensor.h
  2. +3
    -8
      code/espurna/sensors/PZEM004TV30Sensor.h
  3. +45
    -39
      code/espurna/sensors/V9261FSensor.h
  4. +18
    -0
      code/espurna/utils.cpp
  5. +2
    -0
      code/espurna/utils.h

+ 0
- 1
code/espurna/sensors/CSE7766Sensor.h View File

@ -296,7 +296,6 @@ class CSE7766Sensor : public BaseEmonSensor {
_data[_data_index++] = byte;
if (_data_index > 23) {
_serial->flush();
break;
}


+ 3
- 8
code/espurna/sensors/PZEM004TV30Sensor.h View File

@ -472,11 +472,6 @@ public:
});
}
void flush() {
while (_port->read() >= 0) {
}
}
// ---------------------------------------------------------------------
void setDebug(bool debug) {
@ -553,14 +548,14 @@ public:
}
void pre() override {
flush();
consumeAvailable(*_port);
if (_reset_energy) {
const auto result [[gnu::unused]] = modbusResetEnergy();
PZEM_DEBUG_MSG_P(PSTR("[PZEM004TV3] Energy reset - %s\n"),
result ? PSTR("OK") : PSTR("FAIL"));
_reset_energy = false;
flush();
consumeAvailable(*_port);
}
if (TimeSource::now() - _last_update > _update_interval) {
@ -618,7 +613,7 @@ void PZEM004TV30Sensor::command_address(::terminal::CommandContext&& ctx) {
uint8_t address = espurna::settings::internal::convert<uint8_t>(ctx.argv[1]);
_instance->flush();
consumeAvailable(*(_instance->_port));
if (_instance->modbusChangeAddress(address)) {
_instance->_address = address;
setSetting("pzemv30Addr", address);


+ 45
- 39
code/espurna/sensors/V9261FSensor.h View File

@ -150,45 +150,53 @@ class V9261FSensor : public BaseEmonSensor {
void _read() {
// we are seeing the data request
if (_state == 0) {
while (_serial->available()) {
_serial->flush();
_found = true;
_timestamp = TimeSource::now();
const auto available = _serial->available();
if (available <= 0) {
if (_found && (TimeSource::now() - _timestamp > SyncInterval)) {
_index = 0;
_state = 1;
}
return;
}
if (_found && (TimeSource::now() - _timestamp > SyncInterval)) {
_serial->flush();
_index = 0;
_state = 1;
}
consumeAvailable(*_serial);
_found = true;
_timestamp = TimeSource::now();
// ...which we just skip...
} else if (_state == 1) {
while (_serial->available()) {
_serial->read();
if (_index++ >= 7) {
_serial->flush();
_index = 0;
_state = 2;
}
_index += consumeAvailable(*_serial);
if (_index++ >= 7) {
_index = 0;
_state = 2;
}
// ...until we receive response...
} else if (_state == 2) {
while (_serial->available()) {
_data[_index] = _serial->read();
if (_index++ >= 19) {
_serial->flush();
_timestamp = TimeSource::now();
_state = 3;
}
const auto available = _serial->available();
if (available <= 0) {
return;
}
_index += _serial->read(&_data[_index], std::min(
static_cast<size_t>(available), sizeof(_data)));
if (_index >= 19) {
_timestamp = TimeSource::now();
_state = 3;
}
// validate received data and wait for the next request -> response
// FE1104 25F2420069C1BCFF20670C38C05E4101 B6
// ^^^^^^ - HEAD byte, mask, number of valeus
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - u32 4 times
// ^^ - CRC byte
} else if (_state == 3) {
if (_checksum(_data)) {
if (_checksum(&_data[0], &_data[19]) == _data[19]) {
_active = (double) (
(_data[3]) +
@ -241,13 +249,10 @@ class V9261FSensor : public BaseEmonSensor {
_index = 0;
_state = 4;
// ... by waiting for a bit
} else if (_state == 4) {
while (_serial->available()) {
_serial->flush();
_timestamp = TimeSource::now();
}
consumeAvailable(*_serial);
if (TimeSource::now() - _timestamp > SyncInterval) {
_state = 1;
}
@ -256,13 +261,13 @@ class V9261FSensor : public BaseEmonSensor {
}
static bool _checksum(const uint8_t (&data)[24]) {
uint8_t checksum = 0;
for (size_t i = 0; i < 19; i++) {
checksum = checksum + data[i];
static uint8_t _checksum(const uint8_t* begin, const uint8_t* end) {
uint8_t out = 0;
for (auto it = begin; it != end; ++it) {
out += (*it);
}
checksum = ~checksum + 0x33;
return checksum == data[19];
out = ~out + 0x33;
return out;
}
// ---------------------------------------------------------------------
@ -281,11 +286,12 @@ class V9261FSensor : public BaseEmonSensor {
TimeSource::time_point _last_reading;
TimeSource::time_point _timestamp;
unsigned char _state { 0 };
unsigned char _index { 0 };
int _state { 0 };
bool _found { false };
bool _reading { false };
unsigned char _data[24] {0};
uint8_t _data[24] {0};
size_t _index { 0 };
};


+ 18
- 0
code/espurna/utils.cpp View File

@ -442,3 +442,21 @@ size_t hexDecode(const char* in, size_t in_size, uint8_t* out, size_t out_size)
uint8_t* out_ptr { hexDecode(in, in + in_size, out, out + out_size) };
return out_ptr - out;
}
size_t consumeAvailable(Stream& stream) {
const auto result = stream.available();
if (result <= 0) {
return 0;
}
const auto available = static_cast<size_t>(result);
size_t size = 0;
uint8_t buf[64];
do {
const auto chunk = std::min(available, std::size(buf));
stream.read(&buf[0], chunk);
size += chunk;
} while (size != available);
return size;
}

+ 2
- 0
code/espurna/utils.h View File

@ -59,3 +59,5 @@ bool tryParseId(espurna::StringView, size_t limit, size_t& out);
bool tryParseIdPath(espurna::StringView, size_t limit, size_t& out);
espurna::StringView stripNewline(espurna::StringView);
size_t consumeAvailable(Stream&);

Loading…
Cancel
Save