mirror of
https://github.com/meshtastic/firmware.git
synced 2025-04-25 01:42:15 +00:00
Merge pull request #66 from meshtastic/master
mc-hamster/meshtastic-device <- meshtastic/meshtastic-device
This commit is contained in:
commit
abf135abce
14
.github/workflows/main.yml
vendored
14
.github/workflows/main.yml
vendored
@ -22,5 +22,15 @@ jobs:
|
||||
- name: Install extra python tools
|
||||
run: |
|
||||
pip install -U adafruit-nrfutil
|
||||
- name: Build
|
||||
run: platformio run -e tbeam -e heltec -e lora-relay-v1 -e linux
|
||||
- name: Install libs needed for linux build
|
||||
run: |
|
||||
sudo apt install -y libpsocksxx-dev
|
||||
- name: Build for tbeam
|
||||
run: platformio run -e tbeam
|
||||
- name: Build for heltec
|
||||
run: platformio run -e heltec
|
||||
- name: Build for lora-relay-v1
|
||||
run: platformio run -e lora-relay-v1
|
||||
- name: Build for linux
|
||||
run: platformio run -e linux
|
||||
|
||||
|
@ -4,7 +4,7 @@ This is the device side code for the [meshtastic.org](https://www.meshtastic.org
|
||||
|
||||

|
||||
|
||||
Meshtastic™ is a project that lets you use
|
||||
Meshtastic® is a project that lets you use
|
||||
inexpensive GPS mesh radios as an extensible, super long battery life mesh GPS communicator. These radios are great for hiking, skiing, paragliding -
|
||||
essentially any hobby where you don't have reliable internet access. Each member of your private mesh can always see the location and distance of all other
|
||||
members and any text messages sent to your group chat.
|
||||
|
@ -14,8 +14,6 @@ BOARDS_ESP32="tlora-v2 tlora-v1 tlora-v2-1-1.6 tbeam heltec tbeam0.7"
|
||||
# FIXME note nrf52840dk build is for some reason only generating a BIN file but not a HEX file nrf52840dk-geeksville is fine
|
||||
BOARDS_NRF52="lora-relay-v1"
|
||||
|
||||
NUM_JOBS=2 || true
|
||||
|
||||
OUTDIR=release/latest
|
||||
|
||||
# We keep all old builds (and their map files in the archive dir)
|
||||
@ -51,7 +49,7 @@ function do_build() {
|
||||
basename=universal/firmware-$BOARD-$VERSION
|
||||
fi
|
||||
|
||||
pio run --jobs $NUM_JOBS --environment $BOARD # -v
|
||||
pio run --environment $BOARD # -v
|
||||
SRCELF=.pio/build/$BOARD/firmware.elf
|
||||
cp $SRCELF $OUTDIR/elfs/$basename.elf
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
# What is Meshtastic?
|
||||
|
||||
Meshtastic™ is a project that lets you use
|
||||
Meshtastic® is a project that lets you use
|
||||
inexpensive (\$30 ish) GPS radios as an extensible, long battery life, secure, mesh GPS communicator. These radios are great for hiking, skiing, paragliding - essentially any hobby where you don't have reliable internet access. Each member of your private mesh can always see the location and distance of all other members and any text messages sent to your group chat.
|
||||
|
||||
The radios automatically create a mesh to forward packets as needed, so everyone in the group can receive messages from even the furthest member. The radios will optionally work with your phone, but no phone is required.
|
||||
|
||||
Note: Questions after reading this? See our new [forum](https://meshtastic.discourse.group/).
|
||||
|
||||
### Uses
|
||||
## Uses
|
||||
|
||||
- Outdoor sports where cellular coverage is limited. (Hiking, Skiing, Boating, Paragliding, Gliders etc..)
|
||||
- Applications where closed source GPS communicators just won't cut it (it is easy to add features for glider pilots etc...)
|
||||
@ -17,7 +17,7 @@ Note: Questions after reading this? See our new [forum](https://meshtastic.disco
|
||||
|
||||
[](https://www.youtube.com/watch?v=WlNbMbVZlHI "Meshtastic early demo")
|
||||
|
||||
### Features
|
||||
## Features
|
||||
|
||||
Not all of these features are fully implemented yet - see **important** disclaimers below. But they should be in by the time we decide to call this project beta (three months?)
|
||||
|
||||
|
2
proto
2
proto
@ -1 +1 @@
|
||||
Subproject commit c9ad10d7e2f7f465dc477e98d6ec9d3b7059336c
|
||||
Subproject commit 106f4bfdebe277ab0b86d2b8c950ab78a35b0654
|
@ -490,6 +490,8 @@ void setup()
|
||||
DEBUG_MSG("Warning: Failed to find RF95 radio\n");
|
||||
delete rIf;
|
||||
rIf = NULL;
|
||||
} else {
|
||||
DEBUG_MSG("Radio init succeeded, using RF95 radio\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -501,6 +503,8 @@ void setup()
|
||||
DEBUG_MSG("Warning: Failed to find SX1262 radio\n");
|
||||
delete rIf;
|
||||
rIf = NULL;
|
||||
} else {
|
||||
DEBUG_MSG("Radio init succeeded, using SX1262 radio\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -512,6 +516,8 @@ void setup()
|
||||
DEBUG_MSG("Warning: Failed to find simulated radio\n");
|
||||
delete rIf;
|
||||
rIf = NULL;
|
||||
} else {
|
||||
DEBUG_MSG("Using SIMULATED radio!\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -105,7 +105,7 @@ void DSRRouter::sniffReceived(const MeshPacket *p)
|
||||
// packets until ack arrives)
|
||||
// FIXME, if we don't get a route reply at all (or a route error), timeout and generate a routeerror TIMEOUT on our own...
|
||||
break;
|
||||
case SubPacket_route_error_tag:
|
||||
case SubPacket_error_reason_tag:
|
||||
removeRoute(p->decoded.dest);
|
||||
|
||||
// FIXME: if any pending packets were waiting on this route, delete them
|
||||
@ -131,7 +131,7 @@ void DSRRouter::sniffReceived(const MeshPacket *p)
|
||||
assert(p->decoded.source); // I think this is guaranteed by now
|
||||
|
||||
// FIXME - what if the current packet _is_ a route error packet?
|
||||
sendRouteError(p, RouteError_NO_ROUTE);
|
||||
sendRouteError(p, ErrorReason_NO_ROUTE);
|
||||
}
|
||||
|
||||
// FIXME, stop local processing of this packet
|
||||
@ -145,7 +145,7 @@ void DSRRouter::sniffReceived(const MeshPacket *p)
|
||||
if (pending && pending->packet->decoded.source) { // if source not set, this was not a multihop packet, just ignore
|
||||
removeRoute(pending->packet->decoded.dest); // We no longer have a route to the specified node
|
||||
|
||||
sendRouteError(p, RouteError_GOT_NAK);
|
||||
sendRouteError(p, ErrorReason_GOT_NAK);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -230,7 +230,7 @@ void DSRRouter::sendNextHop(NodeNum n, const MeshPacket *p)
|
||||
/**
|
||||
* Send a route error packet towards whoever originally sent this message
|
||||
*/
|
||||
void DSRRouter::sendRouteError(const MeshPacket *p, RouteError err)
|
||||
void DSRRouter::sendRouteError(const MeshPacket *p, ErrorReason err)
|
||||
{
|
||||
DEBUG_MSG("FIXME not implemented sendRouteError\n");
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ class DSRRouter : public ReliableRouter
|
||||
/**
|
||||
* Send a route error packet towards whoever originally sent this message
|
||||
*/
|
||||
void sendRouteError(const MeshPacket *p, RouteError err);
|
||||
void sendRouteError(const MeshPacket *p, ErrorReason err);
|
||||
|
||||
/** make a copy of p, start discovery, but only if we don't
|
||||
* already a discovery in progress for that node number. Caller has already scheduled this message for retransmission
|
||||
|
@ -34,7 +34,7 @@ bool ReliableRouter::shouldFilterReceived(const MeshPacket *p)
|
||||
// the original sending process.
|
||||
if (stopRetransmission(p->from, p->id)) {
|
||||
DEBUG_MSG("Someone is retransmitting for us, generate implicit ack\n");
|
||||
sendAckNak(true, p->from, p->id);
|
||||
sendAckNak(ErrorReason_NONE, p->from, p->id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,7 +60,7 @@ void ReliableRouter::sniffReceived(const MeshPacket *p)
|
||||
if (p->to == ourNode) { // ignore ack/nak/want_ack packets that are not address to us (we only handle 0 hop reliability
|
||||
// - not DSR routing)
|
||||
if (p->want_ack) {
|
||||
sendAckNak(true, p->from, p->id);
|
||||
sendAckNak(ErrorReason_NONE, p->from, p->id);
|
||||
}
|
||||
|
||||
// If the payload is valid, look for ack/nak
|
||||
@ -84,27 +84,6 @@ void ReliableRouter::sniffReceived(const MeshPacket *p)
|
||||
FloodingRouter::sniffReceived(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an ack or a nak packet back towards whoever sent idFrom
|
||||
*/
|
||||
void ReliableRouter::sendAckNak(bool isAck, NodeNum to, PacketId idFrom)
|
||||
{
|
||||
auto p = allocForSending();
|
||||
p->hop_limit = 0; // Assume just immediate neighbors for now
|
||||
p->to = to;
|
||||
DEBUG_MSG("Sending an ack=0x%x,to=0x%x,idFrom=0x%x,id=0x%x\n", isAck, to, idFrom, p->id);
|
||||
|
||||
if (isAck) {
|
||||
p->decoded.ack.success_id = idFrom;
|
||||
p->decoded.which_ack = SubPacket_success_id_tag;
|
||||
} else {
|
||||
p->decoded.ack.fail_id = idFrom;
|
||||
p->decoded.which_ack = SubPacket_fail_id_tag;
|
||||
}
|
||||
|
||||
sendLocal(p); // we sometimes send directly to the local node
|
||||
}
|
||||
|
||||
#define NUM_RETRANSMISSIONS 3
|
||||
|
||||
PendingPacket::PendingPacket(MeshPacket *p)
|
||||
@ -176,7 +155,7 @@ int32_t ReliableRouter::doRetransmissions()
|
||||
if (p.numRetransmissions == 0) {
|
||||
DEBUG_MSG("Reliable send failed, returning a nak fr=0x%x,to=0x%x,id=%d\n", p.packet->from, p.packet->to,
|
||||
p.packet->id);
|
||||
sendAckNak(false, p.packet->from, p.packet->id);
|
||||
sendAckNak(ErrorReason_MAX_RETRANSMIT, p.packet->from, p.packet->id);
|
||||
// Note: we don't stop retransmission here, instead the Nak packet gets processed in sniffReceived - which
|
||||
// allows the DSR version to still be able to look at the PendingPacket
|
||||
stopRetransmission(it->first);
|
||||
|
@ -109,10 +109,6 @@ class ReliableRouter : public FloodingRouter
|
||||
PendingPacket *startRetransmission(MeshPacket *p);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Send an ack or a nak packet back towards whoever sent idFrom
|
||||
*/
|
||||
void sendAckNak(bool isAck, NodeNum to, PacketId idFrom);
|
||||
|
||||
/**
|
||||
* Stop any retransmissions we are doing of the specified node/packet ID pair
|
||||
|
@ -99,6 +99,31 @@ MeshPacket *Router::allocForSending()
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an ack or a nak packet back towards whoever sent idFrom
|
||||
*/
|
||||
void Router::sendAckNak(ErrorReason err, NodeNum to, PacketId idFrom)
|
||||
{
|
||||
auto p = allocForSending();
|
||||
p->hop_limit = 0; // Assume just immediate neighbors for now
|
||||
p->to = to;
|
||||
DEBUG_MSG("Sending an err=%d,to=0x%x,idFrom=0x%x,id=0x%x\n", err, to, idFrom, p->id);
|
||||
|
||||
if (!err) {
|
||||
p->decoded.ack.success_id = idFrom;
|
||||
p->decoded.which_ack = SubPacket_success_id_tag;
|
||||
} else {
|
||||
p->decoded.ack.fail_id = idFrom;
|
||||
p->decoded.which_ack = SubPacket_fail_id_tag;
|
||||
|
||||
// Also send back the error reason
|
||||
p->decoded.which_payload = SubPacket_error_reason_tag;
|
||||
p->decoded.error_reason = err;
|
||||
}
|
||||
|
||||
sendLocal(p); // we sometimes send directly to the local node
|
||||
}
|
||||
|
||||
ErrorCode Router::sendLocal(MeshPacket *p)
|
||||
{
|
||||
// No need to deliver externally if the destination is the local node
|
||||
@ -106,15 +131,24 @@ ErrorCode Router::sendLocal(MeshPacket *p)
|
||||
printPacket("Enqueuing local", p);
|
||||
fromRadioQueue.enqueue(p);
|
||||
return ERRNO_OK;
|
||||
}
|
||||
} else if (!iface) {
|
||||
// We must be sending to remote nodes also, fail if no interface found
|
||||
|
||||
// If we are sending a broadcast, we also treat it as if we just received it ourself
|
||||
// this allows local apps (and PCs) to see broadcasts sourced locally
|
||||
if (p->to == NODENUM_BROADCAST) {
|
||||
handleReceived(p);
|
||||
}
|
||||
// ERROR! no radio found, report failure back to the client and drop the packet
|
||||
DEBUG_MSG("Error: No interface, returning NAK and dropping packet.\n");
|
||||
sendAckNak(ErrorReason_NO_INTERFACE, p->from, p->id);
|
||||
packetPool.release(p);
|
||||
|
||||
return send(p);
|
||||
return ERRNO_NO_INTERFACES;
|
||||
} else {
|
||||
// If we are sending a broadcast, we also treat it as if we just received it ourself
|
||||
// this allows local apps (and PCs) to see broadcasts sourced locally
|
||||
if (p->to == NODENUM_BROADCAST) {
|
||||
handleReceived(p);
|
||||
}
|
||||
|
||||
return send(p);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -154,14 +188,15 @@ ErrorCode Router::send(MeshPacket *p)
|
||||
p->which_payload = MeshPacket_encrypted_tag;
|
||||
}
|
||||
|
||||
if (iface) {
|
||||
// DEBUG_MSG("Sending packet via interface fr=0x%x,to=0x%x,id=%d\n", p->from, p->to, p->id);
|
||||
return iface->send(p);
|
||||
} else {
|
||||
assert(iface); // This should have been detected already in sendLocal (or we just received a packet from outside)
|
||||
// if (iface) {
|
||||
// DEBUG_MSG("Sending packet via interface fr=0x%x,to=0x%x,id=%d\n", p->from, p->to, p->id);
|
||||
return iface->send(p);
|
||||
/* } else {
|
||||
DEBUG_MSG("Dropping packet - no interfaces - fr=0x%x,to=0x%x,id=%d\n", p->from, p->to, p->id);
|
||||
packetPool.release(p);
|
||||
return ERRNO_NO_INTERFACES;
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,7 +48,8 @@ class Router : protected concurrency::OSThread
|
||||
virtual int32_t runOnce();
|
||||
|
||||
/**
|
||||
* Works like send, but if we are sending to the local node, we directly put the message in the receive queue
|
||||
* Works like send, but if we are sending to the local node, we directly put the message in the receive queue.
|
||||
* This is the primary method used for sending packets, because it handles both the remote and local cases.
|
||||
*
|
||||
* NOTE: This method will free the provided packet (even if we return an error code)
|
||||
*/
|
||||
@ -92,6 +93,11 @@ class Router : protected concurrency::OSThread
|
||||
*/
|
||||
bool perhapsDecode(MeshPacket *p);
|
||||
|
||||
/**
|
||||
* Send an ack or a nak packet back towards whoever sent idFrom
|
||||
*/
|
||||
void sendAckNak(ErrorReason err, NodeNum to, PacketId idFrom);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Called from loop()
|
||||
|
@ -11,12 +11,14 @@
|
||||
#endif
|
||||
|
||||
/* Enum definitions */
|
||||
typedef enum _RouteError {
|
||||
RouteError_NONE = 0,
|
||||
RouteError_NO_ROUTE = 1,
|
||||
RouteError_GOT_NAK = 2,
|
||||
RouteError_TIMEOUT = 3
|
||||
} RouteError;
|
||||
typedef enum _ErrorReason {
|
||||
ErrorReason_NONE = 0,
|
||||
ErrorReason_NO_ROUTE = 1,
|
||||
ErrorReason_GOT_NAK = 2,
|
||||
ErrorReason_TIMEOUT = 3,
|
||||
ErrorReason_NO_INTERFACE = 4,
|
||||
ErrorReason_MAX_RETRANSMIT = 5
|
||||
} ErrorReason;
|
||||
|
||||
typedef enum _Constants {
|
||||
Constants_Unused = 0,
|
||||
@ -230,7 +232,7 @@ typedef struct _SubPacket {
|
||||
User user;
|
||||
RouteDiscovery route_request;
|
||||
RouteDiscovery route_reply;
|
||||
RouteError route_error;
|
||||
ErrorReason error_reason;
|
||||
};
|
||||
uint32_t original_id;
|
||||
bool want_response;
|
||||
@ -288,9 +290,9 @@ typedef struct _ToRadio {
|
||||
|
||||
|
||||
/* Helper constants for enums */
|
||||
#define _RouteError_MIN RouteError_NONE
|
||||
#define _RouteError_MAX RouteError_TIMEOUT
|
||||
#define _RouteError_ARRAYSIZE ((RouteError)(RouteError_TIMEOUT+1))
|
||||
#define _ErrorReason_MIN ErrorReason_NONE
|
||||
#define _ErrorReason_MAX ErrorReason_MAX_RETRANSMIT
|
||||
#define _ErrorReason_ARRAYSIZE ((ErrorReason)(ErrorReason_MAX_RETRANSMIT+1))
|
||||
|
||||
#define _Constants_MIN Constants_Unused
|
||||
#define _Constants_MAX Constants_DATA_PAYLOAD_LEN
|
||||
@ -450,7 +452,7 @@ extern "C" {
|
||||
#define SubPacket_user_tag 4
|
||||
#define SubPacket_route_request_tag 6
|
||||
#define SubPacket_route_reply_tag 7
|
||||
#define SubPacket_route_error_tag 13
|
||||
#define SubPacket_error_reason_tag 13
|
||||
#define SubPacket_original_id_tag 2
|
||||
#define SubPacket_want_response_tag 5
|
||||
#define SubPacket_dest_tag 9
|
||||
@ -517,7 +519,7 @@ X(a, STATIC, ONEOF, MESSAGE, (payload,data,data), 3) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload,user,user), 4) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload,route_request,route_request), 6) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload,route_reply,route_reply), 7) \
|
||||
X(a, STATIC, ONEOF, UENUM, (payload,route_error,route_error), 13) \
|
||||
X(a, STATIC, ONEOF, UENUM, (payload,error_reason,error_reason), 13) \
|
||||
X(a, STATIC, SINGULAR, UINT32, original_id, 2) \
|
||||
X(a, STATIC, SINGULAR, BOOL, want_response, 5) \
|
||||
X(a, STATIC, SINGULAR, UINT32, dest, 9) \
|
||||
|
@ -19,7 +19,7 @@ typedef enum _PortNum {
|
||||
PortNum_REPLY_APP = 32,
|
||||
PortNum_IP_TUNNEL_APP = 33,
|
||||
PortNum_SERIAL_APP = 64,
|
||||
PortNum_STORE_REQUEST_APP = 65,
|
||||
PortNum_STORE_FORWARD_APP = 65,
|
||||
PortNum_PRIVATE_APP = 256,
|
||||
PortNum_ATAK_FORWARDER = 257
|
||||
} PortNum;
|
||||
|
@ -1,4 +1,4 @@
|
||||
[VERSION]
|
||||
major = 1
|
||||
minor = 1
|
||||
build = 34
|
||||
build = 42
|
||||
|
Loading…
Reference in New Issue
Block a user