diff --git a/.gitignore b/.gitignore index 77aab2fe..a6d2222f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ ## User settings xcuserdata/ +SupportingFiles/ ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) *.xcscmblueprint diff --git a/Localizable.xcstrings b/Localizable.xcstrings index d6927e7f..e061cceb 100644 --- a/Localizable.xcstrings +++ b/Localizable.xcstrings @@ -20,22 +20,6 @@ } } }, - " %@" : { - "localizations" : { - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : " %@" - } - } - } - }, " %@" : { "localizations" : { "sr" : { @@ -52,22 +36,6 @@ } } }, - " Whether or not use INPUT_PULLUP mode for GPIO pin. Only applicable if the board uses pull-up resistors on the pin" : { - "localizations" : { - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Да ли желите да користите режим INPUT_PULLUP за GPIO пин. Применљиво само ако плоча користи pull-up отпорнике на пиновима" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "是否为 GPIO 引脚使用输入上拉模式。仅适用于电路板在引脚上使用上拉电阻的情况" - } - } - } - }, ": %@" : { "localizations" : { "sr" : { @@ -198,40 +166,6 @@ } } }, - "%@ - 1 Hop" : { - "extractionState" : "stale", - "localizations" : { - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ - 1 Скок" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ - 1 跳" - } - } - } - }, - "%@ - Direct" : { - "extractionState" : "stale", - "localizations" : { - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ - Директно" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ - 直接" - } - } - } - }, "%@ - No Response" : { "localizations" : { "de" : { @@ -347,7 +281,7 @@ "de" : { "stringUnit" : { "state" : "translated", - "value" : "%@ entfernt" + "value" : "%@ entfernt" } }, "sr" : { @@ -366,15 +300,9 @@ }, "%@ can be up to %@ bytes long." : { "localizations" : { - "en" : { - "stringUnit" : { - "state" : "new", - "value" : "%1$@ can be up to %2$@ bytes long." - } - }, "sr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "%1$@ може имати до %2$@ бајтова." } }, @@ -434,19 +362,179 @@ } } }, - "%@ hPa" : { - "extractionState" : "stale", + "%@ Please try connecting again and check the PIN carefully." : { + "extractionState" : "migrated", "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ Bitte versuche es erneut. Achte sorgfältig auf die richtige PIN." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ Merci d'essayer à nouveau en vérifiant bien le code PIN." + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ בבקשה נסה שנית להתחבר למכשיר ובדוק את הקוד." + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ Spróbuj połączyć się ponownie i dokładnie sprawdź PIN." + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ Por favor, tente conectar novamente e verifique cuidadosamente o PIN." + } + }, + "se" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ Försök att ansluta igen och kontrollera PIN-koden noggrant." + } + }, "sr" : { "stringUnit" : { "state" : "translated", - "value" : "%@ hPa" + "value" : "%@ Покушајте поново да се повежете и пажљиво проверите ПИН." } }, "zh-Hans" : { "stringUnit" : { "state" : "translated", - "value" : "%@ hPa" + "value" : "%@ 请再次尝试连接并仔细检查 PIN 码。" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ 請再次嘗試連接並仔細檢查 PIN 碼。" + } + } + } + }, + "%@ The app will automatically reconnect to the preferred radio if it comes back in range." : { + "extractionState" : "migrated", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "%@ Die App wird automatisch wieder zum präferierten Gerät verbinden, sobald es in Reichweite kommt." + } + }, + "fr" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "%@ L'application se reconnectera automatiquement à la radio en favori dès qu'elle sera à nouveau disponible." + } + }, + "he" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "%@ האפליקציה תנסה אוטומטית להתחבר מחדש למכשיר המועדף אם ייראה." + } + }, + "pl" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "%@ Aplikacja automatycznie ponownie połączy się z preferowanym radiem, jeśli wróci w zasięg." + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "%@ O App vai reconetar automaticamente ao rádio preferido se ele voltar ao alcance." + } + }, + "se" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "%@ Appen kommer automatiskt att återansluta till den föredragna radion om den kommer inom räckhåll igen." + } + }, + "sr" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "%@ Апликација ће се аутоматски поново повезати са жељеним радиом ако се врати у домет." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ 如果在默认电台的旁边,App 将会自动重连。" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "%@ 如果在首選電台的旁邊,App 將會自動重連。" + } + } + } + }, + "%@ This error usually cannot be fixed without forgetting the device unders Settings > Bluetooth and re-connecting to the radio." : { + "extractionState" : "migrated", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "%@ Dieser Fehler kann üblicherweise behoben werden, indem man unter Einstellungen > Bluetooth die Verbindung manuell löscht und sich erneut mit dem Gerät verbindet." + } + }, + "fr" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "%@ Cette erreur ne peut généralement pas être corrigée sans aller dans Réglages > Bluetooth et faire > Oublier cet appareil, puis reconnecter la radio." + } + }, + "he" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "%@ שגיאה זו בדרך כלל אינה ניתנת לתיקון ללא שכחחת המכשיר בהגדרות מכשיר > בלוטוס ואז להתחבר מחדש למכשיר." + } + }, + "pl" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "%@ Ten błąd zwykle nie może być naprawiony bez zapomnienia urządzenia w Ustawienia > Bluetooth i ponownego połączenia z radiem." + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "%@ Esse erro geralmente não pode ser corrigido sem esquecer o dispositivo em Configurações > Bluetooth e reconetar ao rádio." + } + }, + "se" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "%@ Detta fel kan vanligtvis inte åtgärdas utan att glömma enheten under Inställningar > Bluetooth och återansluta till radion." + } + }, + "sr" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "%@ Ова грешка обично не може да се поправи без заборављања уређаја испод подешавања > Блутут и поново повезивање са радиом." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ 这个错误通常无法自动修复,你需要在系统设置的蓝牙选项中忽略该电台并重新配对。" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "%@ 這個錯誤通常無法自動修復,你需要在系統設定的藍芽選項中忽略該電台並重新配對。" } } } @@ -526,6 +614,12 @@ } } } + }, + "%@mA" : { + + }, + "%@V" : { + }, "%d" : { "localizations" : { @@ -815,18 +909,12 @@ } } }, - "2.4ghz" : { + "2.4 Ghz" : { "extractionState" : "manual", "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "2.4 GHz" - } - }, "sr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "2.4 GHz" } } @@ -970,133 +1058,11 @@ } } }, - "about" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Über" - } - }, - "en" : { - "stringUnit" : { - "state" : "needs_review", - "value" : "About" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "À propos" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "אודות" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "O programie" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sobre" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Om" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "О" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "关于" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "關於" - } - } - } + "About" : { + }, - "about.meshtastic" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Über Meshtastic" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "About Meshtastic" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "À propos de Meshtastic" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "אודות משטסטיק" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "O Meshtastic" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sobre Meshtastic" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Om Meshtastic" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "О Мештастику" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "关于 Meshtastic" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "關於 Meshtastic" - } - } - } + "About Meshtastic" : { + }, "Accuracy %@" : { "localizations" : { @@ -1176,70 +1142,6 @@ } } }, - "activity" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aktivität" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Activity" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Activity" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "Activity" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Activity" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Actividade" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Activity" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Активност" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "活动" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "Activity" - } - } - } - }, "Activity" : { "localizations" : { "de" : { @@ -1253,6 +1155,12 @@ "state" : "translated", "value" : "Активност" } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "活动" + } } } }, @@ -1324,71 +1232,6 @@ } } }, - "admin" : { - "extractionState" : "migrated", - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "admin" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Admin" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Administrateur" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "אדמין" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Administrator" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Admin" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Administratör" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Админ" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "管理员" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "管理員" - } - } - } - }, "Admin & Direct Message Keys" : { "localizations" : { "de" : { @@ -1411,72 +1254,6 @@ } } }, - "admin.log" : { - "comment" : "On Serbian language Admin and Administrator are the same as in English, but in sentences like this we use the longer version always.", - "extractionState" : "manual", - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Admin Log" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Admin Message Log" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Journal des messages d'administration" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "היסטוריית הודעות אדמין" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Log administratora" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Log das Mensagens do Admin" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Administratörsmeddelandelogg" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Дневник администраторских порука" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "管理员消息日志" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "管理員消息紀錄檔" - } - } - } - }, "Administration" : { "localizations" : { "sr" : { @@ -1563,49 +1340,43 @@ "localizations" : { "de" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "her" } }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "ago" - } - }, "fr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "auparavant" } }, "he" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "עברו" } }, "pl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "temu" } }, "pt-PT" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "há" } }, "se" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "sedan" } }, "sr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "пре" } }, @@ -1617,59 +1388,53 @@ }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "ago" } } } }, - "airtime" : { + "Airtime" : { "localizations" : { "de" : { "stringUnit" : { - "state" : "translated", - "value" : "Airtime" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Airtime" } }, "fr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Temps d'émission" } }, "he" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "זמן אוויר" } }, "pl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Czas nadawania" } }, "pt-PT" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Tempo ao Ár" } }, "se" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Sändningstid" } }, "sr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Време емитовања" } }, @@ -1681,28 +1446,12 @@ }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "廣播時間" } } } }, - "Airtime" : { - "localizations" : { - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Време емитовања" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "广播时间" - } - } - } - }, "Airtime %@%%" : { "localizations" : { "sr" : { @@ -1933,6 +1682,65 @@ } } }, + "Always On" : { + "extractionState" : "migrated", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "Immer an" + } + }, + "fr" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "En permanence" + } + }, + "he" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "תמיד דלוק" + } + }, + "pl" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "Zawsze włączone" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "Sempre Ligado" + } + }, + "se" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "Alltid på" + } + }, + "sr" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "Увек укључен" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "常亮" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "常亮" + } + } + } + }, "Always point north" : { "localizations" : { "de" : { @@ -1949,118 +1757,47 @@ } } }, - "always.on" : { - "extractionState" : "migrated", + "Ambient Lighting" : { "localizations" : { "de" : { "stringUnit" : { - "state" : "translated", - "value" : "Immer an" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Always On" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "En permanence" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "תמיד דלוק" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Zawsze włączone" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sempre Ligado" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Alltid på" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Увек укључен" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "常亮" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "常亮" - } - } - } - }, - "ambient.lighting" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ambient Lighting" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Ambient Lighting" } }, "fr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Lumière ambiante" } }, "he" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "תאורת סביבה" } }, "pl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Ambient Lighting" } }, "pt-PT" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Iluminação Ambiental" } }, "se" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Omgivningsbelysning" } }, "sr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Амбијентално осветљење" } }, @@ -2072,59 +1809,53 @@ }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "環境照明" } } } }, - "ambient.lighting.config" : { + "Ambient Lighting Config" : { "localizations" : { "de" : { "stringUnit" : { - "state" : "translated", - "value" : "Ambient Lighting Config" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Ambient Lighting Config" } }, "fr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Configuration de la lumière ambiante" } }, "he" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "הגדרות תאורת סביבה" } }, "pl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Ambient Lighting Config" } }, "pt-PT" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Configuração Iluminação Ambiental" } }, "se" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Konfiguration av omgivningsbelysning" } }, "sr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Подешавања амбијенталног осветљења" } }, @@ -2136,7 +1867,7 @@ }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "環境照明設定" } } @@ -2260,265 +1991,6 @@ } } }, - "appsettings" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "App Einstellungen" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "App Settings" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Réglages de l'application" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "הגדרות אפליקציה" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ustawienia aplikacji" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Definições do App" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Appinställningar" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Подешавања апликације" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "App 设置" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "設定" - } - } - } - }, - "appsettings.newNodeNotifications" : { - "extractionState" : "manual", - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Mitteilungen über neue Knoten" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "New Node Notifications" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "New Node Notifications" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "New Node Notifications" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "New Node Notifications" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Notificações de Nó Novo" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "New Node Notifications" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Обавештења о новим чворовима" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "新节点通知" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "新節點通知" - } - } - } - }, - "appsettings.provide.location" : { - "extractionState" : "manual", - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Standort im Mesh veröffentlichen" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Share location" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Partager la position" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "שתף מיקום" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Udostępnij lokalizację" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Partilha localização" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Dela plats" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Подели информације о локацији" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "提供定位到 Mesh 网络" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "提供定位到 Mesh 網路" - } - } - } - }, - "appsettings.smartposition" : { - "extractionState" : "manual", - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Smart Position" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Smart Position" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Position intelligente" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "מיקום חכם" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Smart Position" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Posição Inteligente" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Smart position" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Паметно позиционирање" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "智能定位" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "智能定位" - } - } - } - }, "Are you sure you want to delete this message?" : { "localizations" : { "sr" : { @@ -2557,53 +2029,47 @@ } } }, - "are.you.sure" : { + "Are you sure?" : { "localizations" : { "de" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Bist Du sicher?" } }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Are you sure?" - } - }, "fr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Êtes-vous sûr ?" } }, "he" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "האם אתה בטוח?" } }, "pl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Jesteś pewny?" } }, "pt-PT" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Tem a certeza?" } }, "se" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Är du säker?" } }, "sr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Да ли си сигуран?" } }, @@ -2615,159 +2081,23 @@ }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "是否確定?" } } } }, - "ascii.capable" : { + "Australia / New Zealand" : { "extractionState" : "manual", "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "ASCII-fähig" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "ASCII Capable" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "ASCII Compatible" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "בעל יכולת ASCII" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Zgodny z ASCII" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Capacidade ASCII" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "ASCII-kompatibel" - } - }, "sr" : { "stringUnit" : { - "state" : "translated", - "value" : "ASCII способан" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "ASCII 兼容" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "支援 ASCII" - } - } - } - }, - "australia.new.zealand" : { - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Australia / New Zealand" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Аустралија / Нови Зеланд" } } } }, - "automatic.detection" : { - "extractionState" : "migrated", - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Automatische erkennung" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Automatic Detection" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Détection automatique" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "זיהוי אוטומטי" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Automatyczne wykrywanie" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Deteção Automático" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Automatisk upptäckt" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Аутоматска детекција" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "自动识别" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "自動識別" - } - } - } - }, "Automatically toggles to the next page on the screen like a carousel, based the specified interval." : { "localizations" : { "sr" : { @@ -2800,53 +2130,47 @@ } } }, - "available.radios" : { + "Available Radios" : { "localizations" : { "de" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Geräte in der Nähe" } }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Available Radios" - } - }, "fr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Radios disponibles" } }, "he" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "מכשירים זמינים" } }, "pl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Dostępne radia" } }, "pt-PT" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Rádios Disponíveis" } }, "se" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Tillgängliga radioapparater" } }, "sr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Доступни радио уређаји" } }, @@ -2858,7 +2182,7 @@ }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "可以連接的設備" } } @@ -2880,23 +2204,6 @@ } } }, - "Bad" : { - "extractionState" : "stale", - "localizations" : { - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Лош" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "坏" - } - } - } - }, "Bandwidth" : { "localizations" : { "de" : { @@ -2967,6 +2274,64 @@ } } }, + "Battery Level" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "Batterie Ladung" + } + }, + "fr" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "Niveau de batterie" + } + }, + "he" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "רמת סוללה" + } + }, + "pl" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "Poziom naładowania baterii" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "Nível de Bataria" + } + }, + "se" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "Batterinivå" + } + }, + "sr" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "Ниво батерије" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "电池电量" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "電池電量" + } + } + } + }, "Battery Level %" : { "localizations" : { "sr" : { @@ -2983,70 +2348,6 @@ } } }, - "battery.level" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Batterie Ladung" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Battery Level" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Niveau de batterie" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "רמת סוללה" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Poziom naładowania baterii" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nível de Bataria" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Batterinivå" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ниво батерије" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "电池电量" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "電池電量" - } - } - } - }, "Baud" : { "localizations" : { "sr" : { @@ -3063,6 +2364,122 @@ } } }, + "BLE Name" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "BLE Name" + } + }, + "fr" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "Nom du BLE" + } + }, + "he" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "שם בלוטוס" + } + }, + "pl" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "Nazwa BLE" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "Nome BLE" + } + }, + "se" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "BLE-namn" + } + }, + "sr" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "BLE назив" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "蓝牙名称" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "藍芽名稱" + } + } + } + }, + "BLE Pin must be 6 digits long." : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "Die Bluetooth Pin muss 6 Stellen lang sein." + } + }, + "fr" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "Le code pin BLE doit avoir 6 chiffres." + } + }, + "he" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "קוד בלוטוס חייבת להיות בת 6 ספרות." + } + }, + "pl" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "Pin BLE musi mieć długość 6 cyfr." + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "O Pin do BLE deve ter 6 dígitos." + } + }, + "se" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "BLE-PIN måste vara 6 siffror lång." + } + }, + "sr" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "BLE пин мора имати 6 цифара." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "蓝牙 PIN 码必须是 6 位数字。" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "藍芽 PIN 碼必須是 6 位數字。" + } + } + } + }, "BLE RSSI: %lld" : { "localizations" : { "sr" : { @@ -3095,385 +2512,9 @@ } } }, - "ble.connection.timeout %d %@" : { - "extractionState" : "migrated", + "Bluetooth" : { "localizations" : { "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Verbindung nach %d Versuchen zu %@ fehlgeschlagen. Evtl. hilft es, die Verbindung unter Einstellungen > Bluetooth manuell zu löschen." - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Connection failed after %d attempts to connect to %@. You may need to forget your device under Settings > Bluetooth." - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Connexion impossible après %d essais avec %@. Allez dans Réglages > Bluetooth et essayez de faire de faire > Oublier cet appareil." - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "התחברות נכשלה לאחר %d נסיונות להתחבר ל%@. יתכן ויש צורך 'לשכוח' את המכשיר בהגדרות מכשיר > בלוטוס." - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Połączenie nie powiodło się po %d próbach połączenia z %@. Zapomnij o urządzeniu w Ustawienia > Bluetooth." - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Falha de conexão após %d tentativas de conectar a %@. Você pode precisar esquecer seu dispositivo em Configurações > Bluetooth." - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Anslutningen misslyckades efter %d försök att ansluta till %@. Du kan behöva glömma din enhet under Inställningar > Bluetooth." - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Веза није успела након %d покушаја да се повеже са %@. Можда ћете морати да заборавите уређај у Подешавања > Блутут." - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "尝试连接%d失败,你可能需要在系统设置的蓝牙选项中忽略该设备。" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "嘗試連接%d失敗,你可能需要在系统設定的藍芽選項中忽略該電台。" - } - } - } - }, - "ble.errorcode.6" : { - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "The connection has timed out unexpectedly." - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Веза је неочекивано истекла." - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "连接意外超时。" - } - } - } - }, - "ble.errorcode.6 %@" : { - "extractionState" : "migrated", - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ Die App wird automatisch wieder zum präferierten Gerät verbinden, sobald es in Reichweite kommt." - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ The app will automatically reconnect to the preferred radio if it comes back in range." - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ L'application se reconnectera automatiquement à la radio en favori dès qu'elle sera à nouveau disponible." - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ האפליקציה תנסה אוטומטית להתחבר מחדש למכשיר המועדף אם ייראה." - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ Aplikacja automatycznie ponownie połączy się z preferowanym radiem, jeśli wróci w zasięg." - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ O App vai reconetar automaticamente ao rádio preferido se ele voltar ao alcance." - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ Appen kommer automatiskt att återansluta till den föredragna radion om den kommer inom räckhåll igen." - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ Апликација ће се аутоматски поново повезати са жељеним радиом ако се врати у домет." - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ 如果在默认电台的旁边,App 将会自动重连。" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ 如果在首選電台的旁邊,App 將會自動重連。" - } - } - } - }, - "ble.errorcode.14" : { - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Peer removed pairing information." - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Радио уређај је уклонио информације о упаривању." - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "同伴删除了配对信息。" - } - } - } - }, - "ble.errorcode.14 %@" : { - "extractionState" : "migrated", - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ Dieser Fehler kann üblicherweise behoben werden, indem man unter Einstellungen > Bluetooth die Verbindung manuell löscht und sich erneut mit dem Gerät verbindet." - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ This error usually cannot be fixed without forgetting the device unders Settings > Bluetooth and re-connecting to the radio." - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ Cette erreur ne peut généralement pas être corrigée sans aller dans Réglages > Bluetooth et faire > Oublier cet appareil, puis reconnecter la radio." - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ שגיאה זו בדרך כלל אינה ניתנת לתיקון ללא שכחחת המכשיר בהגדרות מכשיר > בלוטוס ואז להתחבר מחדש למכשיר." - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ Ten błąd zwykle nie może być naprawiony bez zapomnienia urządzenia w Ustawienia > Bluetooth i ponownego połączenia z radiem." - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ Esse erro geralmente não pode ser corrigido sem esquecer o dispositivo em Configurações > Bluetooth e reconetar ao rádio." - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ Detta fel kan vanligtvis inte åtgärdas utan att glömma enheten under Inställningar > Bluetooth och återansluta till radion." - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ Ова грешка обично не може да се поправи без заборављања уређаја испод подешавања > Блутут и поново повезивање са радиом." - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ 这个错误通常无法自动修复,你需要在系统设置的蓝牙选项中忽略该电台并重新配对。" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ 這個錯誤通常無法自動修復,你需要在系統設定的藍芽選項中忽略該電台並重新配對。" - } - } - } - }, - "ble.errorcode.pin %@" : { - "extractionState" : "migrated", - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ Bitte versuche es erneut. Achte sorgfältig auf die richtige PIN." - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ Please try connecting again and check the PIN carefully." - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ Merci d'essayer à nouveau en vérifiant bien le code PIN." - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ בבקשה נסה שנית להתחבר למכשיר ובדוק את הקוד." - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ Spróbuj połączyć się ponownie i dokładnie sprawdź PIN." - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ Por favor, tente conectar novamente e verifique cuidadosamente o PIN." - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ Försök att ansluta igen och kontrollera PIN-koden noggrant." - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ Покушајте поново да се повежете и пажљиво проверите ПИН." - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ 请再次尝试连接并仔细检查 PIN 码。" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ 請再次嘗試連接並仔細檢查 PIN 碼。" - } - } - } - }, - "ble.name" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "BLE Name" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "BLE Name" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nom du BLE" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "שם בלוטוס" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nazwa BLE" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nome BLE" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "BLE-namn" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "BLE назив" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "蓝牙名称" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "藍芽名稱" - } - } - } - }, - "bluetooth" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Bluetooth" - } - }, - "en" : { "stringUnit" : { "state" : "translated", "value" : "Bluetooth" @@ -3529,53 +2570,47 @@ } } }, - "bluetooth.config" : { + "Bluetooth Config" : { "localizations" : { "de" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Bluetooth Konfiguration" } }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Bluetooth Config" - } - }, "fr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Configuration Bluetooth" } }, "he" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "הגדרות בלוטוס" } }, "pl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Konfiguracja Bluetooth" } }, "pt-PT" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Configuração Bluetooth" } }, "se" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Bluetooth-konfiguration" } }, "sr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Блутут подешавања" } }, @@ -3587,253 +2622,53 @@ }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "藍芽設置" } } } }, - "bluetooth.mode.fixedpin" : { + "Bluetooth is off" : { "localizations" : { "de" : { "stringUnit" : { - "state" : "translated", - "value" : "Feste PIN" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Fixed PIN" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Code PIN fixe" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "קוד קבוע" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Stały PIN" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "PIN fixo" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Fast PIN" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Фиксни ПИН" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "固定 PIN 码" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "固定 PIN 碼" - } - } - } - }, - "bluetooth.mode.nopin" : { - "extractionState" : "migrated", - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Keine PIN (geht einfach)" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "No PIN (Just Works)" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sans code PIN (connexion directe)" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "ללא קוד (פשוט עובד)" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Brak PINu (po prostu działa)" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sem PIN (Simplesmente Funciona)" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ingen PIN (Bara fungerar)" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Нема ПИН-а (само ради)" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "不使用 PIN 码(直接配对)" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "不使用 PIN 碼(直接配對)" - } - } - } - }, - "bluetooth.mode.randompin" : { - "extractionState" : "migrated", - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Zufällige PIN" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Random PIN" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Code PIN aléatoire" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "קוד אקראי" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Losowy PIN" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "PIN Aleatório" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Slumpmässig PIN" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Насумичан ПИН" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "随机 PIN 码" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "隨機 PIN 碼" - } - } - } - }, - "bluetooth.off" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Bluetooth ist aus" } }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Bluetooth is off" - } - }, "fr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Le Bluetooth est arrêté" } }, "he" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "בלוטוס כבוי" } }, "pl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Bluetooth jest wyłączony" } }, "pt-PT" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Bluetooth está desligado" } }, "se" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Bluetooth är avstängt" } }, "sr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Блутут је искључен" } }, @@ -3845,140 +2680,12 @@ }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "藍芽已關閉" } } } }, - "bluetooth.pairingmode" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Pairing Modus" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Pairing Mode" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Mode d'appairage" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "מצב הצמדה" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tryb parowania" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Modo Pairing" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Parläge" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Мод упаривања" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "配对模式" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "配對模式" - } - } - } - }, - "bluetooth.pin.validation" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Die Bluetooth Pin muss 6 Stellen lang sein." - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "BLE Pin must be 6 digits long." - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Le code pin BLE doit avoir 6 chiffres." - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "קוד בלוטוס חייבת להיות בת 6 ספרות." - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Pin BLE musi mieć długość 6 cyfr." - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "O Pin do BLE deve ter 6 dígitos." - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "BLE-PIN måste vara 6 siffror lång." - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "BLE пин мора имати 6 цифара." - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "蓝牙 PIN 码必须是 6 位数字。" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "藍芽 PIN 碼必須是 6 位數字。" - } - } - } - }, "Broadcast Interval" : { "localizations" : { "sr" : { @@ -4043,54 +2750,48 @@ } } }, - "bytes" : { + "Bytes" : { "extractionState" : "migrated", "localizations" : { "de" : { "stringUnit" : { - "state" : "translated", - "value" : "Bytes" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Bytes" } }, "fr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Octets" } }, "he" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "בייטים" } }, "pl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Bajty" } }, "pt-PT" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Bytes" } }, "se" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Bytes" } }, "sr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Бајтова" } }, @@ -4102,7 +2803,7 @@ }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "位元組" } } @@ -4140,53 +2841,47 @@ } } }, - "cancel" : { + "Cancel" : { "localizations" : { "de" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Abbrechen" } }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Cancel" - } - }, "fr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Annuler" } }, "he" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "בטל" } }, "pl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Anuluj" } }, "pt-PT" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Cancelar" } }, "se" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Avbryt" } }, "sr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Откажи" } }, @@ -4198,81 +2893,53 @@ }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "取消" } } } }, - "Cancel" : { + "Canned Messages" : { "localizations" : { "de" : { "stringUnit" : { - "state" : "translated", - "value" : "Abbrechen" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Откажи" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "取消" - } - } - } - }, - "canned.messages" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Canned Messages" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Canned Messages" } }, "fr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Messages préformatés" } }, "he" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "הודעות קבועות" } }, "pl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Gotowe wiadomości" } }, "pt-PT" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Mensagens Enlatados" } }, "se" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Fördefinierade meddelanden" } }, "sr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Унапред припремљене поруке" } }, @@ -4284,59 +2951,53 @@ }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "罐頭訊息" } } } }, - "canned.messages.config" : { + "Canned Messages Config" : { "localizations" : { "de" : { "stringUnit" : { - "state" : "translated", - "value" : "Canned Messages Config" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Canned Messages Config" } }, "fr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Configuration des messages préformatés" } }, "he" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "הגדרות הודעות קבועות" } }, "pl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Konfiguracja gotowych wiadomości" } }, "pt-PT" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Configuração dos Mensagens Enlatados" } }, "se" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Konfiguration av fördefinierade meddelanden" } }, "sr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Подешавања унапред припремљених порука" } }, @@ -4348,7 +3009,7 @@ }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "通知設定" } } @@ -4581,53 +3242,65 @@ } } }, - "channel" : { + "Ch1 Current" : { + + }, + "Ch1 Voltage" : { + + }, + "Ch2 Current" : { + + }, + "Ch2 Voltage" : { + + }, + "Ch3 Current" : { + + }, + "Ch3 Voltage" : { + + }, + "Channel" : { "localizations" : { "de" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Kanal" } }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Channel" - } - }, "fr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Canal" } }, "he" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "ערוץ" } }, "pl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Kanał" } }, "pt-PT" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Canal" } }, "se" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Kanal" } }, "sr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Канал" } }, @@ -4639,34 +3312,12 @@ }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "頻道" } } } }, - "Channel" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kanal" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Канал" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "频道" - } - } - } - }, "Channel 0 Included" : { "localizations" : { "sr" : { @@ -4682,6 +3333,9 @@ } } } + }, + "Channel 1" : { + }, "Channel 1 Included" : { "localizations" : { @@ -4698,6 +3352,9 @@ } } } + }, + "Channel 2" : { + }, "Channel 2 Included" : { "localizations" : { @@ -4714,6 +3371,9 @@ } } } + }, + "Channel 3" : { + }, "Channel 3 Included" : { "localizations" : { @@ -4858,6 +3518,9 @@ } } } + }, + "Channel URL" : { + }, "Channel Utilization %@%% " : { "localizations" : { @@ -5240,26 +3903,14 @@ } } }, - "china" : { + "China" : { "extractionState" : "manual", "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "China" - } - }, "sr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Кина" } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "CHG" - } } } }, @@ -5278,6 +3929,9 @@ } } } + }, + "Clear Log" : { + }, "clear.app.data" : { "localizations" : { @@ -5343,70 +3997,6 @@ } } }, - "clear.log" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Log löschen" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Clear" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Effacer" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "נקה" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Wyczyść" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Apagar" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Rensa" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Очисти" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "清除日志" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "清除紀錄檔" - } - } - } - }, "Client" : { "localizations" : { "sr" : { @@ -5589,69 +4179,8 @@ } } }, - "communicating" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Verbinde mit Gerät..." - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Communicating with device. ." - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Communication avec l'appareil en cours. ." - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "מתקשר עם מכשיר. ." - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Komunikowanie z urządzeniem. ." - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Comunicando com dispositivo. ." - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kommunicerar med enheten..." - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Комуницирање са уређајем. ." - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "与设备进行通讯中..." - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "與電台進行通訊中..." - } - } - } + "Communicating" : { + }, "Config" : { "localizations" : { @@ -7260,6 +5789,71 @@ } } }, + "Connection failed after %d attempts to connect to %@. You may need to forget your device under Settings > Bluetooth." : { + "extractionState" : "migrated", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verbindung nach %d Versuchen zu %@ fehlgeschlagen. Evtl. hilft es, die Verbindung unter Einstellungen > Bluetooth manuell zu löschen." + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Connection failed after %d attempts to connect to %@. You may need to forget your device under Settings > Bluetooth." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Connexion impossible après %d essais avec %@. Allez dans Réglages > Bluetooth et essayez de faire de faire > Oublier cet appareil." + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "התחברות נכשלה לאחר %d נסיונות להתחבר ל%@. יתכן ויש צורך 'לשכוח' את המכשיר בהגדרות מכשיר > בלוטוס." + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Połączenie nie powiodło się po %d próbach połączenia z %@. Zapomnij o urządzeniu w Ustawienia > Bluetooth." + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Falha de conexão após %d tentativas de conectar a %@. Você pode precisar esquecer seu dispositivo em Configurações > Bluetooth." + } + }, + "se" : { + "stringUnit" : { + "state" : "translated", + "value" : "Anslutningen misslyckades efter %d försök att ansluta till %@. Du kan behöva glömma din enhet under Inställningar > Bluetooth." + } + }, + "sr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Веза није успела након %d покушаја да се повеже са %@. Можда ћете морати да заборавите уређај у Подешавања > Блутут." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "尝试连接%d失败,你可能需要在系统设置的蓝牙选项中忽略该设备。" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "嘗試連接%d失敗,你可能需要在系统設定的藍芽選項中忽略該電台。" + } + } + } + }, "contacts" : { "extractionState" : "manual", "localizations" : { @@ -7462,12 +6056,6 @@ "value" : "Koordinate %1$@, %2$@" } }, - "en" : { - "stringUnit" : { - "state" : "new", - "value" : "Coordinate %1$@, %2$@" - } - }, "sr" : { "stringUnit" : { "state" : "translated", @@ -7498,7 +6086,7 @@ } } }, - "copy" : { + "Copy" : { "localizations" : { "de" : { "stringUnit" : { @@ -7506,12 +6094,6 @@ "value" : "Kopieren" } }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Copy" - } - }, "fr" : { "stringUnit" : { "state" : "translated", @@ -7625,6 +6207,9 @@ } } } + }, + "Current" : { + }, "Current Firmware Version: %@" : { "localizations" : { @@ -7656,12 +6241,6 @@ "value" : "Aktuelle Firmware Version: %1$@, neuste Firmware Version %2$@" } }, - "en" : { - "stringUnit" : { - "state" : "new", - "value" : "Current Firmware Version: %1$@, Latest Firmware Version: %2$@" - } - }, "sr" : { "stringUnit" : { "state" : "translated", @@ -8027,6 +6606,9 @@ } } } + }, + "Delete Power metrics?" : { + }, "Description" : { "localizations" : { @@ -9932,7 +8514,7 @@ } } }, - "disconnect" : { + "Disconnect" : { "localizations" : { "de" : { "stringUnit" : { @@ -9996,7 +8578,7 @@ } } }, - "dismiss.keyboard" : { + "Dismiss" : { "localizations" : { "de" : { "stringUnit" : { @@ -10060,7 +8642,7 @@ } } }, - "display" : { + "Display" : { "localizations" : { "de" : { "stringUnit" : { @@ -11054,7 +9636,7 @@ } } }, - "european.union.433mhz" : { + "European Union 433MHz" : { "extractionState" : "manual", "localizations" : { "en" : { @@ -11071,7 +9653,7 @@ } } }, - "european.union.868mhz" : { + "European Union 868MHz" : { "extractionState" : "manual", "localizations" : { "en" : { @@ -11777,6 +10359,70 @@ } } }, + "Fixed Pin" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Feste PIN" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fixed PIN" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Code PIN fixe" + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "קוד קבוע" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Stały PIN" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "PIN fixo" + } + }, + "se" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fast PIN" + } + }, + "sr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Фиксни ПИН" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "固定 PIN 码" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "固定 PIN 碼" + } + } + } + }, "Fixed Position" : { "localizations" : { "sr" : { @@ -13857,7 +12503,7 @@ } } }, - "india" : { + "India" : { "extractionState" : "manual", "localizations" : { "en" : { @@ -16361,7 +15007,7 @@ } } }, - "japan" : { + "Japan" : { "extractionState" : "manual", "localizations" : { "en" : { @@ -16523,7 +15169,7 @@ } } }, - "korea" : { + "Korea" : { "extractionState" : "manual", "localizations" : { "en" : { @@ -17581,7 +16227,7 @@ } } }, - "malaysia.433mhz" : { + "Malaysia 433mhz" : { "extractionState" : "manual", "localizations" : { "en" : { @@ -17598,7 +16244,7 @@ } } }, - "malaysia.919mhz" : { + "Malaysia 919mhz" : { "extractionState" : "manual", "localizations" : { "en" : { @@ -18658,7 +17304,7 @@ "pt-PT" : { "stringUnit" : { "state" : "translated", - "value" : "Mensagens Padrão solicitadas para o módulo de mensagens para o nó: %@" + "value" : "Mensagens Padrão solicitadas para o módulo de mensagens para o nó: %@" } }, "se" : { @@ -18717,7 +17363,7 @@ "pt-PT" : { "stringUnit" : { "state" : "translated", - "value" : "Mensagens Padrão recebidas para: %@" + "value" : "Mensagens Padrão recebidas para: %@" } }, "se" : { @@ -18776,7 +17422,7 @@ "pt-PT" : { "stringUnit" : { "state" : "translated", - "value" : "Um Canal Enviado para: %@ Índice do Canal %d" + "value" : "Um Canal Enviado para: %@ Índice do Canal %d" } }, "se" : { @@ -19030,7 +17676,7 @@ "pt-PT" : { "stringUnit" : { "state" : "translated", - "value" : "Solicitando os Metadados do Dispositivo para %@" + "value" : "Solicitando os Metadados do Dispositivo para %@" } }, "se" : { @@ -20435,7 +19081,7 @@ "pt-PT" : { "stringUnit" : { "state" : "translated", - "value" : "Falha no envio da mensagem, não conectado corretamente a %@" + "value" : "Falha no envio da mensagem, não conectado corretamente a %@" } }, "se" : { @@ -20500,7 +19146,7 @@ "pt-PT" : { "stringUnit" : { "state" : "translated", - "value" : "Mensagem enviada %@ de %@ para %@" + "value" : "Mensagem enviada %@ de %@ para %@" } }, "se" : { @@ -20754,7 +19400,7 @@ "pt-PT" : { "stringUnit" : { "state" : "translated", - "value" : "Emitindo Configuração Desejada para %@" + "value" : "Emitindo Configuração Desejada para %@" } }, "se" : { @@ -21940,6 +20586,9 @@ } } } + }, + "Navigate to node" : { + }, "Nearby Topics" : { "localizations" : { @@ -22149,7 +20798,72 @@ } } }, - "new.zealand.865mhz" : { + "New Node Notifications" : { + "extractionState" : "manual", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mitteilungen über neue Knoten" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "New Node Notifications" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "New Node Notifications" + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "New Node Notifications" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "New Node Notifications" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Notificações de Nó Novo" + } + }, + "se" : { + "stringUnit" : { + "state" : "translated", + "value" : "New Node Notifications" + } + }, + "sr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Обавештења о новим чворовима" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "新节点通知" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "新節點通知" + } + } + } + }, + "New Zealand 865mhz" : { "extractionState" : "manual", "localizations" : { "en" : { @@ -22230,6 +20944,71 @@ } } }, + "No PIN (Just Works)" : { + "extractionState" : "migrated", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Keine PIN (geht einfach)" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No PIN (Just Works)" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sans code PIN (connexion directe)" + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "ללא קוד (פשוט עובד)" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Brak PINu (po prostu działa)" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sem PIN (Simplesmente Funciona)" + } + }, + "se" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ingen PIN (Bara fungerar)" + } + }, + "sr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Нема ПИН-а (само ради)" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "不使用 PIN 码(直接配对)" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "不使用 PIN 碼(直接配對)" + } + } + } + }, "No Positions" : { "localizations" : { "de" : { @@ -22245,6 +21024,9 @@ } } } + }, + "No Power Metrics" : { + }, "no.nodes" : { "extractionState" : "manual", @@ -23402,6 +22184,70 @@ } } }, + "Pairing Mode" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pairing Modus" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pairing Mode" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mode d'appairage" + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "מצב הצמדה" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tryb parowania" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modo Pairing" + } + }, + "se" : { + "stringUnit" : { + "state" : "translated", + "value" : "Parläge" + } + }, + "sr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Мод упаривања" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "配对模式" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "配對模式" + } + } + } + }, "password" : { "localizations" : { "de" : { @@ -23714,7 +22560,7 @@ } } }, - "philippines.433mhz" : { + "Philippines 433mhz" : { "extractionState" : "manual", "localizations" : { "en" : { @@ -23731,7 +22577,7 @@ } } }, - "philippines.868mhz" : { + "Philippines 868mhz" : { "extractionState" : "manual", "localizations" : { "en" : { @@ -23748,7 +22594,7 @@ } } }, - "philippines.915mhz" : { + "Philippines 915mhz" : { "extractionState" : "manual", "localizations" : { "en" : { @@ -23962,7 +22808,7 @@ } } }, - "please.set.a.region" : { + "Please set a region" : { "extractionState" : "manual", "localizations" : { "en" : { @@ -24259,6 +23105,9 @@ } } } + }, + "Power" : { + }, "Power Metrics" : { "localizations" : { @@ -24269,6 +23118,12 @@ } } } + }, + "Power Metrics Log" : { + + }, + "Power Metrics Log}" : { + }, "Power Off" : { "localizations" : { @@ -24680,6 +23535,71 @@ } } }, + "Random PIN" : { + "extractionState" : "manual", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Zufällige PIN" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Random PIN" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Code PIN aléatoire" + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "קוד אקראי" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Losowy PIN" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "PIN Aleatório" + } + }, + "se" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slumpmässig PIN" + } + }, + "sr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Насумичан ПИН" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "随机 PIN 码" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "隨機 PIN 碼" + } + } + } + }, "range.test" : { "localizations" : { "de" : { @@ -25462,7 +24382,7 @@ } } }, - "reply" : { + "Reply" : { "localizations" : { "de" : { "stringUnit" : { @@ -25950,6 +24870,9 @@ } } } + }, + "Route Recorder" : { + }, "Route recording paused" : { "localizations" : { @@ -25977,70 +24900,6 @@ } } }, - "route.recorder" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Route Recorder" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Route Recorder" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Enregistreur de route" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "מקליט מסלול" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Route Recorder" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Gravador de Rotas" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ruttinspelare" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Снимач руте" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "路径记录器" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "路線錄製" - } - } - } - }, "Router" : { "localizations" : { "sr" : { @@ -26061,69 +24920,8 @@ } } }, - "routes" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Routen" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Routes" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Routes" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "מסלולים" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Routes" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Rotas" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Rutter" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Руте" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "路径" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "路線" - } - } - } + "Routes" : { + }, "routes.activitytype.biking" : { "extractionState" : "migrated", @@ -27395,7 +26193,7 @@ } } }, - "russia" : { + "Russia" : { "extractionState" : "manual", "localizations" : { "en" : { @@ -27679,6 +26477,9 @@ } } } + }, + "Save Channel Settings" : { + }, "Save User Config to %@?" : { "localizations" : { @@ -27962,6 +26763,9 @@ } } } + }, + "Select Channel" : { + }, "select.contact" : { "extractionState" : "manual", @@ -28123,6 +26927,12 @@ } } } + }, + "Send ${messageContent} to ${nodeNumber}" : { + + }, + "Send a Direct Message" : { + }, "Send a Group Message" : { "localizations" : { @@ -28149,6 +26959,9 @@ } } } + }, + "Send a message to a certain meshtastic node" : { + }, "Send a position on the primary channel when the user button is triple clicked." : { "localizations" : { @@ -29447,7 +28260,7 @@ } } }, - "singapore.923mhz" : { + "Singapore 923mhz" : { "extractionState" : "manual", "localizations" : { "en" : { @@ -29840,6 +28653,26 @@ } } }, + "Store & Forward" : { + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "储存 & 转发" + } + } + } + }, + "Store & Forward Config" : { + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "储存 & 转发设置" + } + } + } + }, "Store and forward clients can request history from routers on the network." : { "localizations" : { "sr" : { @@ -29860,134 +28693,6 @@ } } }, - "storeforward" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Store & Forward" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Store & Forward" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Stocker et Transmettre" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "שמירה ושליחה" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Store & Forward" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Armazenar e Encaminhar" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Lagra & Videresänd" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Складиштење и прослеђивање" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "储存 & 转发" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "儲存 & 轉發" - } - } - } - }, - "storeforward.config" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Store & Forward Config" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Store & Forward Config" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Configuration de Stocker et Transmettre" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "הגדרות שמירה ושליחה" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Store & Forward Config" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Configuração de Armazenar e Encaminhar" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Konfiguration för Lagra & Videresänd" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Конфигурација за складиштење и прослеђивање" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "储存 & 转发设置" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "儲存 & 轉發設定" - } - } - } - }, "storeforward.heartbeat" : { "localizations" : { "de" : { @@ -30052,67 +28757,13 @@ } } }, - "subscribed" : { + "Subscribed" : { "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Verbunden mit dem Mesh" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Subscribed to mesh" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Abonné au maillage" - } - }, "he" : { "stringUnit" : { "state" : "translated", "value" : "מחובר למש" } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Zapisano do siatki" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Inscrito no mesh" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Prenumererar på mesh" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Повезано са меш мрежом" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "连接到 Mesh 网络" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "連接到 Mesh 網路" - } } } }, @@ -30158,7 +28809,7 @@ } } }, - "taiwan" : { + "Taiwan" : { "extractionState" : "manual", "localizations" : { "en" : { @@ -30175,7 +28826,10 @@ } } }, - "tapback" : { + "Takes a Meshtastic channel URL and saves the channel settings." : { + + }, + "Tapback" : { "localizations" : { "de" : { "stringUnit" : { @@ -31082,7 +29736,7 @@ } } }, - "thailand" : { + "Thailand" : { "extractionState" : "manual", "localizations" : { "en" : { @@ -31369,6 +30023,9 @@ } } } + }, + "The URL for the channel settings" : { + }, "There has been no response to a request for device metadata over the admin channel for this node." : { "localizations" : { @@ -31436,23 +30093,6 @@ } } }, - "This determines the actual frequency you are transmitting on in the band. If set to 0 this value will be calculated automatically based on the primary channel name." : { - "extractionState" : "stale", - "localizations" : { - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ово одређује стварну фреквенцију на којој преносите у опсегу. Ако је постављено на 0, ова вредност ће се аутоматски израчунати на основу назива примарног канала." - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "这决定了您在频段内的实际发射频率。如果设置为 0,该值将根据主频道名称自动计算。" - } - } - } - }, "This device will send out range test messages on the selected interval." : { "localizations" : { "sr" : { @@ -31640,6 +30280,9 @@ } }, "timestamp" : { + + }, + "Timestamp" : { "localizations" : { "de" : { "stringUnit" : { @@ -32416,29 +31059,6 @@ } } }, - "Trace route received directly by %@ with a SNR of %@ dB" : { - "extractionState" : "stale", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "new", - "value" : "Trace route received directly by %1$@ with a SNR of %2$@ dB" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Захтев за праћење руте комуникације директно примљен од %1$@ са SNR од %2$@ dB." - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "由 %1$@ 直接接收的跟踪路由,信噪比为 %2$@ dB" - } - } - } - }, "Trace Route Sent" : { "localizations" : { "sr" : { @@ -32648,7 +31268,7 @@ } } }, - "ukraine.433mhz" : { + "Ukraine 433mhz" : { "extractionState" : "manual", "localizations" : { "en" : { @@ -32665,7 +31285,7 @@ } } }, - "ukraine.868mhz" : { + "Ukraine 868mhz" : { "extractionState" : "manual", "localizations" : { "en" : { @@ -32692,7 +31312,7 @@ } } }, - "united.states" : { + "United States" : { "extractionState" : "manual", "localizations" : { "en" : { @@ -32720,6 +31340,9 @@ } }, "unknown" : { + + }, + "Unknown" : { "localizations" : { "de" : { "stringUnit" : { @@ -33150,6 +31773,9 @@ } } } + }, + "Uptime" : { + }, "Use a PWM output (like the RAK Buzzer) for tunes instead of an on/off output. This will ignore the output, output duration and active settings and use the device config buzzer GPIO option instead." : { "localizations" : { @@ -33209,27 +31835,8 @@ } } }, - "Wird verwendet, um einen gemeinsamen Schlüssel mit einem entfernten Gerät zu erstellen." : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Verbunden mit einem Knoten" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Користи се за креирање заједничког кључа са удаљеним уређајем." - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "用于与远程设备创建共享密钥。" - } - } - } + "Used to create a shared key with a remote device." : { + }, "user" : { "localizations" : { @@ -33651,6 +32258,9 @@ } } } + }, + "Voltage" : { + }, "Volts %@ " : { "localizations" : { @@ -33668,7 +32278,7 @@ } } }, - "waiting" : { + "Waiting" : { "localizations" : { "de" : { "stringUnit" : { @@ -33891,6 +32501,9 @@ } } } + }, + "Whether or not use INPUT_PULLUP mode for GPIO pin. Only applicable if the board uses pull-up resistors on the pin" : { + }, "WiFi Options" : { "localizations" : { @@ -34120,23 +32733,6 @@ }, "Your MQTT Server must support TLS." : { - }, - "Your MQTT Server must support TLS. Not available via the public mqtt server." : { - "extractionState" : "stale", - "localizations" : { - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ваш MQTT сервер мора подржавати TLS. Није доступно преко јавног MQTT сервера." - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "您的 MQTT 服务器必须支持 TLS。没有可用的公开 MQTT 服务器。" - } - } - } }, "Your node’s operating frequency is calculated based on the region, modem preset, and this field. When 0, the slot is automatically calculated based on the primary channel name." : { diff --git a/Meshtastic.xcodeproj/project.pbxproj b/Meshtastic.xcodeproj/project.pbxproj index f2b3a524..489b0e85 100644 --- a/Meshtastic.xcodeproj/project.pbxproj +++ b/Meshtastic.xcodeproj/project.pbxproj @@ -41,6 +41,9 @@ 8D3F8A412D44C2A6009EAAA4 /* PowerMetricsLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D3F8A402D44C2A6009EAAA4 /* PowerMetricsLog.swift */; }; B399E8A42B6F486400E4488E /* RetryButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B399E8A32B6F486400E4488E /* RetryButton.swift */; }; B3E905B12B71F7F300654D07 /* TextMessageField.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3E905B02B71F7F300654D07 /* TextMessageField.swift */; }; + BC47C2EF2CE0017D008245CA /* MessageNodeIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC47C2EE2CE0017D008245CA /* MessageNodeIntent.swift */; }; + BC5EBA3C2D002A2000C442FF /* MessageNodeIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC5EBA3B2D002A2000C442FF /* MessageNodeIntent.swift */; }; + BC6B45FF2CB2F98900723CEB /* SaveChannelSettingsIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC6B45FE2CB2F98900723CEB /* SaveChannelSettingsIntent.swift */; }; BCB613812C67290800485544 /* SendWaypointIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCB613802C67290800485544 /* SendWaypointIntent.swift */; }; BCB613832C672A2600485544 /* MessageChannelIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCB613822C672A2600485544 /* MessageChannelIntent.swift */; }; BCB613852C68703800485544 /* NodePositionIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCB613842C68703800485544 /* NodePositionIntent.swift */; }; @@ -180,7 +183,6 @@ DDC2E15F26CE248F0042C5E4 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DDC2E15E26CE248F0042C5E4 /* Preview Assets.xcassets */; }; DDC2E18F26CE25FE0042C5E4 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC2E18E26CE25FE0042C5E4 /* ContentView.swift */; }; DDC2E1A726CEB3400042C5E4 /* LocationHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC2E1A626CEB3400042C5E4 /* LocationHelper.swift */; }; - DDC3B274283F411B00AC321C /* LastHeardText.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC3B273283F411B00AC321C /* LastHeardText.swift */; }; DDC4C9FF2A8D982900CE201C /* DetectionSensorConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC4C9FE2A8D982900CE201C /* DetectionSensorConfig.swift */; }; DDC4D568275499A500A4208E /* Persistence.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC4D567275499A500A4208E /* Persistence.swift */; }; DDC94FC129CE063B0082EA6E /* BatteryLevel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC94FC029CE063B0082EA6E /* BatteryLevel.swift */; }; @@ -231,6 +233,7 @@ DDF45C342BC1A48E005ED5F2 /* MQTTIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDF45C332BC1A48E005ED5F2 /* MQTTIcon.swift */; }; DDF45C372BC46A5A005ED5F2 /* TimeZone.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDF45C362BC46A5A005ED5F2 /* TimeZone.swift */; }; DDF6B2482A9AEBF500BA6931 /* StoreForwardConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDF6B2472A9AEBF500BA6931 /* StoreForwardConfig.swift */; }; + DDF82CBD2D5BC69200DC25EC /* NavigateToButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDF82CBC2D5BC69200DC25EC /* NavigateToButton.swift */; }; DDF924CA26FBB953009FE055 /* ConnectedDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDF924C926FBB953009FE055 /* ConnectedDevice.swift */; }; DDFEB3BB29900C1200EE7472 /* CurrentConditionsCompact.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFEB3BA29900C1200EE7472 /* CurrentConditionsCompact.swift */; }; DDFFA7472B3A7F3C004730DB /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFFA7462B3A7F3C004730DB /* Bundle.swift */; }; @@ -297,6 +300,9 @@ 8D3F8A402D44C2A6009EAAA4 /* PowerMetricsLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PowerMetricsLog.swift; sourceTree = ""; }; B399E8A32B6F486400E4488E /* RetryButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RetryButton.swift; sourceTree = ""; }; B3E905B02B71F7F300654D07 /* TextMessageField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextMessageField.swift; sourceTree = ""; }; + BC47C2EE2CE0017D008245CA /* MessageNodeIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageNodeIntent.swift; sourceTree = ""; }; + BC5EBA3B2D002A2000C442FF /* MessageNodeIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageNodeIntent.swift; sourceTree = ""; }; + BC6B45FE2CB2F98900723CEB /* SaveChannelSettingsIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SaveChannelSettingsIntent.swift; sourceTree = ""; }; BCB613802C67290800485544 /* SendWaypointIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendWaypointIntent.swift; sourceTree = ""; }; BCB613822C672A2600485544 /* MessageChannelIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageChannelIntent.swift; sourceTree = ""; }; BCB613842C68703800485544 /* NodePositionIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodePositionIntent.swift; sourceTree = ""; }; @@ -474,7 +480,6 @@ DDC2E16526CE248F0042C5E4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; DDC2E18E26CE25FE0042C5E4 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; DDC2E1A626CEB3400042C5E4 /* LocationHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationHelper.swift; sourceTree = ""; }; - DDC3B273283F411B00AC321C /* LastHeardText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LastHeardText.swift; sourceTree = ""; }; DDC4C9FE2A8D982900CE201C /* DetectionSensorConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetectionSensorConfig.swift; sourceTree = ""; }; DDC4CA012A8DAA3800CE201C /* MeshtasticDataModelV16.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MeshtasticDataModelV16.xcdatamodel; sourceTree = ""; }; DDC4D567275499A500A4208E /* Persistence.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Persistence.swift; sourceTree = ""; }; @@ -484,6 +489,7 @@ DDCDC69A29467643004C1DDA /* MeshtasticDataModelV3.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MeshtasticDataModelV3.xcdatamodel; sourceTree = ""; }; DDCE4E2B2869F92900BE9F8F /* UserConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserConfig.swift; sourceTree = ""; }; DDD28D372C0CD2670063CFA3 /* MeshtasticDataModelV 37.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MeshtasticDataModelV 37.xcdatamodel"; sourceTree = ""; }; + DDD3A2B22D5127CF0045EB48 /* ci_pre_xcodebuild.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = ci_pre_xcodebuild.sh; sourceTree = ""; }; DDD43FE22A78C8900083A3E9 /* MqttClientProxyManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MqttClientProxyManager.swift; sourceTree = ""; }; DDD5BB082C285DDC007E03CA /* AppLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLog.swift; sourceTree = ""; }; DDD5BB0A2C285E45007E03CA /* LogDetail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogDetail.swift; sourceTree = ""; }; @@ -539,6 +545,7 @@ DDF45C382BC46B16005ED5F2 /* MeshtasticDataModelV33.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MeshtasticDataModelV33.xcdatamodel; sourceTree = ""; }; DDF6B2462A9AEB9E00BA6931 /* MeshtasticDataModelV17.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MeshtasticDataModelV17.xcdatamodel; sourceTree = ""; }; DDF6B2472A9AEBF500BA6931 /* StoreForwardConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreForwardConfig.swift; sourceTree = ""; }; + DDF82CBC2D5BC69200DC25EC /* NavigateToButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigateToButton.swift; sourceTree = ""; }; DDF924C926FBB953009FE055 /* ConnectedDevice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectedDevice.swift; sourceTree = ""; }; DDFEB3BA29900C1200EE7472 /* CurrentConditionsCompact.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentConditionsCompact.swift; sourceTree = ""; }; DDFFA7462B3A7F3C004730DB /* Bundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bundle.swift; sourceTree = ""; }; @@ -602,6 +609,7 @@ DDDFE73E2D0D48FF0044463C /* IgnoreNodeButton.swift */, 251926842C3BA97800249DF5 /* FavoriteNodeButton.swift */, 251926892C3BB1B200249DF5 /* ExchangePositionsButton.swift */, + DDF82CBC2D5BC69200DC25EC /* NavigateToButton.swift */, 251926862C3BAE2200249DF5 /* NodeAlertsButton.swift */, 2519268B2C3BB52000249DF5 /* TraceRouteButton.swift */, 2519268F2C3CB44900249DF5 /* ClientHistoryButton.swift */, @@ -630,6 +638,7 @@ BCB6137F2C6728E700485544 /* AppIntents */ = { isa = PBXGroup; children = ( + BC5EBA3B2D002A2000C442FF /* MessageNodeIntent.swift */, BCB613802C67290800485544 /* SendWaypointIntent.swift */, BCB613822C672A2600485544 /* MessageChannelIntent.swift */, BCB613842C68703800485544 /* NodePositionIntent.swift */, @@ -638,6 +647,8 @@ BCE2D3C42C7AE369008E6199 /* RestartNodeIntent.swift */, BCE2D3C82C7C377F008E6199 /* FactoryResetNodeIntent.swift */, BCE2D3C62C7B0D0A008E6199 /* ShortcutsProvider.swift */, + BC6B45FE2CB2F98900723CEB /* SaveChannelSettingsIntent.swift */, + BC47C2EE2CE0017D008245CA /* MessageNodeIntent.swift */, ); path = AppIntents; sourceTree = ""; @@ -904,6 +915,7 @@ DDC2E14B26CE248E0042C5E4 = { isa = PBXGroup; children = ( + DDD3A2B12D5127B40045EB48 /* ci_scripts */, DDDBC87A2BC62E4E001E8DF7 /* Settings.bundle */, 25AECD4E2C2F723200862C8E /* Localizable.xcstrings */, DD3CC6BA28E366DF00FA9159 /* Meshtastic.xcdatamodeld */, @@ -1021,7 +1033,6 @@ DDF924C926FBB953009FE055 /* ConnectedDevice.swift */, DDD94A4F2845C8F5004A87A0 /* DateTimeText.swift */, DDB6ABDA28B0AC6000384BA1 /* DistanceText.swift */, - DDC3B273283F411B00AC321C /* LastHeardText.swift */, DDB75A202A12B954006ED576 /* LoRaSignalStrength.swift */, DDB75A1D2A0B0CD0006ED576 /* LoRaSignalStrengthIndicator.swift */, DD97E96528EFD9820056DDA4 /* MeshtasticLogo.swift */, @@ -1060,6 +1071,14 @@ path = Persistence; sourceTree = ""; }; + DDD3A2B12D5127B40045EB48 /* ci_scripts */ = { + isa = PBXGroup; + children = ( + DDD3A2B22D5127CF0045EB48 /* ci_pre_xcodebuild.sh */, + ); + path = ci_scripts; + sourceTree = ""; + }; DDD43FE12A78C86B0083A3E9 /* Mqtt */ = { isa = PBXGroup; children = ( @@ -1344,6 +1363,7 @@ DDFFA7472B3A7F3C004730DB /* Bundle.swift in Sources */, DD457188293C7E63000C49FB /* BLESignalStrengthIndicator.swift in Sources */, DDA9515C2BC6631200CEA535 /* TelemetryEnums.swift in Sources */, + BC47C2EF2CE0017D008245CA /* MessageNodeIntent.swift in Sources */, DDFEB3BB29900C1200EE7472 /* CurrentConditionsCompact.swift in Sources */, DD836AE726F6B38600ABCC23 /* Connect.swift in Sources */, D93069082B81DF040066FBC8 /* SaveConfigButton.swift in Sources */, @@ -1466,6 +1486,7 @@ DDA1C48E28DB49D3009933EC /* ChannelRoles.swift in Sources */, D9BC22DB2B7DE8E2006A37D5 /* TileDownloadStatus.swift in Sources */, DDD5BB092C285DDC007E03CA /* AppLog.swift in Sources */, + BC5EBA3C2D002A2000C442FF /* MessageNodeIntent.swift in Sources */, DD8ED9C8289CE4B900B3B0AB /* RoutingError.swift in Sources */, DDC1B81A2AB5377B00C71E39 /* MessagesTips.swift in Sources */, DD964FC62975DBFD007C176F /* QueryCoreData.swift in Sources */, @@ -1478,7 +1499,6 @@ 231B3F212D087A4C0069A07D /* MetricTableColumn.swift in Sources */, 231B3F222D087A4C0069A07D /* MetricsColumnList.swift in Sources */, DD8ED9C52898D51F00B3B0AB /* NetworkConfig.swift in Sources */, - DDC3B274283F411B00AC321C /* LastHeardText.swift in Sources */, DDDE5A1029AFE69700490C6C /* MeshActivityAttributes.swift in Sources */, DD1925B928CDA93900720036 /* SerialConfigEnums.swift in Sources */, 251926852C3BA97800249DF5 /* FavoriteNodeButton.swift in Sources */, @@ -1500,6 +1520,7 @@ DDB6ABE428B13FFF00384BA1 /* DisplayEnums.swift in Sources */, DD4975A52B147BA90026544E /* AmbientLightingConfig.swift in Sources */, D93068D92B81509C0066FBC8 /* TapbackResponses.swift in Sources */, + DDF82CBD2D5BC69200DC25EC /* NavigateToButton.swift in Sources */, 8D3F8A3F2D44BB02009EAAA4 /* PowerMetrics.swift in Sources */, 2519268A2C3BB1B200249DF5 /* ExchangePositionsButton.swift in Sources */, DD86D40A287F04F100BAEB7A /* InvalidVersion.swift in Sources */, @@ -1539,6 +1560,7 @@ DDDB444429F8A8DD00EE2349 /* Float.swift in Sources */, DDAB580F2B0DAFBC00147258 /* LocationEntityExtension.swift in Sources */, B3E905B12B71F7F300654D07 /* TextMessageField.swift in Sources */, + BC6B45FF2CB2F98900723CEB /* SaveChannelSettingsIntent.swift in Sources */, D93068D72B8146690066FBC8 /* MessageText.swift in Sources */, DDC2E15826CE248E0042C5E4 /* MeshtasticApp.swift in Sources */, ); @@ -1764,7 +1786,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.5.18; + MARKETING_VERSION = 2.5.19; PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTS_MACCATALYST = YES; @@ -1798,7 +1820,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.5.18; + MARKETING_VERSION = 2.5.19; PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTS_MACCATALYST = YES; @@ -1830,7 +1852,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.5.18; + MARKETING_VERSION = 2.5.19; PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient.Widgets; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1863,7 +1885,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.5.18; + MARKETING_VERSION = 2.5.19; PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient.Widgets; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/Meshtastic.xcodeproj/xcshareddata/xcschemes/Meshtastic.xcscheme b/Meshtastic.xcodeproj/xcshareddata/xcschemes/Meshtastic.xcscheme index e5a73d1e..508a6cab 100644 --- a/Meshtastic.xcodeproj/xcshareddata/xcschemes/Meshtastic.xcscheme +++ b/Meshtastic.xcodeproj/xcshareddata/xcschemes/Meshtastic.xcscheme @@ -78,10 +78,15 @@ isEnabled = "YES"> + + some IntentResult { + if !BLEManager.shared.isConnected { + throw AppIntentErrors.AppIntentError.notConnected + } + + // Convert messageContent to data and check its length + guard let messageData = messageContent.data(using: .utf8) else { + throw AppIntentErrors.AppIntentError.message("Failed to encode message content") + } + + if messageData.count > 200 { + throw $messageContent.needsValueError("Message content exceeds 200 bytes.") + } + + if !BLEManager.shared.sendMessage(message: messageContent, toUserNum: Int64(nodeNumber), channel: 0, isEmoji: false, replyID: 0) { + throw AppIntentErrors.AppIntentError.message("Failed to send message") + } + + return .result() + } +} diff --git a/Meshtastic/AppIntents/NavigateToNodeIntent.swift b/Meshtastic/AppIntents/NavigateToNodeIntent.swift new file mode 100644 index 00000000..06283f3f --- /dev/null +++ b/Meshtastic/AppIntents/NavigateToNodeIntent.swift @@ -0,0 +1,61 @@ +// +// NavigateToNodeIntent.swift +// Meshtastic +// +// Created by Benjamin Faershtein on 2/8/25. +// + +import Foundation +import AppIntents +import CoreLocation +import CoreData +import UIKit + +@available(iOS 16.4, *) +struct NavigateToNodeIntent: ForegroundContinuableIntent { + + static var title: LocalizedStringResource = "Navigate to Node Position" + static var openAppWhenRun: Bool = false + + @Parameter(title: "Node Number") + var nodeNum: Int + + @MainActor + func perform() async throws -> some IntentResult & ProvidesDialog { + if !BLEManager.shared.isConnected { + throw AppIntentErrors.AppIntentError.notConnected + } + + let fetchNodeInfoRequest: NSFetchRequest = NSFetchRequest(entityName: "NodeInfoEntity") + fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(nodeNum)) + + do { + guard let fetchedNode = try PersistenceController.shared.container.viewContext.fetch(fetchNodeInfoRequest) as? [NodeInfoEntity], + fetchedNode.count == 1 else { + throw $nodeNum.needsValueError("Could not find node") + } + + let nodeInfo = fetchedNode[0] + if let latitude = nodeInfo.latestPosition?.coordinate.latitude, + let longitude = nodeInfo.latestPosition?.coordinate.longitude { + + let url = URL(string: "maps://?saddr=&daddr=\(latitude),\(longitude)") + + if let mapURL = url, UIApplication.shared.canOpenURL(mapURL) { + // Request to continue in foreground before opening the app + try await requestToContinueInForeground() + + // Open Apple Maps for navigation + UIApplication.shared.open(mapURL, options: [:], completionHandler: nil) + return .result(dialog: "Navigating to node location.") + } else { + throw AppIntentErrors.AppIntentError.message("Unable to open Apple Maps.") + } + } else { + throw AppIntentErrors.AppIntentError.message("Node does not have a recorded position.") + } + } catch { + throw AppIntentErrors.AppIntentError.message("Failed to fetch node data.") + } + } +} diff --git a/Meshtastic/AppIntents/SaveChannelSettingsIntent.swift b/Meshtastic/AppIntents/SaveChannelSettingsIntent.swift new file mode 100644 index 00000000..902a66cc --- /dev/null +++ b/Meshtastic/AppIntents/SaveChannelSettingsIntent.swift @@ -0,0 +1,61 @@ +// +// SaveChannelSettingsIntent.swift +// Meshtastic +// +// Created by Benjamin Faershtein on 10/6/24. +// + +import Foundation +import AppIntents + +// Define the AppIntent for saving channel settings from a URL +struct SaveChannelSettingsIntent: AppIntent { + // Define a title and description for the intent + static var title: LocalizedStringResource = "Save Channel Settings" + static var description: IntentDescription = "Takes a Meshtastic channel URL and saves the channel settings." + + // Define the input for the intent (the channel URL) + @Parameter(title: "Channel URL", description: "The URL for the channel settings") + var channelUrl: URL + + // Define the function that performs the main logic + func perform() async throws -> some IntentResult { + // Ensure the BLE Manager is connected + if !BLEManager.shared.isConnected { + throw AppIntentErrors.AppIntentError.notConnected + } + + // Ensure the URL contains the expected "meshtastic.org/e/#" structure + if channelUrl.absoluteString.lowercased().contains("meshtastic.org/e/#") { + // Split the URL to get the portion after "#" + let components = channelUrl.absoluteString.components(separatedBy: "#") + + // Add channels flag based on the URL query parameter (if present) + let addChannels = Bool(channelUrl["add"] ?? "false") ?? false + + var channelSettings: String? + + // Extract the Base64 encoded channel settings (after "#") + if let lastComponent = components.last { + channelSettings = lastComponent.components(separatedBy: "?").first // Ignore any query parameters + } + + // If valid channel settings are extracted, attempt to save them + if let channelSettings = channelSettings { + // Call the BLEManager to save the channel settings + let saveResult = BLEManager.shared.saveChannelSet(base64UrlString: channelSettings, addChannels: addChannels) + + if !saveResult { + throw AppIntentErrors.AppIntentError.message("Failed to save the channel settings.") + } + } else { + throw AppIntentErrors.AppIntentError.message("Invalid Channel URL: Unable to extract settings.") + } + + // Return a success result + return .result() + } else { + throw AppIntentErrors.AppIntentError.message("The URL is not a valid Meshtastic channel link.") + } + } +} diff --git a/Meshtastic/Enums/BluetoothModes.swift b/Meshtastic/Enums/BluetoothModes.swift index c4bdad40..f62cc72c 100644 --- a/Meshtastic/Enums/BluetoothModes.swift +++ b/Meshtastic/Enums/BluetoothModes.swift @@ -17,11 +17,11 @@ enum BluetoothModes: Int, CaseIterable, Identifiable { var description: String { switch self { case .randomPin: - return "bluetooth.mode.randompin".localized + return "Random Pin".localized case .fixedPin: - return "bluetooth.mode.fixedpin".localized + return "Fixed Pin".localized case .noPin: - return "bluetooth.mode.nopin".localized + return "No PIN (Just Works)".localized } } func protoEnumValue() -> Config.BluetoothConfig.PairingMode { diff --git a/Meshtastic/Enums/DisplayEnums.swift b/Meshtastic/Enums/DisplayEnums.swift index 8959668a..25753f02 100644 --- a/Meshtastic/Enums/DisplayEnums.swift +++ b/Meshtastic/Enums/DisplayEnums.swift @@ -65,7 +65,7 @@ enum ScreenOnIntervals: Int, CaseIterable, Identifiable { case .oneHour: return "interval.one.hour".localized case .max: - return "always.on".localized + return "Always On".localized } } } @@ -113,7 +113,7 @@ enum OledTypes: Int, CaseIterable, Identifiable { var description: String { switch self { case .auto: - return "automatic.detection".localized + return "Detect Automatically".localized case .ssd1306: return "SSD 1306" case .sh1106: diff --git a/Meshtastic/Enums/LoraConfigEnums.swift b/Meshtastic/Enums/LoraConfigEnums.swift index 691a8298..e6cd4dae 100644 --- a/Meshtastic/Enums/LoraConfigEnums.swift +++ b/Meshtastic/Enums/LoraConfigEnums.swift @@ -83,49 +83,49 @@ enum RegionCodes: Int, CaseIterable, Identifiable { var description: String { switch self { case .unset: - return "please.set.a.region".localized + return "Please set a region".localized case .us: - return "united.states".localized + return "United States".localized case .eu433: - return "european.union.433mhz".localized + return "European Union 433MHz".localized case .eu868: - return "european.union.868mhz".localized + return "European Union 868MHz".localized case .cn: - return "china".localized + return "China".localized case .jp: - return "japan".localized + return "Japan".localized case .anz: - return "australia.new.zealand".localized + return "Australia / New Zealand".localized case .kr: - return "korea".localized + return "Korea".localized case .tw: - return "taiwan".localized + return "Taiwan".localized case .ru: - return "russia".localized + return "Russia".localized case .in: - return "india".localized + return "India".localized case .nz865: - return "new.zealand.865mhz".localized + return "New Zealand 865mhz".localized case .th: - return "thailand".localized + return "Thailand".localized case .ua433: - return "ukraine.433mhz".localized + return "Ukraine 433mhz".localized case .ua868: - return "ukraine.868mhz".localized + return "Ukraine 868mhz".localized case .lora24: - return "2.4ghz".localized + return "2.4 Ghz".localized case .my433: - return "malaysia.433mhz".localized + return "Malaysia 433mhz".localized case .my919: - return "malaysia.919mhz".localized + return "Malaysia 919mhz".localized case .sg923: - return "singapore.923mhz".localized + return "Singapore 923mhz".localized case .ph433: - return "philippines.433mhz".localized + return "Philippines 433mhz".localized case .ph868: - return "philippines.868mhz".localized + return "Philippines 868mhz".localized case .ph915: - return "philippines.915mhz".localized + return "Philippines 915mhz".localized } } var dutyCycle: Int { diff --git a/Meshtastic/Enums/RoutingError.swift b/Meshtastic/Enums/RoutingError.swift index b3962a09..628e1b3f 100644 --- a/Meshtastic/Enums/RoutingError.swift +++ b/Meshtastic/Enums/RoutingError.swift @@ -58,11 +58,11 @@ enum RoutingError: Int, CaseIterable, Identifiable { case .pkiFailed: return "routing.pkifailed".localized case .pkiUnknownPubkey: - return "routing.pkiunknownpubkey".localized + return "Unknown public key".localized case .adminBadSessionKey: - return "routing.adminbadsessionkey".localized + return "Bad admin session key".localized case .adminPublicKeyUnauthorized: - return "routing.adminpublickeyunauthorized".localized + return "Unauthorized admin public key".localized } } var color: Color { diff --git a/Meshtastic/Export/WriteCsvFile.swift b/Meshtastic/Export/WriteCsvFile.swift index 40913ea7..eb424586 100644 --- a/Meshtastic/Export/WriteCsvFile.swift +++ b/Meshtastic/Export/WriteCsvFile.swift @@ -14,7 +14,7 @@ func telemetryToCsvFile(telemetry: [TelemetryEntity], metricsType: Int) -> Strin let dateFormatString = (localeDateFormat ?? "MM/dd/YY j:mma").replacingOccurrences(of: ",", with: "") if metricsType == 0 { // Create Device Metrics Header - csvString = "\("battery.level".localized), \("voltage".localized), \("channel.utilization".localized), \("airtime".localized), \("uptime".localized), \("timestamp".localized)" + csvString = "\("battery.level".localized), \("voltage".localized), \("channel.utilization".localized), \("airtime".localized), \("uptime".localized), \("Timestamp".localized)" for dm in telemetry where dm.metricsType == 0 { csvString += "\n" csvString += String(dm.batteryLevel) @@ -31,7 +31,7 @@ func telemetryToCsvFile(telemetry: [TelemetryEntity], metricsType: Int) -> Strin } } else if metricsType == 1 { // Create Environment Telemetry Header - csvString = "Temperature, Relative Humidity, Barometric Pressure, Indoor Air Quality, Gas Resistance, \("timestamp".localized)" + csvString = "Temperature, Relative Humidity, Barometric Pressure, Indoor Air Quality, Gas Resistance, \("Timestamp".localized)" for dm in telemetry where dm.metricsType == 1 { csvString += "\n" csvString += String(dm.temperature.localeTemperature()) @@ -48,7 +48,7 @@ func telemetryToCsvFile(telemetry: [TelemetryEntity], metricsType: Int) -> Strin } } else if metricsType == 2 { // Create Power Metrics Header - csvString = "Channel 1 Voltage, Channel 1 Current, Channel 2 Voltage, Channel 2 Current, Channel 3 Voltage, Channel 3 Current, \("timestamp".localized)" + csvString = "Channel 1 Voltage, Channel 1 Current, Channel 2 Voltage, Channel 2 Current, Channel 3 Voltage, Channel 3 Current, \("Timestamp".localized)" for dm in telemetry where dm.metricsType == 2 { csvString += "\n" csvString += String(dm.powerCh1Voltage) @@ -74,7 +74,7 @@ func detectionsToCsv(detections: [MessageEntity]) -> String { let localeDateFormat = DateFormatter.dateFormat(fromTemplate: "yyMMddjmma", options: 0, locale: Locale.current) let dateFormatString = (localeDateFormat ?? "MM/dd/YY j:mma").replacingOccurrences(of: ",", with: "") // Create Header - csvString = "Detection event, \("timestamp".localized)" + csvString = "Detection event, \("Timestamp".localized)" for d in detections { csvString += "\n" csvString += d.messagePayload ?? "Detection" @@ -89,7 +89,7 @@ func logToCsvFile(log: [OSLogEntryLog]) -> String { let localeDateFormat = DateFormatter.dateFormat(fromTemplate: "yyMMddjmma", options: 0, locale: Locale.current) let dateFormatString = (localeDateFormat ?? "MM/dd/YY j:mma").replacingOccurrences(of: ",", with: "") // Create PAX Header - csvString = "Process, Category, Level, Message, \("timestamp".localized)" + csvString = "Process, Category, Level, Message, \("Timestamp".localized)" for l in log { csvString += "\n" csvString += String(l.process) @@ -110,7 +110,7 @@ func paxToCsvFile(pax: [PaxCounterEntity]) -> String { let localeDateFormat = DateFormatter.dateFormat(fromTemplate: "yyMMddjmma", options: 0, locale: Locale.current) let dateFormatString = (localeDateFormat ?? "MM/dd/YY j:mma").replacingOccurrences(of: ",", with: "") // Create PAX Header - csvString = "BLE, WiFi, Total Pax, Uptime, \("timestamp".localized)" + csvString = "BLE, WiFi, Total Pax, Uptime, \("Timestamp".localized)" for p in pax { csvString += "\n" csvString += String(p.ble) @@ -131,7 +131,7 @@ func positionToCsvFile(positions: [PositionEntity]) -> String { let localeDateFormat = DateFormatter.dateFormat(fromTemplate: "yyMMddjmma", options: 0, locale: Locale.current) let dateFormatString = (localeDateFormat ?? "MM/dd/YY j:mma").replacingOccurrences(of: ",", with: "") // Create Position Header - csvString = "SeqNo, Latitude, Longitude, Altitude, Sats, Speed, Heading, SNR, \("timestamp".localized)" + csvString = "SeqNo, Latitude, Longitude, Altitude, Sats, Speed, Heading, SNR, \("Timestamp".localized)" for pos in positions { csvString += "\n" csvString += String(pos.seqNo) diff --git a/Meshtastic/Extensions/Date.swift b/Meshtastic/Extensions/Date.swift index 7fc72b33..0736fc63 100644 --- a/Meshtastic/Extensions/Date.swift +++ b/Meshtastic/Extensions/Date.swift @@ -9,6 +9,14 @@ import Foundation extension Date { + var lastHeard: String { + if timeIntervalSince1970 > 0 { + formatted() + } else { + "unknown" + } + } + func formattedDate(format: String) -> String { let dateformat = DateFormatter() dateformat.dateFormat = format diff --git a/Meshtastic/Extensions/Measurement.swift b/Meshtastic/Extensions/Measurement.swift index 4947c823..ca867c09 100644 --- a/Meshtastic/Extensions/Measurement.swift +++ b/Meshtastic/Extensions/Measurement.swift @@ -8,14 +8,6 @@ import Foundation import Charts -extension Measurement where UnitType == UnitAngle { - func reciprocal() -> Measurement { - var recip = self.converted(to: .degrees) - recip.value = (recip.value + 180).truncatingRemainder(dividingBy: 360) - return recip.converted(to: self.unit) - } -} - struct PlottableMeasurement { var measurement: Measurement } diff --git a/Meshtastic/Helpers/BLEManager.swift b/Meshtastic/Helpers/BLEManager.swift index b81c3247..13bb65e8 100644 --- a/Meshtastic/Helpers/BLEManager.swift +++ b/Meshtastic/Helpers/BLEManager.swift @@ -118,7 +118,7 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate } self.isConnected = false self.isConnecting = false - self.lastConnectionError = "🚨 " + String.localizedStringWithFormat("ble.connection.timeout %d %@".localized, timeoutTimerCount, name) + self.lastConnectionError = "🚨 " + String.localizedStringWithFormat("Connection failed after %d attempts to connect to %@. You may need to forget your device under Settings > Bluetooth.".localized, timeoutTimerCount, name) MeshLogger.log(lastConnectionError) self.timeoutTimerCount = 0 self.startScanning() @@ -241,7 +241,7 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate let errorCode = (e as NSError).code if errorCode == 6 { // CBError.Code.connectionTimeout The connection has timed out unexpectedly. // Happens when device is manually reset / powered off - lastConnectionError = "🚨" + String.localizedStringWithFormat("ble.errorcode.6 %@".localized, e.localizedDescription) + lastConnectionError = "🚨" + String.localizedStringWithFormat("%@ The app will automatically reconnect to the preferred radio if it comes back in range.".localized, e.localizedDescription) Logger.services.error("🚨 [BLE] Disconnected: \(peripheral.name ?? "Unknown".localized, privacy: .public) Error Code: \(errorCode, privacy: .public) Error: \(e.localizedDescription, privacy: .public)") } else if errorCode == 7 { // CBError.Code.peripheralDisconnected The specified device has disconnected from us. // Seems to be what is received when a tbeam sleeps, immediately recconnecting does not work. @@ -262,7 +262,7 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate Logger.services.error("🚨 [BLE] Disconnected: \(peripheral.name ?? "Unknown".localized, privacy: .public) Error Code: \(errorCode, privacy: .public) Error: \(e.localizedDescription, privacy: .public)") } else if errorCode == 14 { // Peer removed pairing information // Forgetting and reconnecting seems to be necessary so we need to show the user an error telling them to do that - lastConnectionError = "🚨 " + String.localizedStringWithFormat("ble.errorcode.14 %@".localized, e.localizedDescription) + lastConnectionError = "🚨 " + String.localizedStringWithFormat("%@ This error usually cannot be fixed without forgetting the device unders Settings > Bluetooth and re-connecting to the radio.".localized, e.localizedDescription) Logger.services.error("🚨 [BLE] Disconnected: \(peripheral.name ?? "Unknown".localized) Error Code: \(errorCode, privacy: .public) Error: \(self.lastConnectionError, privacy: .public)") } else { if UserDefaults.preferredPeripheralId == peripheral.identifier.uuidString { @@ -575,7 +575,7 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate // BLE PIN connection errors // 5 CBATTErrorDomain Code=5 "Authentication is insufficient." // 15 CBATTErrorDomain Code=15 "Encryption is insufficient." - lastConnectionError = "🚨" + String.localizedStringWithFormat("ble.errorcode.pin %@".localized, error.localizedDescription) + lastConnectionError = "🚨" + String.localizedStringWithFormat("%@ Please try connecting again and check the PIN carefully.".localized, error.localizedDescription) Logger.services.error("🚫 [BLE] \(error.localizedDescription, privacy: .public) Please try connecting again and check the PIN carefully.") self.disconnectPeripheral(reconnect: false) } diff --git a/Meshtastic/Helpers/LocalNotificationManager.swift b/Meshtastic/Helpers/LocalNotificationManager.swift index 817c90a4..d5f25749 100644 --- a/Meshtastic/Helpers/LocalNotificationManager.swift +++ b/Meshtastic/Helpers/LocalNotificationManager.swift @@ -7,7 +7,7 @@ class LocalNotificationManager { var notifications = [Notification]() let thumbsUpAction = UNNotificationAction(identifier: "messageNotification.thumbsUpAction", title: "👍 \(Tapbacks.thumbsUp.description)", options: []) let thumbsDownAction = UNNotificationAction(identifier: "messageNotification.thumbsDownAction", title: "👎 \(Tapbacks.thumbsDown.description)", options: []) - let replyInputAction = UNTextInputNotificationAction(identifier: "messageNotification.replyInputAction", title: "reply".localized, options: []) + let replyInputAction = UNTextInputNotificationAction(identifier: "messageNotification.replyInputAction", title: "Reply".localized, options: []) // Step 1 Request Permissions for notifications private func requestAuthorization() { diff --git a/Meshtastic/Helpers/LocationsHandler.swift b/Meshtastic/Helpers/LocationsHandler.swift index 99d8b41a..6754891c 100644 --- a/Meshtastic/Helpers/LocationsHandler.swift +++ b/Meshtastic/Helpers/LocationsHandler.swift @@ -145,6 +145,5 @@ import OSLog } return sats } - } diff --git a/Meshtastic/Helpers/MeshPackets.swift b/Meshtastic/Helpers/MeshPackets.swift index b792db29..8c85751f 100644 --- a/Meshtastic/Helpers/MeshPackets.swift +++ b/Meshtastic/Helpers/MeshPackets.swift @@ -682,7 +682,6 @@ func telemetryPacket(packet: MeshPacket, connectedNode: Int64, context: NSManage let logString = String.localizedStringWithFormat("mesh.log.telemetry.received %@".localized, String(packet.from)) MeshLogger.log("📈 \(logString)") - if telemetryMessage.variant != Telemetry.OneOf_Variant.deviceMetrics(telemetryMessage.deviceMetrics) && telemetryMessage.variant != Telemetry.OneOf_Variant.environmentMetrics(telemetryMessage.environmentMetrics) && telemetryMessage.variant != Telemetry.OneOf_Variant.localStats(telemetryMessage.localStats) && telemetryMessage.variant != Telemetry.OneOf_Variant.powerMetrics(telemetryMessage.powerMetrics) { /// Other unhandled telemetry packets return @@ -739,7 +738,7 @@ func telemetryPacket(packet: MeshPacket, connectedNode: Int64, context: NSManage Logger.statistics.info("📈 [Mesh Statistics] Channel Utilization: \(telemetryMessage.localStats.channelUtilization, privacy: .public) Airtime: \(telemetryMessage.localStats.airUtilTx, privacy: .public) Packets Sent: \(telemetryMessage.localStats.numPacketsTx, privacy: .public) Packets Received: \(telemetryMessage.localStats.numPacketsRx, privacy: .public) Bad Packets Received: \(telemetryMessage.localStats.numPacketsRxBad, privacy: .public) Nodes Online: \(telemetryMessage.localStats.numOnlineNodes, privacy: .public) of \(telemetryMessage.localStats.numTotalNodes, privacy: .public) nodes for Node: \(packet.from.toHex(), privacy: .public)") } else if telemetryMessage.variant == Telemetry.OneOf_Variant.powerMetrics(telemetryMessage.powerMetrics) { Logger.data.info("📈 [Power Metrics] Received for Node: \(packet.from.toHex(), privacy: .public)") - + if telemetryMessage.powerMetrics.hasCh1Voltage { telemetry.powerCh1Voltage = telemetryMessage.powerMetrics.ch1Voltage telemetry.metricsType = 2 diff --git a/Meshtastic/Helpers/Mqtt/MqttClientProxyManager.swift b/Meshtastic/Helpers/Mqtt/MqttClientProxyManager.swift index eba2d41f..cac34de8 100644 --- a/Meshtastic/Helpers/Mqtt/MqttClientProxyManager.swift +++ b/Meshtastic/Helpers/Mqtt/MqttClientProxyManager.swift @@ -26,7 +26,7 @@ class MqttClientProxyManager { var debugLog = false func connectFromConfigSettings(node: NodeInfoEntity) { let defaultServerAddress = "mqtt.meshtastic.org" - var useSsl = node.mqttConfig?.tlsEnabled == true + let useSsl = node.mqttConfig?.tlsEnabled == true var defaultServerPort = useSsl ? 8883 : 1883 var host = node.mqttConfig?.address if host == nil || host!.isEmpty { @@ -37,17 +37,15 @@ class MqttClientProxyManager { defaultServerPort = Int(fullHost.components(separatedBy: ":")[1]) ?? (useSsl ? 8883 : 1883) } } - + if let host = host { let port = defaultServerPort var username = node.mqttConfig?.username var password = node.mqttConfig?.password - if host == defaultServerAddress { - - // username = ProcessInfo.processInfo.environment["publicMqttUsername"] - // password = ProcessInfo.processInfo.environment["publicMqttPsk"] - useSsl = false - } + // if host == defaultServerAddress { + //username = ProcessInfo.processInfo.environment["PUBLIC_MQTT_USERNAME"] + //password = ProcessInfo.processInfo.environment["PUBLIC_MQTT_PASSWORD"] + // } let root = node.mqttConfig?.root?.count ?? 0 > 0 ? node.mqttConfig?.root : "msh" let prefix = root! topic = prefix + "/2/e" + "/#" diff --git a/Meshtastic/Views/Bluetooth/Connect.swift b/Meshtastic/Views/Bluetooth/Connect.swift index ed9728c6..2d86e15a 100644 --- a/Meshtastic/Views/Bluetooth/Connect.swift +++ b/Meshtastic/Views/Bluetooth/Connect.swift @@ -63,14 +63,14 @@ struct Connect: View { if node != nil { Text(connectedPeripheral.longName).font(.title2) } - Text("ble.name").font(.callout)+Text(": \(bleManager.connectedPeripheral?.peripheral.name ?? "unknown".localized)") + Text("BLE Name").font(.callout)+Text(": \(bleManager.connectedPeripheral?.peripheral.name ?? "unknown".localized)") .font(.callout).foregroundColor(Color.gray) if node != nil { Text("firmware.version").font(.callout)+Text(": \(node?.metadata?.firmwareVersion ?? "unknown".localized)") .font(.callout).foregroundColor(Color.gray) } if bleManager.isSubscribed { - Text("subscribed").font(.callout) + Text("Subscribed").font(.callout) .foregroundColor(.green) } else { HStack { @@ -78,7 +78,7 @@ struct Connect: View { .symbolRenderingMode(.multicolor) .symbolEffect(.variableColor.reversing.cumulative, options: .repeat(20).speed(3)) .foregroundColor(.orange) - Text("communicating").font(.callout) + Text("Communicating").font(.callout) .foregroundColor(.orange) } } @@ -95,7 +95,7 @@ struct Connect: View { bleManager.disconnectPeripheral(reconnect: false) } } label: { - Label("disconnect", systemImage: "antenna.radiowaves.left.and.right.slash") + Label("Disconnect", systemImage: "antenna.radiowaves.left.and.right.slash") } } .contextMenu { @@ -172,7 +172,7 @@ struct Connect: View { Button(role: .destructive) { bleManager.cancelPeripheralConnection() } label: { - Label("disconnect", systemImage: "antenna.radiowaves.left.and.right.slash") + Label("Disconnect", systemImage: "antenna.radiowaves.left.and.right.slash") } } @@ -197,7 +197,7 @@ struct Connect: View { .textCase(nil) if !self.bleManager.isConnected { - Section(header: Text("available.radios").font(.title)) { + Section(header: Text("Available Radios").font(.title)) { ForEach(bleManager.peripherals.filter({ $0.peripheral.state == CBPeripheralState.disconnected }).sorted(by: { $0.name < $1.name })) { peripheral in HStack { if UserDefaults.preferredPeripheralId == peripheral.peripheral.identifier.uuidString { @@ -243,7 +243,7 @@ struct Connect: View { } } else { - Text("bluetooth.off") + Text("Bluetooth is off") .foregroundColor(.red) .font(.title) } @@ -258,7 +258,7 @@ struct Connect: View { bleManager.disconnectPeripheral(reconnect: false) } }) { - Label("disconnect", systemImage: "antenna.radiowaves.left.and.right.slash") + Label("Disconnect", systemImage: "antenna.radiowaves.left.and.right.slash") } .buttonStyle(.bordered) .buttonBorderShape(.capsule) @@ -270,7 +270,7 @@ struct Connect: View { bleManager.cancelPeripheralConnection() }) { - Label("disconnect", systemImage: "antenna.radiowaves.left.and.right.slash") + Label("Disconnect", systemImage: "antenna.radiowaves.left.and.right.slash") } .buttonStyle(.bordered) .buttonBorderShape(.capsule) @@ -282,7 +282,7 @@ struct Connect: View { } .padding(.bottom, 10) } - .navigationTitle("bluetooth") + .navigationTitle("Bluetooth") .navigationBarItems( leading: MeshtasticLogo(), trailing: ZStack { diff --git a/Meshtastic/Views/ContentView.swift b/Meshtastic/Views/ContentView.swift index b122b0aa..d6b2fd6b 100644 --- a/Meshtastic/Views/ContentView.swift +++ b/Meshtastic/Views/ContentView.swift @@ -26,7 +26,7 @@ struct ContentView: View { Connect() .tabItem { - Label("bluetooth", systemImage: "antenna.radiowaves.left.and.right") + Label("Bluetooth", systemImage: "antenna.radiowaves.left.and.right") } .tag(NavigationState.Tab.bluetooth) diff --git a/Meshtastic/Views/Helpers/ConnectedDevice.swift b/Meshtastic/Views/Helpers/ConnectedDevice.swift index c57a4c5d..42b0ac70 100644 --- a/Meshtastic/Views/Helpers/ConnectedDevice.swift +++ b/Meshtastic/Views/Helpers/ConnectedDevice.swift @@ -36,7 +36,7 @@ struct ConnectedDevice: View { .symbolRenderingMode(.hierarchical) } } else { - Text("bluetooth.off").font(.subheadline).foregroundColor(.red) + Text("Bluetooth is off").font(.subheadline).foregroundColor(.red) } } } diff --git a/Meshtastic/Views/Helpers/LastHeardText.swift b/Meshtastic/Views/Helpers/LastHeardText.swift deleted file mode 100644 index 5981d9c2..00000000 --- a/Meshtastic/Views/Helpers/LastHeardText.swift +++ /dev/null @@ -1,28 +0,0 @@ -import SwiftUI -// -// LastHeardText.swift -// Meshtastic Apple -// -// Created by Garth Vander Houwen on 5/25/22. -// -struct LastHeardText: View { - var lastHeard: Date? - - var body: some View { - if let lastHeard, lastHeard.timeIntervalSince1970 > 0 { - Text(lastHeard.formatted()) - } else { - Text("unknown") - } - } -} -struct LastHeardText_Previews: PreviewProvider { - static var previews: some View { - LastHeardText(lastHeard: Date()) - .previewLayout(.fixed(width: 300, height: 100)) - .environment(\.locale, .init(identifier: "en")) - LastHeardText(lastHeard: Date()) - .previewLayout(.fixed(width: 300, height: 100)) - .environment(\.locale, .init(identifier: "de")) - } -} diff --git a/Meshtastic/Views/Helpers/PowerMetrics.swift b/Meshtastic/Views/Helpers/PowerMetrics.swift index 4b4076d5..cbff60a2 100644 --- a/Meshtastic/Views/Helpers/PowerMetrics.swift +++ b/Meshtastic/Views/Helpers/PowerMetrics.swift @@ -17,8 +17,7 @@ struct PowerMetrics: View { LazyVGrid(columns: gridItemLayout) { - - if(metric.powerCh1Voltage != nil) { + if metric.powerCh1Voltage != nil { PowerMetricCompactWidget( type: .voltage, value: metric.powerCh1Voltage, @@ -26,7 +25,7 @@ struct PowerMetrics: View { ) } - if(metric.powerCh1Current != nil) { + if metric.powerCh1Current != nil { PowerMetricCompactWidget( type: .current, value: metric.powerCh1Current, @@ -34,7 +33,7 @@ struct PowerMetrics: View { ) } - if(metric.powerCh2Voltage != nil) { + if metric.powerCh2Voltage != nil { PowerMetricCompactWidget( type: .voltage, value: metric.powerCh2Voltage, @@ -42,7 +41,7 @@ struct PowerMetrics: View { ) } - if(metric.powerCh2Current != nil) { + if metric.powerCh2Current != nil { PowerMetricCompactWidget( type: .current, value: metric.powerCh2Current, @@ -50,7 +49,7 @@ struct PowerMetrics: View { ) } - if(metric.powerCh3Voltage != nil) { + if metric.powerCh3Voltage != nil { PowerMetricCompactWidget( type: .voltage, value: metric.powerCh3Voltage, @@ -58,7 +57,7 @@ struct PowerMetrics: View { ) } - if(metric.powerCh3Current != nil) { + if metric.powerCh3Current != nil { PowerMetricCompactWidget( type: .current, value: metric.powerCh3Current, diff --git a/Meshtastic/Views/Messages/ChannelMessageList.swift b/Meshtastic/Views/Messages/ChannelMessageList.swift index 1b783427..573a7dc8 100644 --- a/Meshtastic/Views/Messages/ChannelMessageList.swift +++ b/Meshtastic/Views/Messages/ChannelMessageList.swift @@ -127,13 +127,17 @@ struct ChannelMessageList: View { } } } - .padding([.top]) - .scrollDismissesKeyboard(.immediately) + .scrollDismissesKeyboard(.interactively) .onFirstAppear { withAnimation { scrollView.scrollTo(channel.allPrivateMessages.last?.messageId ?? 0, anchor: .bottom) } } + .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardDidShowNotification)) { _ in + withAnimation { + scrollView.scrollTo(channel.allPrivateMessages.last?.messageId ?? 0, anchor: .bottom) + } + } .onChange(of: channel.allPrivateMessages) { withAnimation { scrollView.scrollTo(channel.allPrivateMessages.last?.messageId ?? 0, anchor: .bottom) diff --git a/Meshtastic/Views/Messages/MessageContextMenuItems.swift b/Meshtastic/Views/Messages/MessageContextMenuItems.swift index c9c37cdc..1d8642a0 100644 --- a/Meshtastic/Views/Messages/MessageContextMenuItems.swift +++ b/Meshtastic/Views/Messages/MessageContextMenuItems.swift @@ -16,10 +16,10 @@ struct MessageContextMenuItems: View { if message.pkiEncrypted { Label("Encrypted", systemImage: "lock") } - Text("channel") + Text(": \(message.channel)") + Text("Channel") + Text(": \(message.channel)") } - Menu("tapback") { + Menu("Tapback") { ForEach(Tapbacks.allCases) { tb in Button { let sentMessage = bleManager.sendMessage( @@ -40,14 +40,14 @@ struct MessageContextMenuItems: View { } Button(action: onReply) { - Text("reply") + Text("Reply") Image(systemName: "arrowshape.turn.up.left") } Button { UIPasteboard.general.string = message.messagePayload } label: { - Text("copy") + Text("Copy") Image(systemName: "doc.on.doc") } @@ -74,7 +74,7 @@ struct MessageContextMenuItems: View { } } else if isCurrentUser && message.ackError == 0 { // Empty Error - Text("waiting") + Text("Waiting") } else if isCurrentUser && message.ackError > 0 { let ackErrorVal = RoutingError(rawValue: Int(message.ackError)) Text("\(ackErrorVal?.display ?? "Empty Ack Error")") diff --git a/Meshtastic/Views/Messages/TextMessageField/TextMessageField.swift b/Meshtastic/Views/Messages/TextMessageField/TextMessageField.swift index 1eca5015..c8def69b 100644 --- a/Meshtastic/Views/Messages/TextMessageField/TextMessageField.swift +++ b/Meshtastic/Views/Messages/TextMessageField/TextMessageField.swift @@ -41,7 +41,7 @@ struct TextMessageField: View { .keyboardType(.default) .toolbar { ToolbarItemGroup(placement: .keyboard) { - Button("dismiss.keyboard") { + Button("Dismiss") { isFocused = false } .font(.subheadline) diff --git a/Meshtastic/Views/Messages/TextMessageField/TextMessageSize.swift b/Meshtastic/Views/Messages/TextMessageField/TextMessageSize.swift index c939b825..aacbd60d 100644 --- a/Meshtastic/Views/Messages/TextMessageField/TextMessageSize.swift +++ b/Meshtastic/Views/Messages/TextMessageField/TextMessageSize.swift @@ -5,7 +5,7 @@ struct TextMessageSize: View { let totalBytes: Int var body: some View { - ProgressView("\("bytes".localized): \(totalBytes) / \(maxbytes)", value: Double(totalBytes), total: Double(maxbytes)) + ProgressView("\("Bytes".localized): \(totalBytes) / \(maxbytes)", value: Double(totalBytes), total: Double(maxbytes)) .frame(width: 130) .padding(5) .font(.subheadline) diff --git a/Meshtastic/Views/Messages/UserMessageList.swift b/Meshtastic/Views/Messages/UserMessageList.swift index 7ce190fc..68db6280 100644 --- a/Meshtastic/Views/Messages/UserMessageList.swift +++ b/Meshtastic/Views/Messages/UserMessageList.swift @@ -115,13 +115,17 @@ struct UserMessageList: View { } } } - .padding([.top]) - .scrollDismissesKeyboard(.immediately) + .scrollDismissesKeyboard(.interactively) .onFirstAppear { withAnimation { scrollView.scrollTo(user.messageList.last?.messageId ?? 0, anchor: .bottom) } } + .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardDidShowNotification)) { _ in + withAnimation { + scrollView.scrollTo(user.messageList.last?.messageId ?? 0, anchor: .bottom) + } + } .onChange(of: user.messageList) { withAnimation { scrollView.scrollTo(user.messageList.last?.messageId ?? 0, anchor: .bottom) diff --git a/Meshtastic/Views/Nodes/DetectionSensorLog.swift b/Meshtastic/Views/Nodes/DetectionSensorLog.swift index 06c468ca..1eeb499e 100644 --- a/Meshtastic/Views/Nodes/DetectionSensorLog.swift +++ b/Meshtastic/Views/Nodes/DetectionSensorLog.swift @@ -71,7 +71,7 @@ struct DetectionSensorLog: View { Text(d.messagePayload ?? "Detected") } - TableColumn("timestamp") { d in + TableColumn("Timestamp") { d in Text(d.timestamp.formattedDate(format: dateFormatString)) } .width(min: 180) @@ -87,7 +87,7 @@ struct DetectionSensorLog: View { Text("Detection") .font(.caption) .fontWeight(.bold) - Text("timestamp") + Text("Timestamp") .font(.caption) .fontWeight(.bold) } diff --git a/Meshtastic/Views/Nodes/DeviceMetricsLog.swift b/Meshtastic/Views/Nodes/DeviceMetricsLog.swift index 0239e476..958fefa4 100644 --- a/Meshtastic/Views/Nodes/DeviceMetricsLog.swift +++ b/Meshtastic/Views/Nodes/DeviceMetricsLog.swift @@ -113,7 +113,7 @@ struct DeviceMetricsLog: View { if idiom == .phone { /// Single Cell Compact display for phones Table(deviceMetrics, selection: $selection, sortOrder: $sortOrder) { - TableColumn("battery.level") { dm in + TableColumn("Battery Level") { dm in HStack { Text(dm.time?.formattedDate(format: dateFormatString) ?? "unknown.age".localized) .font(.caption) @@ -140,7 +140,7 @@ struct DeviceMetricsLog: View { } else { /// Multi Column table for ipads and mac Table(deviceMetrics, selection: $selection, sortOrder: $sortOrder) { - TableColumn("battery.level") { dm in + TableColumn("Battery Level") { dm in if dm.batteryLevel > 100 { Text("Powered") } else { @@ -154,17 +154,17 @@ struct DeviceMetricsLog: View { Text("\(String(format: "%.2f", dm.channelUtilization))%") .foregroundColor(dm.channelUtilization < 25 ? .green : (dm.channelUtilization > 50 ? .red : .orange)) } - TableColumn("airtime") { dm in + TableColumn("Airtime") { dm in Text("\(String(format: "%.2f", dm.airUtilTx))%") } - TableColumn("uptime") { dm in + TableColumn("Uptime") { dm in let now = Date.now let later = now + TimeInterval(dm.uptimeSeconds) let components = (now.. = NSFetchRequest(entityName: "NodeInfoEntity") + fetchRequest.predicate = NSPredicate(format: "num == %lld", Int64(userNum)) + + do { + let fetchedNodes = try PersistenceController.shared.container.viewContext.fetch(fetchRequest) + + guard let nodeInfo = fetchedNodes.first else { + Logger.services.error("NavigateToAction: Node with userNum \(userNum) not found in Core Data") + return + } + + if let latitude = nodeInfo.latestPosition?.latitude, + let longitude = nodeInfo.latestPosition?.longitude { + if let url = URL(string: "maps://?saddr=&daddr=\(latitude),\(longitude)") { + UIApplication.shared.open(url, options: [:], completionHandler: nil) + } else { + Logger.services.error("Failed to create URL for navigation") + } + } else { + Logger.services.warning("NavigateToAction: Node \(userNum) has invalid or missing coordinates") + } + } catch { + Logger.services.error("NavigateToAction: Failed to fetch node with userNum \(userNum): \(error.localizedDescription)") + } + } label: { + Label { + Text("Navigate to node") + } icon: { + Image(systemName: "map") + .symbolRenderingMode(.hierarchical) + } + } + } +} diff --git a/Meshtastic/Views/Nodes/Helpers/Map/PositionPopover.swift b/Meshtastic/Views/Nodes/Helpers/Map/PositionPopover.swift index 8874ba98..f68354c0 100644 --- a/Meshtastic/Views/Nodes/Helpers/Map/PositionPopover.swift +++ b/Meshtastic/Views/Nodes/Helpers/Map/PositionPopover.swift @@ -55,7 +55,7 @@ struct PositionPopover: View { if idiom != .phone { Text("heard".localized + ":") } - LastHeardText(lastHeard: position.time) + Text(position.time?.lastHeard ?? "unknown") .foregroundColor(.primary) .font(idiom == .phone ? .callout : .body) .allowsTightening(/*@START_MENU_TOKEN@*/true/*@END_MENU_TOKEN@*/) @@ -143,7 +143,7 @@ struct PositionPopover: View { /// Heading let degrees = Angle.degrees(Double(position.heading)) Label { - let heading = Measurement(value: degrees.degrees, unit: UnitAngle.degrees).reciprocal() + let heading = Measurement(value: degrees.degrees, unit: UnitAngle.degrees) Text("Heading: \(heading.formatted(.measurement(width: .narrow, numberFormatStyle: .number.precision(.fractionLength(0)))))") } icon: { Image(systemName: "location.north") diff --git a/Meshtastic/Views/Nodes/Helpers/Map/WaypointForm.swift b/Meshtastic/Views/Nodes/Helpers/Map/WaypointForm.swift index 2c2c267a..8c8feb32 100644 --- a/Meshtastic/Views/Nodes/Helpers/Map/WaypointForm.swift +++ b/Meshtastic/Views/Nodes/Helpers/Map/WaypointForm.swift @@ -181,7 +181,7 @@ struct WaypointForm: View { Button(role: .cancel) { dismiss() } label: { - Label("cancel", systemImage: "x.circle") + Label("Cancel", systemImage: "x.circle") } .buttonStyle(.bordered) .buttonBorderShape(.capsule) diff --git a/Meshtastic/Views/Nodes/Helpers/NodeDetail.swift b/Meshtastic/Views/Nodes/Helpers/NodeDetail.swift index e251c64c..e3039306 100644 --- a/Meshtastic/Views/Nodes/Helpers/NodeDetail.swift +++ b/Meshtastic/Views/Nodes/Helpers/NodeDetail.swift @@ -260,18 +260,6 @@ struct NodeDetail: View { } .disabled(!node.hasDeviceMetrics) - NavigationLink{ - PowerMetricsLog(node: node) - } label: { - Label { - Text("Power Metrics Log") - } icon: { - Image(systemName: "bolt") - .symbolRenderingMode(.multicolor) - } - } - .disabled(!node.hasPowerMetrics) - NavigationLink { NodeMapSwiftUI(node: node, showUserLocation: connectedNode?.num ?? 0 == node.num) } label: { @@ -320,6 +308,18 @@ struct NodeDetail: View { } .disabled(node.traceRoutes?.count ?? 0 == 0) + NavigationLink { + PowerMetricsLog(node: node) + } label: { + Label { + Text("Power Metrics Log") + } icon: { + Image(systemName: "bolt") + .symbolRenderingMode(.multicolor) + } + } + .disabled(!node.hasPowerMetrics) + NavigationLink { DetectionSensorLog(node: node) } label: { @@ -378,6 +378,9 @@ struct NodeDetail: View { node: node ) } + if node.hasPositions { + NavigateToButton(node: node) + } IgnoreNodeButton( bleManager: bleManager, context: context, @@ -423,7 +426,7 @@ struct NodeDetail: View { } label: { Label("Power Off", systemImage: "power") }.confirmationDialog( - "are.you.sure", + "Are you sure?", isPresented: $showingShutdownConfirm ) { Button("Shutdown Node?", role: .destructive) { @@ -446,7 +449,7 @@ struct NodeDetail: View { systemImage: "arrow.triangle.2.circlepath" ) }.confirmationDialog( - "are.you.sure", + "Are you sure?", isPresented: $showingRebootConfirm ) { Button("reboot.node", role: .destructive) { diff --git a/Meshtastic/Views/Nodes/Helpers/NodeListFilter.swift b/Meshtastic/Views/Nodes/Helpers/NodeListFilter.swift index 454b3607..a29a0749 100644 --- a/Meshtastic/Views/Nodes/Helpers/NodeListFilter.swift +++ b/Meshtastic/Views/Nodes/Helpers/NodeListFilter.swift @@ -174,14 +174,14 @@ struct NodeListFilter: View { VStack { List(DeviceRoles.allCases, selection: $deviceRoles) { dr in Label { - Text(" \(dr.name)") + Text("\(dr.name)") } icon: { Image(systemName: dr.systemName) } } .listStyle(.plain) .environment(\.editMode, $editMode) /// bind it here! - .frame(minHeight: 490, maxHeight: .infinity) + .frame(minHeight: 510, maxHeight: .infinity) } } } @@ -200,7 +200,7 @@ struct NodeListFilter: View { .padding(.bottom) #endif } - .presentationDetents([.fraction(0.75), .large]) + .presentationDetents([.fraction(0.80), .large]) .presentationContentInteraction(.scrolls) .presentationDragIndicator(.visible) .presentationBackgroundInteraction(.enabled(upThrough: .large)) diff --git a/Meshtastic/Views/Nodes/Helpers/NodeListItem.swift b/Meshtastic/Views/Nodes/Helpers/NodeListItem.swift index 8fe387db..9819ef38 100644 --- a/Meshtastic/Views/Nodes/Helpers/NodeListItem.swift +++ b/Meshtastic/Views/Nodes/Helpers/NodeListItem.swift @@ -15,12 +15,43 @@ struct NodeListItem: View { var connectedNode: Int64 var modemPreset: ModemPresets = ModemPresets(rawValue: UserDefaults.modemPreset) ?? ModemPresets.longFast - var body: some View { + var userKeyStatus: (String, Color) { + var image = "lock.open.fill" + var color = Color.yellow + if node.user?.pkiEncrypted ?? false { + if !(node.user?.keyMatch ?? false) { + /// Public Key on the User and the Public Key on the Last Message don't match + image = "key.slash" + color = .red + } else { + image = "lock.fill" + color = .green + } + } + return (image, color) + } + var locationData: (PositionEntity, CLLocation)? { + guard let lastPostion = node.positions?.lastObject as? PositionEntity else { + return nil + } + guard let currentLocation = LocationsHandler.shared.locationsArray.last else { + return nil + } + + let myCoord = CLLocation(latitude: currentLocation.coordinate.latitude, longitude: currentLocation.coordinate.longitude) + + if lastPostion.nodeCoordinate != nil && myCoord.coordinate.longitude != LocationsHandler.DefaultLocation.longitude && myCoord.coordinate.latitude != LocationsHandler.DefaultLocation.latitude { + return (lastPostion, myCoord) + } + return nil + } + + var body: some View { NavigationLink(value: node) { LazyVStack(alignment: .leading) { HStack { - VStack(alignment: .leading) { + VStack(alignment: .center) { CircleText(text: node.user?.shortName ?? "?", color: Color(UIColor(hex: UInt32(node.num))), circleSize: 70) .padding(.trailing, 5) if node.latestDeviceMetrics != nil { @@ -30,23 +61,11 @@ struct NodeListItem: View { } VStack(alignment: .leading) { HStack { - if node.user?.pkiEncrypted ?? false { - if !(node.user?.keyMatch ?? false) { - /// Public Key on the User and the Public Key on the Last Message don't match - Image(systemName: "key.slash") - .foregroundColor(.red) - } else { - Image(systemName: "lock.fill") - .foregroundColor(.green) - } - } else { - Image(systemName: "lock.open.fill") - .foregroundColor(.yellow) - } - Text(node.user?.longName ?? "unknown".localized) - .font(.headline) - .fontWeight(.regular) - .allowsTightening(true) + let (image, color) = userKeyStatus + IconAndText(systemName: image, + imageColor: color, + text: node.user?.longName ?? "unknown".localized, + textColor: .primary) if node.favorite { Spacer() Image(systemName: "star.fill") @@ -54,149 +73,84 @@ struct NodeListItem: View { } } if connected { - HStack { - Image(systemName: "antenna.radiowaves.left.and.right.circle.fill") - .font(.callout) - .symbolRenderingMode(.hierarchical) - .foregroundColor(.green) - .frame(width: 30) - Text("connected") - .font(UIDevice.current.userInterfaceIdiom == .phone ? .callout : .caption) - .foregroundColor(.gray) - } + IconAndText(systemName: "antenna.radiowaves.left.and.right.circle.fill", + imageColor: .green, + text: "connected".localized) } - HStack { - Image(systemName: node.isOnline ? "checkmark.circle.fill" : "moon.circle.fill") - .font(.callout) - .symbolRenderingMode(.hierarchical) - .foregroundColor(node.isOnline ? .green : .orange) - .frame(width: 30) - LastHeardText(lastHeard: node.lastHeard) - .font(UIDevice.current.userInterfaceIdiom == .phone ? .callout : .caption) - .foregroundColor(.gray) - } - HStack { - let role = DeviceRoles(rawValue: Int(node.user?.role ?? 0)) - Image(systemName: role?.systemName ?? "figure") - .font(.callout) - .symbolRenderingMode(.hierarchical) - .frame(width: 30) - Text("Role: \(role?.name ?? "unknown".localized)") - .font(UIDevice.current.userInterfaceIdiom == .phone ? .callout : .caption) - .foregroundColor(.gray) - + if node.lastHeard?.timeIntervalSince1970 ?? 0 > 0 { + IconAndText(systemName: node.isOnline ? "checkmark.circle.fill" : "moon.circle.fill", + imageColor: node.isOnline ? .green : .orange, + text: node.lastHeard?.formatted() ?? "unknown") } + let role = DeviceRoles(rawValue: Int(node.user?.role ?? 0)) + IconAndText(systemName: role?.systemName ?? "figure", + text: "Role: \(role?.name ?? "unknown".localized)") if node.isStoreForwardRouter { - HStack { - Image(systemName: "envelope.arrow.triangle.branch") - .font(.callout) - .symbolRenderingMode(.multicolor) - .frame(width: 30) - Text("storeforward".localized) - .font(UIDevice.current.userInterfaceIdiom == .phone ? .callout : .caption) - .foregroundColor(.secondary) - } + IconAndText(systemName: "envelope.arrow.triangle.branch", + renderingMode: .multicolor, + text: "Store & Forward".localized) } if node.positions?.count ?? 0 > 0 && connectedNode != node.num { HStack { - if let lastPostion = node.positions?.lastObject as? PositionEntity { - if let currentLocation = LocationsHandler.shared.locationsArray.last { - let myCoord = CLLocation(latitude: currentLocation.coordinate.latitude, longitude: currentLocation.coordinate.longitude) - if lastPostion.nodeCoordinate != nil && myCoord.coordinate.longitude != LocationsHandler.DefaultLocation.longitude && myCoord.coordinate.latitude != LocationsHandler.DefaultLocation.latitude { - let nodeCoord = CLLocation(latitude: lastPostion.nodeCoordinate!.latitude, longitude: lastPostion.nodeCoordinate!.longitude) - let metersAway = nodeCoord.distance(from: myCoord) - Image(systemName: "lines.measurement.horizontal") - .font(.callout) - .symbolRenderingMode(.multicolor) - .frame(width: 30) - DistanceText(meters: metersAway) - .font(UIDevice.current.userInterfaceIdiom == .phone ? .callout : .caption) - .foregroundColor(.gray) - let trueBearing = getBearingBetweenTwoPoints(point1: myCoord, point2: nodeCoord) - let headingDegrees = Measurement(value: trueBearing, unit: UnitAngle.degrees).reciprocal() - Image(systemName: "location.north") - .font(.callout) - .symbolRenderingMode(.multicolor) - .clipShape(Circle()) - .rotationEffect(Angle(degrees: headingDegrees.value)) - let heading = Measurement(value: trueBearing, unit: UnitAngle.degrees).reciprocal() - Text("\(heading.formatted(.measurement(width: .narrow, numberFormatStyle: .number.precision(.fractionLength(0)))))") - .font(UIDevice.current.userInterfaceIdiom == .phone ? .callout : .caption) - .foregroundColor(.gray) - } - } + if let (lastPostion, myCoord) = locationData { + let nodeCoord = CLLocation(latitude: lastPostion.nodeCoordinate!.latitude, longitude: lastPostion.nodeCoordinate!.longitude) + let metersAway = nodeCoord.distance(from: myCoord) + Image(systemName: "lines.measurement.horizontal") + .font(.callout) + .symbolRenderingMode(.multicolor) + .frame(width: 30) + DistanceText(meters: metersAway) + .font(UIDevice.current.userInterfaceIdiom == .phone ? .callout : .caption) + .foregroundColor(.gray) + let trueBearing = getBearingBetweenTwoPoints(point1: myCoord, point2: nodeCoord) + let headingDegrees = Measurement(value: trueBearing, unit: UnitAngle.degrees) + Image(systemName: "location.north") + .font(.callout) + .symbolRenderingMode(.multicolor) + .clipShape(Circle()) + .rotationEffect(Angle(degrees: headingDegrees.value)) + let heading = Measurement(value: trueBearing, unit: UnitAngle.degrees) + Text("\(heading.formatted(.measurement(width: .narrow, numberFormatStyle: .number.precision(.fractionLength(0)))))") + .font(UIDevice.current.userInterfaceIdiom == .phone ? .callout : .caption) + .foregroundColor(.gray) } } } HStack { if node.channel > 0 { - HStack { - Image(systemName: "\(node.channel).circle.fill") - .font(.title2) - .frame(width: 30) - Text("Channel") - .foregroundColor(.secondary) - .font(UIDevice.current.userInterfaceIdiom == .phone ? .callout : .caption) - } + IconAndText(systemName: "\(node.channel).circle.fill", text: "Channel") } if node.viaMqtt && connectedNode != node.num { - Image(systemName: "dot.radiowaves.up.forward") - .symbolRenderingMode(.multicolor) - .font(.callout) - .frame(width: 30) - Text("MQTT") - .foregroundColor(.gray) - .font(UIDevice.current.userInterfaceIdiom == .phone ? .callout : .caption) + IconAndText(systemName: "dot.radiowaves.up.forward", + renderingMode: .multicolor, + text: "MQTT") } } if node.hasPositions || node.hasEnvironmentMetrics || node.hasDetectionSensorMetrics || node.hasTraceRoutes { HStack { - Image(systemName: "scroll") - .symbolRenderingMode(.hierarchical) - .font(.callout) - Text("Logs:") - .foregroundColor(.gray) - .font(UIDevice.current.userInterfaceIdiom == .phone ? .callout : .caption2) - .allowsTightening(true) + IconAndText(systemName: "scroll", text: "Logs:") if node.hasDeviceMetrics { - Image(systemName: "flipphone") - .symbolRenderingMode(.hierarchical) - .font(.callout) + DefaultIcon(systemName: "flipphone") } if node.hasPositions { - Image(systemName: "mappin.and.ellipse") - .symbolRenderingMode(.hierarchical) - .font(.callout) - + DefaultIcon(systemName: "mappin.and.ellipse") } if node.hasEnvironmentMetrics { - Image(systemName: "cloud.sun.rain") - .symbolRenderingMode(.hierarchical) - .font(.callout) - + DefaultIcon(systemName: "cloud.sun.rain") } if node.hasDetectionSensorMetrics { - Image(systemName: "sensor") - .symbolRenderingMode(.hierarchical) - .font(.callout) + DefaultIcon(systemName: "sensor") } if node.hasTraceRoutes { - Image(systemName: "signpost.right.and.left") - .symbolRenderingMode(.hierarchical) - .font(.callout) + DefaultIcon(systemName: "signpost.right.and.left") } } } if node.hopsAway > 0 { HStack { - Image(systemName: "hare") - .font(.callout) - .symbolRenderingMode(.multicolor) - Text("Hops Away:") - .foregroundColor(.secondary) - .font(UIDevice.current.userInterfaceIdiom == .phone ? .callout : .caption) + IconAndText(systemName: "hare", text: "Hops Away:") Image(systemName: "\(node.hopsAway).square") .font(.title2) } @@ -215,3 +169,60 @@ struct NodeListItem: View { .padding(.bottom, 4) } } + +struct DefaultIcon: View { + let systemName: String + + var body: some View { + Image(systemName: systemName) + .symbolRenderingMode(.hierarchical) + .font(.callout) + } +} + +struct IconAndText: View { + let systemName: String + var imageColor: Color? + var renderingMode: SymbolRenderingMode = .hierarchical + let text: String + var textColor: Color = .gray + + @ViewBuilder + var image: some View { + if let color = imageColor { + Image(systemName: systemName) + .foregroundColor(color) + } else { + Image(systemName: systemName) + } + } + + var body: some View { + HStack { + image + .font(.callout) + .symbolRenderingMode(renderingMode) + .frame(width: 30) + Text(text) + .font(UIDevice.current.userInterfaceIdiom == .phone ? .callout : .caption) + .foregroundColor(textColor) + .allowsTightening(true) + } + } +} + +#Preview { + VStack(alignment: .leading) { + IconAndText(systemName: "antenna.radiowaves.left.and.right.circle.fill", text: "foo") + IconAndText(systemName: "antenna.radiowaves.left.and.right.circle", text: "bar") + NodeListItem(node: { + let context = PersistenceController.preview.container.viewContext + let nodeInfo = NodeInfoEntity(context: context) + let user = UserEntity(context: context) + user.longName = "Test User" + user.shortName = "TU" + nodeInfo.user = user + return nodeInfo + }(), connected: true, connectedNode: 0, modemPreset: .longFast) + } +} diff --git a/Meshtastic/Views/Nodes/NodeList.swift b/Meshtastic/Views/Nodes/NodeList.swift index 32e01bb2..12c76cd2 100644 --- a/Meshtastic/Views/Nodes/NodeList.swift +++ b/Meshtastic/Views/Nodes/NodeList.swift @@ -93,7 +93,7 @@ struct NodeList: View { ) /// Don't show message, trace route, position exchange or delete context menu items for the connected node if connectedNode.num != node.num { - if (!node.viaMqtt || node.viaMqtt && node.hopsAway == 0) { + if !node.viaMqtt || node.viaMqtt && node.hopsAway == 0 { Button(action: { if let url = URL(string: "meshtastic:///messages?userNum=\(node.num)") { UIApplication.shared.open(url) @@ -200,7 +200,6 @@ struct NodeList: View { .controlSize(.regular) .padding(5) } - .padding(.bottom, 5) .searchable(text: $searchText, placement: .automatic, prompt: "Find a node") .disableAutocorrection(true) .scrollDismissesKeyboard(.immediately) @@ -228,7 +227,7 @@ struct NodeList: View { Text("This could take a while, response will appear in the trace route log for the node it was sent to.") } .confirmationDialog( - "are.you.sure", + "Are you sure?", isPresented: $isPresentingDeleteNodeAlert, titleVisibility: .visible ) { diff --git a/Meshtastic/Views/Nodes/PaxCounterLog.swift b/Meshtastic/Views/Nodes/PaxCounterLog.swift index bb03aa9b..6be95332 100644 --- a/Meshtastic/Views/Nodes/PaxCounterLog.swift +++ b/Meshtastic/Views/Nodes/PaxCounterLog.swift @@ -104,7 +104,7 @@ struct PaxCounterLog: View { let components = (now.. 0 { @@ -82,11 +82,13 @@ struct MQTTConfig: View { } .toggleStyle(SwitchToggleStyle(tint: .accentColor)) - Toggle(isOn: $jsonEnabled) { - Label("JSON Enabled", systemImage: "ellipsis.curlybraces") - Text("JSON mode is a limited, unencrypted MQTT output for locally integrating with home assistant") + if !proxyToClientEnabled { + Toggle(isOn: $jsonEnabled) { + Label("JSON Enabled", systemImage: "ellipsis.curlybraces") + Text("JSON mode is a limited, unencrypted MQTT output for locally integrating with home assistant") + } + .toggleStyle(SwitchToggleStyle(tint: .accentColor)) } - .toggleStyle(SwitchToggleStyle(tint: .accentColor)) } Section(header: Text("Map Report")) { @@ -194,6 +196,7 @@ struct MQTTConfig: View { } .keyboardType(.default) .scrollDismissesKeyboard(.interactively) + HStack { Label("password", systemImage: "wallet.pass") TextField("password", text: $password) @@ -214,11 +217,13 @@ struct MQTTConfig: View { .keyboardType(.default) .scrollDismissesKeyboard(.interactively) .listRowSeparator(/*@START_MENU_TOKEN@*/.visible/*@END_MENU_TOKEN@*/) - Toggle(isOn: $tlsEnabled) { - Label("TLS Enabled", systemImage: "checkmark.shield.fill") - Text("Your MQTT Server must support TLS.") + if !proxyToClientEnabled { + Toggle(isOn: $tlsEnabled) { + Label("TLS Enabled", systemImage: "checkmark.shield.fill") + Text("Your MQTT Server must support TLS.") + } + .toggleStyle(SwitchToggleStyle(tint: .accentColor)) } - .toggleStyle(SwitchToggleStyle(tint: .accentColor)) } } Text("For all Mqtt functionality other than the map report you must also set uplink and downlink for each channel you want to bridge over Mqtt.") @@ -269,10 +274,11 @@ struct MQTTConfig: View { .onChange(of: proxyToClientEnabled) { _, newProxyToClientEnabled in if newProxyToClientEnabled { jsonEnabled = false + tlsEnabled = false } if newProxyToClientEnabled != node?.mqttConfig?.proxyToClientEnabled { hasChanges = true } } - .onChange(of: address) { _, newAddress in + .onChange(of: address) { newAddress in if newAddress != node?.mqttConfig?.address ?? "" { hasChanges = true } } .onChange(of: username) { newUsername in @@ -281,7 +287,7 @@ struct MQTTConfig: View { .onChange(of: password) { newPassword in if newPassword != node?.mqttConfig?.password ?? "" { hasChanges = true } } - .onChange(of: root) { newRoot in + .onChange(of: root) { _, newRoot in if newRoot != node?.mqttConfig?.root ?? "" { hasChanges = true } } .onChange(of: selectedTopic) { _, newSelectedTopic in diff --git a/Meshtastic/Views/Settings/Config/Module/StoreForwardConfig.swift b/Meshtastic/Views/Settings/Config/Module/StoreForwardConfig.swift index 9c247acf..f0718ac2 100644 --- a/Meshtastic/Views/Settings/Config/Module/StoreForwardConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/StoreForwardConfig.swift @@ -32,7 +32,7 @@ struct StoreForwardConfig: View { var body: some View { VStack { Form { - ConfigHeader(title: "storeforward", config: \.storeForwardConfig, node: node, onAppear: setStoreAndForwardValues) + ConfigHeader(title: "Store & Forward", config: \.storeForwardConfig, node: node, onAppear: setStoreAndForwardValues) Section(header: Text("options")) { @@ -136,7 +136,7 @@ struct StoreForwardConfig: View { } } } - .navigationTitle("storeforward.config") + .navigationTitle("Store & Forward Config") .navigationBarItems( trailing: ZStack { ConnectedDevice( diff --git a/Meshtastic/Views/Settings/Config/PowerConfig.swift b/Meshtastic/Views/Settings/Config/PowerConfig.swift index e9f7c0e5..abd2e30f 100644 --- a/Meshtastic/Views/Settings/Config/PowerConfig.swift +++ b/Meshtastic/Views/Settings/Config/PowerConfig.swift @@ -112,7 +112,7 @@ struct PowerConfig: View { .toolbar { ToolbarItemGroup(placement: .keyboard) { Spacer() - Button("dismiss.keyboard") { + Button("Dismiss") { isFocused = false } .font(.subheadline) diff --git a/Meshtastic/Views/Settings/Config/SaveConfigButton.swift b/Meshtastic/Views/Settings/Config/SaveConfigButton.swift index 6d200b2d..3b185129 100644 --- a/Meshtastic/Views/Settings/Config/SaveConfigButton.swift +++ b/Meshtastic/Views/Settings/Config/SaveConfigButton.swift @@ -20,7 +20,7 @@ struct SaveConfigButton: View { .controlSize(.large) .padding() .confirmationDialog( - "are.you.sure", + "Are you sure?", isPresented: $isPresentingSaveConfirm, titleVisibility: .visible ) { diff --git a/Meshtastic/Views/Settings/GPSStatus.swift b/Meshtastic/Views/Settings/GPSStatus.swift index 7e0a6588..c92a647c 100644 --- a/Meshtastic/Views/Settings/GPSStatus.swift +++ b/Meshtastic/Views/Settings/GPSStatus.swift @@ -22,7 +22,7 @@ struct GPSStatus: View { let altitiude = Measurement(value: newLocation.altitude, unit: UnitLength.meters) let speed = Measurement(value: newLocation.speed, unit: UnitSpeed.kilometersPerHour) let speedAccuracy = Measurement(value: newLocation.speedAccuracy, unit: UnitSpeed.metersPerSecond) - let courseAccuracy = Measurement(value: newLocation.courseAccuracy, unit: UnitAngle.degrees).reciprocal() + let courseAccuracy = Measurement(value: newLocation.courseAccuracy, unit: UnitAngle.degrees) Label("Coordinate \(String(format: "%.5f", newLocation.coordinate.latitude)), \(String(format: "%.5f", newLocation.coordinate.longitude))", systemImage: "mappin") .font(largeFont) @@ -45,7 +45,7 @@ struct GPSStatus: View { HStack { let degrees = Angle.degrees(newLocation.course) Label { - let heading = Measurement(value: degrees.degrees, unit: UnitAngle.degrees).reciprocal() + let heading = Measurement(value: degrees.degrees, unit: UnitAngle.degrees) Text("Heading: \(heading.formatted(.measurement(width: .narrow, numberFormatStyle: .number.precision(.fractionLength(0)))))") } icon: { Image(systemName: "location.north") diff --git a/Meshtastic/Views/Settings/RouteRecorder.swift b/Meshtastic/Views/Settings/RouteRecorder.swift index 82e7bb32..9a5b90c5 100644 --- a/Meshtastic/Views/Settings/RouteRecorder.swift +++ b/Meshtastic/Views/Settings/RouteRecorder.swift @@ -153,7 +153,7 @@ struct RouteRecorder: View { .symbolRenderingMode(.multicolor) .font(.title3) .foregroundColor(.accentColor) - Text("activity") + Text("Activity") Picker(selection: $activity, label: Text("Activity")) { ForEach(ActivityType.allCases) { r in Text(r.description) diff --git a/Meshtastic/Views/Settings/Routes.swift b/Meshtastic/Views/Settings/Routes.swift index 74f9ac72..91638ab6 100644 --- a/Meshtastic/Views/Settings/Routes.swift +++ b/Meshtastic/Views/Settings/Routes.swift @@ -208,7 +208,7 @@ struct Routes: View { } HStack { - Button("cancel", role: .cancel) { + Button("Cancel", role: .cancel) { selectedRoute = nil } .buttonStyle(.bordered) diff --git a/Meshtastic/Views/Settings/SaveChannelQRCode.swift b/Meshtastic/Views/Settings/SaveChannelQRCode.swift index ac8138fa..0e8e13f1 100644 --- a/Meshtastic/Views/Settings/SaveChannelQRCode.swift +++ b/Meshtastic/Views/Settings/SaveChannelQRCode.swift @@ -54,7 +54,7 @@ struct SaveChannelQRCode: View { Button { dismiss() } label: { - Label("cancel", systemImage: "xmark") + Label("Cancel", systemImage: "xmark") } .buttonStyle(.bordered) @@ -66,7 +66,7 @@ struct SaveChannelQRCode: View { Button { dismiss() } label: { - Label("cancel", systemImage: "xmark") + Label("Cancel", systemImage: "xmark") } .buttonStyle(.bordered) diff --git a/Meshtastic/Views/Settings/Settings.swift b/Meshtastic/Views/Settings/Settings.swift index ab8c97b3..36809f17 100644 --- a/Meshtastic/Views/Settings/Settings.swift +++ b/Meshtastic/Views/Settings/Settings.swift @@ -104,7 +104,7 @@ struct Settings: View { NavigationLink(value: SettingsNavigationState.bluetooth) { Label { - Text("bluetooth") + Text("Bluetooth") } icon: { Image(systemName: "antenna.radiowaves.left.and.right") } @@ -120,7 +120,7 @@ struct Settings: View { NavigationLink(value: SettingsNavigationState.display) { Label { - Text("display") + Text("Display") } icon: { Image(systemName: "display") } @@ -156,7 +156,7 @@ struct Settings: View { Section("module.configuration") { NavigationLink(value: SettingsNavigationState.ambientLighting) { Label { - Text("ambient.lighting") + Text("Ambient Lighting") } icon: { Image(systemName: "light.max") } @@ -164,7 +164,7 @@ struct Settings: View { NavigationLink(value: SettingsNavigationState.cannedMessages) { Label { - Text("canned.messages") + Text("Canned Messages") } icon: { Image(systemName: "list.bullet.rectangle.fill") } @@ -231,7 +231,7 @@ struct Settings: View { NavigationLink(value: SettingsNavigationState.storeAndForward) { Label { - Text("storeforward") + Text("Store & Forward") } icon: { Image(systemName: "envelope.arrow.triangle.branch") } @@ -306,7 +306,7 @@ struct Settings: View { List { NavigationLink(value: SettingsNavigationState.about) { Label { - Text("about.meshtastic") + Text("About Meshtastic") } icon: { Image(systemName: "questionmark.app") } @@ -314,14 +314,14 @@ struct Settings: View { NavigationLink(value: SettingsNavigationState.appSettings) { Label { - Text("appsettings") + Text("App Settings") } icon: { Image(systemName: "gearshape") } } NavigationLink(value: SettingsNavigationState.routes) { Label { - Text("routes") + Text("Routes") } icon: { Image(systemName: "road.lanes.curved.right") } @@ -329,7 +329,7 @@ struct Settings: View { NavigationLink(value: SettingsNavigationState.routeRecorder) { Label { - Text("route.recorder") + Text("Route Recorder") } icon: { Image(systemName: "record.circle") .foregroundColor(.red) diff --git a/Meshtastic/Views/Settings/ShareChannels.swift b/Meshtastic/Views/Settings/ShareChannels.swift index 1e10c571..7ea643ae 100644 --- a/Meshtastic/Views/Settings/ShareChannels.swift +++ b/Meshtastic/Views/Settings/ShareChannels.swift @@ -66,7 +66,7 @@ struct ShareChannels: View { .font(.caption) .fontWeight(.bold) .padding(.trailing) - Text("channel") + Text("Channel") .font(.caption) .fontWeight(.bold) .padding(.trailing) diff --git a/Meshtastic/Views/Settings/UserConfig.swift b/Meshtastic/Views/Settings/UserConfig.swift index daacb849..5b388ca7 100644 --- a/Meshtastic/Views/Settings/UserConfig.swift +++ b/Meshtastic/Views/Settings/UserConfig.swift @@ -109,7 +109,7 @@ struct UserConfig: View { TextField("Frequency Override", value: $overrideFrequency, formatter: floatFormatter) .toolbar { ToolbarItemGroup(placement: .keyboard) { - Button("dismiss.keyboard") { + Button("Dismiss") { focusedField = nil } .font(.subheadline) @@ -142,7 +142,7 @@ struct UserConfig: View { .controlSize(.large) .padding() .confirmationDialog( - "are.you.sure", + "Are you sure?", isPresented: $isPresentingSaveConfirm, titleVisibility: .visible ) { diff --git a/MeshtasticProtobufs/Sources/meshtastic/admin.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/admin.pb.swift index 15510b87..1f51447d 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/admin.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/admin.pb.swift @@ -1,6 +1,5 @@ // DO NOT EDIT. // swift-format-ignore-file -// swiftlint:disable all // // Generated by the Swift generator plugin for the protocol buffer compiler. // Source: meshtastic/admin.proto @@ -25,7 +24,7 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP /// This message is handled by the Admin module and is responsible for all settings/channel read/write operations. /// This message is used to do settings operations to both remote AND local nodes. /// (Prior to 1.2 these operations were done via special ToRadio operations) -public struct AdminMessage: @unchecked Sendable { +public struct AdminMessage { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -534,7 +533,7 @@ public struct AdminMessage: @unchecked Sendable { /// /// TODO: REPLACE - public enum OneOf_PayloadVariant: Equatable, Sendable { + public enum OneOf_PayloadVariant: Equatable { /// /// Send the specified channel in the response to this message /// NOTE: This field is sent with the channel index + 1 (to ensure we never try to send 'zero' - which protobufs treats as not present) @@ -690,11 +689,213 @@ public struct AdminMessage: @unchecked Sendable { /// Tell the node to reset the nodedb. case nodedbReset(Int32) + #if !swift(>=4.1) + public static func ==(lhs: AdminMessage.OneOf_PayloadVariant, rhs: AdminMessage.OneOf_PayloadVariant) -> Bool { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch (lhs, rhs) { + case (.getChannelRequest, .getChannelRequest): return { + guard case .getChannelRequest(let l) = lhs, case .getChannelRequest(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.getChannelResponse, .getChannelResponse): return { + guard case .getChannelResponse(let l) = lhs, case .getChannelResponse(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.getOwnerRequest, .getOwnerRequest): return { + guard case .getOwnerRequest(let l) = lhs, case .getOwnerRequest(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.getOwnerResponse, .getOwnerResponse): return { + guard case .getOwnerResponse(let l) = lhs, case .getOwnerResponse(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.getConfigRequest, .getConfigRequest): return { + guard case .getConfigRequest(let l) = lhs, case .getConfigRequest(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.getConfigResponse, .getConfigResponse): return { + guard case .getConfigResponse(let l) = lhs, case .getConfigResponse(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.getModuleConfigRequest, .getModuleConfigRequest): return { + guard case .getModuleConfigRequest(let l) = lhs, case .getModuleConfigRequest(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.getModuleConfigResponse, .getModuleConfigResponse): return { + guard case .getModuleConfigResponse(let l) = lhs, case .getModuleConfigResponse(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.getCannedMessageModuleMessagesRequest, .getCannedMessageModuleMessagesRequest): return { + guard case .getCannedMessageModuleMessagesRequest(let l) = lhs, case .getCannedMessageModuleMessagesRequest(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.getCannedMessageModuleMessagesResponse, .getCannedMessageModuleMessagesResponse): return { + guard case .getCannedMessageModuleMessagesResponse(let l) = lhs, case .getCannedMessageModuleMessagesResponse(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.getDeviceMetadataRequest, .getDeviceMetadataRequest): return { + guard case .getDeviceMetadataRequest(let l) = lhs, case .getDeviceMetadataRequest(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.getDeviceMetadataResponse, .getDeviceMetadataResponse): return { + guard case .getDeviceMetadataResponse(let l) = lhs, case .getDeviceMetadataResponse(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.getRingtoneRequest, .getRingtoneRequest): return { + guard case .getRingtoneRequest(let l) = lhs, case .getRingtoneRequest(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.getRingtoneResponse, .getRingtoneResponse): return { + guard case .getRingtoneResponse(let l) = lhs, case .getRingtoneResponse(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.getDeviceConnectionStatusRequest, .getDeviceConnectionStatusRequest): return { + guard case .getDeviceConnectionStatusRequest(let l) = lhs, case .getDeviceConnectionStatusRequest(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.getDeviceConnectionStatusResponse, .getDeviceConnectionStatusResponse): return { + guard case .getDeviceConnectionStatusResponse(let l) = lhs, case .getDeviceConnectionStatusResponse(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.setHamMode, .setHamMode): return { + guard case .setHamMode(let l) = lhs, case .setHamMode(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.getNodeRemoteHardwarePinsRequest, .getNodeRemoteHardwarePinsRequest): return { + guard case .getNodeRemoteHardwarePinsRequest(let l) = lhs, case .getNodeRemoteHardwarePinsRequest(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.getNodeRemoteHardwarePinsResponse, .getNodeRemoteHardwarePinsResponse): return { + guard case .getNodeRemoteHardwarePinsResponse(let l) = lhs, case .getNodeRemoteHardwarePinsResponse(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.enterDfuModeRequest, .enterDfuModeRequest): return { + guard case .enterDfuModeRequest(let l) = lhs, case .enterDfuModeRequest(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.deleteFileRequest, .deleteFileRequest): return { + guard case .deleteFileRequest(let l) = lhs, case .deleteFileRequest(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.setScale, .setScale): return { + guard case .setScale(let l) = lhs, case .setScale(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.setOwner, .setOwner): return { + guard case .setOwner(let l) = lhs, case .setOwner(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.setChannel, .setChannel): return { + guard case .setChannel(let l) = lhs, case .setChannel(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.setConfig, .setConfig): return { + guard case .setConfig(let l) = lhs, case .setConfig(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.setModuleConfig, .setModuleConfig): return { + guard case .setModuleConfig(let l) = lhs, case .setModuleConfig(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.setCannedMessageModuleMessages, .setCannedMessageModuleMessages): return { + guard case .setCannedMessageModuleMessages(let l) = lhs, case .setCannedMessageModuleMessages(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.setRingtoneMessage, .setRingtoneMessage): return { + guard case .setRingtoneMessage(let l) = lhs, case .setRingtoneMessage(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.removeByNodenum, .removeByNodenum): return { + guard case .removeByNodenum(let l) = lhs, case .removeByNodenum(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.setFavoriteNode, .setFavoriteNode): return { + guard case .setFavoriteNode(let l) = lhs, case .setFavoriteNode(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.removeFavoriteNode, .removeFavoriteNode): return { + guard case .removeFavoriteNode(let l) = lhs, case .removeFavoriteNode(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.setFixedPosition, .setFixedPosition): return { + guard case .setFixedPosition(let l) = lhs, case .setFixedPosition(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.removeFixedPosition, .removeFixedPosition): return { + guard case .removeFixedPosition(let l) = lhs, case .removeFixedPosition(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.setTimeOnly, .setTimeOnly): return { + guard case .setTimeOnly(let l) = lhs, case .setTimeOnly(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.getUiConfigRequest, .getUiConfigRequest): return { + guard case .getUiConfigRequest(let l) = lhs, case .getUiConfigRequest(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.getUiConfigResponse, .getUiConfigResponse): return { + guard case .getUiConfigResponse(let l) = lhs, case .getUiConfigResponse(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.storeUiConfig, .storeUiConfig): return { + guard case .storeUiConfig(let l) = lhs, case .storeUiConfig(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.setIgnoredNode, .setIgnoredNode): return { + guard case .setIgnoredNode(let l) = lhs, case .setIgnoredNode(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.removeIgnoredNode, .removeIgnoredNode): return { + guard case .removeIgnoredNode(let l) = lhs, case .removeIgnoredNode(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.beginEditSettings, .beginEditSettings): return { + guard case .beginEditSettings(let l) = lhs, case .beginEditSettings(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.commitEditSettings, .commitEditSettings): return { + guard case .commitEditSettings(let l) = lhs, case .commitEditSettings(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.factoryResetDevice, .factoryResetDevice): return { + guard case .factoryResetDevice(let l) = lhs, case .factoryResetDevice(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.rebootOtaSeconds, .rebootOtaSeconds): return { + guard case .rebootOtaSeconds(let l) = lhs, case .rebootOtaSeconds(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.exitSimulator, .exitSimulator): return { + guard case .exitSimulator(let l) = lhs, case .exitSimulator(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.rebootSeconds, .rebootSeconds): return { + guard case .rebootSeconds(let l) = lhs, case .rebootSeconds(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.shutdownSeconds, .shutdownSeconds): return { + guard case .shutdownSeconds(let l) = lhs, case .shutdownSeconds(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.factoryResetConfig, .factoryResetConfig): return { + guard case .factoryResetConfig(let l) = lhs, case .factoryResetConfig(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.nodedbReset, .nodedbReset): return { + guard case .nodedbReset(let l) = lhs, case .nodedbReset(let r) = rhs else { preconditionFailure() } + return l == r + }() + default: return false + } + } + #endif } /// /// TODO: REPLACE - public enum ConfigType: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum ConfigType: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -771,25 +972,11 @@ public struct AdminMessage: @unchecked Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [AdminMessage.ConfigType] = [ - .deviceConfig, - .positionConfig, - .powerConfig, - .networkConfig, - .displayConfig, - .loraConfig, - .bluetoothConfig, - .securityConfig, - .sessionkeyConfig, - .deviceuiConfig, - ] - } /// /// TODO: REPLACE - public enum ModuleConfigType: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum ModuleConfigType: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -887,31 +1074,53 @@ public struct AdminMessage: @unchecked Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [AdminMessage.ModuleConfigType] = [ - .mqttConfig, - .serialConfig, - .extnotifConfig, - .storeforwardConfig, - .rangetestConfig, - .telemetryConfig, - .cannedmsgConfig, - .audioConfig, - .remotehardwareConfig, - .neighborinfoConfig, - .ambientlightingConfig, - .detectionsensorConfig, - .paxcounterConfig, - ] - } public init() {} } +#if swift(>=4.2) + +extension AdminMessage.ConfigType: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [AdminMessage.ConfigType] = [ + .deviceConfig, + .positionConfig, + .powerConfig, + .networkConfig, + .displayConfig, + .loraConfig, + .bluetoothConfig, + .securityConfig, + .sessionkeyConfig, + .deviceuiConfig, + ] +} + +extension AdminMessage.ModuleConfigType: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [AdminMessage.ModuleConfigType] = [ + .mqttConfig, + .serialConfig, + .extnotifConfig, + .storeforwardConfig, + .rangetestConfig, + .telemetryConfig, + .cannedmsgConfig, + .audioConfig, + .remotehardwareConfig, + .neighborinfoConfig, + .ambientlightingConfig, + .detectionsensorConfig, + .paxcounterConfig, + ] +} + +#endif // swift(>=4.2) + /// /// Parameters for setting up Meshtastic for ameteur radio usage -public struct HamParameters: Sendable { +public struct HamParameters { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -941,7 +1150,7 @@ public struct HamParameters: Sendable { /// /// Response envelope for node_remote_hardware_pins -public struct NodeRemoteHardwarePinsResponse: Sendable { +public struct NodeRemoteHardwarePinsResponse { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -955,6 +1164,15 @@ public struct NodeRemoteHardwarePinsResponse: Sendable { public init() {} } +#if swift(>=5.5) && canImport(_Concurrency) +extension AdminMessage: @unchecked Sendable {} +extension AdminMessage.OneOf_PayloadVariant: @unchecked Sendable {} +extension AdminMessage.ConfigType: @unchecked Sendable {} +extension AdminMessage.ModuleConfigType: @unchecked Sendable {} +extension HamParameters: @unchecked Sendable {} +extension NodeRemoteHardwarePinsResponse: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + // MARK: - Code below here is support for the SwiftProtobuf runtime. fileprivate let _protobuf_package = "meshtastic" @@ -1762,7 +1980,7 @@ extension HamParameters: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementa if self.txPower != 0 { try visitor.visitSingularInt32Field(value: self.txPower, fieldNumber: 2) } - if self.frequency.bitPattern != 0 { + if self.frequency != 0 { try visitor.visitSingularFloatField(value: self.frequency, fieldNumber: 3) } if !self.shortName.isEmpty { diff --git a/MeshtasticProtobufs/Sources/meshtastic/apponly.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/apponly.pb.swift index 52dac5ca..0457077c 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/apponly.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/apponly.pb.swift @@ -1,6 +1,5 @@ // DO NOT EDIT. // swift-format-ignore-file -// swiftlint:disable all // // Generated by the Swift generator plugin for the protocol buffer compiler. // Source: meshtastic/apponly.proto @@ -8,6 +7,7 @@ // For information on using the generated types, please see the documentation: // https://github.com/apple/swift-protobuf/ +import Foundation import SwiftProtobuf // If the compiler emits an error on this type, it is because this file @@ -26,7 +26,7 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP /// any SECONDARY channels. /// No DISABLED channels are included. /// This abstraction is used only on the the 'app side' of the world (ie python, javascript and android etc) to show a group of Channels as a (long) URL -public struct ChannelSet: Sendable { +public struct ChannelSet { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -53,6 +53,10 @@ public struct ChannelSet: Sendable { fileprivate var _loraConfig: Config.LoRaConfig? = nil } +#if swift(>=5.5) && canImport(_Concurrency) +extension ChannelSet: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + // MARK: - Code below here is support for the SwiftProtobuf runtime. fileprivate let _protobuf_package = "meshtastic" diff --git a/MeshtasticProtobufs/Sources/meshtastic/atak.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/atak.pb.swift index 06d6af88..867648a9 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/atak.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/atak.pb.swift @@ -1,6 +1,5 @@ // DO NOT EDIT. // swift-format-ignore-file -// swiftlint:disable all // // Generated by the Swift generator plugin for the protocol buffer compiler. // Source: meshtastic/atak.proto @@ -21,7 +20,7 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP typealias Version = _2 } -public enum Team: SwiftProtobuf.Enum, Swift.CaseIterable { +public enum Team: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -131,6 +130,11 @@ public enum Team: SwiftProtobuf.Enum, Swift.CaseIterable { } } +} + +#if swift(>=4.2) + +extension Team: CaseIterable { // The compiler won't synthesize support with the UNRECOGNIZED case. public static let allCases: [Team] = [ .unspecifedColor, @@ -149,12 +153,13 @@ public enum Team: SwiftProtobuf.Enum, Swift.CaseIterable { .darkGreen, .brown, ] - } +#endif // swift(>=4.2) + /// /// Role of the group member -public enum MemberRole: SwiftProtobuf.Enum, Swift.CaseIterable { +public enum MemberRole: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -228,6 +233,11 @@ public enum MemberRole: SwiftProtobuf.Enum, Swift.CaseIterable { } } +} + +#if swift(>=4.2) + +extension MemberRole: CaseIterable { // The compiler won't synthesize support with the UNRECOGNIZED case. public static let allCases: [MemberRole] = [ .unspecifed, @@ -240,12 +250,13 @@ public enum MemberRole: SwiftProtobuf.Enum, Swift.CaseIterable { .rto, .k9, ] - } +#endif // swift(>=4.2) + /// /// Packets for the official ATAK Plugin -public struct TAKPacket: @unchecked Sendable { +public struct TAKPacket { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -326,7 +337,7 @@ public struct TAKPacket: @unchecked Sendable { /// /// The payload of the packet - public enum OneOf_PayloadVariant: Equatable, @unchecked Sendable { + public enum OneOf_PayloadVariant: Equatable { /// /// TAK position report case pli(PLI) @@ -338,6 +349,28 @@ public struct TAKPacket: @unchecked Sendable { /// May be compressed / truncated by the sender (EUD) case detail(Data) + #if !swift(>=4.1) + public static func ==(lhs: TAKPacket.OneOf_PayloadVariant, rhs: TAKPacket.OneOf_PayloadVariant) -> Bool { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch (lhs, rhs) { + case (.pli, .pli): return { + guard case .pli(let l) = lhs, case .pli(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.chat, .chat): return { + guard case .chat(let l) = lhs, case .chat(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.detail, .detail): return { + guard case .detail(let l) = lhs, case .detail(let r) = rhs else { preconditionFailure() } + return l == r + }() + default: return false + } + } + #endif } public init() {} @@ -349,7 +382,7 @@ public struct TAKPacket: @unchecked Sendable { /// /// ATAK GeoChat message -public struct GeoChat: Sendable { +public struct GeoChat { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -391,7 +424,7 @@ public struct GeoChat: Sendable { /// /// ATAK Group /// <__group role='Team Member' name='Cyan'/> -public struct Group: Sendable { +public struct Group { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -413,7 +446,7 @@ public struct Group: Sendable { /// /// ATAK EUD Status /// -public struct Status: Sendable { +public struct Status { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -430,7 +463,7 @@ public struct Status: Sendable { /// /// ATAK Contact /// -public struct Contact: Sendable { +public struct Contact { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -450,7 +483,7 @@ public struct Contact: Sendable { /// /// Position Location Information from ATAK -public struct PLI: Sendable { +public struct PLI { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -482,6 +515,18 @@ public struct PLI: Sendable { public init() {} } +#if swift(>=5.5) && canImport(_Concurrency) +extension Team: @unchecked Sendable {} +extension MemberRole: @unchecked Sendable {} +extension TAKPacket: @unchecked Sendable {} +extension TAKPacket.OneOf_PayloadVariant: @unchecked Sendable {} +extension GeoChat: @unchecked Sendable {} +extension Group: @unchecked Sendable {} +extension Status: @unchecked Sendable {} +extension Contact: @unchecked Sendable {} +extension PLI: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + // MARK: - Code below here is support for the SwiftProtobuf runtime. fileprivate let _protobuf_package = "meshtastic" diff --git a/MeshtasticProtobufs/Sources/meshtastic/cannedmessages.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/cannedmessages.pb.swift index ce1f0503..1b8c84de 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/cannedmessages.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/cannedmessages.pb.swift @@ -1,6 +1,5 @@ // DO NOT EDIT. // swift-format-ignore-file -// swiftlint:disable all // // Generated by the Swift generator plugin for the protocol buffer compiler. // Source: meshtastic/cannedmessages.proto @@ -8,6 +7,7 @@ // For information on using the generated types, please see the documentation: // https://github.com/apple/swift-protobuf/ +import Foundation import SwiftProtobuf // If the compiler emits an error on this type, it is because this file @@ -22,7 +22,7 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP /// /// Canned message module configuration. -public struct CannedMessageModuleConfig: Sendable { +public struct CannedMessageModuleConfig { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -36,6 +36,10 @@ public struct CannedMessageModuleConfig: Sendable { public init() {} } +#if swift(>=5.5) && canImport(_Concurrency) +extension CannedMessageModuleConfig: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + // MARK: - Code below here is support for the SwiftProtobuf runtime. fileprivate let _protobuf_package = "meshtastic" diff --git a/MeshtasticProtobufs/Sources/meshtastic/channel.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/channel.pb.swift index 180cd698..5b9c7e49 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/channel.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/channel.pb.swift @@ -1,6 +1,5 @@ // DO NOT EDIT. // swift-format-ignore-file -// swiftlint:disable all // // Generated by the Swift generator plugin for the protocol buffer compiler. // Source: meshtastic/channel.proto @@ -37,15 +36,13 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP /// FIXME: Add description of multi-channel support and how primary vs secondary channels are used. /// FIXME: explain how apps use channels for security. /// explain how remote settings and remote gpio are managed as an example -public struct ChannelSettings: @unchecked Sendable { +public struct ChannelSettings { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. /// /// Deprecated in favor of LoraConfig.channel_num - /// - /// NOTE: This field was marked as deprecated in the .proto file. public var channelNum: UInt32 = 0 /// @@ -114,7 +111,7 @@ public struct ChannelSettings: @unchecked Sendable { /// /// This message is specifically for modules to store per-channel configuration data. -public struct ModuleSettings: Sendable { +public struct ModuleSettings { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -135,7 +132,7 @@ public struct ModuleSettings: Sendable { /// /// A pair of a channel number, mode and the (sharable) settings for that channel -public struct Channel: Sendable { +public struct Channel { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -173,7 +170,7 @@ public struct Channel: Sendable { /// cross band routing as needed. /// If a device has only a single radio (the common case) only one channel can be PRIMARY at a time /// (but any number of SECONDARY channels can't be sent received on that common frequency) - public enum Role: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum Role: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -212,13 +209,6 @@ public struct Channel: Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [Channel.Role] = [ - .disabled, - .primary, - .secondary, - ] - } public init() {} @@ -226,6 +216,26 @@ public struct Channel: Sendable { fileprivate var _settings: ChannelSettings? = nil } +#if swift(>=4.2) + +extension Channel.Role: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [Channel.Role] = [ + .disabled, + .primary, + .secondary, + ] +} + +#endif // swift(>=4.2) + +#if swift(>=5.5) && canImport(_Concurrency) +extension ChannelSettings: @unchecked Sendable {} +extension ModuleSettings: @unchecked Sendable {} +extension Channel: @unchecked Sendable {} +extension Channel.Role: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + // MARK: - Code below here is support for the SwiftProtobuf runtime. fileprivate let _protobuf_package = "meshtastic" diff --git a/MeshtasticProtobufs/Sources/meshtastic/clientonly.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/clientonly.pb.swift index d72c0ae1..f89a8e3c 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/clientonly.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/clientonly.pb.swift @@ -1,6 +1,5 @@ // DO NOT EDIT. // swift-format-ignore-file -// swiftlint:disable all // // Generated by the Swift generator plugin for the protocol buffer compiler. // Source: meshtastic/clientonly.proto @@ -8,6 +7,7 @@ // For information on using the generated types, please see the documentation: // https://github.com/apple/swift-protobuf/ +import Foundation import SwiftProtobuf // If the compiler emits an error on this type, it is because this file @@ -23,7 +23,7 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP /// /// This abstraction is used to contain any configuration for provisioning a node on any client. /// It is useful for importing and exporting configurations. -public struct DeviceProfile: Sendable { +public struct DeviceProfile { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -130,6 +130,10 @@ public struct DeviceProfile: Sendable { fileprivate var _cannedMessages: String? = nil } +#if swift(>=5.5) && canImport(_Concurrency) +extension DeviceProfile: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + // MARK: - Code below here is support for the SwiftProtobuf runtime. fileprivate let _protobuf_package = "meshtastic" diff --git a/MeshtasticProtobufs/Sources/meshtastic/config.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/config.pb.swift index 566b3ef1..a5f8cbc5 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/config.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/config.pb.swift @@ -1,6 +1,5 @@ // DO NOT EDIT. // swift-format-ignore-file -// swiftlint:disable all // // Generated by the Swift generator plugin for the protocol buffer compiler. // Source: meshtastic/config.proto @@ -21,7 +20,7 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP typealias Version = _2 } -public struct Config: Sendable { +public struct Config { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -114,7 +113,7 @@ public struct Config: Sendable { /// /// Payload Variant - public enum OneOf_PayloadVariant: Equatable, Sendable { + public enum OneOf_PayloadVariant: Equatable { case device(Config.DeviceConfig) case position(Config.PositionConfig) case power(Config.PowerConfig) @@ -126,11 +125,61 @@ public struct Config: Sendable { case sessionkey(Config.SessionkeyConfig) case deviceUi(DeviceUIConfig) + #if !swift(>=4.1) + public static func ==(lhs: Config.OneOf_PayloadVariant, rhs: Config.OneOf_PayloadVariant) -> Bool { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch (lhs, rhs) { + case (.device, .device): return { + guard case .device(let l) = lhs, case .device(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.position, .position): return { + guard case .position(let l) = lhs, case .position(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.power, .power): return { + guard case .power(let l) = lhs, case .power(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.network, .network): return { + guard case .network(let l) = lhs, case .network(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.display, .display): return { + guard case .display(let l) = lhs, case .display(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.lora, .lora): return { + guard case .lora(let l) = lhs, case .lora(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.bluetooth, .bluetooth): return { + guard case .bluetooth(let l) = lhs, case .bluetooth(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.security, .security): return { + guard case .security(let l) = lhs, case .security(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.sessionkey, .sessionkey): return { + guard case .sessionkey(let l) = lhs, case .sessionkey(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.deviceUi, .deviceUi): return { + guard case .deviceUi(let l) = lhs, case .deviceUi(let r) = rhs else { preconditionFailure() } + return l == r + }() + default: return false + } + } + #endif } /// /// Configuration - public struct DeviceConfig: Sendable { + public struct DeviceConfig { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -142,8 +191,6 @@ public struct Config: Sendable { /// /// Disabling this will disable the SerialConsole by not initilizing the StreamAPI /// Moved to SecurityConfig - /// - /// NOTE: This field was marked as deprecated in the .proto file. public var serialEnabled: Bool = false /// @@ -173,8 +220,6 @@ public struct Config: Sendable { /// If true, device is considered to be "managed" by a mesh administrator /// Clients should then limit available configuration and administrative options inside the user interface /// Moved to SecurityConfig - /// - /// NOTE: This field was marked as deprecated in the .proto file. public var isManaged: Bool = false /// @@ -193,7 +238,7 @@ public struct Config: Sendable { /// /// Defines the device's role on the Mesh network - public enum Role: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum Role: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -211,8 +256,6 @@ public struct Config: Sendable { /// The wifi radio and the oled screen will be put to sleep. /// This mode may still potentially have higher power usage due to it's preference in message rebroadcasting on the mesh. case router // = 2 - - /// NOTE: This enum value was marked as deprecated in the .proto file case routerClient // = 3 /// @@ -313,27 +356,11 @@ public struct Config: Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [Config.DeviceConfig.Role] = [ - .client, - .clientMute, - .router, - .routerClient, - .repeater, - .tracker, - .sensor, - .tak, - .clientHidden, - .lostAndFound, - .takTracker, - .routerLate, - ] - } /// /// Defines the device's behavior for how messages are rebroadcast - public enum RebroadcastMode: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum RebroadcastMode: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -394,16 +421,6 @@ public struct Config: Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [Config.DeviceConfig.RebroadcastMode] = [ - .all, - .allSkipDecoding, - .localOnly, - .knownOnly, - .none, - .corePortnumsOnly, - ] - } public init() {} @@ -411,7 +428,7 @@ public struct Config: Sendable { /// /// Position Config - public struct PositionConfig: Sendable { + public struct PositionConfig { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -433,8 +450,6 @@ public struct Config: Sendable { /// /// Is GPS enabled for this node? - /// - /// NOTE: This field was marked as deprecated in the .proto file. public var gpsEnabled: Bool = false /// @@ -445,8 +460,6 @@ public struct Config: Sendable { /// /// Deprecated in favor of using smart / regular broadcast intervals as implicit attempt time - /// - /// NOTE: This field was marked as deprecated in the .proto file. public var gpsAttemptTime: UInt32 = 0 /// @@ -487,7 +500,7 @@ public struct Config: Sendable { /// are always included (also time if GPS-synced) /// NOTE: the more fields are included, the larger the message will be - /// leading to longer airtime and a higher risk of packet loss - public enum PositionFlags: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum PositionFlags: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -577,24 +590,9 @@ public struct Config: Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [Config.PositionConfig.PositionFlags] = [ - .unset, - .altitude, - .altitudeMsl, - .geoidalSeparation, - .dop, - .hvdop, - .satinview, - .seqNo, - .timestamp, - .heading, - .speed, - ] - } - public enum GpsMode: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum GpsMode: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -632,13 +630,6 @@ public struct Config: Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [Config.PositionConfig.GpsMode] = [ - .disabled, - .enabled, - .notPresent, - ] - } public init() {} @@ -647,7 +638,7 @@ public struct Config: Sendable { /// /// Power Config\ /// See [Power Config](/docs/settings/config/power) for additional power config details. - public struct PowerConfig: Sendable { + public struct PowerConfig { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -707,7 +698,7 @@ public struct Config: Sendable { /// /// Network Config - public struct NetworkConfig: Sendable { + public struct NetworkConfig { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -758,7 +749,7 @@ public struct Config: Sendable { public var unknownFields = SwiftProtobuf.UnknownStorage() - public enum AddressMode: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum AddressMode: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -790,17 +781,11 @@ public struct Config: Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [Config.NetworkConfig.AddressMode] = [ - .dhcp, - .static, - ] - } /// /// Available flags auxiliary network protocols - public enum ProtocolFlags: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum ProtocolFlags: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -832,15 +817,9 @@ public struct Config: Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [Config.NetworkConfig.ProtocolFlags] = [ - .noBroadcast, - .udpBroadcast, - ] - } - public struct IpV4Config: Sendable { + public struct IpV4Config { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -873,7 +852,7 @@ public struct Config: Sendable { /// /// Display Config - public struct DisplayConfig: Sendable { + public struct DisplayConfig { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -925,11 +904,16 @@ public struct Config: Sendable { /// Indicates how to rotate or invert the compass output to accurate display on the display. public var compassOrientation: Config.DisplayConfig.CompassOrientation = .degrees0 + /// + /// If false (default), the device will display the time in 24-hour format on screen. + /// If true, the device will display the time in 12-hour format on screen. + public var use12HClock: Bool = false + public var unknownFields = SwiftProtobuf.UnknownStorage() /// /// How the GPS coordinates are displayed on the OLED screen. - public enum GpsCoordinateFormat: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum GpsCoordinateFormat: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -992,21 +976,11 @@ public struct Config: Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [Config.DisplayConfig.GpsCoordinateFormat] = [ - .dec, - .dms, - .utm, - .mgrs, - .olc, - .osgr, - ] - } /// /// Unit display preference - public enum DisplayUnits: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum DisplayUnits: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -1038,17 +1012,11 @@ public struct Config: Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [Config.DisplayConfig.DisplayUnits] = [ - .metric, - .imperial, - ] - } /// /// Override OLED outo detect with this if it fails. - public enum OledType: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum OledType: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -1092,17 +1060,9 @@ public struct Config: Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [Config.DisplayConfig.OledType] = [ - .oledAuto, - .oledSsd1306, - .oledSh1106, - .oledSh1107, - ] - } - public enum DisplayMode: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum DisplayMode: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -1146,17 +1106,9 @@ public struct Config: Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [Config.DisplayConfig.DisplayMode] = [ - .default, - .twocolor, - .inverted, - .color, - ] - } - public enum CompassOrientation: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum CompassOrientation: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -1224,18 +1176,6 @@ public struct Config: Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [Config.DisplayConfig.CompassOrientation] = [ - .degrees0, - .degrees90, - .degrees180, - .degrees270, - .degrees0Inverted, - .degrees90Inverted, - .degrees180Inverted, - .degrees270Inverted, - ] - } public init() {} @@ -1243,7 +1183,7 @@ public struct Config: Sendable { /// /// Lora Config - public struct LoRaConfig: @unchecked Sendable { + public struct LoRaConfig { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -1407,7 +1347,7 @@ public struct Config: Sendable { public var unknownFields = SwiftProtobuf.UnknownStorage() - public enum RegionCode: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum RegionCode: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -1559,38 +1499,12 @@ public struct Config: Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [Config.LoRaConfig.RegionCode] = [ - .unset, - .us, - .eu433, - .eu868, - .cn, - .jp, - .anz, - .kr, - .tw, - .ru, - .in, - .nz865, - .th, - .lora24, - .ua433, - .ua868, - .my433, - .my919, - .sg923, - .ph433, - .ph868, - .ph915, - ] - } /// /// Standard predefined channel settings /// Note: these mappings must match ModemPreset Choice in the device code. - public enum ModemPreset: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum ModemPreset: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -1604,8 +1518,6 @@ public struct Config: Sendable { /// /// Very Long Range - Slow /// Deprecated in 2.5: Works only with txco and is unusably slow - /// - /// NOTE: This enum value was marked as deprecated in the .proto file case veryLongSlow // = 2 /// @@ -1669,19 +1581,6 @@ public struct Config: Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [Config.LoRaConfig.ModemPreset] = [ - .longFast, - .longSlow, - .veryLongSlow, - .mediumSlow, - .mediumFast, - .shortSlow, - .shortFast, - .longModerate, - .shortTurbo, - ] - } public init() {} @@ -1689,7 +1588,7 @@ public struct Config: Sendable { fileprivate var _storage = _StorageClass.defaultInstance } - public struct BluetoothConfig: Sendable { + public struct BluetoothConfig { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -1708,7 +1607,7 @@ public struct Config: Sendable { public var unknownFields = SwiftProtobuf.UnknownStorage() - public enum PairingMode: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum PairingMode: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -1746,19 +1645,12 @@ public struct Config: Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [Config.BluetoothConfig.PairingMode] = [ - .randomPin, - .fixedPin, - .noPin, - ] - } public init() {} } - public struct SecurityConfig: @unchecked Sendable { + public struct SecurityConfig { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -1802,7 +1694,7 @@ public struct Config: Sendable { /// /// Blank config request, strictly for getting the session key - public struct SessionkeyConfig: Sendable { + public struct SessionkeyConfig { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -1815,6 +1707,217 @@ public struct Config: Sendable { public init() {} } +#if swift(>=4.2) + +extension Config.DeviceConfig.Role: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [Config.DeviceConfig.Role] = [ + .client, + .clientMute, + .router, + .routerClient, + .repeater, + .tracker, + .sensor, + .tak, + .clientHidden, + .lostAndFound, + .takTracker, + .routerLate, + ] +} + +extension Config.DeviceConfig.RebroadcastMode: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [Config.DeviceConfig.RebroadcastMode] = [ + .all, + .allSkipDecoding, + .localOnly, + .knownOnly, + .none, + .corePortnumsOnly, + ] +} + +extension Config.PositionConfig.PositionFlags: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [Config.PositionConfig.PositionFlags] = [ + .unset, + .altitude, + .altitudeMsl, + .geoidalSeparation, + .dop, + .hvdop, + .satinview, + .seqNo, + .timestamp, + .heading, + .speed, + ] +} + +extension Config.PositionConfig.GpsMode: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [Config.PositionConfig.GpsMode] = [ + .disabled, + .enabled, + .notPresent, + ] +} + +extension Config.NetworkConfig.AddressMode: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [Config.NetworkConfig.AddressMode] = [ + .dhcp, + .static, + ] +} + +extension Config.NetworkConfig.ProtocolFlags: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [Config.NetworkConfig.ProtocolFlags] = [ + .noBroadcast, + .udpBroadcast, + ] +} + +extension Config.DisplayConfig.GpsCoordinateFormat: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [Config.DisplayConfig.GpsCoordinateFormat] = [ + .dec, + .dms, + .utm, + .mgrs, + .olc, + .osgr, + ] +} + +extension Config.DisplayConfig.DisplayUnits: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [Config.DisplayConfig.DisplayUnits] = [ + .metric, + .imperial, + ] +} + +extension Config.DisplayConfig.OledType: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [Config.DisplayConfig.OledType] = [ + .oledAuto, + .oledSsd1306, + .oledSh1106, + .oledSh1107, + ] +} + +extension Config.DisplayConfig.DisplayMode: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [Config.DisplayConfig.DisplayMode] = [ + .default, + .twocolor, + .inverted, + .color, + ] +} + +extension Config.DisplayConfig.CompassOrientation: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [Config.DisplayConfig.CompassOrientation] = [ + .degrees0, + .degrees90, + .degrees180, + .degrees270, + .degrees0Inverted, + .degrees90Inverted, + .degrees180Inverted, + .degrees270Inverted, + ] +} + +extension Config.LoRaConfig.RegionCode: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [Config.LoRaConfig.RegionCode] = [ + .unset, + .us, + .eu433, + .eu868, + .cn, + .jp, + .anz, + .kr, + .tw, + .ru, + .in, + .nz865, + .th, + .lora24, + .ua433, + .ua868, + .my433, + .my919, + .sg923, + .ph433, + .ph868, + .ph915, + ] +} + +extension Config.LoRaConfig.ModemPreset: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [Config.LoRaConfig.ModemPreset] = [ + .longFast, + .longSlow, + .veryLongSlow, + .mediumSlow, + .mediumFast, + .shortSlow, + .shortFast, + .longModerate, + .shortTurbo, + ] +} + +extension Config.BluetoothConfig.PairingMode: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [Config.BluetoothConfig.PairingMode] = [ + .randomPin, + .fixedPin, + .noPin, + ] +} + +#endif // swift(>=4.2) + +#if swift(>=5.5) && canImport(_Concurrency) +extension Config: @unchecked Sendable {} +extension Config.OneOf_PayloadVariant: @unchecked Sendable {} +extension Config.DeviceConfig: @unchecked Sendable {} +extension Config.DeviceConfig.Role: @unchecked Sendable {} +extension Config.DeviceConfig.RebroadcastMode: @unchecked Sendable {} +extension Config.PositionConfig: @unchecked Sendable {} +extension Config.PositionConfig.PositionFlags: @unchecked Sendable {} +extension Config.PositionConfig.GpsMode: @unchecked Sendable {} +extension Config.PowerConfig: @unchecked Sendable {} +extension Config.NetworkConfig: @unchecked Sendable {} +extension Config.NetworkConfig.AddressMode: @unchecked Sendable {} +extension Config.NetworkConfig.ProtocolFlags: @unchecked Sendable {} +extension Config.NetworkConfig.IpV4Config: @unchecked Sendable {} +extension Config.DisplayConfig: @unchecked Sendable {} +extension Config.DisplayConfig.GpsCoordinateFormat: @unchecked Sendable {} +extension Config.DisplayConfig.DisplayUnits: @unchecked Sendable {} +extension Config.DisplayConfig.OledType: @unchecked Sendable {} +extension Config.DisplayConfig.DisplayMode: @unchecked Sendable {} +extension Config.DisplayConfig.CompassOrientation: @unchecked Sendable {} +extension Config.LoRaConfig: @unchecked Sendable {} +extension Config.LoRaConfig.RegionCode: @unchecked Sendable {} +extension Config.LoRaConfig.ModemPreset: @unchecked Sendable {} +extension Config.BluetoothConfig: @unchecked Sendable {} +extension Config.BluetoothConfig.PairingMode: @unchecked Sendable {} +extension Config.SecurityConfig: @unchecked Sendable {} +extension Config.SessionkeyConfig: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + // MARK: - Code below here is support for the SwiftProtobuf runtime. fileprivate let _protobuf_package = "meshtastic" @@ -2322,7 +2425,7 @@ extension Config.PowerConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImple if self.onBatteryShutdownAfterSecs != 0 { try visitor.visitSingularUInt32Field(value: self.onBatteryShutdownAfterSecs, fieldNumber: 2) } - if self.adcMultiplierOverride.bitPattern != 0 { + if self.adcMultiplierOverride != 0 { try visitor.visitSingularFloatField(value: self.adcMultiplierOverride, fieldNumber: 3) } if self.waitBluetoothSecs != 0 { @@ -2523,6 +2626,7 @@ extension Config.DisplayConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImp 9: .standard(proto: "heading_bold"), 10: .standard(proto: "wake_on_tap_or_motion"), 11: .standard(proto: "compass_orientation"), + 12: .standard(proto: "use_12h_clock"), ] public mutating func decodeMessage(decoder: inout D) throws { @@ -2542,6 +2646,7 @@ extension Config.DisplayConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImp case 9: try { try decoder.decodeSingularBoolField(value: &self.headingBold) }() case 10: try { try decoder.decodeSingularBoolField(value: &self.wakeOnTapOrMotion) }() case 11: try { try decoder.decodeSingularEnumField(value: &self.compassOrientation) }() + case 12: try { try decoder.decodeSingularBoolField(value: &self.use12HClock) }() default: break } } @@ -2581,6 +2686,9 @@ extension Config.DisplayConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImp if self.compassOrientation != .degrees0 { try visitor.visitSingularEnumField(value: self.compassOrientation, fieldNumber: 11) } + if self.use12HClock != false { + try visitor.visitSingularBoolField(value: self.use12HClock, fieldNumber: 12) + } try unknownFields.traverse(visitor: &visitor) } @@ -2596,6 +2704,7 @@ extension Config.DisplayConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImp if lhs.headingBold != rhs.headingBold {return false} if lhs.wakeOnTapOrMotion != rhs.wakeOnTapOrMotion {return false} if lhs.compassOrientation != rhs.compassOrientation {return false} + if lhs.use12HClock != rhs.use12HClock {return false} if lhs.unknownFields != rhs.unknownFields {return false} return true } @@ -2783,7 +2892,7 @@ extension Config.LoRaConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem if _storage._codingRate != 0 { try visitor.visitSingularUInt32Field(value: _storage._codingRate, fieldNumber: 5) } - if _storage._frequencyOffset.bitPattern != 0 { + if _storage._frequencyOffset != 0 { try visitor.visitSingularFloatField(value: _storage._frequencyOffset, fieldNumber: 6) } if _storage._region != .unset { @@ -2807,7 +2916,7 @@ extension Config.LoRaConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem if _storage._sx126XRxBoostedGain != false { try visitor.visitSingularBoolField(value: _storage._sx126XRxBoostedGain, fieldNumber: 13) } - if _storage._overrideFrequency.bitPattern != 0 { + if _storage._overrideFrequency != 0 { try visitor.visitSingularFloatField(value: _storage._overrideFrequency, fieldNumber: 14) } if _storage._paFanDisabled != false { @@ -3024,8 +3133,8 @@ extension Config.SessionkeyConfig: SwiftProtobuf.Message, SwiftProtobuf._Message public static let _protobuf_nameMap = SwiftProtobuf._NameMap() public mutating func decodeMessage(decoder: inout D) throws { - // Load everything into unknown fields - while try decoder.nextFieldNumber() != nil {} + while let _ = try decoder.nextFieldNumber() { + } } public func traverse(visitor: inout V) throws { diff --git a/MeshtasticProtobufs/Sources/meshtastic/connection_status.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/connection_status.pb.swift index 6847c0e3..a2ec180e 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/connection_status.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/connection_status.pb.swift @@ -1,6 +1,5 @@ // DO NOT EDIT. // swift-format-ignore-file -// swiftlint:disable all // // Generated by the Swift generator plugin for the protocol buffer compiler. // Source: meshtastic/connection_status.proto @@ -8,6 +7,7 @@ // For information on using the generated types, please see the documentation: // https://github.com/apple/swift-protobuf/ +import Foundation import SwiftProtobuf // If the compiler emits an error on this type, it is because this file @@ -20,7 +20,7 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP typealias Version = _2 } -public struct DeviceConnectionStatus: Sendable { +public struct DeviceConnectionStatus { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -81,7 +81,7 @@ public struct DeviceConnectionStatus: Sendable { /// /// WiFi connection status -public struct WifiConnectionStatus: Sendable { +public struct WifiConnectionStatus { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -114,7 +114,7 @@ public struct WifiConnectionStatus: Sendable { /// /// Ethernet connection status -public struct EthernetConnectionStatus: Sendable { +public struct EthernetConnectionStatus { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -139,7 +139,7 @@ public struct EthernetConnectionStatus: Sendable { /// /// Ethernet or WiFi connection status -public struct NetworkConnectionStatus: Sendable { +public struct NetworkConnectionStatus { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -167,7 +167,7 @@ public struct NetworkConnectionStatus: Sendable { /// /// Bluetooth connection status -public struct BluetoothConnectionStatus: Sendable { +public struct BluetoothConnectionStatus { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -191,7 +191,7 @@ public struct BluetoothConnectionStatus: Sendable { /// /// Serial connection status -public struct SerialConnectionStatus: Sendable { +public struct SerialConnectionStatus { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -209,6 +209,15 @@ public struct SerialConnectionStatus: Sendable { public init() {} } +#if swift(>=5.5) && canImport(_Concurrency) +extension DeviceConnectionStatus: @unchecked Sendable {} +extension WifiConnectionStatus: @unchecked Sendable {} +extension EthernetConnectionStatus: @unchecked Sendable {} +extension NetworkConnectionStatus: @unchecked Sendable {} +extension BluetoothConnectionStatus: @unchecked Sendable {} +extension SerialConnectionStatus: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + // MARK: - Code below here is support for the SwiftProtobuf runtime. fileprivate let _protobuf_package = "meshtastic" diff --git a/MeshtasticProtobufs/Sources/meshtastic/device_ui.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/device_ui.pb.swift index eaf3951c..5e13b166 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/device_ui.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/device_ui.pb.swift @@ -1,6 +1,5 @@ // DO NOT EDIT. // swift-format-ignore-file -// swiftlint:disable all // // Generated by the Swift generator plugin for the protocol buffer compiler. // Source: meshtastic/device_ui.proto @@ -21,7 +20,7 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP typealias Version = _2 } -public enum Theme: SwiftProtobuf.Enum, Swift.CaseIterable { +public enum Theme: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -59,18 +58,24 @@ public enum Theme: SwiftProtobuf.Enum, Swift.CaseIterable { } } +} + +#if swift(>=4.2) + +extension Theme: CaseIterable { // The compiler won't synthesize support with the UNRECOGNIZED case. public static let allCases: [Theme] = [ .dark, .light, .red, ] - } +#endif // swift(>=4.2) + /// /// Localization -public enum Language: SwiftProtobuf.Enum, Swift.CaseIterable { +public enum Language: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -198,6 +203,11 @@ public enum Language: SwiftProtobuf.Enum, Swift.CaseIterable { } } +} + +#if swift(>=4.2) + +extension Language: CaseIterable { // The compiler won't synthesize support with the UNRECOGNIZED case. public static let allCases: [Language] = [ .english, @@ -219,10 +229,11 @@ public enum Language: SwiftProtobuf.Enum, Swift.CaseIterable { .simplifiedChinese, .traditionalChinese, ] - } -public struct DeviceUIConfig: @unchecked Sendable { +#endif // swift(>=4.2) + +public struct DeviceUIConfig { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -332,7 +343,7 @@ public struct DeviceUIConfig: @unchecked Sendable { fileprivate var _storage = _StorageClass.defaultInstance } -public struct NodeFilter: Sendable { +public struct NodeFilter { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -370,7 +381,7 @@ public struct NodeFilter: Sendable { public init() {} } -public struct NodeHighlight: Sendable { +public struct NodeHighlight { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -400,6 +411,14 @@ public struct NodeHighlight: Sendable { public init() {} } +#if swift(>=5.5) && canImport(_Concurrency) +extension Theme: @unchecked Sendable {} +extension Language: @unchecked Sendable {} +extension DeviceUIConfig: @unchecked Sendable {} +extension NodeFilter: @unchecked Sendable {} +extension NodeHighlight: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + // MARK: - Code below here is support for the SwiftProtobuf runtime. fileprivate let _protobuf_package = "meshtastic" diff --git a/MeshtasticProtobufs/Sources/meshtastic/deviceonly.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/deviceonly.pb.swift index a8f57eaf..34a33373 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/deviceonly.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/deviceonly.pb.swift @@ -1,6 +1,5 @@ // DO NOT EDIT. // swift-format-ignore-file -// swiftlint:disable all // // Generated by the Swift generator plugin for the protocol buffer compiler. // Source: meshtastic/deviceonly.proto @@ -23,7 +22,7 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP /// /// Position with static location information only for NodeDBLite -public struct PositionLite: Sendable { +public struct PositionLite { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -58,15 +57,13 @@ public struct PositionLite: Sendable { public init() {} } -public struct UserLite: @unchecked Sendable { +public struct UserLite { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. /// /// This is the addr of the radio. - /// - /// NOTE: This field was marked as deprecated in the .proto file. public var macaddr: Data = Data() /// @@ -105,7 +102,7 @@ public struct UserLite: @unchecked Sendable { public init() {} } -public struct NodeInfoLite: @unchecked Sendable { +public struct NodeInfoLite { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -227,7 +224,7 @@ public struct NodeInfoLite: @unchecked Sendable { /// FIXME, since we write this each time we enter deep sleep (and have infinite /// flash) it would be better to use some sort of append only data structure for /// the receive queue and use the preferences store for the other stuff -public struct DeviceState: @unchecked Sendable { +public struct DeviceState { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -287,8 +284,6 @@ public struct DeviceState: @unchecked Sendable { /// Used only during development. /// Indicates developer is testing and changes should never be saved to flash. /// Deprecated in 2.3.1 - /// - /// NOTE: This field was marked as deprecated in the .proto file. public var noSave: Bool { get {return _storage._noSave} set {_uniqueStorage()._noSave = newValue} @@ -337,7 +332,7 @@ public struct DeviceState: @unchecked Sendable { /// /// The on-disk saved channels -public struct ChannelFile: Sendable { +public struct ChannelFile { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -357,6 +352,14 @@ public struct ChannelFile: Sendable { public init() {} } +#if swift(>=5.5) && canImport(_Concurrency) +extension PositionLite: @unchecked Sendable {} +extension UserLite: @unchecked Sendable {} +extension NodeInfoLite: @unchecked Sendable {} +extension DeviceState: @unchecked Sendable {} +extension ChannelFile: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + // MARK: - Code below here is support for the SwiftProtobuf runtime. fileprivate let _protobuf_package = "meshtastic" @@ -592,7 +595,7 @@ extension NodeInfoLite: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat try { if let v = _storage._position { try visitor.visitSingularMessageField(value: v, fieldNumber: 3) } }() - if _storage._snr.bitPattern != 0 { + if _storage._snr != 0 { try visitor.visitSingularFloatField(value: _storage._snr, fieldNumber: 4) } if _storage._lastHeard != 0 { diff --git a/MeshtasticProtobufs/Sources/meshtastic/localonly.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/localonly.pb.swift index c3356286..0af27466 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/localonly.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/localonly.pb.swift @@ -1,6 +1,5 @@ // DO NOT EDIT. // swift-format-ignore-file -// swiftlint:disable all // // Generated by the Swift generator plugin for the protocol buffer compiler. // Source: meshtastic/localonly.proto @@ -8,6 +7,7 @@ // For information on using the generated types, please see the documentation: // https://github.com/apple/swift-protobuf/ +import Foundation import SwiftProtobuf // If the compiler emits an error on this type, it is because this file @@ -20,7 +20,7 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP typealias Version = _2 } -public struct LocalConfig: @unchecked Sendable { +public struct LocalConfig { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -129,7 +129,7 @@ public struct LocalConfig: @unchecked Sendable { fileprivate var _storage = _StorageClass.defaultInstance } -public struct LocalModuleConfig: @unchecked Sendable { +public struct LocalModuleConfig { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -293,6 +293,11 @@ public struct LocalModuleConfig: @unchecked Sendable { fileprivate var _storage = _StorageClass.defaultInstance } +#if swift(>=5.5) && canImport(_Concurrency) +extension LocalConfig: @unchecked Sendable {} +extension LocalModuleConfig: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + // MARK: - Code below here is support for the SwiftProtobuf runtime. fileprivate let _protobuf_package = "meshtastic" diff --git a/MeshtasticProtobufs/Sources/meshtastic/mesh.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/mesh.pb.swift index cf3cb4ee..bea1d14d 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/mesh.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/mesh.pb.swift @@ -1,6 +1,5 @@ // DO NOT EDIT. // swift-format-ignore-file -// swiftlint:disable all // // Generated by the Swift generator plugin for the protocol buffer compiler. // Source: meshtastic/mesh.proto @@ -26,7 +25,7 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP /// bin/build-all.sh script. /// Because they will be used to find firmware filenames in the android app for OTA updates. /// To match the old style filenames, _ is converted to -, p is converted to . -public enum HardwareModel: SwiftProtobuf.Enum, Swift.CaseIterable { +public enum HardwareModel: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -398,6 +397,11 @@ public enum HardwareModel: SwiftProtobuf.Enum, Swift.CaseIterable { /// https://github.com/valzzu/Mesh-Tab case meshTab // = 86 + /// + /// MeshLink board developed by LoraItalia. NRF52840, eByte E22900M22S (Will also come with other frequencies), 25w MPPT solar charger (5v,12v,18v selectable), support for gps, buzzer, oled or e-ink display, 10 gpios, hardware watchdog + /// https://www.loraitalia.it + case meshlink // = 87 + /// /// ------------------------------------------------------------------------------------------------------------------------------------------ /// Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits. @@ -498,6 +502,7 @@ public enum HardwareModel: SwiftProtobuf.Enum, Swift.CaseIterable { case 84: self = .wismeshTap case 85: self = .routastic case 86: self = .meshTab + case 87: self = .meshlink case 255: self = .privateHw default: self = .UNRECOGNIZED(rawValue) } @@ -592,11 +597,17 @@ public enum HardwareModel: SwiftProtobuf.Enum, Swift.CaseIterable { case .wismeshTap: return 84 case .routastic: return 85 case .meshTab: return 86 + case .meshlink: return 87 case .privateHw: return 255 case .UNRECOGNIZED(let i): return i } } +} + +#if swift(>=4.2) + +extension HardwareModel: CaseIterable { // The compiler won't synthesize support with the UNRECOGNIZED case. public static let allCases: [HardwareModel] = [ .unset, @@ -686,14 +697,16 @@ public enum HardwareModel: SwiftProtobuf.Enum, Swift.CaseIterable { .wismeshTap, .routastic, .meshTab, + .meshlink, .privateHw, ] - } +#endif // swift(>=4.2) + /// /// Shared constants between device and phone -public enum Constants: SwiftProtobuf.Enum, Swift.CaseIterable { +public enum Constants: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -728,20 +741,26 @@ public enum Constants: SwiftProtobuf.Enum, Swift.CaseIterable { } } +} + +#if swift(>=4.2) + +extension Constants: CaseIterable { // The compiler won't synthesize support with the UNRECOGNIZED case. public static let allCases: [Constants] = [ .zero, .dataPayloadLen, ] - } +#endif // swift(>=4.2) + /// /// Error codes for critical errors /// The device might report these fault codes on the screen. /// If you encounter a fault code, please post on the meshtastic.discourse.group /// and we'll try to help. -public enum CriticalErrorCode: SwiftProtobuf.Enum, Swift.CaseIterable { +public enum CriticalErrorCode: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -850,6 +869,11 @@ public enum CriticalErrorCode: SwiftProtobuf.Enum, Swift.CaseIterable { } } +} + +#if swift(>=4.2) + +extension CriticalErrorCode: CaseIterable { // The compiler won't synthesize support with the UNRECOGNIZED case. public static let allCases: [CriticalErrorCode] = [ .none, @@ -867,14 +891,15 @@ public enum CriticalErrorCode: SwiftProtobuf.Enum, Swift.CaseIterable { .flashCorruptionRecoverable, .flashCorruptionUnrecoverable, ] - } +#endif // swift(>=4.2) + /// /// Enum for modules excluded from a device's configuration. /// Each value represents a ModuleConfigType that can be toggled as excluded /// by setting its corresponding bit in the `excluded_modules` bitmask field. -public enum ExcludedModules: SwiftProtobuf.Enum, Swift.CaseIterable { +public enum ExcludedModules: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -978,6 +1003,11 @@ public enum ExcludedModules: SwiftProtobuf.Enum, Swift.CaseIterable { } } +} + +#if swift(>=4.2) + +extension ExcludedModules: CaseIterable { // The compiler won't synthesize support with the UNRECOGNIZED case. public static let allCases: [ExcludedModules] = [ .excludedNone, @@ -995,12 +1025,13 @@ public enum ExcludedModules: SwiftProtobuf.Enum, Swift.CaseIterable { .detectionsensorConfig, .paxcounterConfig, ] - } +#endif // swift(>=4.2) + /// /// A GPS Position -public struct Position: @unchecked Sendable { +public struct Position { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -1217,7 +1248,7 @@ public struct Position: @unchecked Sendable { /// /// How the location was acquired: manual, onboard GPS, external (EUD) GPS - public enum LocSource: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum LocSource: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -1261,20 +1292,12 @@ public struct Position: @unchecked Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [Position.LocSource] = [ - .locUnset, - .locManual, - .locInternal, - .locExternal, - ] - } /// /// How the altitude was acquired: manual, GPS int/ext, etc /// Default: same as location_source if present - public enum AltSource: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum AltSource: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -1324,15 +1347,6 @@ public struct Position: @unchecked Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [Position.AltSource] = [ - .altUnset, - .altManual, - .altInternal, - .altExternal, - .altBarometric, - ] - } public init() {} @@ -1340,6 +1354,31 @@ public struct Position: @unchecked Sendable { fileprivate var _storage = _StorageClass.defaultInstance } +#if swift(>=4.2) + +extension Position.LocSource: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [Position.LocSource] = [ + .locUnset, + .locManual, + .locInternal, + .locExternal, + ] +} + +extension Position.AltSource: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [Position.AltSource] = [ + .altUnset, + .altManual, + .altInternal, + .altExternal, + .altBarometric, + ] +} + +#endif // swift(>=4.2) + /// /// Broadcast when a newly powered mesh node wants to find a node num it can use /// Sent from the phone over bluetooth to set the user id for the owner of this node. @@ -1361,7 +1400,7 @@ public struct Position: @unchecked Sendable { /// A few nodenums are reserved and will never be requested: /// 0xff - broadcast /// 0 through 3 - for future use -public struct User: @unchecked Sendable { +public struct User { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -1386,8 +1425,6 @@ public struct User: @unchecked Sendable { /// Deprecated in Meshtastic 2.1.x /// This is the addr of the radio. /// Not populated by the phone, but added by the esp32 when broadcasting - /// - /// NOTE: This field was marked as deprecated in the .proto file. public var macaddr: Data = Data() /// @@ -1419,7 +1456,7 @@ public struct User: @unchecked Sendable { /// /// A message used in a traceroute -public struct RouteDiscovery: Sendable { +public struct RouteDiscovery { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -1447,7 +1484,7 @@ public struct RouteDiscovery: Sendable { /// /// A Routing control Data packet handled by the routing module -public struct Routing: Sendable { +public struct Routing { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -1487,7 +1524,7 @@ public struct Routing: Sendable { public var unknownFields = SwiftProtobuf.UnknownStorage() - public enum OneOf_Variant: Equatable, Sendable { + public enum OneOf_Variant: Equatable { /// /// A route request going from the requester case routeRequest(RouteDiscovery) @@ -1499,12 +1536,34 @@ public struct Routing: Sendable { /// in addition to ack.fail_id to provide details on the type of failure). case errorReason(Routing.Error) + #if !swift(>=4.1) + public static func ==(lhs: Routing.OneOf_Variant, rhs: Routing.OneOf_Variant) -> Bool { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch (lhs, rhs) { + case (.routeRequest, .routeRequest): return { + guard case .routeRequest(let l) = lhs, case .routeRequest(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.routeReply, .routeReply): return { + guard case .routeReply(let l) = lhs, case .routeReply(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.errorReason, .errorReason): return { + guard case .errorReason(let l) = lhs, case .errorReason(let r) = rhs else { preconditionFailure() } + return l == r + }() + default: return false + } + } + #endif } /// /// A failure in delivering a message (usually used for routing control messages, but might be provided in addition to ack.fail_id to provide /// details on the type of failure). - public enum Error: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum Error: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -1622,36 +1681,42 @@ public struct Routing: Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [Routing.Error] = [ - .none, - .noRoute, - .gotNak, - .timeout, - .noInterface, - .maxRetransmit, - .noChannel, - .tooLarge, - .noResponse, - .dutyCycleLimit, - .badRequest, - .notAuthorized, - .pkiFailed, - .pkiUnknownPubkey, - .adminBadSessionKey, - .adminPublicKeyUnauthorized, - ] - } public init() {} } +#if swift(>=4.2) + +extension Routing.Error: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [Routing.Error] = [ + .none, + .noRoute, + .gotNak, + .timeout, + .noInterface, + .maxRetransmit, + .noChannel, + .tooLarge, + .noResponse, + .dutyCycleLimit, + .badRequest, + .notAuthorized, + .pkiFailed, + .pkiUnknownPubkey, + .adminBadSessionKey, + .adminPublicKeyUnauthorized, + ] +} + +#endif // swift(>=4.2) + /// /// (Formerly called SubPacket) /// The payload portion fo a packet, this is the actual bytes that are sent /// inside a radio packet (because from/to are broken out by the comms library) -public struct DataMessage: @unchecked Sendable { +public struct DataMessage { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -1718,7 +1783,7 @@ public struct DataMessage: @unchecked Sendable { /// /// Waypoint message, used to share arbitrary locations across the mesh -public struct Waypoint: Sendable { +public struct Waypoint { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -1780,7 +1845,7 @@ public struct Waypoint: Sendable { /// /// This message will be proxied over the PhoneAPI for the client to deliver to the MQTT server -public struct MqttClientProxyMessage: @unchecked Sendable { +public struct MqttClientProxyMessage { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -1821,7 +1886,7 @@ public struct MqttClientProxyMessage: @unchecked Sendable { /// /// The actual service envelope payload or text for mqtt pub / sub - public enum OneOf_PayloadVariant: Equatable, @unchecked Sendable { + public enum OneOf_PayloadVariant: Equatable { /// /// Bytes case data(Data) @@ -1829,6 +1894,24 @@ public struct MqttClientProxyMessage: @unchecked Sendable { /// Text case text(String) + #if !swift(>=4.1) + public static func ==(lhs: MqttClientProxyMessage.OneOf_PayloadVariant, rhs: MqttClientProxyMessage.OneOf_PayloadVariant) -> Bool { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch (lhs, rhs) { + case (.data, .data): return { + guard case .data(let l) = lhs, case .data(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.text, .text): return { + guard case .text(let l) = lhs, case .text(let r) = rhs else { preconditionFailure() } + return l == r + }() + default: return false + } + } + #endif } public init() {} @@ -1838,7 +1921,7 @@ public struct MqttClientProxyMessage: @unchecked Sendable { /// A packet envelope sent/received over the mesh /// only payload_variant is sent in the payload portion of the LORA packet. /// The other fields are either not sent at all, or sent in the special 16 byte LORA header. -public struct MeshPacket: @unchecked Sendable { +public struct MeshPacket { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -1972,8 +2055,6 @@ public struct MeshPacket: @unchecked Sendable { /// /// Describe if this message is delayed - /// - /// NOTE: This field was marked as deprecated in the .proto file. public var delayed: MeshPacket.Delayed { get {return _storage._delayed} set {_uniqueStorage()._delayed = newValue} @@ -2035,7 +2116,7 @@ public struct MeshPacket: @unchecked Sendable { public var unknownFields = SwiftProtobuf.UnknownStorage() - public enum OneOf_PayloadVariant: Equatable, @unchecked Sendable { + public enum OneOf_PayloadVariant: Equatable { /// /// TODO: REPLACE case decoded(DataMessage) @@ -2043,6 +2124,24 @@ public struct MeshPacket: @unchecked Sendable { /// TODO: REPLACE case encrypted(Data) + #if !swift(>=4.1) + public static func ==(lhs: MeshPacket.OneOf_PayloadVariant, rhs: MeshPacket.OneOf_PayloadVariant) -> Bool { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch (lhs, rhs) { + case (.decoded, .decoded): return { + guard case .decoded(let l) = lhs, case .decoded(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.encrypted, .encrypted): return { + guard case .encrypted(let l) = lhs, case .encrypted(let r) = rhs else { preconditionFailure() } + return l == r + }() + default: return false + } + } + #endif } /// @@ -2064,7 +2163,7 @@ public struct MeshPacket: @unchecked Sendable { /// So I bit the bullet and implemented a new (internal - not sent over the air) /// field in MeshPacket called 'priority'. /// And the transmission queue in the router object is now a priority queue. - public enum Priority: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum Priority: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -2148,25 +2247,11 @@ public struct MeshPacket: @unchecked Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [MeshPacket.Priority] = [ - .unset, - .min, - .background, - .default, - .reliable, - .response, - .high, - .alert, - .ack, - .max, - ] - } /// /// Identify if this is a delayed packet - public enum Delayed: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum Delayed: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -2204,13 +2289,6 @@ public struct MeshPacket: @unchecked Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [MeshPacket.Delayed] = [ - .noDelay, - .broadcast, - .direct, - ] - } public init() {} @@ -2218,6 +2296,35 @@ public struct MeshPacket: @unchecked Sendable { fileprivate var _storage = _StorageClass.defaultInstance } +#if swift(>=4.2) + +extension MeshPacket.Priority: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [MeshPacket.Priority] = [ + .unset, + .min, + .background, + .default, + .reliable, + .response, + .high, + .alert, + .ack, + .max, + ] +} + +extension MeshPacket.Delayed: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [MeshPacket.Delayed] = [ + .noDelay, + .broadcast, + .direct, + ] +} + +#endif // swift(>=4.2) + /// /// The bluetooth to device link: /// Old BTLE protocol docs from TODO, merge in above and make real docs... @@ -2235,7 +2342,7 @@ public struct MeshPacket: @unchecked Sendable { /// level etc) SET_CONFIG (switches device to a new set of radio params and /// preshared key, drops all existing nodes, force our node to rejoin this new group) /// Full information about a node on the mesh -public struct NodeInfo: @unchecked Sendable { +public struct NodeInfo { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -2348,7 +2455,7 @@ public struct NodeInfo: @unchecked Sendable { /// Unique local debugging info for this node /// Note: we don't include position or the user info, because that will come in the /// Sent to the phone in response to WantNodes. -public struct MyNodeInfo: @unchecked Sendable { +public struct MyNodeInfo { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -2387,7 +2494,7 @@ public struct MyNodeInfo: @unchecked Sendable { /// on the message it is assumed to be a continuation of the previously sent message. /// This allows the device code to use fixed maxlen 64 byte strings for messages, /// and then extend as needed by emitting multiple records. -public struct LogRecord: Sendable { +public struct LogRecord { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -2412,7 +2519,7 @@ public struct LogRecord: Sendable { /// /// Log levels, chosen to match python logging conventions. - public enum Level: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum Level: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -2474,23 +2581,29 @@ public struct LogRecord: Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [LogRecord.Level] = [ - .unset, - .critical, - .error, - .warning, - .info, - .debug, - .trace, - ] - } public init() {} } -public struct QueueStatus: Sendable { +#if swift(>=4.2) + +extension LogRecord.Level: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [LogRecord.Level] = [ + .unset, + .critical, + .error, + .warning, + .info, + .debug, + .trace, + ] +} + +#endif // swift(>=4.2) + +public struct QueueStatus { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -2517,7 +2630,7 @@ public struct QueueStatus: Sendable { /// It will support READ and NOTIFY. When a new packet arrives the device will BLE notify? /// It will sit in that descriptor until consumed by the phone, /// at which point the next item in the FIFO will be populated. -public struct FromRadio: Sendable { +public struct FromRadio { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -2703,7 +2816,7 @@ public struct FromRadio: Sendable { /// /// Log levels, chosen to match python logging conventions. - public enum OneOf_PayloadVariant: Equatable, Sendable { + public enum OneOf_PayloadVariant: Equatable { /// /// Log levels, chosen to match python logging conventions. case packet(MeshPacket) @@ -2761,6 +2874,80 @@ public struct FromRadio: Sendable { /// Persistent data for device-ui case deviceuiConfig(DeviceUIConfig) + #if !swift(>=4.1) + public static func ==(lhs: FromRadio.OneOf_PayloadVariant, rhs: FromRadio.OneOf_PayloadVariant) -> Bool { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch (lhs, rhs) { + case (.packet, .packet): return { + guard case .packet(let l) = lhs, case .packet(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.myInfo, .myInfo): return { + guard case .myInfo(let l) = lhs, case .myInfo(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.nodeInfo, .nodeInfo): return { + guard case .nodeInfo(let l) = lhs, case .nodeInfo(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.config, .config): return { + guard case .config(let l) = lhs, case .config(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.logRecord, .logRecord): return { + guard case .logRecord(let l) = lhs, case .logRecord(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.configCompleteID, .configCompleteID): return { + guard case .configCompleteID(let l) = lhs, case .configCompleteID(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.rebooted, .rebooted): return { + guard case .rebooted(let l) = lhs, case .rebooted(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.moduleConfig, .moduleConfig): return { + guard case .moduleConfig(let l) = lhs, case .moduleConfig(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.channel, .channel): return { + guard case .channel(let l) = lhs, case .channel(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.queueStatus, .queueStatus): return { + guard case .queueStatus(let l) = lhs, case .queueStatus(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.xmodemPacket, .xmodemPacket): return { + guard case .xmodemPacket(let l) = lhs, case .xmodemPacket(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.metadata, .metadata): return { + guard case .metadata(let l) = lhs, case .metadata(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.mqttClientProxyMessage, .mqttClientProxyMessage): return { + guard case .mqttClientProxyMessage(let l) = lhs, case .mqttClientProxyMessage(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.fileInfo, .fileInfo): return { + guard case .fileInfo(let l) = lhs, case .fileInfo(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.clientNotification, .clientNotification): return { + guard case .clientNotification(let l) = lhs, case .clientNotification(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.deviceuiConfig, .deviceuiConfig): return { + guard case .deviceuiConfig(let l) = lhs, case .deviceuiConfig(let r) = rhs else { preconditionFailure() } + return l == r + }() + default: return false + } + } + #endif } public init() {} @@ -2771,7 +2958,7 @@ public struct FromRadio: Sendable { /// To be used for important messages that should to be displayed to the user /// in the form of push notifications or validation messages when saving /// invalid configuration. -public struct ClientNotification: Sendable { +public struct ClientNotification { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -2808,7 +2995,7 @@ public struct ClientNotification: Sendable { /// /// Individual File info for the device -public struct FileInfo: Sendable { +public struct FileInfo { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -2829,7 +3016,7 @@ public struct FileInfo: Sendable { /// /// Packets/commands to the radio will be written (reliably) to the toRadio characteristic. /// Once the write completes the phone can assume it is handled. -public struct ToRadio: Sendable { +public struct ToRadio { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -2909,7 +3096,7 @@ public struct ToRadio: Sendable { /// /// Log levels, chosen to match python logging conventions. - public enum OneOf_PayloadVariant: Equatable, Sendable { + public enum OneOf_PayloadVariant: Equatable { /// /// Send this packet on the mesh case packet(MeshPacket) @@ -2936,6 +3123,40 @@ public struct ToRadio: Sendable { /// Heartbeat message (used to keep the device connection awake on serial) case heartbeat(Heartbeat) + #if !swift(>=4.1) + public static func ==(lhs: ToRadio.OneOf_PayloadVariant, rhs: ToRadio.OneOf_PayloadVariant) -> Bool { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch (lhs, rhs) { + case (.packet, .packet): return { + guard case .packet(let l) = lhs, case .packet(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.wantConfigID, .wantConfigID): return { + guard case .wantConfigID(let l) = lhs, case .wantConfigID(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.disconnect, .disconnect): return { + guard case .disconnect(let l) = lhs, case .disconnect(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.xmodemPacket, .xmodemPacket): return { + guard case .xmodemPacket(let l) = lhs, case .xmodemPacket(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.mqttClientProxyMessage, .mqttClientProxyMessage): return { + guard case .mqttClientProxyMessage(let l) = lhs, case .mqttClientProxyMessage(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.heartbeat, .heartbeat): return { + guard case .heartbeat(let l) = lhs, case .heartbeat(let r) = rhs else { preconditionFailure() } + return l == r + }() + default: return false + } + } + #endif } public init() {} @@ -2943,7 +3164,7 @@ public struct ToRadio: Sendable { /// /// Compressed message payload -public struct Compressed: @unchecked Sendable { +public struct Compressed { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -2963,7 +3184,7 @@ public struct Compressed: @unchecked Sendable { /// /// Full info on edges for a single node -public struct NeighborInfo: Sendable { +public struct NeighborInfo { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -2991,7 +3212,7 @@ public struct NeighborInfo: Sendable { /// /// A single edge in the mesh -public struct Neighbor: Sendable { +public struct Neighbor { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -3021,7 +3242,7 @@ public struct Neighbor: Sendable { /// /// Device metadata response -public struct DeviceMetadata: Sendable { +public struct DeviceMetadata { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -3083,7 +3304,7 @@ public struct DeviceMetadata: Sendable { /// /// A heartbeat message is sent to the node from the client to keep the connection alive. /// This is currently only needed to keep serial connections alive, but can be used by any PhoneAPI. -public struct Heartbeat: Sendable { +public struct Heartbeat { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -3095,7 +3316,7 @@ public struct Heartbeat: Sendable { /// /// RemoteHardwarePins associated with a node -public struct NodeRemoteHardwarePin: Sendable { +public struct NodeRemoteHardwarePin { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -3122,7 +3343,7 @@ public struct NodeRemoteHardwarePin: Sendable { fileprivate var _pin: RemoteHardwarePin? = nil } -public struct ChunkedPayload: @unchecked Sendable { +public struct ChunkedPayload { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -3150,7 +3371,7 @@ public struct ChunkedPayload: @unchecked Sendable { /// /// Wrapper message for broken repeated oneof support -public struct resend_chunks: Sendable { +public struct resend_chunks { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -3164,7 +3385,7 @@ public struct resend_chunks: Sendable { /// /// Responses to a ChunkedPayload request -public struct ChunkedPayloadResponse: Sendable { +public struct ChunkedPayloadResponse { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -3207,7 +3428,7 @@ public struct ChunkedPayloadResponse: Sendable { public var unknownFields = SwiftProtobuf.UnknownStorage() - public enum OneOf_PayloadVariant: Equatable, Sendable { + public enum OneOf_PayloadVariant: Equatable { /// /// Request to transfer chunked payload case requestTransfer(Bool) @@ -3218,11 +3439,77 @@ public struct ChunkedPayloadResponse: Sendable { /// Request missing indexes in the chunked payload case resendChunks(resend_chunks) + #if !swift(>=4.1) + public static func ==(lhs: ChunkedPayloadResponse.OneOf_PayloadVariant, rhs: ChunkedPayloadResponse.OneOf_PayloadVariant) -> Bool { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch (lhs, rhs) { + case (.requestTransfer, .requestTransfer): return { + guard case .requestTransfer(let l) = lhs, case .requestTransfer(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.acceptTransfer, .acceptTransfer): return { + guard case .acceptTransfer(let l) = lhs, case .acceptTransfer(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.resendChunks, .resendChunks): return { + guard case .resendChunks(let l) = lhs, case .resendChunks(let r) = rhs else { preconditionFailure() } + return l == r + }() + default: return false + } + } + #endif } public init() {} } +#if swift(>=5.5) && canImport(_Concurrency) +extension HardwareModel: @unchecked Sendable {} +extension Constants: @unchecked Sendable {} +extension CriticalErrorCode: @unchecked Sendable {} +extension ExcludedModules: @unchecked Sendable {} +extension Position: @unchecked Sendable {} +extension Position.LocSource: @unchecked Sendable {} +extension Position.AltSource: @unchecked Sendable {} +extension User: @unchecked Sendable {} +extension RouteDiscovery: @unchecked Sendable {} +extension Routing: @unchecked Sendable {} +extension Routing.OneOf_Variant: @unchecked Sendable {} +extension Routing.Error: @unchecked Sendable {} +extension DataMessage: @unchecked Sendable {} +extension Waypoint: @unchecked Sendable {} +extension MqttClientProxyMessage: @unchecked Sendable {} +extension MqttClientProxyMessage.OneOf_PayloadVariant: @unchecked Sendable {} +extension MeshPacket: @unchecked Sendable {} +extension MeshPacket.OneOf_PayloadVariant: @unchecked Sendable {} +extension MeshPacket.Priority: @unchecked Sendable {} +extension MeshPacket.Delayed: @unchecked Sendable {} +extension NodeInfo: @unchecked Sendable {} +extension MyNodeInfo: @unchecked Sendable {} +extension LogRecord: @unchecked Sendable {} +extension LogRecord.Level: @unchecked Sendable {} +extension QueueStatus: @unchecked Sendable {} +extension FromRadio: @unchecked Sendable {} +extension FromRadio.OneOf_PayloadVariant: @unchecked Sendable {} +extension ClientNotification: @unchecked Sendable {} +extension FileInfo: @unchecked Sendable {} +extension ToRadio: @unchecked Sendable {} +extension ToRadio.OneOf_PayloadVariant: @unchecked Sendable {} +extension Compressed: @unchecked Sendable {} +extension NeighborInfo: @unchecked Sendable {} +extension Neighbor: @unchecked Sendable {} +extension DeviceMetadata: @unchecked Sendable {} +extension Heartbeat: @unchecked Sendable {} +extension NodeRemoteHardwarePin: @unchecked Sendable {} +extension ChunkedPayload: @unchecked Sendable {} +extension resend_chunks: @unchecked Sendable {} +extension ChunkedPayloadResponse: @unchecked Sendable {} +extension ChunkedPayloadResponse.OneOf_PayloadVariant: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + // MARK: - Code below here is support for the SwiftProtobuf runtime. fileprivate let _protobuf_package = "meshtastic" @@ -3316,6 +3603,7 @@ extension HardwareModel: SwiftProtobuf._ProtoNameProviding { 84: .same(proto: "WISMESH_TAP"), 85: .same(proto: "ROUTASTIC"), 86: .same(proto: "MESH_TAB"), + 87: .same(proto: "MESHLINK"), 255: .same(proto: "PRIVATE_HW"), ] } @@ -4271,7 +4559,7 @@ extension MeshPacket: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementatio if _storage._rxTime != 0 { try visitor.visitSingularFixed32Field(value: _storage._rxTime, fieldNumber: 7) } - if _storage._rxSnr.bitPattern != 0 { + if _storage._rxSnr != 0 { try visitor.visitSingularFloatField(value: _storage._rxSnr, fieldNumber: 8) } if _storage._hopLimit != 0 { @@ -4473,7 +4761,7 @@ extension NodeInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB try { if let v = _storage._position { try visitor.visitSingularMessageField(value: v, fieldNumber: 3) } }() - if _storage._snr.bitPattern != 0 { + if _storage._snr != 0 { try visitor.visitSingularFloatField(value: _storage._snr, fieldNumber: 4) } if _storage._lastHeard != 0 { @@ -5352,7 +5640,7 @@ extension Neighbor: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB if self.nodeID != 0 { try visitor.visitSingularUInt32Field(value: self.nodeID, fieldNumber: 1) } - if self.snr.bitPattern != 0 { + if self.snr != 0 { try visitor.visitSingularFloatField(value: self.snr, fieldNumber: 2) } if self.lastRxTime != 0 { @@ -5477,8 +5765,8 @@ extension Heartbeat: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation public static let _protobuf_nameMap = SwiftProtobuf._NameMap() public mutating func decodeMessage(decoder: inout D) throws { - // Load everything into unknown fields - while try decoder.nextFieldNumber() != nil {} + while let _ = try decoder.nextFieldNumber() { + } } public func traverse(visitor: inout V) throws { diff --git a/MeshtasticProtobufs/Sources/meshtastic/module_config.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/module_config.pb.swift index 2cb3291b..bcf4041c 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/module_config.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/module_config.pb.swift @@ -1,6 +1,5 @@ // DO NOT EDIT. // swift-format-ignore-file -// swiftlint:disable all // // Generated by the Swift generator plugin for the protocol buffer compiler. // Source: meshtastic/module_config.proto @@ -8,6 +7,7 @@ // For information on using the generated types, please see the documentation: // https://github.com/apple/swift-protobuf/ +import Foundation import SwiftProtobuf // If the compiler emits an error on this type, it is because this file @@ -20,7 +20,7 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP typealias Version = _2 } -public enum RemoteHardwarePinType: SwiftProtobuf.Enum, Swift.CaseIterable { +public enum RemoteHardwarePinType: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -58,18 +58,24 @@ public enum RemoteHardwarePinType: SwiftProtobuf.Enum, Swift.CaseIterable { } } +} + +#if swift(>=4.2) + +extension RemoteHardwarePinType: CaseIterable { // The compiler won't synthesize support with the UNRECOGNIZED case. public static let allCases: [RemoteHardwarePinType] = [ .unknown, .digitalRead, .digitalWrite, ] - } +#endif // swift(>=4.2) + /// /// Module Config -public struct ModuleConfig: Sendable { +public struct ModuleConfig { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -212,7 +218,7 @@ public struct ModuleConfig: Sendable { /// /// TODO: REPLACE - public enum OneOf_PayloadVariant: Equatable, Sendable { + public enum OneOf_PayloadVariant: Equatable { /// /// TODO: REPLACE case mqtt(ModuleConfig.MQTTConfig) @@ -253,11 +259,73 @@ public struct ModuleConfig: Sendable { /// TODO: REPLACE case paxcounter(ModuleConfig.PaxcounterConfig) + #if !swift(>=4.1) + public static func ==(lhs: ModuleConfig.OneOf_PayloadVariant, rhs: ModuleConfig.OneOf_PayloadVariant) -> Bool { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch (lhs, rhs) { + case (.mqtt, .mqtt): return { + guard case .mqtt(let l) = lhs, case .mqtt(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.serial, .serial): return { + guard case .serial(let l) = lhs, case .serial(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.externalNotification, .externalNotification): return { + guard case .externalNotification(let l) = lhs, case .externalNotification(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.storeForward, .storeForward): return { + guard case .storeForward(let l) = lhs, case .storeForward(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.rangeTest, .rangeTest): return { + guard case .rangeTest(let l) = lhs, case .rangeTest(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.telemetry, .telemetry): return { + guard case .telemetry(let l) = lhs, case .telemetry(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.cannedMessage, .cannedMessage): return { + guard case .cannedMessage(let l) = lhs, case .cannedMessage(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.audio, .audio): return { + guard case .audio(let l) = lhs, case .audio(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.remoteHardware, .remoteHardware): return { + guard case .remoteHardware(let l) = lhs, case .remoteHardware(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.neighborInfo, .neighborInfo): return { + guard case .neighborInfo(let l) = lhs, case .neighborInfo(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.ambientLighting, .ambientLighting): return { + guard case .ambientLighting(let l) = lhs, case .ambientLighting(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.detectionSensor, .detectionSensor): return { + guard case .detectionSensor(let l) = lhs, case .detectionSensor(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.paxcounter, .paxcounter): return { + guard case .paxcounter(let l) = lhs, case .paxcounter(let r) = rhs else { preconditionFailure() } + return l == r + }() + default: return false + } + } + #endif } /// /// MQTT Client Config - public struct MQTTConfig: Sendable { + public struct MQTTConfig { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -332,7 +400,7 @@ public struct ModuleConfig: Sendable { /// /// Settings for reporting unencrypted information about our node to a map via MQTT - public struct MapReportSettings: Sendable { + public struct MapReportSettings { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -352,7 +420,7 @@ public struct ModuleConfig: Sendable { /// /// RemoteHardwareModule Config - public struct RemoteHardwareConfig: Sendable { + public struct RemoteHardwareConfig { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -376,7 +444,7 @@ public struct ModuleConfig: Sendable { /// /// NeighborInfoModule Config - public struct NeighborInfoConfig: Sendable { + public struct NeighborInfoConfig { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -402,7 +470,7 @@ public struct ModuleConfig: Sendable { /// /// Detection Sensor Module Config - public struct DetectionSensorConfig: Sendable { + public struct DetectionSensorConfig { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -449,7 +517,7 @@ public struct ModuleConfig: Sendable { public var unknownFields = SwiftProtobuf.UnknownStorage() - public enum TriggerType: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum TriggerType: SwiftProtobuf.Enum { public typealias RawValue = Int /// Event is triggered if pin is low @@ -501,16 +569,6 @@ public struct ModuleConfig: Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [ModuleConfig.DetectionSensorConfig.TriggerType] = [ - .logicLow, - .logicHigh, - .fallingEdge, - .risingEdge, - .eitherEdgeActiveLow, - .eitherEdgeActiveHigh, - ] - } public init() {} @@ -518,7 +576,7 @@ public struct ModuleConfig: Sendable { /// /// Audio Config for codec2 voice - public struct AudioConfig: Sendable { + public struct AudioConfig { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -555,7 +613,7 @@ public struct ModuleConfig: Sendable { /// /// Baudrate for codec2 voice - public enum Audio_Baud: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum Audio_Baud: SwiftProtobuf.Enum { public typealias RawValue = Int case codec2Default // = 0 case codec23200 // = 1 @@ -602,19 +660,6 @@ public struct ModuleConfig: Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [ModuleConfig.AudioConfig.Audio_Baud] = [ - .codec2Default, - .codec23200, - .codec22400, - .codec21600, - .codec21400, - .codec21300, - .codec21200, - .codec2700, - .codec2700B, - ] - } public init() {} @@ -622,7 +667,7 @@ public struct ModuleConfig: Sendable { /// /// Config for the Paxcounter Module - public struct PaxcounterConfig: Sendable { + public struct PaxcounterConfig { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -648,7 +693,7 @@ public struct ModuleConfig: Sendable { /// /// Serial Config - public struct SerialConfig: Sendable { + public struct SerialConfig { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -691,7 +736,7 @@ public struct ModuleConfig: Sendable { /// /// TODO: REPLACE - public enum Serial_Baud: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum Serial_Baud: SwiftProtobuf.Enum { public typealias RawValue = Int case baudDefault // = 0 case baud110 // = 1 @@ -759,31 +804,11 @@ public struct ModuleConfig: Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [ModuleConfig.SerialConfig.Serial_Baud] = [ - .baudDefault, - .baud110, - .baud300, - .baud600, - .baud1200, - .baud2400, - .baud4800, - .baud9600, - .baud19200, - .baud38400, - .baud57600, - .baud115200, - .baud230400, - .baud460800, - .baud576000, - .baud921600, - ] - } /// /// TODO: REPLACE - public enum Serial_Mode: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum Serial_Mode: SwiftProtobuf.Enum { public typealias RawValue = Int case `default` // = 0 case simple // = 1 @@ -828,17 +853,6 @@ public struct ModuleConfig: Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [ModuleConfig.SerialConfig.Serial_Mode] = [ - .default, - .simple, - .proto, - .textmsg, - .nmea, - .caltopo, - .ws85, - ] - } public init() {} @@ -846,7 +860,7 @@ public struct ModuleConfig: Sendable { /// /// External Notifications Config - public struct ExternalNotificationConfig: Sendable { + public struct ExternalNotificationConfig { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -929,7 +943,7 @@ public struct ModuleConfig: Sendable { /// /// Store and Forward Module Config - public struct StoreForwardConfig: Sendable { + public struct StoreForwardConfig { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -965,7 +979,7 @@ public struct ModuleConfig: Sendable { /// /// Preferences for the RangeTestModule - public struct RangeTestConfig: Sendable { + public struct RangeTestConfig { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -990,7 +1004,7 @@ public struct ModuleConfig: Sendable { /// /// Configuration for both device and environment metrics - public struct TelemetryConfig: Sendable { + public struct TelemetryConfig { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -1058,8 +1072,8 @@ public struct ModuleConfig: Sendable { } /// - /// TODO: REPLACE - public struct CannedMessageConfig: Sendable { + /// Canned Messages Module Config + public struct CannedMessageConfig { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -1114,7 +1128,7 @@ public struct ModuleConfig: Sendable { /// /// TODO: REPLACE - public enum InputEventChar: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum InputEventChar: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -1182,18 +1196,6 @@ public struct ModuleConfig: Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [ModuleConfig.CannedMessageConfig.InputEventChar] = [ - .none, - .up, - .down, - .left, - .right, - .select, - .back, - .cancel, - ] - } public init() {} @@ -1202,7 +1204,7 @@ public struct ModuleConfig: Sendable { /// ///Ambient Lighting Module - Settings for control of onboard LEDs to allow users to adjust the brightness levels and respective color levels. ///Initially created for the RAK14001 RGB LED module. - public struct AmbientLightingConfig: Sendable { + public struct AmbientLightingConfig { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -1235,9 +1237,89 @@ public struct ModuleConfig: Sendable { public init() {} } +#if swift(>=4.2) + +extension ModuleConfig.DetectionSensorConfig.TriggerType: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [ModuleConfig.DetectionSensorConfig.TriggerType] = [ + .logicLow, + .logicHigh, + .fallingEdge, + .risingEdge, + .eitherEdgeActiveLow, + .eitherEdgeActiveHigh, + ] +} + +extension ModuleConfig.AudioConfig.Audio_Baud: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [ModuleConfig.AudioConfig.Audio_Baud] = [ + .codec2Default, + .codec23200, + .codec22400, + .codec21600, + .codec21400, + .codec21300, + .codec21200, + .codec2700, + .codec2700B, + ] +} + +extension ModuleConfig.SerialConfig.Serial_Baud: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [ModuleConfig.SerialConfig.Serial_Baud] = [ + .baudDefault, + .baud110, + .baud300, + .baud600, + .baud1200, + .baud2400, + .baud4800, + .baud9600, + .baud19200, + .baud38400, + .baud57600, + .baud115200, + .baud230400, + .baud460800, + .baud576000, + .baud921600, + ] +} + +extension ModuleConfig.SerialConfig.Serial_Mode: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [ModuleConfig.SerialConfig.Serial_Mode] = [ + .default, + .simple, + .proto, + .textmsg, + .nmea, + .caltopo, + .ws85, + ] +} + +extension ModuleConfig.CannedMessageConfig.InputEventChar: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [ModuleConfig.CannedMessageConfig.InputEventChar] = [ + .none, + .up, + .down, + .left, + .right, + .select, + .back, + .cancel, + ] +} + +#endif // swift(>=4.2) + /// /// A GPIO pin definition for remote hardware module -public struct RemoteHardwarePin: Sendable { +public struct RemoteHardwarePin { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -1259,6 +1341,32 @@ public struct RemoteHardwarePin: Sendable { public init() {} } +#if swift(>=5.5) && canImport(_Concurrency) +extension RemoteHardwarePinType: @unchecked Sendable {} +extension ModuleConfig: @unchecked Sendable {} +extension ModuleConfig.OneOf_PayloadVariant: @unchecked Sendable {} +extension ModuleConfig.MQTTConfig: @unchecked Sendable {} +extension ModuleConfig.MapReportSettings: @unchecked Sendable {} +extension ModuleConfig.RemoteHardwareConfig: @unchecked Sendable {} +extension ModuleConfig.NeighborInfoConfig: @unchecked Sendable {} +extension ModuleConfig.DetectionSensorConfig: @unchecked Sendable {} +extension ModuleConfig.DetectionSensorConfig.TriggerType: @unchecked Sendable {} +extension ModuleConfig.AudioConfig: @unchecked Sendable {} +extension ModuleConfig.AudioConfig.Audio_Baud: @unchecked Sendable {} +extension ModuleConfig.PaxcounterConfig: @unchecked Sendable {} +extension ModuleConfig.SerialConfig: @unchecked Sendable {} +extension ModuleConfig.SerialConfig.Serial_Baud: @unchecked Sendable {} +extension ModuleConfig.SerialConfig.Serial_Mode: @unchecked Sendable {} +extension ModuleConfig.ExternalNotificationConfig: @unchecked Sendable {} +extension ModuleConfig.StoreForwardConfig: @unchecked Sendable {} +extension ModuleConfig.RangeTestConfig: @unchecked Sendable {} +extension ModuleConfig.TelemetryConfig: @unchecked Sendable {} +extension ModuleConfig.CannedMessageConfig: @unchecked Sendable {} +extension ModuleConfig.CannedMessageConfig.InputEventChar: @unchecked Sendable {} +extension ModuleConfig.AmbientLightingConfig: @unchecked Sendable {} +extension RemoteHardwarePin: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + // MARK: - Code below here is support for the SwiftProtobuf runtime. fileprivate let _protobuf_package = "meshtastic" diff --git a/MeshtasticProtobufs/Sources/meshtastic/mqtt.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/mqtt.pb.swift index 006fd9c8..efe6cdd5 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/mqtt.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/mqtt.pb.swift @@ -1,6 +1,5 @@ // DO NOT EDIT. // swift-format-ignore-file -// swiftlint:disable all // // Generated by the Swift generator plugin for the protocol buffer compiler. // Source: meshtastic/mqtt.proto @@ -8,6 +7,7 @@ // For information on using the generated types, please see the documentation: // https://github.com/apple/swift-protobuf/ +import Foundation import SwiftProtobuf // If the compiler emits an error on this type, it is because this file @@ -22,7 +22,7 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP /// /// This message wraps a MeshPacket with extra metadata about the sender and how it arrived. -public struct ServiceEnvelope: Sendable { +public struct ServiceEnvelope { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -57,7 +57,7 @@ public struct ServiceEnvelope: Sendable { /// /// Information about a node intended to be reported unencrypted to a map using MQTT. -public struct MapReport: Sendable { +public struct MapReport { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -121,6 +121,11 @@ public struct MapReport: Sendable { public init() {} } +#if swift(>=5.5) && canImport(_Concurrency) +extension ServiceEnvelope: @unchecked Sendable {} +extension MapReport: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + // MARK: - Code below here is support for the SwiftProtobuf runtime. fileprivate let _protobuf_package = "meshtastic" diff --git a/MeshtasticProtobufs/Sources/meshtastic/paxcount.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/paxcount.pb.swift index e24ed371..cf8aa463 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/paxcount.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/paxcount.pb.swift @@ -1,6 +1,5 @@ // DO NOT EDIT. // swift-format-ignore-file -// swiftlint:disable all // // Generated by the Swift generator plugin for the protocol buffer compiler. // Source: meshtastic/paxcount.proto @@ -8,6 +7,7 @@ // For information on using the generated types, please see the documentation: // https://github.com/apple/swift-protobuf/ +import Foundation import SwiftProtobuf // If the compiler emits an error on this type, it is because this file @@ -22,7 +22,7 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP /// /// TODO: REPLACE -public struct Paxcount: Sendable { +public struct Paxcount { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -44,6 +44,10 @@ public struct Paxcount: Sendable { public init() {} } +#if swift(>=5.5) && canImport(_Concurrency) +extension Paxcount: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + // MARK: - Code below here is support for the SwiftProtobuf runtime. fileprivate let _protobuf_package = "meshtastic" diff --git a/MeshtasticProtobufs/Sources/meshtastic/portnums.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/portnums.pb.swift index 79dfd7f1..3f9afc46 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/portnums.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/portnums.pb.swift @@ -1,6 +1,5 @@ // DO NOT EDIT. // swift-format-ignore-file -// swiftlint:disable all // // Generated by the Swift generator plugin for the protocol buffer compiler. // Source: meshtastic/portnums.proto @@ -8,6 +7,7 @@ // For information on using the generated types, please see the documentation: // https://github.com/apple/swift-protobuf/ +import Foundation import SwiftProtobuf // If the compiler emits an error on this type, it is because this file @@ -33,7 +33,7 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP /// Note: This was formerly a Type enum named 'typ' with the same id # /// We have change to this 'portnum' based scheme for specifying app handlers for particular payloads. /// This change is backwards compatible by treating the legacy OPAQUE/CLEAR_TEXT values identically. -public enum PortNum: SwiftProtobuf.Enum, Swift.CaseIterable { +public enum PortNum: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -283,6 +283,11 @@ public enum PortNum: SwiftProtobuf.Enum, Swift.CaseIterable { } } +} + +#if swift(>=4.2) + +extension PortNum: CaseIterable { // The compiler won't synthesize support with the UNRECOGNIZED case. public static let allCases: [PortNum] = [ .unknownApp, @@ -315,9 +320,14 @@ public enum PortNum: SwiftProtobuf.Enum, Swift.CaseIterable { .atakForwarder, .max, ] - } +#endif // swift(>=4.2) + +#if swift(>=5.5) && canImport(_Concurrency) +extension PortNum: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + // MARK: - Code below here is support for the SwiftProtobuf runtime. extension PortNum: SwiftProtobuf._ProtoNameProviding { diff --git a/MeshtasticProtobufs/Sources/meshtastic/powermon.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/powermon.pb.swift index 58c21701..5f51e948 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/powermon.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/powermon.pb.swift @@ -1,6 +1,5 @@ // DO NOT EDIT. // swift-format-ignore-file -// swiftlint:disable all // // Generated by the Swift generator plugin for the protocol buffer compiler. // Source: meshtastic/powermon.proto @@ -8,6 +7,7 @@ // For information on using the generated types, please see the documentation: // https://github.com/apple/swift-protobuf/ +import Foundation import SwiftProtobuf // If the compiler emits an error on this type, it is because this file @@ -22,7 +22,7 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP /// Note: There are no 'PowerMon' messages normally in use (PowerMons are sent only as structured logs - slogs). ///But we wrap our State enum in this message to effectively nest a namespace (without our linter yelling at us) -public struct PowerMon: Sendable { +public struct PowerMon { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -31,7 +31,7 @@ public struct PowerMon: Sendable { /// Any significant power changing event in meshtastic should be tagged with a powermon state transition. ///If you are making new meshtastic features feel free to add new entries at the end of this definition. - public enum State: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum State: SwiftProtobuf.Enum { public typealias RawValue = Int case none // = 0 case cpuDeepSleep // = 1 @@ -104,31 +104,37 @@ public struct PowerMon: Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [PowerMon.State] = [ - .none, - .cpuDeepSleep, - .cpuLightSleep, - .vext1On, - .loraRxon, - .loraTxon, - .loraRxactive, - .btOn, - .ledOn, - .screenOn, - .screenDrawing, - .wifiOn, - .gpsActive, - ] - } public init() {} } +#if swift(>=4.2) + +extension PowerMon.State: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [PowerMon.State] = [ + .none, + .cpuDeepSleep, + .cpuLightSleep, + .vext1On, + .loraRxon, + .loraTxon, + .loraRxactive, + .btOn, + .ledOn, + .screenOn, + .screenDrawing, + .wifiOn, + .gpsActive, + ] +} + +#endif // swift(>=4.2) + /// /// PowerStress testing support via the C++ PowerStress module -public struct PowerStressMessage: Sendable { +public struct PowerStressMessage { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -145,7 +151,7 @@ public struct PowerStressMessage: Sendable { /// What operation would we like the UUT to perform. ///note: senders should probably set want_response in their request packets, so that they can know when the state ///machine has started processing their request - public enum Opcode: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum Opcode: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -266,35 +272,48 @@ public struct PowerStressMessage: Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [PowerStressMessage.Opcode] = [ - .unset, - .printInfo, - .forceQuiet, - .endQuiet, - .screenOn, - .screenOff, - .cpuIdle, - .cpuDeepsleep, - .cpuFullon, - .ledOn, - .ledOff, - .loraOff, - .loraTx, - .loraRx, - .btOff, - .btOn, - .wifiOff, - .wifiOn, - .gpsOff, - .gpsOn, - ] - } public init() {} } +#if swift(>=4.2) + +extension PowerStressMessage.Opcode: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [PowerStressMessage.Opcode] = [ + .unset, + .printInfo, + .forceQuiet, + .endQuiet, + .screenOn, + .screenOff, + .cpuIdle, + .cpuDeepsleep, + .cpuFullon, + .ledOn, + .ledOff, + .loraOff, + .loraTx, + .loraRx, + .btOff, + .btOn, + .wifiOff, + .wifiOn, + .gpsOff, + .gpsOn, + ] +} + +#endif // swift(>=4.2) + +#if swift(>=5.5) && canImport(_Concurrency) +extension PowerMon: @unchecked Sendable {} +extension PowerMon.State: @unchecked Sendable {} +extension PowerStressMessage: @unchecked Sendable {} +extension PowerStressMessage.Opcode: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + // MARK: - Code below here is support for the SwiftProtobuf runtime. fileprivate let _protobuf_package = "meshtastic" @@ -304,8 +323,8 @@ extension PowerMon: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB public static let _protobuf_nameMap = SwiftProtobuf._NameMap() public mutating func decodeMessage(decoder: inout D) throws { - // Load everything into unknown fields - while try decoder.nextFieldNumber() != nil {} + while let _ = try decoder.nextFieldNumber() { + } } public func traverse(visitor: inout V) throws { @@ -360,7 +379,7 @@ extension PowerStressMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImple if self.cmd != .unset { try visitor.visitSingularEnumField(value: self.cmd, fieldNumber: 1) } - if self.numSeconds.bitPattern != 0 { + if self.numSeconds != 0 { try visitor.visitSingularFloatField(value: self.numSeconds, fieldNumber: 2) } try unknownFields.traverse(visitor: &visitor) diff --git a/MeshtasticProtobufs/Sources/meshtastic/remote_hardware.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/remote_hardware.pb.swift index d23dc07b..ac6eeb26 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/remote_hardware.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/remote_hardware.pb.swift @@ -1,6 +1,5 @@ // DO NOT EDIT. // swift-format-ignore-file -// swiftlint:disable all // // Generated by the Swift generator plugin for the protocol buffer compiler. // Source: meshtastic/remote_hardware.proto @@ -8,6 +7,7 @@ // For information on using the generated types, please see the documentation: // https://github.com/apple/swift-protobuf/ +import Foundation import SwiftProtobuf // If the compiler emits an error on this type, it is because this file @@ -30,7 +30,7 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP /// because no security yet (beyond the channel mechanism). /// It should be off by default and then protected based on some TBD mechanism /// (a special channel once multichannel support is included?) -public struct HardwareMessage: Sendable { +public struct HardwareMessage { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -52,7 +52,7 @@ public struct HardwareMessage: Sendable { /// /// TODO: REPLACE - public enum TypeEnum: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum TypeEnum: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -110,21 +110,32 @@ public struct HardwareMessage: Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [HardwareMessage.TypeEnum] = [ - .unset, - .writeGpios, - .watchGpios, - .gpiosChanged, - .readGpios, - .readGpiosReply, - ] - } public init() {} } +#if swift(>=4.2) + +extension HardwareMessage.TypeEnum: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [HardwareMessage.TypeEnum] = [ + .unset, + .writeGpios, + .watchGpios, + .gpiosChanged, + .readGpios, + .readGpiosReply, + ] +} + +#endif // swift(>=4.2) + +#if swift(>=5.5) && canImport(_Concurrency) +extension HardwareMessage: @unchecked Sendable {} +extension HardwareMessage.TypeEnum: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + // MARK: - Code below here is support for the SwiftProtobuf runtime. fileprivate let _protobuf_package = "meshtastic" diff --git a/MeshtasticProtobufs/Sources/meshtastic/rtttl.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/rtttl.pb.swift index 38d0c880..6fdf3208 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/rtttl.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/rtttl.pb.swift @@ -1,6 +1,5 @@ // DO NOT EDIT. // swift-format-ignore-file -// swiftlint:disable all // // Generated by the Swift generator plugin for the protocol buffer compiler. // Source: meshtastic/rtttl.proto @@ -8,6 +7,7 @@ // For information on using the generated types, please see the documentation: // https://github.com/apple/swift-protobuf/ +import Foundation import SwiftProtobuf // If the compiler emits an error on this type, it is because this file @@ -22,7 +22,7 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP /// /// Canned message module configuration. -public struct RTTTLConfig: Sendable { +public struct RTTTLConfig { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -36,6 +36,10 @@ public struct RTTTLConfig: Sendable { public init() {} } +#if swift(>=5.5) && canImport(_Concurrency) +extension RTTTLConfig: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + // MARK: - Code below here is support for the SwiftProtobuf runtime. fileprivate let _protobuf_package = "meshtastic" diff --git a/MeshtasticProtobufs/Sources/meshtastic/storeforward.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/storeforward.pb.swift index deb96569..54efa77b 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/storeforward.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/storeforward.pb.swift @@ -1,6 +1,5 @@ // DO NOT EDIT. // swift-format-ignore-file -// swiftlint:disable all // // Generated by the Swift generator plugin for the protocol buffer compiler. // Source: meshtastic/storeforward.proto @@ -23,7 +22,7 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP /// /// TODO: REPLACE -public struct StoreAndForward: @unchecked Sendable { +public struct StoreAndForward { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -80,7 +79,7 @@ public struct StoreAndForward: @unchecked Sendable { /// /// TODO: REPLACE - public enum OneOf_Variant: Equatable, @unchecked Sendable { + public enum OneOf_Variant: Equatable { /// /// TODO: REPLACE case stats(StoreAndForward.Statistics) @@ -94,12 +93,38 @@ public struct StoreAndForward: @unchecked Sendable { /// Text from history message. case text(Data) + #if !swift(>=4.1) + public static func ==(lhs: StoreAndForward.OneOf_Variant, rhs: StoreAndForward.OneOf_Variant) -> Bool { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch (lhs, rhs) { + case (.stats, .stats): return { + guard case .stats(let l) = lhs, case .stats(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.history, .history): return { + guard case .history(let l) = lhs, case .history(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.heartbeat, .heartbeat): return { + guard case .heartbeat(let l) = lhs, case .heartbeat(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.text, .text): return { + guard case .text(let l) = lhs, case .text(let r) = rhs else { preconditionFailure() } + return l == r + }() + default: return false + } + } + #endif } /// /// 001 - 063 = From Router /// 064 - 127 = From Client - public enum RequestResponse: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum RequestResponse: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -217,31 +242,11 @@ public struct StoreAndForward: @unchecked Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [StoreAndForward.RequestResponse] = [ - .unset, - .routerError, - .routerHeartbeat, - .routerPing, - .routerPong, - .routerBusy, - .routerHistory, - .routerStats, - .routerTextDirect, - .routerTextBroadcast, - .clientError, - .clientHistory, - .clientStats, - .clientPing, - .clientPong, - .clientAbort, - ] - } /// /// TODO: REPLACE - public struct Statistics: Sendable { + public struct Statistics { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -289,7 +294,7 @@ public struct StoreAndForward: @unchecked Sendable { /// /// TODO: REPLACE - public struct History: Sendable { + public struct History { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -314,7 +319,7 @@ public struct StoreAndForward: @unchecked Sendable { /// /// TODO: REPLACE - public struct Heartbeat: Sendable { + public struct Heartbeat { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -335,6 +340,41 @@ public struct StoreAndForward: @unchecked Sendable { public init() {} } +#if swift(>=4.2) + +extension StoreAndForward.RequestResponse: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [StoreAndForward.RequestResponse] = [ + .unset, + .routerError, + .routerHeartbeat, + .routerPing, + .routerPong, + .routerBusy, + .routerHistory, + .routerStats, + .routerTextDirect, + .routerTextBroadcast, + .clientError, + .clientHistory, + .clientStats, + .clientPing, + .clientPong, + .clientAbort, + ] +} + +#endif // swift(>=4.2) + +#if swift(>=5.5) && canImport(_Concurrency) +extension StoreAndForward: @unchecked Sendable {} +extension StoreAndForward.OneOf_Variant: @unchecked Sendable {} +extension StoreAndForward.RequestResponse: @unchecked Sendable {} +extension StoreAndForward.Statistics: @unchecked Sendable {} +extension StoreAndForward.History: @unchecked Sendable {} +extension StoreAndForward.Heartbeat: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + // MARK: - Code below here is support for the SwiftProtobuf runtime. fileprivate let _protobuf_package = "meshtastic" diff --git a/MeshtasticProtobufs/Sources/meshtastic/telemetry.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/telemetry.pb.swift index 737ebf95..e652a89c 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/telemetry.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/telemetry.pb.swift @@ -1,6 +1,5 @@ // DO NOT EDIT. // swift-format-ignore-file -// swiftlint:disable all // // Generated by the Swift generator plugin for the protocol buffer compiler. // Source: meshtastic/telemetry.proto @@ -8,6 +7,7 @@ // For information on using the generated types, please see the documentation: // https://github.com/apple/swift-protobuf/ +import Foundation import SwiftProtobuf // If the compiler emits an error on this type, it is because this file @@ -22,7 +22,7 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP /// /// Supported I2C Sensors for telemetry in Meshtastic -public enum TelemetrySensorType: SwiftProtobuf.Enum, Swift.CaseIterable { +public enum TelemetrySensorType: SwiftProtobuf.Enum { public typealias RawValue = Int /// @@ -164,6 +164,10 @@ public enum TelemetrySensorType: SwiftProtobuf.Enum, Swift.CaseIterable { /// /// High accuracy current and voltage case ina226 // = 34 + + /// + /// DFRobot Gravity tipping bucket rain gauge + case dfrobotRain // = 35 case UNRECOGNIZED(Int) public init() { @@ -207,6 +211,7 @@ public enum TelemetrySensorType: SwiftProtobuf.Enum, Swift.CaseIterable { case 32: self = .scd4X case 33: self = .radsens case 34: self = .ina226 + case 35: self = .dfrobotRain default: self = .UNRECOGNIZED(rawValue) } } @@ -248,10 +253,16 @@ public enum TelemetrySensorType: SwiftProtobuf.Enum, Swift.CaseIterable { case .scd4X: return 32 case .radsens: return 33 case .ina226: return 34 + case .dfrobotRain: return 35 case .UNRECOGNIZED(let i): return i } } +} + +#if swift(>=4.2) + +extension TelemetrySensorType: CaseIterable { // The compiler won't synthesize support with the UNRECOGNIZED case. public static let allCases: [TelemetrySensorType] = [ .sensorUnset, @@ -289,13 +300,15 @@ public enum TelemetrySensorType: SwiftProtobuf.Enum, Swift.CaseIterable { .scd4X, .radsens, .ina226, + .dfrobotRain, ] - } +#endif // swift(>=4.2) + /// /// Key native device metrics such as battery level -public struct DeviceMetrics: Sendable { +public struct DeviceMetrics { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -368,7 +381,7 @@ public struct DeviceMetrics: Sendable { /// /// Weather station or other environmental metrics -public struct EnvironmentMetrics: @unchecked Sendable { +public struct EnvironmentMetrics { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -573,6 +586,28 @@ public struct EnvironmentMetrics: @unchecked Sendable { /// Clears the value of `radiation`. Subsequent reads from it will return its default value. public mutating func clearRadiation() {_uniqueStorage()._radiation = nil} + /// + /// Rainfall in the last hour in mm + public var rainfall1H: Float { + get {return _storage._rainfall1H ?? 0} + set {_uniqueStorage()._rainfall1H = newValue} + } + /// Returns true if `rainfall1H` has been explicitly set. + public var hasRainfall1H: Bool {return _storage._rainfall1H != nil} + /// Clears the value of `rainfall1H`. Subsequent reads from it will return its default value. + public mutating func clearRainfall1H() {_uniqueStorage()._rainfall1H = nil} + + /// + /// Rainfall in the last 24 hours in mm + public var rainfall24H: Float { + get {return _storage._rainfall24H ?? 0} + set {_uniqueStorage()._rainfall24H = newValue} + } + /// Returns true if `rainfall24H` has been explicitly set. + public var hasRainfall24H: Bool {return _storage._rainfall24H != nil} + /// Clears the value of `rainfall24H`. Subsequent reads from it will return its default value. + public mutating func clearRainfall24H() {_uniqueStorage()._rainfall24H = nil} + public var unknownFields = SwiftProtobuf.UnknownStorage() public init() {} @@ -582,7 +617,7 @@ public struct EnvironmentMetrics: @unchecked Sendable { /// /// Power Metrics (voltage / current / etc) -public struct PowerMetrics: Sendable { +public struct PowerMetrics { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -667,7 +702,7 @@ public struct PowerMetrics: Sendable { /// /// Air quality metrics -public struct AirQualityMetrics: Sendable { +public struct AirQualityMetrics { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -836,7 +871,7 @@ public struct AirQualityMetrics: Sendable { /// /// Local device mesh statistics -public struct LocalStats: Sendable { +public struct LocalStats { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -894,7 +929,7 @@ public struct LocalStats: Sendable { /// /// Health telemetry metrics -public struct HealthMetrics: Sendable { +public struct HealthMetrics { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -943,7 +978,7 @@ public struct HealthMetrics: Sendable { /// /// Types of Measurements the telemetry module is equipped to handle -public struct Telemetry: Sendable { +public struct Telemetry { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -1016,7 +1051,7 @@ public struct Telemetry: Sendable { public var unknownFields = SwiftProtobuf.UnknownStorage() - public enum OneOf_Variant: Equatable, Sendable { + public enum OneOf_Variant: Equatable { /// /// Key native device metrics such as battery level case deviceMetrics(DeviceMetrics) @@ -1036,6 +1071,40 @@ public struct Telemetry: Sendable { /// Health telemetry metrics case healthMetrics(HealthMetrics) + #if !swift(>=4.1) + public static func ==(lhs: Telemetry.OneOf_Variant, rhs: Telemetry.OneOf_Variant) -> Bool { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch (lhs, rhs) { + case (.deviceMetrics, .deviceMetrics): return { + guard case .deviceMetrics(let l) = lhs, case .deviceMetrics(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.environmentMetrics, .environmentMetrics): return { + guard case .environmentMetrics(let l) = lhs, case .environmentMetrics(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.airQualityMetrics, .airQualityMetrics): return { + guard case .airQualityMetrics(let l) = lhs, case .airQualityMetrics(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.powerMetrics, .powerMetrics): return { + guard case .powerMetrics(let l) = lhs, case .powerMetrics(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.localStats, .localStats): return { + guard case .localStats(let l) = lhs, case .localStats(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.healthMetrics, .healthMetrics): return { + guard case .healthMetrics(let l) = lhs, case .healthMetrics(let r) = rhs else { preconditionFailure() } + return l == r + }() + default: return false + } + } + #endif } public init() {} @@ -1043,7 +1112,7 @@ public struct Telemetry: Sendable { /// /// NAU7802 Telemetry configuration, for saving to flash -public struct Nau7802Config: Sendable { +public struct Nau7802Config { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -1061,6 +1130,19 @@ public struct Nau7802Config: Sendable { public init() {} } +#if swift(>=5.5) && canImport(_Concurrency) +extension TelemetrySensorType: @unchecked Sendable {} +extension DeviceMetrics: @unchecked Sendable {} +extension EnvironmentMetrics: @unchecked Sendable {} +extension PowerMetrics: @unchecked Sendable {} +extension AirQualityMetrics: @unchecked Sendable {} +extension LocalStats: @unchecked Sendable {} +extension HealthMetrics: @unchecked Sendable {} +extension Telemetry: @unchecked Sendable {} +extension Telemetry.OneOf_Variant: @unchecked Sendable {} +extension Nau7802Config: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + // MARK: - Code below here is support for the SwiftProtobuf runtime. fileprivate let _protobuf_package = "meshtastic" @@ -1102,6 +1184,7 @@ extension TelemetrySensorType: SwiftProtobuf._ProtoNameProviding { 32: .same(proto: "SCD4X"), 33: .same(proto: "RADSENS"), 34: .same(proto: "INA226"), + 35: .same(proto: "DFROBOT_RAIN"), ] } @@ -1186,6 +1269,8 @@ extension EnvironmentMetrics: SwiftProtobuf.Message, SwiftProtobuf._MessageImple 16: .standard(proto: "wind_gust"), 17: .standard(proto: "wind_lull"), 18: .same(proto: "radiation"), + 19: .standard(proto: "rainfall_1h"), + 20: .standard(proto: "rainfall_24h"), ] fileprivate class _StorageClass { @@ -1207,6 +1292,8 @@ extension EnvironmentMetrics: SwiftProtobuf.Message, SwiftProtobuf._MessageImple var _windGust: Float? = nil var _windLull: Float? = nil var _radiation: Float? = nil + var _rainfall1H: Float? = nil + var _rainfall24H: Float? = nil #if swift(>=5.10) // This property is used as the initial default value for new instances of the type. @@ -1239,6 +1326,8 @@ extension EnvironmentMetrics: SwiftProtobuf.Message, SwiftProtobuf._MessageImple _windGust = source._windGust _windLull = source._windLull _radiation = source._radiation + _rainfall1H = source._rainfall1H + _rainfall24H = source._rainfall24H } } @@ -1275,6 +1364,8 @@ extension EnvironmentMetrics: SwiftProtobuf.Message, SwiftProtobuf._MessageImple case 16: try { try decoder.decodeSingularFloatField(value: &_storage._windGust) }() case 17: try { try decoder.decodeSingularFloatField(value: &_storage._windLull) }() case 18: try { try decoder.decodeSingularFloatField(value: &_storage._radiation) }() + case 19: try { try decoder.decodeSingularFloatField(value: &_storage._rainfall1H) }() + case 20: try { try decoder.decodeSingularFloatField(value: &_storage._rainfall24H) }() default: break } } @@ -1341,6 +1432,12 @@ extension EnvironmentMetrics: SwiftProtobuf.Message, SwiftProtobuf._MessageImple try { if let v = _storage._radiation { try visitor.visitSingularFloatField(value: v, fieldNumber: 18) } }() + try { if let v = _storage._rainfall1H { + try visitor.visitSingularFloatField(value: v, fieldNumber: 19) + } }() + try { if let v = _storage._rainfall24H { + try visitor.visitSingularFloatField(value: v, fieldNumber: 20) + } }() } try unknownFields.traverse(visitor: &visitor) } @@ -1368,6 +1465,8 @@ extension EnvironmentMetrics: SwiftProtobuf.Message, SwiftProtobuf._MessageImple if _storage._windGust != rhs_storage._windGust {return false} if _storage._windLull != rhs_storage._windLull {return false} if _storage._radiation != rhs_storage._radiation {return false} + if _storage._rainfall1H != rhs_storage._rainfall1H {return false} + if _storage._rainfall24H != rhs_storage._rainfall24H {return false} return true } if !storagesAreEqual {return false} @@ -1593,10 +1692,10 @@ extension LocalStats: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementatio if self.uptimeSeconds != 0 { try visitor.visitSingularUInt32Field(value: self.uptimeSeconds, fieldNumber: 1) } - if self.channelUtilization.bitPattern != 0 { + if self.channelUtilization != 0 { try visitor.visitSingularFloatField(value: self.channelUtilization, fieldNumber: 2) } - if self.airUtilTx.bitPattern != 0 { + if self.airUtilTx != 0 { try visitor.visitSingularFloatField(value: self.airUtilTx, fieldNumber: 3) } if self.numPacketsTx != 0 { @@ -1863,7 +1962,7 @@ extension Nau7802Config: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementa if self.zeroOffset != 0 { try visitor.visitSingularInt32Field(value: self.zeroOffset, fieldNumber: 1) } - if self.calibrationFactor.bitPattern != 0 { + if self.calibrationFactor != 0 { try visitor.visitSingularFloatField(value: self.calibrationFactor, fieldNumber: 2) } try unknownFields.traverse(visitor: &visitor) diff --git a/MeshtasticProtobufs/Sources/meshtastic/xmodem.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/xmodem.pb.swift index 46907a58..1f41fe0b 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/xmodem.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/xmodem.pb.swift @@ -1,6 +1,5 @@ // DO NOT EDIT. // swift-format-ignore-file -// swiftlint:disable all // // Generated by the Swift generator plugin for the protocol buffer compiler. // Source: meshtastic/xmodem.proto @@ -21,7 +20,7 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP typealias Version = _2 } -public struct XModem: @unchecked Sendable { +public struct XModem { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -36,7 +35,7 @@ public struct XModem: @unchecked Sendable { public var unknownFields = SwiftProtobuf.UnknownStorage() - public enum Control: SwiftProtobuf.Enum, Swift.CaseIterable { + public enum Control: SwiftProtobuf.Enum { public typealias RawValue = Int case nul // = 0 case soh // = 1 @@ -80,23 +79,34 @@ public struct XModem: @unchecked Sendable { } } - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [XModem.Control] = [ - .nul, - .soh, - .stx, - .eot, - .ack, - .nak, - .can, - .ctrlz, - ] - } public init() {} } +#if swift(>=4.2) + +extension XModem.Control: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [XModem.Control] = [ + .nul, + .soh, + .stx, + .eot, + .ack, + .nak, + .can, + .ctrlz, + ] +} + +#endif // swift(>=4.2) + +#if swift(>=5.5) && canImport(_Concurrency) +extension XModem: @unchecked Sendable {} +extension XModem.Control: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + // MARK: - Code below here is support for the SwiftProtobuf runtime. fileprivate let _protobuf_package = "meshtastic" diff --git a/ci_scripts/ci_pre_xcodebuild.sh b/ci_scripts/ci_pre_xcodebuild.sh new file mode 100755 index 00000000..23aec511 --- /dev/null +++ b/ci_scripts/ci_pre_xcodebuild.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +echo "Stage: PRE-Xcode Build is activated .... " + +# Move to the place where the scripts are located. +# This is important because the position of the subsequently mentioned files depend of this origin. +cd $CI_PRIMARY_REPOSITORY_PATH/ci_scripts || exit 1 + +# Write a JSON File containing all the environment variables and secrets. +printf "{\"PUBLIC_MQTT_USERNAME\":\"%s\",\"PUBLIC_MQTT_PASSWORD\":\"%s\"}" "$PUBLIC_MQTT_USERNAME" "$PUBLIC_MQTT_PASSWORD" >> .\ $CI_PRIMARY_REPOSITORY_PATH/SupportingFiles/secrets.json + +echo "Wrote Secrets.json file." + +echo "Stage: PRE-Xcode Build is DONE .... " + +exit 0 diff --git a/protobufs b/protobufs index 76f806e1..06864665 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 76f806e1bb1e2a7b157a14fadd095775f63db5e4 +Subproject commit 068646653e8375fc145988026ad242a3cf70f7ab