diff --git a/TODO.md b/TODO.md index 5c4b8be4..e31723ed 100644 --- a/TODO.md +++ b/TODO.md @@ -5,6 +5,7 @@ * solder debug headers to board * make message send from android go to service, then to mesh radio * make message receive from radio go through to android +* test loopback tx/rx path code without using radio * have MeshService keep a node DB by sniffing user messages * have meshservice send location data on mesh (if device has a GPS) @@ -20,6 +21,8 @@ * sendToMesh can currently block for a long time, instead have it just queue a packet for a radio freertos thread * see section 7.3 of https://cdn.sparkfun.com/assets/learn_tutorials/8/0/4/RFM95_96_97_98W.pdf and have hope radio wake only when a valid packet is received. Possibly even wake the ESP32 from deep sleep via GPIO. * fix the logo +* do debug logging to android over bluetooth +* break out my bluetooth OTA software as a seperate library so others can use it # Pre-beta priority diff --git a/src/MemoryPool.h b/src/MemoryPool.h index 969ee291..d41f5a0a 100644 --- a/src/MemoryPool.h +++ b/src/MemoryPool.h @@ -3,6 +3,7 @@ #include #include +#include "PointerQueue.h" /** * A pool based allocator @@ -10,12 +11,13 @@ * Eventually this routine will even be safe for ISR use... */ template class MemoryPool { - TypedQueue dead; + PointerQueue dead; T *buf; // our large raw block of memory + size_t maxElements; public: - MemoryPool(int maxElements): queued(maxElements), dead(maxElements) { + MemoryPool(size_t _maxElements): dead(_maxElements), maxElements(_maxElements) { buf = new T[maxElements]; // prefill dead @@ -29,19 +31,28 @@ public: /// Return a queable object which has been prefilled with zeros T *allocZeroed(TickType_t maxWait = portMAX_DELAY) { - T *p; - - if(dead.dequeue(&p, maxWait) != pdTRUE) - return NULL; - - memset(p, 0, sizeof(T)); + T *p = dead.dequeuePtr(maxWait); + + if(p) + memset(p, 0, sizeof(T)); return p; } + /// Return a queable object which is a copy of some other object + T *allocCopy(const T &src, TickType_t maxWait = portMAX_DELAY) { + T *p = dead.dequeuePtr(maxWait); + + if(p) + memcpy(p, &src, sizeof(T)); + return p; + } + + /// Return a buffer for use by others - void free(T *p) { + void release(T *p) { int res = dead.enqueue(p, 0); assert(res == pdTRUE); + assert(p >= buf && (p - buf) < maxElements); // sanity check to make sure a programmer didn't free something that didn't come from this pool } }; diff --git a/src/MeshBluetoothService.cpp b/src/MeshBluetoothService.cpp index 6de61207..1d1a7a14 100644 --- a/src/MeshBluetoothService.cpp +++ b/src/MeshBluetoothService.cpp @@ -8,148 +8,8 @@ #include #include #include "mesh.pb.h" -#include "MeshRadio.h" -#include "TypedQueue.h" -#include "MemoryPool.h" +#include "MeshService.h" -/* -receivedPacketQueue - this is a queue of messages we've received from the mesh, which we are keeping to deliver to the phone. -It is implemented with a FreeRTos queue (wrapped with a little RTQueue class) of pointers to MeshPacket protobufs (which were alloced with new). -After a packet ptr is removed from the queue and processed it should be deleted. (eventually we should move sent packets into a 'sentToPhone' queue -of packets we can delete just as soon as we are sure the phone has acked those packets - when the phone writes to FromNum) - -mesh - an instance of Mesh class. Which manages the interface to the mesh radio library, reception of packets from other nodes, arbitrating to select -a node number and keeping the current nodedb. - - -typedef in32_t NodeNum; - -class NodeInfo { - position; - last_seen - user -}; - -class NodeDB { - NodeNum provisionalNodeNum; // if we are trying to find a node num this is our current attempt - - NodeNum ourNodeNum; // -1 if not yet found - - HashMap nodes; -public: - /// don't do mesh based algoritm for node id assignment (initially) - instead just store in flash - possibly even in the initial alpha release do this hack - - /// if returns false, that means our node should send a DenyNodeNum response. If true, we think the number is okay for use - // bool handleWantNodeNum(NodeNum n); - - void handleDenyNodeNum(NodeNum FIXME read mesh proto docs, perhaps picking a random node num is not a great idea - and instead we should use a special 'im unconfigured node number' and include our desired node number in the wantnum message. the - unconfigured node num would only be used while initially joining the mesh so low odds of conflicting (especially if we randomly select - from a small number of nodenums which can be used temporarily for this operation). figure out what the lower level - mesh sw does if it does conflict? would it be better for people who are replying with denynode num to just broadcast their denial?) -}; - - - - - -*/ - -#define MAX_PACKETS 32 // max number of packets which can be in flight (either queued from reception or queued for sending) -#define MAX_RX_TOPHONE 16 // max number of packets which can be waiting for delivery to android - -/// A temporary buffer used for sending packets, sized to hold the biggest buffer we might need -static uint8_t outbuf[MeshPacket_size]; - -/** - * Top level app for this service. keeps the mesh, the radio config and the queue of received packets. - * - */ -class MeshService -{ - MemoryPool packetPool; - - /// received packets waiting for the phone to process them - /// FIXME, change to a DropOldestQueue and keep a count of the number of dropped packets to ensure - /// we never hang because android hasn't been there in a while - PointerQueue toPhoneQueue; - - /// Packets which have just arrived from the radio, ready to be processed by this service and possibly - /// forwarded to the phone. Note: not using yet - seeing if I can just handle everything asap in handleFromRadio - // PointerQueue fromRadioQueue; - -public: - MeshService() : packetPool(MAX_PACKETS), toPhoneQueue(MAX_RX_TOPHONE) { - - } - - /// Do idle processing (mostly processing messages which have been queued from the radio) - // void loop() { } - - /** - * handle an incoming MeshPacket from the radio, update DB state and queue it for the phone - */ - void handleFromRadio(NodeNum from, NodeNum to, const uint8_t *buf, size_t len) { - MeshPacket *p = packetPool.allocZeroed(); - assert(p); - - pb_istream_t stream = pb_istream_from_buffer(buf, len); - if (!pb_decode(&stream, MeshPacket_fields, p) || !p->has_payload) - { - Serial.printf("Error: can't decode MeshPacket %s\n", PB_GET_ERROR(&stream)); - } - else - { - // FIXME - update DB state based on payload and show recevied texts - - toPhoneQueue.enqueue(p); - } - } - - /// Given a ToRadio buffer parse it and properly handle it (setup radio, owner or send packet into the mesh) - void handleToRadio(std::string s) - { - static ToRadio r; // new ToRadio(); FIXME dynamically allocate - - pb_istream_t stream = pb_istream_from_buffer((const uint8_t *)s.c_str(), s.length()); - if (!pb_decode(&stream, ToRadio_fields, &r)) - { - Serial.printf("Error: can't decode ToRadio %s\n", PB_GET_ERROR(&stream)); - } - else - { - switch (r.which_variant) - { - case ToRadio_packet_tag: - sendToMesh(r.variant.packet); - break; - - default: - Serial.println("Error: unexpected ToRadio variant"); - break; - } - } - } - -private: - /// Send a packet into the mesh - void sendToMesh(const MeshPacket &p) - { - assert(p.has_payload); - - pb_ostream_t stream = pb_ostream_from_buffer(outbuf, sizeof(outbuf)); - if (!pb_encode(&stream, MeshPacket_fields, &p)) - { - Serial.printf("Error: can't encode MeshPacket %s\n", PB_GET_ERROR(&stream)); - } - else - { - assert(radio.sendTo(p.to, outbuf, stream.bytes_written) == ERRNO_OK); - } - } -}; - -MeshService service; static BLECharacteristic meshFromRadioCharacteristic("8ba2bcc2-ee02-4a55-a531-c525c5e454d5", BLECharacteristic::PROPERTY_READ); static BLECharacteristic meshToRadioCharacteristic("f75c76d2-129e-4dad-a1dd-7866124401e7", BLECharacteristic::PROPERTY_WRITE); diff --git a/src/MeshRadio.cpp b/src/MeshRadio.cpp index 637ca389..59b49eb9 100644 --- a/src/MeshRadio.cpp +++ b/src/MeshRadio.cpp @@ -3,103 +3,127 @@ #include #include +#include +#include #include "MeshRadio.h" #include "configuration.h" - - // Change to 434.0 or other frequency, must match RX's freq! #define RF95_FREQ 915.0 -MeshRadio radio; /** * get our starting (provisional) nodenum from flash. But check first if anyone else is using it, by trying to send a message to it (arping) */ -NodeNum getDesiredNodeNum() { - uint8_t dmac[6]; - esp_efuse_mac_get_default(dmac); - - // FIXME not the right way to guess node numes - uint8_t r = dmac[5]; - assert(r != 0xff); // It better not be the broadcast address - return r; -} - - -MeshRadio::MeshRadio() : rf95(NSS_GPIO, DIO0_GPIO), manager(rf95, getDesiredNodeNum()) { - -} - -bool MeshRadio::init() { - pinMode(RESET_GPIO, OUTPUT); // Deassert reset - digitalWrite(RESET_GPIO, HIGH); - - // pulse reset - digitalWrite(RESET_GPIO, LOW); - delay(10); - digitalWrite(RESET_GPIO, HIGH); - delay(10); - - if (!manager.init()) { - Serial.println("LoRa radio init failed"); - Serial.println("Uncomment '#define SERIAL_DEBUG' in RH_RF95.cpp for detailed debug info"); - return false; - } - - Serial.println("LoRa radio init OK!"); - - // Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM - if (!rf95.setFrequency(RF95_FREQ)) { - Serial.println("setFrequency failed"); - while (1); - } - Serial.print("Set Freq to: "); Serial.println(RF95_FREQ); - - // Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on - - // The default transmitter power is 13dBm, using PA_BOOST. - // If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then - // you can set transmitter powers from 5 to 23 dBm: - // FIXME - can we do this? It seems to be in the Heltec board. - rf95.setTxPower(23, false); - - return true; -} - - -ErrorCode MeshRadio::sendTo(NodeNum dest, const uint8_t *buf, size_t len) { - Serial.printf("mesh sendTo %d bytes to %d\n", len, dest); - // FIXME - for now we do all packets as broadcast - dest = NODENUM_BROADCAST; - - // Note: we don't use sendToWait here because we don't want to wait and for the time being don't require - // reliable delivery - // return manager.sendtoWait((uint8_t *) buf, len, dest); - return manager.sendto((uint8_t *) buf, len, dest) ? ERRNO_OK : ERRNO_UNKNOWN; -} - -void MeshRadio::loop() { - // FIXME read from radio with recvfromAckTimeout -} - -void mesh_init() { - while (!radio.init()) { - Serial.println("radio init failed"); - while (1); - } -} - -int16_t packetnum = 0; // packet counter, we increment per xmission - -void mesh_loop() +NodeNum getDesiredNodeNum() { - radio.loop(); + uint8_t dmac[6]; + esp_efuse_mac_get_default(dmac); - delay(1000); // Wait 1 second between transmits, could also 'sleep' here! + // FIXME not the right way to guess node numes + uint8_t r = dmac[5]; + assert(r != 0xff); // It better not be the broadcast address + return r; +} + +MeshRadio::MeshRadio(MemoryPool &_pool, PointerQueue &_rxDest) + : rf95(NSS_GPIO, DIO0_GPIO), + manager(rf95, getDesiredNodeNum()), + pool(_pool), + rxDest(_rxDest), + txQueue(MAX_TX_QUEUE) +{ +} + +bool MeshRadio::init() +{ + pinMode(RESET_GPIO, OUTPUT); // Deassert reset + digitalWrite(RESET_GPIO, HIGH); + + // pulse reset + digitalWrite(RESET_GPIO, LOW); + delay(10); + digitalWrite(RESET_GPIO, HIGH); + delay(10); + + if (!manager.init()) + { + Serial.println("LoRa radio init failed"); + Serial.println("Uncomment '#define SERIAL_DEBUG' in RH_RF95.cpp for detailed debug info"); + return false; + } + + Serial.println("LoRa radio init OK!"); + + // Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM + if (!rf95.setFrequency(RF95_FREQ)) + { + Serial.println("setFrequency failed"); + while (1) + ; + } + Serial.print("Set Freq to: "); + Serial.println(RF95_FREQ); + + // Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on + + // The default transmitter power is 13dBm, using PA_BOOST. + // If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then + // you can set transmitter powers from 5 to 23 dBm: + // FIXME - can we do this? It seems to be in the Heltec board. + rf95.setTxPower(23, false); + + return true; +} + +ErrorCode MeshRadio::send(MeshPacket *p) +{ + int res = ERRNO_UNKNOWN; + + /// A temporary buffer used for sending packets, sized to hold the biggest buffer we might need + static uint8_t outbuf[SubPacket_size]; + + assert(p->has_payload); + + pb_ostream_t stream = pb_ostream_from_buffer(outbuf, sizeof(outbuf)); + if (!pb_encode(&stream, SubPacket_fields, &p->payload)) + { + Serial.printf("Error: can't encode SubPacket %s\n", PB_GET_ERROR(&stream)); + } + else + { + res = sendTo(p->to, outbuf, stream.bytes_written); + } + + pool.release(p); + return res; +} + +ErrorCode MeshRadio::sendTo(NodeNum dest, const uint8_t *buf, size_t len) +{ + Serial.printf("mesh sendTo %d bytes to %d\n", len, dest); + // FIXME - for now we do all packets as broadcast + dest = NODENUM_BROADCAST; + + // Note: we don't use sendToWait here because we don't want to wait and for the time being don't require + // reliable delivery + // return manager.sendtoWait((uint8_t *) buf, len, dest); + return manager.sendto((uint8_t *)buf, len, dest) ? ERRNO_OK : ERRNO_UNKNOWN; +} + +void MeshRadio::loop() +{ + // FIXME read from radio with recvfromAckTimeout + +#if 0 +static int16_t packetnum = 0; // packet counter, we increment per xmission char radiopacket[20] = "Hello World # "; sprintf(radiopacket, "hello %d", packetnum++); - assert(radio.sendTo(NODENUM_BROADCAST, (uint8_t *)radiopacket, sizeof(radiopacket)) == ERRNO_OK); + assert(sendTo(NODENUM_BROADCAST, (uint8_t *)radiopacket, sizeof(radiopacket)) == ERRNO_OK); +#endif + + // manager.recvfromAckTimeout() } + diff --git a/src/MeshRadio.h b/src/MeshRadio.h index 9d11665c..9d4eecde 100644 --- a/src/MeshRadio.h +++ b/src/MeshRadio.h @@ -2,6 +2,9 @@ #include #include +#include "MemoryPool.h" +#include "mesh.pb.h" +#include "PointerQueue.h" #define NODENUM_BROADCAST 255 #define ERRNO_OK 0 @@ -10,37 +13,42 @@ typedef int ErrorCode; typedef uint8_t NodeNum; -/// Callback for a receive packet, the callee must copy/queue the payload elsewhere before returning -typedef void (*MeshRXHandler)(NodeNum from, NodeNum to, const uint8_t *buf, size_t len); +#define MAX_TX_QUEUE 4 // max number of packets which can be waiting for transmission + /** * A raw low level interface to our mesh. Only understands nodenums and bytes (not protobufs or node ids) */ class MeshRadio { public: - MeshRadio(); + /** pool is the pool we will alloc our rx packets from + * rxDest is where we will send any rx packets, it becomes receivers responsibility to return packet to the pool + */ + MeshRadio(MemoryPool &pool, PointerQueue &rxDest); bool init(); /// Prepare the radio to enter sleep mode, where it should draw only 0.2 uA void sleep() { rf95.sleep(); } - /// Send a packet - the current implementation blocks for a while possibly (FIXME) - ErrorCode sendTo(NodeNum dest, const uint8_t *buf, size_t len); + /// Send a packet (possibly by enquing in a private fifo). This routine will + /// later free() the packet to pool. + ErrorCode send(MeshPacket *p); /// Do loop callback operations (we currently FIXME poll the receive mailbox here) /// for received packets it will call the rx handler void loop(); - void setRXHandler(MeshRXHandler h) { rxHandler = h; } - private: RH_RF95 rf95; // the raw radio interface RHMesh manager; - MeshRXHandler rxHandler; + // MeshRXHandler rxHandler; + + MemoryPool &pool; + PointerQueue &rxDest; + PointerQueue txQueue; + + /// low level send, might block for mutiple seconds + ErrorCode sendTo(NodeNum dest, const uint8_t *buf, size_t len); }; -extern MeshRadio radio; - -void mesh_init(); -void mesh_loop(); \ No newline at end of file diff --git a/src/MeshService.cpp b/src/MeshService.cpp new file mode 100644 index 00000000..c99ff87b --- /dev/null +++ b/src/MeshService.cpp @@ -0,0 +1,103 @@ + +#include +#include + +#include +#include +#include "mesh.pb.h" +#include "MeshService.h" + +/* +receivedPacketQueue - this is a queue of messages we've received from the mesh, which we are keeping to deliver to the phone. +It is implemented with a FreeRTos queue (wrapped with a little RTQueue class) of pointers to MeshPacket protobufs (which were alloced with new). +After a packet ptr is removed from the queue and processed it should be deleted. (eventually we should move sent packets into a 'sentToPhone' queue +of packets we can delete just as soon as we are sure the phone has acked those packets - when the phone writes to FromNum) + +mesh - an instance of Mesh class. Which manages the interface to the mesh radio library, reception of packets from other nodes, arbitrating to select +a node number and keeping the current nodedb. + + +typedef in32_t NodeNum; + +class NodeInfo { + position; + last_seen + user +}; + +class NodeDB { + NodeNum provisionalNodeNum; // if we are trying to find a node num this is our current attempt + + NodeNum ourNodeNum; // -1 if not yet found + + HashMap nodes; +public: + /// don't do mesh based algoritm for node id assignment (initially) - instead just store in flash - possibly even in the initial alpha release do this hack + + /// if returns false, that means our node should send a DenyNodeNum response. If true, we think the number is okay for use + // bool handleWantNodeNum(NodeNum n); + + void handleDenyNodeNum(NodeNum FIXME read mesh proto docs, perhaps picking a random node num is not a great idea + and instead we should use a special 'im unconfigured node number' and include our desired node number in the wantnum message. the + unconfigured node num would only be used while initially joining the mesh so low odds of conflicting (especially if we randomly select + from a small number of nodenums which can be used temporarily for this operation). figure out what the lower level + mesh sw does if it does conflict? would it be better for people who are replying with denynode num to just broadcast their denial?) +}; + +*/ + +MeshService service; + +#define MAX_PACKETS 32 // max number of packets which can be in flight (either queued from reception or queued for sending) +#define MAX_RX_TOPHONE 16 // max number of packets which can be waiting for delivery to android + +MeshService::MeshService() : packetPool(MAX_PACKETS), toPhoneQueue(MAX_RX_TOPHONE), radio(packetPool, toPhoneQueue) +{ +} + +void MeshService::init() +{ + if (!radio.init()) + Serial.println("radio init failed"); +} + +/// Do idle processing (mostly processing messages which have been queued from the radio) +void MeshService::loop() +{ + radio.loop(); // FIXME, possibly move radio interaction to own thread +} + +/// Given a ToRadio buffer parse it and properly handle it (setup radio, owner or send packet into the mesh) +void MeshService::handleToRadio(std::string s) +{ + static ToRadio r; // this is a static scratch object, any data must be copied elsewhere before returning + + pb_istream_t stream = pb_istream_from_buffer((const uint8_t *)s.c_str(), s.length()); + if (!pb_decode(&stream, ToRadio_fields, &r)) + { + Serial.printf("Error: can't decode ToRadio %s\n", PB_GET_ERROR(&stream)); + } + else + { + switch (r.which_variant) + { + case ToRadio_packet_tag: + sendToMesh(r.variant.packet); + break; + + default: + Serial.println("Error: unexpected ToRadio variant"); + break; + } + } +} + +/// Send a packet into the mesh - note p is read only and should be copied into a pool based MeshPacket before +/// sending. +void MeshService::sendToMesh(const MeshPacket &pIn) +{ + MeshPacket *pOut = packetPool.allocCopy(pIn); + assert(pOut); // FIXME + + assert(radio.send(pOut) == pdTRUE); +} diff --git a/src/MeshService.h b/src/MeshService.h new file mode 100644 index 00000000..daa896e9 --- /dev/null +++ b/src/MeshService.h @@ -0,0 +1,73 @@ +#pragma once + +#include +#include + +#include "mesh.pb.h" +#include "MeshRadio.h" +#include "PointerQueue.h" +#include "MemoryPool.h" + +/** + * Top level app for this service. keeps the mesh, the radio config and the queue of received packets. + * + */ +class MeshService +{ + MemoryPool packetPool; + + /// received packets waiting for the phone to process them + /// FIXME, change to a DropOldestQueue and keep a count of the number of dropped packets to ensure + /// we never hang because android hasn't been there in a while + PointerQueue toPhoneQueue; + + /// Packets which have just arrived from the radio, ready to be processed by this service and possibly + /// forwarded to the phone. Note: not using yet - seeing if I can just handle everything asap in handleFromRadio + // PointerQueue fromRadioQueue; + +public: + + MeshRadio radio; + + MeshService(); + + void init(); + + /// Do idle processing (mostly processing messages which have been queued from the radio) + void loop(); + +#if 0 + /** + * handle an incoming MeshPacket from the radio, update DB state and queue it for the phone + */ + void handleFromRadio(NodeNum from, NodeNum to, const uint8_t *buf, size_t len) { + MeshPacket *p = packetPool.allocZeroed(); + assert(p); + + pb_istream_t stream = pb_istream_from_buffer(buf, len); + if (!pb_decode(&stream, MeshPacket_fields, p) || !p->has_payload) + { + Serial.printf("Error: can't decode MeshPacket %s\n", PB_GET_ERROR(&stream)); + } + else + { + // FIXME - update DB state based on payload and show recevied texts + + toPhoneQueue.enqueue(p); + } + } +#endif + + /// Given a ToRadio buffer (from bluetooth) parse it and properly handle it (setup radio, owner or send packet into the mesh) + void handleToRadio(std::string s); + +private: + + /// Send a packet into the mesh - note p is read only and should be copied into a pool based MeshPacket before + /// sending. + void sendToMesh(const MeshPacket &p); + +}; + +extern MeshService service; + diff --git a/src/PointerQueue.h b/src/PointerQueue.h new file mode 100644 index 00000000..f45fec8b --- /dev/null +++ b/src/PointerQueue.h @@ -0,0 +1,21 @@ +#pragma once + +#include "TypedQueue.h" + + +/** + * A wrapper for freertos queues that assumes each element is a pointer + */ +template class PointerQueue: public TypedQueue { +public: + PointerQueue(int maxElements) : TypedQueue(maxElements) { + } + + // preturns a ptr or null if the queue was empty + T *dequeuePtr(TickType_t maxWait = portMAX_DELAY) { + T *p; + + return this->dequeue(&p, maxWait) == pdTRUE ? p : NULL; + } +}; + diff --git a/src/TypedQueue.h b/src/TypedQueue.h index 0ee42d51..61c58478 100644 --- a/src/TypedQueue.h +++ b/src/TypedQueue.h @@ -29,22 +29,3 @@ public: return xQueueReceive(h, p, maxWait); } }; - - -/** - * A wrapper for freertos queues that assumes each element is a pointer - */ -template class PointerQueue: public TypedQueue { - TypedQueue h; -public: - PointerQueue(int maxElements) : TypedQueue(maxElements) { - } - - // preturns a ptr or null if the queue was empty - T *dequeuePtr(TickType_t maxWait = portMAX_DELAY) { - T *p; - - return dequeue(&p, maxWait) == pdTRUE ? p : NULL; - } -}; - diff --git a/src/main.ino b/src/main.ino index daecf8da..fd402c4b 100644 --- a/src/main.ino +++ b/src/main.ino @@ -28,7 +28,7 @@ #include #include "BluetoothUtil.h" #include "MeshBluetoothService.h" -#include "MeshRadio.h" +#include "MeshService.h" #ifdef T_BEAM_V10 #include "axp20x.h" @@ -62,7 +62,7 @@ void doDeepSleep(uint64_t msecToWake) screen_off(); // datasheet says this will draw only 10ua // Put radio in sleep mode (will still draw power but only 0.2uA) - radio.sleep(); + service.radio.sleep(); #ifdef RESET_OLED digitalWrite(RESET_OLED, 1); // put the display in reset before killing its power @@ -345,7 +345,7 @@ void setup() delay(LOGO_DELAY); //} - mesh_init(); + service.init(); BLEServer *serve = initBLE("KHBT Test"); // FIXME, use a real name based on the macaddr BLEService *bts = createMeshBluetoothService(serve); bts->start(); @@ -356,7 +356,7 @@ void loop() { gps_loop(); screen_loop(); - mesh_loop(); + service.loop(); loopBLE(); #ifdef LED_PIN