Add native narrow-band CW capture, ACK-first remote sessions, retained LoRa-readable pages, checked restoration and transport-safe progress. Add stock-compatible negotiated heartbeat/autosleep and recovery. Include host regressions and identity-bound HIL runners; keep unverified faster tuning HIL-only and document outstanding hardware validation.
61 lines
2.4 KiB
C++
61 lines
2.4 KiB
C++
#include <helpers/MorseLoopPolicy.h>
|
|
static uint32_t now_ms = 100;
|
|
uint32_t millis() { return now_ms; }
|
|
#define PUB_KEY_SIZE 32
|
|
struct ClientInfo {
|
|
struct { uint8_t pub_key[32] = {}; } id;
|
|
bool admin = true;
|
|
bool isAdmin() const { return admin; }
|
|
};
|
|
struct ACL {
|
|
std::vector<ClientInfo> clients;
|
|
size_t requested_key_size = 0;
|
|
const ClientInfo* getClient(const uint8_t* key, size_t size) {
|
|
requested_key_size = size;
|
|
assert(size == 32);
|
|
for (const auto& client : clients) if (!memcmp(client.id.pub_key, key, size)) return &client;
|
|
return nullptr;
|
|
}
|
|
};
|
|
struct Callbacks { TestRadio* radio; mesh::Radio* getProfileRadio() { return radio; } };
|
|
struct CommonCLI {
|
|
mesh::MorseReplyHandoff _morse_reply;
|
|
ACL* _acl;
|
|
Callbacks* _callbacks;
|
|
struct Profiles { unsigned loops = 0; void loop() { ++loops; } } _radio_profiles;
|
|
unsigned management_loops = 0;
|
|
CommonCLI(ACL& acl, Callbacks& callbacks) : _acl(&acl), _callbacks(&callbacks) {}
|
|
void loopManagement() { ++management_loops; }
|
|
void loop();
|
|
};
|
|
@LOOP@
|
|
|
|
int main() {
|
|
const uint8_t key[32] = {1, 2, 3, 4};
|
|
for (int scenario = 0; scenario < 5; ++scenario) {
|
|
TestRadio radio; radio.rx_supported = true;
|
|
ACL acl; ClientInfo actor; memcpy(actor.id.pub_key, key, 32); acl.clients.push_back(actor);
|
|
Callbacks callbacks{&radio}; CommonCLI cli(acl, callbacks);
|
|
int packet;
|
|
cli._morse_reply.beginCommand(key);
|
|
assert(cli._morse_reply.stage(902100, 25, 60000, now_ms));
|
|
cli._morse_reply.endCommand(); cli._morse_reply.prepareReply(&packet);
|
|
cli._morse_reply.armReply(&packet, true);
|
|
cli.loop(); assert(radio.rx_starts == 0); // shared loop must still wait for PHY completion
|
|
cli._morse_reply.complete(&packet);
|
|
if (scenario == 0) acl.clients[0].admin = false;
|
|
if (scenario == 1) { acl.clients[0].id.pub_key[31] = 1; } // reused slot, same short key
|
|
if (scenario == 2) {
|
|
acl.clients[0].id.pub_key[31] = 1; acl.clients.push_back(actor); // original full identity moved
|
|
}
|
|
if (scenario == 3) mesh::usable = false;
|
|
if (scenario == 4) mesh::current.frequency_khz = 902101;
|
|
cli.loop();
|
|
const bool allowed = scenario == 2;
|
|
assert(radio.rx_starts == unsigned(allowed) && !cli._morse_reply.pending());
|
|
assert(acl.requested_key_size == 32 && cli._radio_profiles.loops == unsigned(allowed ? 1 : 2));
|
|
assert(cli.management_loops == unsigned(allowed ? 1 : 2));
|
|
mesh::usable = true; mesh::current = mesh::MorseSettings();
|
|
}
|
|
}
|