From 122e4567b1e698c14fc6e9b3dccadd125d8579df Mon Sep 17 00:00:00 2001 From: Martin Grill Date: Sat, 19 Mar 2022 15:04:21 +0100 Subject: [PATCH] switched to dynamic payload mode, added a pretender --- tools/rpi/discover/CMakeLists.txt | 4 ++ tools/rpi/discover/common.cpp | 45 ++++++++++++++++ tools/rpi/discover/common.hpp | 18 +++++++ tools/rpi/discover/discover.cpp | 21 ++++---- tools/rpi/discover/pretender.cpp | 90 +++++++++++++++++++++++++++++++ 5 files changed, 168 insertions(+), 10 deletions(-) create mode 100644 tools/rpi/discover/common.cpp create mode 100644 tools/rpi/discover/common.hpp create mode 100644 tools/rpi/discover/pretender.cpp diff --git a/tools/rpi/discover/CMakeLists.txt b/tools/rpi/discover/CMakeLists.txt index af3f27ee..761276a1 100644 --- a/tools/rpi/discover/CMakeLists.txt +++ b/tools/rpi/discover/CMakeLists.txt @@ -8,3 +8,7 @@ message(STATUS "using RF24 library: ${RF24}") add_executable(discover discover.cpp) target_link_libraries(discover PUBLIC ${RF24} pthread) + +add_executable(pretender pretender.cpp common.cpp) +target_link_libraries(pretender PUBLIC ${RF24} pthread) + diff --git a/tools/rpi/discover/common.cpp b/tools/rpi/discover/common.cpp new file mode 100644 index 00000000..ce344518 --- /dev/null +++ b/tools/rpi/discover/common.cpp @@ -0,0 +1,45 @@ +#include "common.hpp" + +#include +#include +#include + +using namespace std; + +/** Convert given 5-byte address to human readable hex string */ +string prettyPrintAddr(string &a) +{ + ostringstream o; + o << hex << setw(2) + << setfill('0') << setw(2) << int(a[0]) + << ":" << setw(2) << int(a[1]) + << ":" << setw(2) << int(a[2]) + << ":" << setw(2) << int(a[3]) + << ":" << setw(2) << int(a[4]) << dec; + return o.str(); +} + + +/** Convert a Hoymiles inverter/DTU serial number into its + * corresponding NRF24 address byte sequence (5 bytes). + * + * The inverters use a BCD representation of the last 8 + * digits of their serial number, in reverse byte order, + * followed by \x01. + */ +string serno2shockburstaddrbytes(uint64_t n) +{ + char b[5]; + b[3] = (((n/10)%10) << 4) | ((n/1)%10); + b[2] = (((n/1000)%10) << 4) | ((n/100)%10); + b[1] = (((n/100000)%10) << 4) | ((n/10000)%10); + b[0] = (((n/10000000)%10) << 4) | ((n/1000000)%10); + b[4] = 0x01; + + string s = string(b, sizeof(b)); + + cout << dec << "ser# " << n << " --> addr " + << prettyPrintAddr(s) << endl; + return s; +} + diff --git a/tools/rpi/discover/common.hpp b/tools/rpi/discover/common.hpp new file mode 100644 index 00000000..7ba2f9b1 --- /dev/null +++ b/tools/rpi/discover/common.hpp @@ -0,0 +1,18 @@ +#include +#include + +using namespace std; + +/** Convert given 5-byte address to human readable hex string */ +string prettyPrintAddr(string &a); + + +/** Convert a Hoymiles inverter/DTU serial number into its + * corresponding NRF24 address byte sequence (5 bytes). + * + * The inverters use a BCD representation of the last 8 + * digits of their serial number, in reverse byte order, + * followed by \x01. + */ +string serno2shockburstaddrbytes(uint64_t n); + diff --git a/tools/rpi/discover/discover.cpp b/tools/rpi/discover/discover.cpp index 85df891c..05149c68 100644 --- a/tools/rpi/discover/discover.cpp +++ b/tools/rpi/discover/discover.cpp @@ -22,10 +22,7 @@ using namespace std; // Generic: RF24 radio(22, 0); -/****************** Linux (BBB,x86,etc) ***********************/ // See http://nRF24.github.io/RF24/pages.html for more information on usage -// See http://iotdk.intel.com/docs/master/mraa/ for more information on MRAA -// See https://www.kernel.org/doc/Documentation/spi/spidev for more information on SPIDEV // For this example, we'll be using a payload containing // a single float number that will be incremented @@ -58,12 +55,12 @@ string prettyPrintAddr(string &a) } -/** Convert a hoymiles inverter/DTU serial number into its +/** Convert a Hoymiles inverter/DTU serial number into its * corresponding NRF24 address byte sequence (5 bytes). * * The inverters use a BCD representation of the last 8 - * digits of the serial number, in reverse byte order, - * followed by a \x01. + * digits of their serial number, in reverse byte order, + * followed by \x01. */ string serno2shockburstaddrbytes(uint64_t n) { @@ -88,7 +85,8 @@ string serno2shockburstaddrbytes(uint64_t n) bool doPing(int ch, string src, string dst) { // radio.setPayloadSize(sizeof(payload)); // float datatype occupies 4 bytes - radio.setPayloadSize(4); // float datatype occupies 4 bytes +// radio.setPayloadSize(4); // float datatype occupies 4 bytes + radio.enableDynamicPayloads(); radio.setChannel(ch); radio.setPALevel(RF24_PA_MIN); // RF24_PA_MAX is default. @@ -99,12 +97,13 @@ bool doPing(int ch, string src, string dst) // set the RX address of the TX node into a RX pipe radio.openReadingPipe(1, (const uint8_t *)src.c_str()); + // ...not that this matters for simple ping/ack radio.stopListening(); // put radio in TX mode clock_gettime(CLOCK_MONOTONIC_RAW, &startTimer); // start the timer // bool report = radio.write(&payload, sizeof(float)); // transmit & save the report - bool report = radio.write(&payload, 4); // transmit & save the report + bool report = radio.write("P", 1); // transmit & save the report uint32_t timerEllapsed = getMicros(); // end the timer if (report) { @@ -148,7 +147,9 @@ int main(int argc, char** argv) // well-known valid DTU serial number // just in case the inverter only responds to addresses // that fulfil certain requirements. - string masteraddr = serno2shockburstaddrbytes(99912345678); + //string masteraddr = serno2shockburstaddrbytes(99912345678); + string masteraddr = serno2shockburstaddrbytes(999970535453); + // serial numbers of all inverters that we are trying to find vector dstaddrs; @@ -158,7 +159,7 @@ int main(int argc, char** argv) dstaddrs.push_back(serno2shockburstaddrbytes(114174608177)); // channels that we will scan - vector channels{1, 3, 6, 9, 11, 23, 40, 61, 75, 76, 99}; + vector channels{1, 3, 6, 9, 11, 23, 40, 41, 61, 75, 76, 99}; for(auto & ch : channels) { diff --git a/tools/rpi/discover/pretender.cpp b/tools/rpi/discover/pretender.cpp new file mode 100644 index 00000000..2d75548a --- /dev/null +++ b/tools/rpi/discover/pretender.cpp @@ -0,0 +1,90 @@ +/* based on "gettingstarted.cpp" by 2bdy5 */ + +/** + * Behave like we expect a Hoymiles microinverter to behave. + */ +#include // time() +#include // cin, cout, endl +#include +#include // string, getline() +#include +#include +#include // CLOCK_MONOTONIC_RAW, timespec, clock_gettime() +#include // RF24, RF24_PA_LOW, delay() + +using namespace std; + +#include "common.hpp" + +// Generic: +RF24 radio(22, 0); +// See http://nRF24.github.io/RF24/pages.html for more information on usage + + +/** Receive forever + */ +void receiveForever(int ch, string myaddr) +{ + uint8_t buf[30]; + + radio.enableDynamicPayloads(); + radio.setChannel(ch); + + radio.setPALevel(RF24_PA_MIN); // RF24_PA_MAX is default. + radio.setDataRate(RF24_250KBPS); + + // set the RX address of the TX node into a RX pipe + radio.openReadingPipe(1, (const uint8_t *)myaddr.c_str()); + + while (true) + { + uint8_t pipe; + if (radio.available(&pipe)) + { + uint8_t bytes = radio.getPayloadSize(); // get the size of the payload + cout << "I was notified of having received " << (unsigned int)bytes; + cout << " bytes on pipe " << (unsigned int)pipe << flush; + radio.read(buf, bytes); // fetch payload from FIFO + //cout << ": " << payload; // print the payload's value + //cout << " hex: " << hex << (unsigned int)b[0] << " " << (unsigned int)b[1] << " " + // << (unsigned int)b[2] << " " << (unsigned int)b[3] << " " <