Merge remote-tracking branch 'origin/develop'
This commit is contained in:
@@ -201,6 +201,7 @@ jobs:
|
|||||||
./device-*.bat
|
./device-*.bat
|
||||||
./littlefs-*.bin
|
./littlefs-*.bin
|
||||||
./bleota*bin
|
./bleota*bin
|
||||||
|
./mt-*-ota.bin
|
||||||
./Meshtastic_nRF52_factory_erase*.uf2
|
./Meshtastic_nRF52_factory_erase*.uf2
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -48,5 +48,5 @@ arduino-lib-builder*
|
|||||||
dependencies.lock
|
dependencies.lock
|
||||||
idf_component.yml
|
idf_component.yml
|
||||||
CMakeLists.txt
|
CMakeLists.txt
|
||||||
sdkconfig.*
|
/sdkconfig.*
|
||||||
.dummy/*
|
.dummy/*
|
||||||
@@ -105,6 +105,8 @@ Lora:
|
|||||||
|
|
||||||
GPS:
|
GPS:
|
||||||
# SerialPath: /dev/ttyS0
|
# SerialPath: /dev/ttyS0
|
||||||
|
# ExtraPins:
|
||||||
|
# - 22
|
||||||
|
|
||||||
### Specify I2C device, or leave blank for none
|
### Specify I2C device, or leave blank for none
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -114,8 +114,7 @@ lib_deps =
|
|||||||
[radiolib_base]
|
[radiolib_base]
|
||||||
lib_deps =
|
lib_deps =
|
||||||
# renovate: datasource=custom.pio depName=RadioLib packageName=jgromes/library/RadioLib
|
# renovate: datasource=custom.pio depName=RadioLib packageName=jgromes/library/RadioLib
|
||||||
# jgromes/RadioLib@7.4.0
|
jgromes/RadioLib@7.5.0
|
||||||
https://github.com/jgromes/RadioLib/archive/536c7267362e2c1345be7054ba45e503252975ff.zip
|
|
||||||
|
|
||||||
[device-ui_base]
|
[device-ui_base]
|
||||||
lib_deps =
|
lib_deps =
|
||||||
|
|||||||
@@ -41,7 +41,8 @@ extern "C" void logLegacy(const char *level, const char *fmt, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if HAS_NETWORKING
|
#if HAS_NETWORKING
|
||||||
|
namespace meshtastic
|
||||||
|
{
|
||||||
Syslog::Syslog(UDP &client)
|
Syslog::Syslog(UDP &client)
|
||||||
{
|
{
|
||||||
this->_client = &client;
|
this->_client = &client;
|
||||||
@@ -195,4 +196,6 @@ inline bool Syslog::_sendLog(uint16_t pri, const char *appName, const char *mess
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}; // namespace meshtastic
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -162,6 +162,8 @@ extern "C" void logLegacy(const char *level, const char *fmt, ...);
|
|||||||
|
|
||||||
#if HAS_NETWORKING
|
#if HAS_NETWORKING
|
||||||
|
|
||||||
|
namespace meshtastic
|
||||||
|
{
|
||||||
class Syslog
|
class Syslog
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@@ -195,4 +197,6 @@ class Syslog
|
|||||||
bool vlogf(uint16_t pri, const char *appName, const char *fmt, va_list args) __attribute__((format(printf, 3, 0)));
|
bool vlogf(uint16_t pri, const char *appName, const char *fmt, va_list args) __attribute__((format(printf, 3, 0)));
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // HAS_NETWORKING
|
}; // namespace meshtastic
|
||||||
|
|
||||||
|
#endif // HAS_NETWORKING
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAS_NETWORKING
|
#if HAS_NETWORKING
|
||||||
extern Syslog syslog;
|
extern meshtastic::Syslog syslog;
|
||||||
#endif
|
#endif
|
||||||
void RedirectablePrint::rpInit()
|
void RedirectablePrint::rpInit()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -378,6 +378,8 @@ extern meshtastic_CriticalErrorCode error_code;
|
|||||||
extern uint32_t error_address;
|
extern uint32_t error_address;
|
||||||
#define NODEINFO_BITFIELD_IS_KEY_MANUALLY_VERIFIED_SHIFT 0
|
#define NODEINFO_BITFIELD_IS_KEY_MANUALLY_VERIFIED_SHIFT 0
|
||||||
#define NODEINFO_BITFIELD_IS_KEY_MANUALLY_VERIFIED_MASK (1 << NODEINFO_BITFIELD_IS_KEY_MANUALLY_VERIFIED_SHIFT)
|
#define NODEINFO_BITFIELD_IS_KEY_MANUALLY_VERIFIED_MASK (1 << NODEINFO_BITFIELD_IS_KEY_MANUALLY_VERIFIED_SHIFT)
|
||||||
|
#define NODEINFO_BITFIELD_IS_MUTED_SHIFT 1
|
||||||
|
#define NODEINFO_BITFIELD_IS_MUTED_MASK (1 << NODEINFO_BITFIELD_IS_MUTED_SHIFT)
|
||||||
|
|
||||||
#define Module_Config_size \
|
#define Module_Config_size \
|
||||||
(ModuleConfig_CannedMessageConfig_size + ModuleConfig_ExternalNotificationConfig_size + ModuleConfig_MQTTConfig_size + \
|
(ModuleConfig_CannedMessageConfig_size + ModuleConfig_ExternalNotificationConfig_size + ModuleConfig_MQTTConfig_size + \
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ meshtastic_NodeInfo TypeConversions::ConvertToNodeInfo(const meshtastic_NodeInfo
|
|||||||
info.is_favorite = lite->is_favorite;
|
info.is_favorite = lite->is_favorite;
|
||||||
info.is_ignored = lite->is_ignored;
|
info.is_ignored = lite->is_ignored;
|
||||||
info.is_key_manually_verified = lite->bitfield & NODEINFO_BITFIELD_IS_KEY_MANUALLY_VERIFIED_MASK;
|
info.is_key_manually_verified = lite->bitfield & NODEINFO_BITFIELD_IS_KEY_MANUALLY_VERIFIED_MASK;
|
||||||
|
info.is_muted = lite->bitfield & NODEINFO_BITFIELD_IS_MUTED_MASK;
|
||||||
|
|
||||||
if (lite->has_hops_away) {
|
if (lite->has_hops_away) {
|
||||||
info.has_hops_away = true;
|
info.has_hops_away = true;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ uint32_t ntp_renew = 0;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
EthernetUDP syslogClient;
|
EthernetUDP syslogClient;
|
||||||
Syslog syslog(syslogClient);
|
meshtastic::Syslog syslog(syslogClient);
|
||||||
|
|
||||||
bool ethStartupComplete = 0;
|
bool ethStartupComplete = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ bool needReconnect = true; // If we create our reconnector, run it once at the
|
|||||||
bool isReconnecting = false; // If we are currently reconnecting
|
bool isReconnecting = false; // If we are currently reconnecting
|
||||||
|
|
||||||
WiFiUDP syslogClient;
|
WiFiUDP syslogClient;
|
||||||
Syslog syslog(syslogClient);
|
meshtastic::Syslog syslog(syslogClient);
|
||||||
|
|
||||||
Periodic *wifiReconnect;
|
Periodic *wifiReconnect;
|
||||||
|
|
||||||
|
|||||||
@@ -383,6 +383,16 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case meshtastic_AdminMessage_toggle_muted_node_tag: {
|
||||||
|
LOG_INFO("Client received toggle_muted_node command");
|
||||||
|
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(r->toggle_muted_node);
|
||||||
|
if (node != NULL) {
|
||||||
|
node->bitfield ^= (1 << NODEINFO_BITFIELD_IS_MUTED_SHIFT);
|
||||||
|
saveChanges(SEGMENT_NODEDATABASE, false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case meshtastic_AdminMessage_set_fixed_position_tag: {
|
case meshtastic_AdminMessage_set_fixed_position_tag: {
|
||||||
LOG_INFO("Client received set_fixed_position command");
|
LOG_INFO("Client received set_fixed_position command");
|
||||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
||||||
|
|||||||
@@ -459,7 +459,13 @@ ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
meshtastic_NodeInfoLite *sender = nodeDB->getMeshNode(mp.from);
|
||||||
|
bool mutedNode = false;
|
||||||
|
if (sender) {
|
||||||
|
mutedNode = (sender->bitfield & NODEINFO_BITFIELD_IS_MUTED_MASK);
|
||||||
|
}
|
||||||
meshtastic_Channel ch = channels.getByIndex(mp.channel ? mp.channel : channels.getPrimaryIndex());
|
meshtastic_Channel ch = channels.getByIndex(mp.channel ? mp.channel : channels.getPrimaryIndex());
|
||||||
|
|
||||||
if (moduleConfig.external_notification.alert_bell) {
|
if (moduleConfig.external_notification.alert_bell) {
|
||||||
if (containsBell) {
|
if (containsBell) {
|
||||||
LOG_INFO("externalNotificationModule - Notification Bell");
|
LOG_INFO("externalNotificationModule - Notification Bell");
|
||||||
@@ -510,7 +516,7 @@ ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (moduleConfig.external_notification.alert_message &&
|
if (moduleConfig.external_notification.alert_message && !mutedNode &&
|
||||||
(!ch.settings.has_module_settings || !ch.settings.module_settings.is_muted)) {
|
(!ch.settings.has_module_settings || !ch.settings.module_settings.is_muted)) {
|
||||||
LOG_INFO("externalNotificationModule - Notification Module");
|
LOG_INFO("externalNotificationModule - Notification Module");
|
||||||
isNagging = true;
|
isNagging = true;
|
||||||
@@ -522,7 +528,7 @@ ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (moduleConfig.external_notification.alert_message_vibra &&
|
if (moduleConfig.external_notification.alert_message_vibra && !mutedNode &&
|
||||||
(!ch.settings.has_module_settings || !ch.settings.module_settings.is_muted)) {
|
(!ch.settings.has_module_settings || !ch.settings.module_settings.is_muted)) {
|
||||||
LOG_INFO("externalNotificationModule - Notification Module (Vibra)");
|
LOG_INFO("externalNotificationModule - Notification Module (Vibra)");
|
||||||
isNagging = true;
|
isNagging = true;
|
||||||
@@ -534,7 +540,7 @@ ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (moduleConfig.external_notification.alert_message_buzzer &&
|
if (moduleConfig.external_notification.alert_message_buzzer && !mutedNode &&
|
||||||
(!ch.settings.has_module_settings || !ch.settings.module_settings.is_muted)) {
|
(!ch.settings.has_module_settings || !ch.settings.module_settings.is_muted)) {
|
||||||
LOG_INFO("externalNotificationModule - Notification Module (Buzzer)");
|
LOG_INFO("externalNotificationModule - Notification Module (Buzzer)");
|
||||||
if (config.device.buzzer_mode != meshtastic_Config_DeviceConfig_BuzzerMode_DIRECT_MSG_ONLY ||
|
if (config.device.buzzer_mode != meshtastic_Config_DeviceConfig_BuzzerMode_DIRECT_MSG_ONLY ||
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include "ProtobufModule.h"
|
#include "ProtobufModule.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#if defined(ARCH_ESP32)
|
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_PAXCOUNTER
|
||||||
#include "../mesh/generated/meshtastic/paxcount.pb.h"
|
#include "../mesh/generated/meshtastic/paxcount.pb.h"
|
||||||
#include "NodeDB.h"
|
#include "NodeDB.h"
|
||||||
#include <libpax_api.h>
|
#include <libpax_api.h>
|
||||||
@@ -35,4 +35,4 @@ class PaxcounterModule : private concurrency::OSThread, public ProtobufModule<me
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern PaxcounterModule *paxcounterModule;
|
extern PaxcounterModule *paxcounterModule;
|
||||||
#endif
|
#endif
|
||||||
@@ -487,6 +487,11 @@ void portduinoSetup()
|
|||||||
max_GPIO = i->pin;
|
max_GPIO = i->pin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto i : portduino_config.extra_pins) {
|
||||||
|
if (i.enabled && i.pin > max_GPIO)
|
||||||
|
max_GPIO = i.pin;
|
||||||
|
}
|
||||||
|
|
||||||
gpioInit(max_GPIO + 1); // Done here so we can inform Portduino how many GPIOs we need.
|
gpioInit(max_GPIO + 1); // Done here so we can inform Portduino how many GPIOs we need.
|
||||||
|
|
||||||
// Need to bind all the configured GPIO pins so they're not simulated
|
// Need to bind all the configured GPIO pins so they're not simulated
|
||||||
@@ -504,6 +509,19 @@ void portduinoSetup()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (auto i : portduino_config.extra_pins) {
|
||||||
|
// In the case of a ch341 Lora device, we don't want to touch the system GPIO lines for Lora
|
||||||
|
// Those GPIO are handled in our usermode driver instead.
|
||||||
|
if (i.config_section == "Lora" && portduino_config.lora_spi_dev == "ch341") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (i.enabled) {
|
||||||
|
if (initGPIOPin(i.pin, gpioChipName + std::to_string(i.gpiochip), i.line) != ERRNO_OK) {
|
||||||
|
printf("Error setting pin number %d. It may not exist, or may already be in use.\n", i.line);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Only initialize the radio pins when dealing with real, kernel controlled SPI hardware
|
// Only initialize the radio pins when dealing with real, kernel controlled SPI hardware
|
||||||
if (portduino_config.lora_spi_dev != "" && portduino_config.lora_spi_dev != "ch341") {
|
if (portduino_config.lora_spi_dev != "" && portduino_config.lora_spi_dev != "ch341") {
|
||||||
@@ -717,6 +735,16 @@ bool loadConfig(const char *configPath)
|
|||||||
portduino_config.has_gps = 1;
|
portduino_config.has_gps = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (yamlConfig["GPIO"]["ExtraPins"]) {
|
||||||
|
for (auto extra_pin : yamlConfig["GPIO"]["ExtraPins"]) {
|
||||||
|
portduino_config.extra_pins.push_back(pinMapping());
|
||||||
|
portduino_config.extra_pins.back().config_section = "GPIO";
|
||||||
|
portduino_config.extra_pins.back().config_name = "ExtraPins";
|
||||||
|
portduino_config.extra_pins.back().enabled = true;
|
||||||
|
readGPIOFromYaml(extra_pin, portduino_config.extra_pins.back());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (yamlConfig["I2C"]) {
|
if (yamlConfig["I2C"]) {
|
||||||
portduino_config.i2cdev = yamlConfig["I2C"]["I2CDevice"].as<std::string>("");
|
portduino_config.i2cdev = yamlConfig["I2C"]["I2CDevice"].as<std::string>("");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "LR11x0Interface.h"
|
#include "LR11x0Interface.h"
|
||||||
#include "Module.h"
|
#include "Module.h"
|
||||||
@@ -97,6 +98,7 @@ extern struct portduino_config_struct {
|
|||||||
pinMapping lora_txen_pin = {"Lora", "TXen"};
|
pinMapping lora_txen_pin = {"Lora", "TXen"};
|
||||||
pinMapping lora_rxen_pin = {"Lora", "RXen"};
|
pinMapping lora_rxen_pin = {"Lora", "RXen"};
|
||||||
pinMapping lora_sx126x_ant_sw_pin = {"Lora", "SX126X_ANT_SW"};
|
pinMapping lora_sx126x_ant_sw_pin = {"Lora", "SX126X_ANT_SW"};
|
||||||
|
std::vector<pinMapping> extra_pins = {};
|
||||||
|
|
||||||
// GPS
|
// GPS
|
||||||
bool has_gps = false;
|
bool has_gps = false;
|
||||||
@@ -300,6 +302,20 @@ extern struct portduino_config_struct {
|
|||||||
}
|
}
|
||||||
out << YAML::EndMap; // Lora
|
out << YAML::EndMap; // Lora
|
||||||
|
|
||||||
|
if (!extra_pins.empty()) {
|
||||||
|
out << YAML::Key << "GPIO" << YAML::Value << YAML::BeginMap;
|
||||||
|
out << YAML::Key << "ExtraPins" << YAML::Value << YAML::BeginSeq;
|
||||||
|
for (auto extra : extra_pins) {
|
||||||
|
out << YAML::BeginMap;
|
||||||
|
out << YAML::Key << "pin" << YAML::Value << extra.pin;
|
||||||
|
out << YAML::Key << "line" << YAML::Value << extra.line;
|
||||||
|
out << YAML::Key << "gpiochip" << YAML::Value << extra.gpiochip;
|
||||||
|
out << YAML::EndMap;
|
||||||
|
}
|
||||||
|
out << YAML::EndSeq;
|
||||||
|
out << YAML::EndMap; // GPIO
|
||||||
|
}
|
||||||
|
|
||||||
if (i2cdev != "") {
|
if (i2cdev != "") {
|
||||||
out << YAML::Key << "I2C" << YAML::Value << YAML::BeginMap;
|
out << YAML::Key << "I2C" << YAML::Value << YAML::BeginMap;
|
||||||
out << YAML::Key << "I2CDevice" << YAML::Value << i2cdev;
|
out << YAML::Key << "I2CDevice" << YAML::Value << i2cdev;
|
||||||
|
|||||||
@@ -65,8 +65,6 @@ lib_deps =
|
|||||||
https://github.com/dbinfrago/libpax/archive/3cdc0371c375676a97967547f4065607d4c53fd1.zip
|
https://github.com/dbinfrago/libpax/archive/3cdc0371c375676a97967547f4065607d4c53fd1.zip
|
||||||
# renovate: datasource=github-tags depName=XPowersLib packageName=lewisxhe/XPowersLib
|
# renovate: datasource=github-tags depName=XPowersLib packageName=lewisxhe/XPowersLib
|
||||||
https://github.com/lewisxhe/XPowersLib/archive/v0.3.2.zip
|
https://github.com/lewisxhe/XPowersLib/archive/v0.3.2.zip
|
||||||
# renovate: datasource=git-refs depName=meshtastic-ESP32_Codec2 packageName=https://github.com/meshtastic/ESP32_Codec2 gitBranch=master
|
|
||||||
https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip
|
|
||||||
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
|
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
|
||||||
rweather/Crypto@0.4.0
|
rweather/Crypto@0.4.0
|
||||||
|
|
||||||
|
|||||||
@@ -5,4 +5,5 @@ extends = esp32_common
|
|||||||
custom_esp32_kind = esp32
|
custom_esp32_kind = esp32
|
||||||
|
|
||||||
build_flags =
|
build_flags =
|
||||||
${esp32_common.build_flags}
|
${esp32_common.build_flags}
|
||||||
|
-DMESHTASTIC_EXCLUDE_AUDIO=1
|
||||||
@@ -4,3 +4,8 @@ custom_esp32_kind = esp32c3
|
|||||||
|
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
monitor_filters = esp32_c3_exception_decoder
|
monitor_filters = esp32_c3_exception_decoder
|
||||||
|
|
||||||
|
lib_deps =
|
||||||
|
${esp32_common.lib_deps}
|
||||||
|
# renovate: datasource=git-refs depName=meshtastic-ESP32_Codec2 packageName=https://github.com/meshtastic/ESP32_Codec2 gitBranch=master
|
||||||
|
https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip
|
||||||
@@ -12,7 +12,12 @@ build_flags =
|
|||||||
-DHAS_BLUETOOTH=0
|
-DHAS_BLUETOOTH=0
|
||||||
-DMESHTASTIC_EXCLUDE_PAXCOUNTER
|
-DMESHTASTIC_EXCLUDE_PAXCOUNTER
|
||||||
-DMESHTASTIC_EXCLUDE_BLUETOOTH
|
-DMESHTASTIC_EXCLUDE_BLUETOOTH
|
||||||
|
|
||||||
|
lib_deps =
|
||||||
|
${esp32_common.lib_deps}
|
||||||
|
# renovate: datasource=git-refs depName=meshtastic-ESP32_Codec2 packageName=https://github.com/meshtastic/ESP32_Codec2 gitBranch=master
|
||||||
|
https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip
|
||||||
|
|
||||||
lib_ignore =
|
lib_ignore =
|
||||||
${esp32_common.lib_ignore}
|
${esp32_common.lib_ignore}
|
||||||
NimBLE-Arduino
|
NimBLE-Arduino
|
||||||
|
|||||||
@@ -3,3 +3,8 @@ extends = esp32_common
|
|||||||
custom_esp32_kind = esp32s3
|
custom_esp32_kind = esp32s3
|
||||||
|
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
|
||||||
|
lib_deps =
|
||||||
|
${esp32_common.lib_deps}
|
||||||
|
# renovate: datasource=git-refs depName=meshtastic-ESP32_Codec2 packageName=https://github.com/meshtastic/ESP32_Codec2 gitBranch=master
|
||||||
|
https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip
|
||||||
Reference in New Issue
Block a user