diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 000000000..ae9c20b82 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,50 @@ +image: python:latest + +variables: + # make sure GitLab check out submodules + GIT_SUBMODULE_STRATEGY: recursive + +stages: + - buildall + - upload + +build: + stage: buildall + + before_script: + # we need zip later for packaging + - "apt update;apt -y install zip" + - "pip install -U platformio" + + script: + # clean up residues from previous run + - rm -rf release + - bin/build-all.sh + + # This is for my local environment, if your runners are tagged differently, modify or remove + tags: + - dockerized + + # The files which are to be made available in GitLab + artifacts: + paths: + - release/archive/firmware*.zip + + +upload: + image: curlimages/curl:latest + + stage: upload + + script: + - | + PACKAGE_REGISTRY_URL="${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/${CI_PROJECT_NAME}/master" + cd release/archive + for f in *.zip; do + curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file ${f} ${PACKAGE_REGISTRY_URL}/${f} + done + echo 'Package uploaded!' + + # This is for my local environment, if your runners are tagged differently, modify or remove + tags: + - dockerized diff --git a/bin/device-install.sh b/bin/device-install.sh index 85e39892e..b0ba6ef37 100755 --- a/bin/device-install.sh +++ b/bin/device-install.sh @@ -46,10 +46,10 @@ shift "$((OPTIND-1))" if [ -f "${FILENAME}" ]; then echo "Trying to flash ${FILENAME}, but first erasing and writing system information" - $PYTHON -m esptool --baud 921600 erase_flash - $PYTHON -m esptool --baud 921600 write_flash 0x1000 system-info.bin - $PYTHON -m esptool --baud 921600 write_flash 0x00390000 spiffs-*.bin - $PYTHON -m esptool --baud 921600 write_flash 0x10000 ${FILENAME} + $PYTHON -m esptool erase_flash + $PYTHON -m esptool write_flash 0x1000 system-info.bin + $PYTHON -m esptool write_flash 0x00390000 spiffs-*.bin + $PYTHON -m esptool write_flash 0x10000 ${FILENAME} else echo "Invalid file: ${FILENAME}" show_help diff --git a/geeksville-private/TODO.md b/geeksville-private/TODO.md index 732627108..7059ddbe2 100644 --- a/geeksville-private/TODO.md +++ b/geeksville-private/TODO.md @@ -325,7 +325,7 @@ Items after the first final candidate release. - add "store and forward" support for messages, or move to the DB sync model. This would allow messages to be eventually delivered even if nodes are out of contact at the moment. - use variable length Strings in protobufs (instead of current fixed buffers). This would save lots of RAM - use BLEDevice::setPower to lower our BLE transmit power - extra range doesn't help us, it costs amps and it increases snoopability -- make a HAM build: just a new frequency list, a bool to say 'never do encryption' and use hte callsign as that node's unique id. -from Girts +- make a Ham build: just a new frequency list, a bool to say 'never do encryption' and use the callsign as that node's unique id. -from Girts - don't forward redundant pings or ping responses to the phone, it just wastes phone battery - don't send location packets if we haven't moved significantly - scrub default radio config settings for bandwidth/range/speed diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index b9243d3d3..502c60b02 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -27,20 +27,20 @@ along with this program. If not, see . #include "NodeDB.h" #include "Screen.h" #include "fonts.h" +#include "gps/GeoCoord.h" #include "gps/RTC.h" #include "graphics/images.h" #include "main.h" #include "mesh-pb-constants.h" #include "mesh/Channels.h" #include "plugins/TextMessagePlugin.h" +#include "sleep.h" #include "target_specific.h" #include "utils.h" -#include "gps/GeoCoord.h" -#include "sleep.h" #ifndef NO_ESP32 -#include "mesh/http/WiFiAPClient.h" #include "esp_task_wdt.h" +#include "mesh/http/WiFiAPClient.h" #endif using namespace meshtastic; /** @todo remove */ @@ -253,10 +253,10 @@ static void drawCriticalFaultFrame(OLEDDisplay *display, OLEDDisplayUiState *sta } // Ignore messages orginating from phone (from the current node 0x0) unless range test or store and forward plugin are enabled -static bool shouldDrawMessage(const MeshPacket *packet) { - return packet->from != 0 && - !radioConfig.preferences.range_test_plugin_enabled && - !radioConfig.preferences.store_forward_plugin_enabled; +static bool shouldDrawMessage(const MeshPacket *packet) +{ + return packet->from != 0 && !radioConfig.preferences.range_test_plugin_enabled && + !radioConfig.preferences.store_forward_plugin_enabled; } /// Draw the last text message we received @@ -445,18 +445,19 @@ static void drawGPScoordinates(OLEDDisplay *display, int16_t x, int16_t y, const sprintf(coordinateLine, "%2i%1c %06i %07i", geoCoord.getUTMZone(), geoCoord.getUTMBand(), geoCoord.getUTMEasting(), geoCoord.getUTMNorthing()); } else if (gpsFormat == GpsCoordinateFormat_GpsFormatMGRS) { // Military Grid Reference System - sprintf(coordinateLine, "%2i%1c %1c%1c %05i %05i", geoCoord.getMGRSZone(), geoCoord.getMGRSBand(), geoCoord.getMGRSEast100k(), - geoCoord.getMGRSNorth100k(), geoCoord.getMGRSEasting(), geoCoord.getMGRSNorthing()); + sprintf(coordinateLine, "%2i%1c %1c%1c %05i %05i", geoCoord.getMGRSZone(), geoCoord.getMGRSBand(), + geoCoord.getMGRSEast100k(), geoCoord.getMGRSNorth100k(), geoCoord.getMGRSEasting(), + geoCoord.getMGRSNorthing()); } else if (gpsFormat == GpsCoordinateFormat_GpsFormatOLC) { // Open Location Code geoCoord.getOLCCode(coordinateLine); - } else if (gpsFormat == GpsCoordinateFormat_GpsFormatOSGR) { // Ordnance Survey Grid Reference + } else if (gpsFormat == GpsCoordinateFormat_GpsFormatOSGR) { // Ordnance Survey Grid Reference if (geoCoord.getOSGRE100k() == 'I' || geoCoord.getOSGRN100k() == 'I') // OSGR is only valid around the UK region sprintf(coordinateLine, "%s", "Out of Boundary"); else - sprintf(coordinateLine, "%1c%1c %05i %05i", geoCoord.getOSGRE100k(),geoCoord.getOSGRN100k(), + sprintf(coordinateLine, "%1c%1c %05i %05i", geoCoord.getOSGRE100k(), geoCoord.getOSGRN100k(), geoCoord.getOSGREasting(), geoCoord.getOSGRNorthing()); } - + // If fixed position, display text "Fixed GPS" alternating with the coordinates. if (radioConfig.preferences.fixed_position) { if ((millis() / 10000) % 2) { @@ -473,7 +474,7 @@ static void drawGPScoordinates(OLEDDisplay *display, int16_t x, int16_t y, const char lonLine[22]; sprintf(latLine, "%2i° %2i' %2.4f\" %1c", geoCoord.getDMSLatDeg(), geoCoord.getDMSLatMin(), geoCoord.getDMSLatSec(), geoCoord.getDMSLatCP()); - sprintf(lonLine, "%3i° %2i' %2.4f\" %1c", geoCoord.getDMSLonDeg(), geoCoord.getDMSLonMin(), geoCoord.getDMSLonSec(), + sprintf(lonLine, "%3i° %2i' %2.4f\" %1c", geoCoord.getDMSLonDeg(), geoCoord.getDMSLonMin(), geoCoord.getDMSLonSec(), geoCoord.getDMSLonCP()); display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(latLine))) / 2, y - FONT_HEIGHT_SMALL * 1, latLine); display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(lonLine))) / 2, y, lonLine); @@ -618,11 +619,6 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_ n = nodeDB.getNodeByIndex(nodeIndex); } displayedNodeNum = n->num; - - // We just changed to a new node screen, ask that node for updated state if it's older than 2 minutes - if (sinceLastSeen(n) > 120) { - service.sendNetworkPing(displayedNodeNum, true); - } } NodeInfo *node = nodeDB.getNodeByIndex(nodeIndex); @@ -665,7 +661,8 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_ // display direction toward node hasNodeHeading = true; Position &p = node->position; - float d = GeoCoord::latLongToMeter(DegD(p.latitude_i), DegD(p.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i)); + float d = + GeoCoord::latLongToMeter(DegD(p.latitude_i), DegD(p.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i)); if (d < 2000) snprintf(distStr, sizeof(distStr), "%.0f m", d); else @@ -673,7 +670,8 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_ // FIXME, also keep the guess at the operators heading and add/substract // it. currently we don't do this and instead draw north up only. - float bearingToOther = GeoCoord::bearing(DegD(p.latitude_i), DegD(p.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i)); + float bearingToOther = + GeoCoord::bearing(DegD(p.latitude_i), DegD(p.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i)); headingRadian = bearingToOther - myHeading; drawNodeHeading(display, compassX, compassY, headingRadian); } @@ -915,13 +913,13 @@ int32_t Screen::runOnce() // standard screen switching is stopped. if (showingNormalScreen) { // standard screen loop handling here - if (radioConfig.preferences.auto_screen_carousel_secs > 0 && + if (radioConfig.preferences.auto_screen_carousel_secs > 0 && (millis() - lastScreenTransition) > (radioConfig.preferences.auto_screen_carousel_secs * 1000)) { DEBUG_MSG("LastScreenTransition exceeded %ums transitioning to next frame\n", (millis() - lastScreenTransition)); handleOnPress(); } } - + // DEBUG_MSG("want fps %d, fixed=%d\n", targetFramerate, // ui.getUiState()->frameState); If we are scrolling we need to be called // soon, otherwise just 1 fps (to save CPU) We also ask to be called twice @@ -1087,7 +1085,7 @@ void Screen::handlePrint(const char *text) } void Screen::handleOnPress() -{ +{ // If screen was off, just wake it, otherwise advance to next frame // If we are in a transition, the press must have bounced, drop it. if (ui.getUiState()->frameState == FIXED) { @@ -1450,7 +1448,8 @@ int Screen::handleStatusUpdate(const meshtastic::Status *arg) return 0; } -int Screen::handleTextMessage(const MeshPacket *packet) { +int Screen::handleTextMessage(const MeshPacket *packet) +{ if (showingNormalScreen) { setFrames(); // Regen the list of screens (will show new text message) } diff --git a/src/mesh/http/ContentHandler.cpp b/src/mesh/http/ContentHandler.cpp index 5f9ef8031..4174c0a23 100644 --- a/src/mesh/http/ContentHandler.cpp +++ b/src/mesh/http/ContentHandler.cpp @@ -74,7 +74,7 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer) ResourceNode *nodeJsonReport = new ResourceNode("/json/report", "GET", &handleReport); ResourceNode *nodeJsonSpiffsBrowseStatic = new ResourceNode("/json/spiffs/browse/static", "GET", &handleSpiffsBrowseStatic); ResourceNode *nodeJsonDelete = new ResourceNode("/json/spiffs/delete/static", "DELETE", &handleSpiffsDeleteStatic); - + ResourceNode *nodeRoot = new ResourceNode("/*", "GET", &handleStatic); // Secure nodes @@ -106,7 +106,6 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer) insecureServer->registerNode(nodeJsonDelete); insecureServer->registerNode(nodeJsonReport); insecureServer->registerNode(nodeRoot); - } void handleAPIv1FromRadio(HTTPRequest *req, HTTPResponse *res) @@ -176,7 +175,6 @@ void handleAPIv1ToRadio(HTTPRequest *req, HTTPResponse *res) res->setHeader("Access-Control-Allow-Methods", "PUT, OPTIONS"); res->setHeader("X-Protobuf-Schema", "https://raw.githubusercontent.com/meshtastic/Meshtastic-protobufs/master/mesh.proto"); - if (req->getMethod() == "OPTIONS") { res->setStatusCode(204); // Success with no content // res->print(""); @todo remove @@ -285,7 +283,6 @@ void handleStatic(HTTPRequest *req, HTTPResponse *res) std::string filename = "/static/" + parameter1; std::string filenameGzip = "/static/" + parameter1 + ".gz"; - // Try to open the file from SPIFFS File file; diff --git a/src/mesh/http/ContentHelper.h b/src/mesh/http/ContentHelper.h index ca3fee3c2..a80c39f47 100644 --- a/src/mesh/http/ContentHelper.h +++ b/src/mesh/http/ContentHelper.h @@ -3,6 +3,4 @@ #define BoolToString(x) ((x) ? "true" : "false") - void replaceAll(std::string &str, const std::string &from, const std::string &to); - diff --git a/src/mesh/http/WebServer.cpp b/src/mesh/http/WebServer.cpp index e450c566b..cbf25271d 100644 --- a/src/mesh/http/WebServer.cpp +++ b/src/mesh/http/WebServer.cpp @@ -1,13 +1,12 @@ -#include "main.h" #include "mesh/http/WebServer.h" #include "NodeDB.h" +#include "graphics/Screen.h" +#include "main.h" #include "mesh/http/WiFiAPClient.h" +#include "sleep.h" #include #include #include -#include "sleep.h" -#include "graphics/Screen.h" - #include #include @@ -60,10 +59,9 @@ static void handleWebResponse() // will be ignored by the NRF boards. handleDNSResponse(); - if(secureServer) + if (secureServer) secureServer->loop(); insecureServer->loop(); - } } } @@ -72,7 +70,6 @@ static void taskCreateCert(void *parameter) { prefs.begin("MeshtasticHTTPS", false); - #if 0 // Delete the saved certs (used in debugging) DEBUG_MSG("Deleting any saved SSL keys ...\n"); @@ -81,7 +78,6 @@ static void taskCreateCert(void *parameter) prefs.remove("cert"); #endif - DEBUG_MSG("Checking if we have a previously saved SSL Certificate.\n"); size_t pkLen = prefs.getBytesLength("PK"); @@ -142,11 +138,11 @@ void createSSLCert() // jm@casler.org (Oct 2020) xTaskCreate(taskCreateCert, /* Task function. */ "createCert", /* String with name of task. */ - //16384, /* Stack size in bytes. */ - 8192, /* Stack size in bytes. */ - NULL, /* Parameter passed as input of the task */ - 16, /* Priority of the task. */ - NULL); /* Task handle. */ + // 16384, /* Stack size in bytes. */ + 8192, /* Stack size in bytes. */ + NULL, /* Parameter passed as input of the task */ + 16, /* Priority of the task. */ + NULL); /* Task handle. */ DEBUG_MSG("Waiting for SSL Cert to be generated.\n"); while (!isCertReady) { @@ -157,8 +153,8 @@ void createSSLCert() yield(); esp_task_wdt_reset(); - if (millis() / 1000 >= 3) { - screen->setSSLFrames(); + if (millis() / 1000 >= 3) { + screen->setSSLFrames(); } } runLoop = false; @@ -193,11 +189,11 @@ void initWebServer() registerHandlers(insecureServer, secureServer); - if(secureServer) { + if (secureServer) { DEBUG_MSG("Starting Secure Web Server...\n"); secureServer->start(); } - DEBUG_MSG("Starting Insecure Web Server...\n"); + DEBUG_MSG("Starting Insecure Web Server...\n"); insecureServer->start(); if (insecureServer->isRunning()) { DEBUG_MSG("Web Servers Ready! :-) \n"); diff --git a/src/mesh/http/WebServer.h b/src/mesh/http/WebServer.h index 74b299dcf..63a61367d 100644 --- a/src/mesh/http/WebServer.h +++ b/src/mesh/http/WebServer.h @@ -15,7 +15,6 @@ class WebServerThread : private concurrency::OSThread WebServerThread(); protected: - virtual int32_t runOnce(); }; diff --git a/src/mesh/http/WiFiAPClient.h b/src/mesh/http/WiFiAPClient.h index acbbdb19b..fa9be8feb 100644 --- a/src/mesh/http/WiFiAPClient.h +++ b/src/mesh/http/WiFiAPClient.h @@ -21,4 +21,3 @@ void handleDNSResponse(); bool isSoftAPForced(); uint8_t getWifiDisconnectReason(); - diff --git a/src/nrf52/main-nrf52.cpp b/src/nrf52/main-nrf52.cpp index ab109205b..88166e4fa 100644 --- a/src/nrf52/main-nrf52.cpp +++ b/src/nrf52/main-nrf52.cpp @@ -38,18 +38,13 @@ void __attribute__((noreturn)) __assert_func(const char *file, int line, const c void getMacAddr(uint8_t *dmac) { - ble_gap_addr_t addr; - if (sd_ble_gap_addr_get(&addr) == NRF_SUCCESS) { - memcpy(dmac, addr.addr, 6); - } else { - const uint8_t *src = (const uint8_t *)NRF_FICR->DEVICEADDR; - dmac[5] = src[0]; - dmac[4] = src[1]; - dmac[3] = src[2]; - dmac[2] = src[3]; - dmac[1] = src[4]; - dmac[0] = src[5] | 0xc0; // MSB high two bits get set elsewhere in the bluetooth stack - } + const uint8_t *src = (const uint8_t *)NRF_FICR->DEVICEADDR; + dmac[5] = src[0]; + dmac[4] = src[1]; + dmac[3] = src[2]; + dmac[2] = src[3]; + dmac[1] = src[4]; + dmac[0] = src[5] | 0xc0; // MSB high two bits get set elsewhere in the bluetooth stack } static void initBrownout() diff --git a/src/plugins/esp32/StoreForwardPlugin.cpp b/src/plugins/esp32/StoreForwardPlugin.cpp index 39ad50148..10dedda41 100644 --- a/src/plugins/esp32/StoreForwardPlugin.cpp +++ b/src/plugins/esp32/StoreForwardPlugin.cpp @@ -80,8 +80,7 @@ void StoreForwardPlugin::populatePSRAM() /* Use a maximum of 2/3 the available PSRAM unless otherwise specified. Note: This needs to be done after every thing that would use PSRAM */ - uint32_t numberOfPackets = - (this->records ? this->records : (((ESP.getFreePsram() / 3) * 2) / sizeof(PacketHistoryStruct))); + uint32_t numberOfPackets = (this->records ? this->records : (((ESP.getFreePsram() / 3) * 2) / sizeof(PacketHistoryStruct))); this->packetHistory = static_cast(ps_calloc(numberOfPackets, sizeof(PacketHistoryStruct))); @@ -107,7 +106,7 @@ void StoreForwardPlugin::historyReport() void StoreForwardPlugin::historySend(uint32_t msAgo, uint32_t to) { - //uint32_t packetsSent = 0; + // uint32_t packetsSent = 0; uint32_t queueSize = storeForwardPlugin->historyQueueCreate(msAgo, to); @@ -144,13 +143,16 @@ uint32_t StoreForwardPlugin::historyQueueCreate(uint32_t msAgo, uint32_t to) Copy the messages that were received by the router in the last msAgo to the packetHistoryTXQueue structure. - TODO: The condition (this->packetHistory[i].to & 0xffffffff) == to) is not tested since + TODO: The condition (this->packetHistory[i].to & NODENUM_BROADCAST) == to) is not tested since I don't have an easy way to target a specific user. Will need to do this soon. */ - if ((this->packetHistory[i].to & 0xffffffff) == 0xffffffff || ((this->packetHistory[i].to & 0xffffffff) == to)) { + if ((this->packetHistory[i].to & NODENUM_BROADCAST) == NODENUM_BROADCAST || + ((this->packetHistory[i].to & NODENUM_BROADCAST) == to)) { + this->packetHistoryTXQueue[this->packetHistoryTXQueue_size].time = this->packetHistory[i].time; this->packetHistoryTXQueue[this->packetHistoryTXQueue_size].time = this->packetHistory[i].time; this->packetHistoryTXQueue[this->packetHistoryTXQueue_size].to = this->packetHistory[i].to; this->packetHistoryTXQueue[this->packetHistoryTXQueue_size].from = this->packetHistory[i].from; + this->packetHistoryTXQueue[this->packetHistoryTXQueue_size].channel = this->packetHistory[i].channel; this->packetHistoryTXQueue[this->packetHistoryTXQueue_size].payload_size = this->packetHistory[i].payload_size; memcpy(this->packetHistoryTXQueue[this->packetHistoryTXQueue_size].payload, this->packetHistory[i].payload, Constants_DATA_PAYLOAD_LEN); @@ -171,6 +173,7 @@ void StoreForwardPlugin::historyAdd(const MeshPacket &mp) this->packetHistory[this->packetHistoryCurrent].time = millis(); this->packetHistory[this->packetHistoryCurrent].to = mp.to; + this->packetHistory[this->packetHistoryCurrent].channel = mp.channel; this->packetHistory[this->packetHistoryCurrent].from = mp.from; this->packetHistory[this->packetHistoryCurrent].payload_size = p.payload.size; memcpy(this->packetHistory[this->packetHistoryCurrent].payload, p.payload.bytes, Constants_DATA_PAYLOAD_LEN); @@ -191,6 +194,7 @@ void StoreForwardPlugin::sendPayload(NodeNum dest, uint32_t packetHistory_index) p->to = dest; p->from = this->packetHistoryTXQueue[packetHistory_index].from; + p->channel = this->packetHistoryTXQueue[packetHistory_index].channel; // Let's assume that if the router received the S&F request that the client is in range. // TODO: Make this configurable. @@ -210,6 +214,10 @@ void StoreForwardPlugin::sendMessage(NodeNum dest, char *str) p->to = dest; + // FIXME - Determine if the delayed packet is broadcast or delayed. For now, assume + // everything is broadcast. + p->delayed = MeshPacket_Delayed_DELAYED_BROADCAST; + // Let's assume that if the router received the S&F request that the client is in range. // TODO: Make this configurable. p->want_ack = false; @@ -351,7 +359,6 @@ ProcessMessage StoreForwardPlugin::handleReceivedProtobuf(const MeshPacket &mp, DEBUG_MSG("StoreAndForward_RequestResponse_ROUTER_PONG\n"); break; - default: assert(0); // unexpected state - FIXME, make an error code and reboot } @@ -407,9 +414,8 @@ StoreForwardPlugin::StoreForwardPlugin() // Popupate PSRAM with our data structures. this->populatePSRAM(); - - //this->packetTimeMax = 2000; - //DEBUG_MSG("SF Time to Transmit maxPacketSize (%d bytes) %d ms\n", maxPacketSize, this->packetTimeMax); + // this->packetTimeMax = 2000; + // DEBUG_MSG("SF Time to Transmit maxPacketSize (%d bytes) %d ms\n", maxPacketSize, this->packetTimeMax); } else { DEBUG_MSG("Device has less than 1M of PSRAM free. Aborting startup.\n"); diff --git a/src/plugins/esp32/StoreForwardPlugin.h b/src/plugins/esp32/StoreForwardPlugin.h index 65b4f1897..dd252dbae 100644 --- a/src/plugins/esp32/StoreForwardPlugin.h +++ b/src/plugins/esp32/StoreForwardPlugin.h @@ -12,6 +12,7 @@ struct PacketHistoryStruct { uint32_t time; uint32_t to; uint32_t from; + uint8_t channel; bool ack; uint8_t payload[Constants_DATA_PAYLOAD_LEN]; pb_size_t payload_size;