mirror of
https://github.com/lumapu/ahoy.git
synced 2025-06-05 04:01:41 +02:00
switched to dynamic payload mode, added a pretender
This commit is contained in:
parent
c0abc8daae
commit
122e4567b1
5 changed files with 168 additions and 10 deletions
|
@ -8,3 +8,7 @@ message(STATUS "using RF24 library: ${RF24}")
|
||||||
|
|
||||||
add_executable(discover discover.cpp)
|
add_executable(discover discover.cpp)
|
||||||
target_link_libraries(discover PUBLIC ${RF24} pthread)
|
target_link_libraries(discover PUBLIC ${RF24} pthread)
|
||||||
|
|
||||||
|
add_executable(pretender pretender.cpp common.cpp)
|
||||||
|
target_link_libraries(pretender PUBLIC ${RF24} pthread)
|
||||||
|
|
||||||
|
|
45
tools/rpi/discover/common.cpp
Normal file
45
tools/rpi/discover/common.cpp
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#include "common.hpp"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
18
tools/rpi/discover/common.hpp
Normal file
18
tools/rpi/discover/common.hpp
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#include <string>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
|
@ -22,10 +22,7 @@ using namespace std;
|
||||||
|
|
||||||
// Generic:
|
// Generic:
|
||||||
RF24 radio(22, 0);
|
RF24 radio(22, 0);
|
||||||
/****************** Linux (BBB,x86,etc) ***********************/
|
|
||||||
// See http://nRF24.github.io/RF24/pages.html for more information on usage
|
// 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
|
// For this example, we'll be using a payload containing
|
||||||
// a single float number that will be incremented
|
// 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).
|
* corresponding NRF24 address byte sequence (5 bytes).
|
||||||
*
|
*
|
||||||
* The inverters use a BCD representation of the last 8
|
* The inverters use a BCD representation of the last 8
|
||||||
* digits of the serial number, in reverse byte order,
|
* digits of their serial number, in reverse byte order,
|
||||||
* followed by a \x01.
|
* followed by \x01.
|
||||||
*/
|
*/
|
||||||
string serno2shockburstaddrbytes(uint64_t n)
|
string serno2shockburstaddrbytes(uint64_t n)
|
||||||
{
|
{
|
||||||
|
@ -88,7 +85,8 @@ string serno2shockburstaddrbytes(uint64_t n)
|
||||||
bool doPing(int ch, string src, string dst)
|
bool doPing(int ch, string src, string dst)
|
||||||
{
|
{
|
||||||
// radio.setPayloadSize(sizeof(payload)); // float datatype occupies 4 bytes
|
// 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.setChannel(ch);
|
||||||
|
|
||||||
radio.setPALevel(RF24_PA_MIN); // RF24_PA_MAX is default.
|
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
|
// set the RX address of the TX node into a RX pipe
|
||||||
radio.openReadingPipe(1, (const uint8_t *)src.c_str());
|
radio.openReadingPipe(1, (const uint8_t *)src.c_str());
|
||||||
|
// ...not that this matters for simple ping/ack
|
||||||
|
|
||||||
radio.stopListening(); // put radio in TX mode
|
radio.stopListening(); // put radio in TX mode
|
||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC_RAW, &startTimer); // start the timer
|
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, 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
|
uint32_t timerEllapsed = getMicros(); // end the timer
|
||||||
|
|
||||||
if (report) {
|
if (report) {
|
||||||
|
@ -148,7 +147,9 @@ int main(int argc, char** argv)
|
||||||
// well-known valid DTU serial number
|
// well-known valid DTU serial number
|
||||||
// just in case the inverter only responds to addresses
|
// just in case the inverter only responds to addresses
|
||||||
// that fulfil certain requirements.
|
// 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
|
// serial numbers of all inverters that we are trying to find
|
||||||
vector<string> dstaddrs;
|
vector<string> dstaddrs;
|
||||||
|
@ -158,7 +159,7 @@ int main(int argc, char** argv)
|
||||||
dstaddrs.push_back(serno2shockburstaddrbytes(114174608177));
|
dstaddrs.push_back(serno2shockburstaddrbytes(114174608177));
|
||||||
|
|
||||||
// channels that we will scan
|
// channels that we will scan
|
||||||
vector<int> channels{1, 3, 6, 9, 11, 23, 40, 61, 75, 76, 99};
|
vector<int> channels{1, 3, 6, 9, 11, 23, 40, 41, 61, 75, 76, 99};
|
||||||
|
|
||||||
for(auto & ch : channels)
|
for(auto & ch : channels)
|
||||||
{
|
{
|
||||||
|
|
90
tools/rpi/discover/pretender.cpp
Normal file
90
tools/rpi/discover/pretender.cpp
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
/* based on "gettingstarted.cpp" by 2bdy5 */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Behave like we expect a Hoymiles microinverter to behave.
|
||||||
|
*/
|
||||||
|
#include <ctime> // time()
|
||||||
|
#include <iostream> // cin, cout, endl
|
||||||
|
#include <iomanip>
|
||||||
|
#include <string> // string, getline()
|
||||||
|
#include <vector>
|
||||||
|
#include <sstream>
|
||||||
|
#include <time.h> // CLOCK_MONOTONIC_RAW, timespec, clock_gettime()
|
||||||
|
#include <RF24/RF24.h> // 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] << " " <<endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
if (!radio.begin()) {
|
||||||
|
cout << "radio hardware is not responding!!" << endl;
|
||||||
|
return 0; // quit now
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!radio.isPVariant())
|
||||||
|
{
|
||||||
|
printf("not nRF24L01+\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!radio.isChipConnected())
|
||||||
|
{
|
||||||
|
printf("not connected\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// we probably want
|
||||||
|
// - 8-bit crc
|
||||||
|
// - dynamic payloads (check in rf logs)
|
||||||
|
// - what's the "primary mode"?
|
||||||
|
// - do we need/want "custom ack payloads"?
|
||||||
|
// - use isAckPayloadAvailable() once we've actually contacted an inverter successfully!
|
||||||
|
|
||||||
|
radio.printPrettyDetails();
|
||||||
|
|
||||||
|
string addr = serno2shockburstaddrbytes(114174608177);
|
||||||
|
receiveForever(41, addr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue