diff --git a/lib/connector/meshcore_protocol.dart b/lib/connector/meshcore_protocol.dart index 0f2deefa..44692ca5 100644 --- a/lib/connector/meshcore_protocol.dart +++ b/lib/connector/meshcore_protocol.dart @@ -227,6 +227,12 @@ const int reqTypeGetTelemetry = 0x03; const int reqTypeGetAccessList = 0x05; const int reqTypeGetNeighbors = 0x06; +Uint8List buildTelemetryBinaryPayload() { + // Room servers/repeaters read byte 1 as an inverse telemetry permission mask. + // Zero means "request every telemetry field allowed for this contact". + return Uint8List.fromList([reqTypeGetTelemetry, 0x00, 0x00, 0x00, 0x00]); +} + const int anonReqTypeRegions = 0x01; // Control data sub-types used by MeshCore discovery packets. diff --git a/lib/helpers/cayenne_lpp.dart b/lib/helpers/cayenne_lpp.dart index 07909e63..021e9cc5 100644 --- a/lib/helpers/cayenne_lpp.dart +++ b/lib/helpers/cayenne_lpp.dart @@ -96,6 +96,34 @@ class CayenneLpp { } switch (type) { + case lppDigitalInput: + telemetry.add({ + 'channel': channel, + 'type': type, + 'value': buffer.readUInt8(), + }); + break; + case lppDigitalOutput: + telemetry.add({ + 'channel': channel, + 'type': type, + 'value': buffer.readUInt8(), + }); + break; + case lppAnalogInput: + telemetry.add({ + 'channel': channel, + 'type': type, + 'value': buffer.readInt16BE() / 100, + }); + break; + case lppAnalogOutput: + telemetry.add({ + 'channel': channel, + 'type': type, + 'value': buffer.readInt16BE() / 100, + }); + break; case lppGenericSensor: telemetry.add({ 'channel': channel, @@ -131,6 +159,17 @@ class CayenneLpp { 'value': buffer.readUInt8() / 2, }); break; + case lppAccelerometer: + telemetry.add({ + 'channel': channel, + 'type': type, + 'value': { + 'x': buffer.readInt16BE() / 1000, + 'y': buffer.readInt16BE() / 1000, + 'z': buffer.readInt16BE() / 1000, + }, + }); + break; case lppBarometricPressure: telemetry.add({ 'channel': channel, @@ -138,6 +177,13 @@ class CayenneLpp { 'value': buffer.readUInt16BE() / 10, }); break; + case lppAltitude: + telemetry.add({ + 'channel': channel, + 'type': type, + 'value': buffer.readInt16BE(), + }); + break; case lppVoltage: telemetry.add({ 'channel': channel, @@ -152,6 +198,13 @@ class CayenneLpp { 'value': buffer.readInt16BE() / 1000, }); break; + case lppFrequency: + telemetry.add({ + 'channel': channel, + 'type': type, + 'value': buffer.readUInt32BE(), + }); + break; case lppPercentage: telemetry.add({ 'channel': channel, @@ -173,6 +226,56 @@ class CayenneLpp { 'value': buffer.readUInt16BE(), }); break; + case lppDistance: + telemetry.add({ + 'channel': channel, + 'type': type, + 'value': buffer.readUInt32BE() / 1000, + }); + break; + case lppEnergy: + telemetry.add({ + 'channel': channel, + 'type': type, + 'value': buffer.readUInt32BE() / 1000, + }); + break; + case lppDirection: + telemetry.add({ + 'channel': channel, + 'type': type, + 'value': buffer.readUInt16BE(), + }); + break; + case lppUnixTime: + telemetry.add({ + 'channel': channel, + 'type': type, + 'value': buffer.readUInt32BE(), + }); + break; + case lppGyrometer: + telemetry.add({ + 'channel': channel, + 'type': type, + 'value': { + 'x': buffer.readInt16BE() / 100, + 'y': buffer.readInt16BE() / 100, + 'z': buffer.readInt16BE() / 100, + }, + }); + break; + case lppColour: + telemetry.add({ + 'channel': channel, + 'type': type, + 'value': { + 'red': buffer.readUInt8(), + 'green': buffer.readUInt8(), + 'blue': buffer.readUInt8(), + }, + }); + break; case lppGps: telemetry.add({ 'channel': channel, @@ -184,6 +287,24 @@ class CayenneLpp { }, }); break; + case lppSwitch: + telemetry.add({ + 'channel': channel, + 'type': type, + 'value': buffer.readUInt8(), + }); + break; + case lppPolyline: + final size = buffer.readUInt8(); + telemetry.add({ + 'channel': channel, + 'type': type, + 'value': { + 'size': size, + 'data': _bytesToHex(_readPolylinePayload(buffer, size)), + }, + }); + break; default: return telemetry; } @@ -216,6 +337,19 @@ class CayenneLpp { ); switch (type) { + case lppDigitalInput: + channelData['values']['digitalInput'] = buffer.readUInt8(); + break; + case lppDigitalOutput: + channelData['values']['digitalOutput'] = buffer.readUInt8(); + break; + case lppAnalogInput: + channelData['values']['analogInput'] = buffer.readInt16BE() / 100.0; + break; + case lppAnalogOutput: + channelData['values']['analogOutput'] = + buffer.readInt16BE() / 100.0; + break; case lppGenericSensor: channelData['values']['generic'] = buffer.readUInt32BE(); break; @@ -231,15 +365,29 @@ class CayenneLpp { case lppRelativeHumidity: channelData['values']['humidity'] = buffer.readUInt8() / 2.0; break; + case lppAccelerometer: + channelData['values']['accelerometer'] = { + 'x': buffer.readInt16BE() / 1000.0, + 'y': buffer.readInt16BE() / 1000.0, + 'z': buffer.readInt16BE() / 1000.0, + }; + break; case lppBarometricPressure: channelData['values']['pressure'] = buffer.readUInt16BE() / 10.0; break; + case lppAltitude: + // MeshCore encodes standalone barometric altitude as LPP type 121. + channelData['values']['altitude'] = buffer.readInt16BE(); + break; case lppVoltage: channelData['values']['voltage'] = buffer.readInt16BE() / 100.0; break; case lppCurrent: channelData['values']['current'] = buffer.readInt16BE() / 1000.0; break; + case lppFrequency: + channelData['values']['frequency'] = buffer.readUInt32BE(); + break; case lppPercentage: channelData['values']['percentage'] = buffer.readUInt8(); break; @@ -249,6 +397,32 @@ class CayenneLpp { case lppPower: channelData['values']['power'] = buffer.readUInt16BE(); break; + case lppDistance: + channelData['values']['distance'] = buffer.readUInt32BE() / 1000.0; + break; + case lppEnergy: + channelData['values']['energy'] = buffer.readUInt32BE() / 1000.0; + break; + case lppDirection: + channelData['values']['direction'] = buffer.readUInt16BE(); + break; + case lppUnixTime: + channelData['values']['time'] = buffer.readUInt32BE(); + break; + case lppGyrometer: + channelData['values']['gyrometer'] = { + 'x': buffer.readInt16BE() / 100.0, + 'y': buffer.readInt16BE() / 100.0, + 'z': buffer.readInt16BE() / 100.0, + }; + break; + case lppColour: + channelData['values']['colour'] = { + 'red': buffer.readUInt8(), + 'green': buffer.readUInt8(), + 'blue': buffer.readUInt8(), + }; + break; case lppGps: channelData['values']['gps'] = { 'latitude': buffer.readInt24BE() / 10000.0, @@ -256,22 +430,48 @@ class CayenneLpp { 'altitude': buffer.readInt24BE() / 100.0, }; break; - // Add more types as needed... + case lppSwitch: + channelData['values']['switch'] = buffer.readUInt8() != 0; + break; + case lppPolyline: + final size = buffer.readUInt8(); + channelData['values']['polyline'] = { + 'size': size, + 'data': _bytesToHex(_readPolylinePayload(buffer, size)), + }; + break; default: - //Stopped parsing to avoid misalignment - return channels.values.toList(); + // Stop parsing to avoid losing alignment on an unknown LPP type. + return _sortedChannelValues(channels); } } - final List> channelsOut = channels.values.toList(); - channelsOut.sort((a, b) => a['channel'].compareTo(b['channel'])); - return channelsOut; + return _sortedChannelValues(channels); } catch (e) { // Handle parsing errors, possibly due to malformed data appLogger.error('Error parsing Cayenne LPP data: $e'); - return < - Map - >[]; // Return an empty list on error to avoid crashing the app + // Preserve any fields parsed before the malformed value. + return _sortedChannelValues(channels); } } + + static Uint8List _readPolylinePayload(BufferReader buffer, int size) { + final declaredPayloadSize = size > 0 ? size - 1 : 0; + final availablePayloadSize = declaredPayloadSize <= buffer.remaining + ? declaredPayloadSize + : buffer.remaining; + return buffer.readBytes(availablePayloadSize); + } + + static List> _sortedChannelValues( + Map> channels, + ) { + final channelsOut = channels.values.toList(); + channelsOut.sort((a, b) => a['channel'].compareTo(b['channel'])); + return channelsOut; + } + + static String _bytesToHex(Uint8List bytes) { + return bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join(); + } } diff --git a/lib/l10n/app_bg.arb b/lib/l10n/app_bg.arb index c70ca78d..496b3e3d 100644 --- a/lib/l10n/app_bg.arb +++ b/lib/l10n/app_bg.arb @@ -33,6 +33,8 @@ "common_remove": "Изтрий", "common_enable": "Активирай", "common_disable": "Деактивирай", + "common_autoRefresh": "Автоматично обновяване", + "common_interval": "Интервал", "common_reboot": "Рестартирай", "common_loading": "Зареждане...", "common_notAvailable": "—", @@ -1280,6 +1282,43 @@ } } }, + "telemetry_digitalInputLabel": "Цифров вход", + "telemetry_digitalOutputLabel": "Цифров изход", + "telemetry_analogInputLabel": "Аналогов вход", + "telemetry_analogOutputLabel": "Аналогов изход", + "telemetry_genericLabel": "Общ сензор", + "telemetry_luminosityLabel": "Осветеност", + "telemetry_presenceLabel": "Присъствие", + "telemetry_humidityLabel": "Влажност", + "telemetry_accelerometerLabel": "Акселерометър", + "telemetry_pressureLabel": "Налягане", + "telemetry_altitudeLabel": "Надморска височина", + "telemetry_frequencyLabel": "Честота", + "telemetry_percentageLabel": "Процент", + "telemetry_concentrationLabel": "Концентрация", + "telemetry_powerLabel": "Мощност", + "telemetry_distanceLabel": "Разстояние", + "telemetry_energyLabel": "Енергия", + "telemetry_directionLabel": "Посока", + "telemetry_timeLabel": "Време", + "telemetry_gyrometerLabel": "Жироскоп", + "telemetry_colourLabel": "Цвят", + "telemetry_gpsLabel": "GPS", + "telemetry_switchLabel": "Превключвател", + "telemetry_polylineLabel": "Полилиния", + "telemetry_altitudeValue": "{meters} m", + "telemetry_frequencyValue": "{hertz} Hz", + "telemetry_pressureValue": "{hpa} hPa", + "telemetry_luminosityValue": "{lux} lx", + "telemetry_powerValue": "{watts} W", + "telemetry_distanceValue": "{meters} m", + "telemetry_energyValue": "{kilowattHours} kWh", + "telemetry_directionValue": "{degrees}°", + "telemetry_concentrationValue": "{ppm} ppm", + "telemetry_percentageValue": "{percent}%", + "telemetry_analogValue": "{value}", + "telemetry_autoFetchQuantity": "Брой заявки", + "telemetry_error": "Неуспешно получаване на данни", "telemetry_noData": "Няма налични данни за телеметрията.", "telemetry_channelTitle": "Канал {channel}", "@telemetry_channelTitle": { diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index cd4f562f..61d3acf3 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -33,6 +33,8 @@ "common_remove": "Löschen", "common_enable": "Aktivieren", "common_disable": "Deaktivieren", + "common_autoRefresh": "Automatische Aktualisierung", + "common_interval": "Intervall", "common_reboot": "Neustart", "common_loading": "Laden...", "common_notAvailable": "—", @@ -1280,6 +1282,43 @@ } } }, + "telemetry_digitalInputLabel": "Digitaleingang", + "telemetry_digitalOutputLabel": "Digitalausgang", + "telemetry_analogInputLabel": "Analogeingang", + "telemetry_analogOutputLabel": "Analogausgang", + "telemetry_genericLabel": "Allgemeiner Sensor", + "telemetry_luminosityLabel": "Helligkeit", + "telemetry_presenceLabel": "Anwesenheit", + "telemetry_humidityLabel": "Luftfeuchtigkeit", + "telemetry_accelerometerLabel": "Beschleunigungsmesser", + "telemetry_pressureLabel": "Druck", + "telemetry_altitudeLabel": "Höhe", + "telemetry_frequencyLabel": "Frequenz", + "telemetry_percentageLabel": "Prozentsatz", + "telemetry_concentrationLabel": "Konzentration", + "telemetry_powerLabel": "Leistung", + "telemetry_distanceLabel": "Entfernung", + "telemetry_energyLabel": "Energie", + "telemetry_directionLabel": "Richtung", + "telemetry_timeLabel": "Zeit", + "telemetry_gyrometerLabel": "Gyroskop", + "telemetry_colourLabel": "Farbe", + "telemetry_gpsLabel": "GPS", + "telemetry_switchLabel": "Schalter", + "telemetry_polylineLabel": "Polylinie", + "telemetry_altitudeValue": "{meters} m", + "telemetry_frequencyValue": "{hertz} Hz", + "telemetry_pressureValue": "{hpa} hPa", + "telemetry_luminosityValue": "{lux} lx", + "telemetry_powerValue": "{watts} W", + "telemetry_distanceValue": "{meters} m", + "telemetry_energyValue": "{kilowattHours} kWh", + "telemetry_directionValue": "{degrees}°", + "telemetry_concentrationValue": "{ppm} ppm", + "telemetry_percentageValue": "{percent}%", + "telemetry_analogValue": "{value}", + "telemetry_autoFetchQuantity": "Anzahl der Anfragen", + "telemetry_error": "Daten konnten nicht abgerufen werden", "telemetry_noData": "Keine Telemetriedaten verfügbar.", "telemetry_channelTitle": "Kanal {channel}", "@telemetry_channelTitle": { diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index ddcdd075..398b270c 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -47,6 +47,8 @@ } } }, + "common_autoRefresh": "Autorefresh", + "common_interval": "Interval", "scanner_title": "MeshCore Open", "connectionChoiceUsbLabel": "USB", "connectionChoiceBluetoothLabel": "Bluetooth", @@ -1692,6 +1694,120 @@ } } }, + "telemetry_digitalInputLabel": "Digital Input", + "telemetry_digitalOutputLabel": "Digital Output", + "telemetry_analogInputLabel": "Analog Input", + "telemetry_analogOutputLabel": "Analog Output", + "telemetry_genericLabel": "Generic Sensor", + "telemetry_luminosityLabel": "Luminosity", + "telemetry_presenceLabel": "Presence", + "telemetry_humidityLabel": "Humidity", + "telemetry_accelerometerLabel": "Accelerometer", + "telemetry_pressureLabel": "Pressure", + "telemetry_altitudeLabel": "Altitude", + "telemetry_frequencyLabel": "Frequency", + "telemetry_percentageLabel": "Percentage", + "telemetry_concentrationLabel": "Concentration", + "telemetry_powerLabel": "Power", + "telemetry_distanceLabel": "Distance", + "telemetry_energyLabel": "Energy", + "telemetry_directionLabel": "Direction", + "telemetry_timeLabel": "Time", + "telemetry_gyrometerLabel": "Gyrometer", + "telemetry_colourLabel": "Colour", + "telemetry_gpsLabel": "GPS", + "telemetry_switchLabel": "Switch", + "telemetry_polylineLabel": "Polyline", + "telemetry_altitudeValue": "{meters} m", + "@telemetry_altitudeValue": { + "placeholders": { + "meters": { + "type": "String" + } + } + }, + "telemetry_frequencyValue": "{hertz} Hz", + "@telemetry_frequencyValue": { + "placeholders": { + "hertz": { + "type": "String" + } + } + }, + "telemetry_pressureValue": "{hpa} hPa", + "@telemetry_pressureValue": { + "placeholders": { + "hpa": { + "type": "String" + } + } + }, + "telemetry_luminosityValue": "{lux} lx", + "@telemetry_luminosityValue": { + "placeholders": { + "lux": { + "type": "String" + } + } + }, + "telemetry_powerValue": "{watts} W", + "@telemetry_powerValue": { + "placeholders": { + "watts": { + "type": "String" + } + } + }, + "telemetry_distanceValue": "{meters} m", + "@telemetry_distanceValue": { + "placeholders": { + "meters": { + "type": "String" + } + } + }, + "telemetry_energyValue": "{kilowattHours} kWh", + "@telemetry_energyValue": { + "placeholders": { + "kilowattHours": { + "type": "String" + } + } + }, + "telemetry_directionValue": "{degrees}°", + "@telemetry_directionValue": { + "placeholders": { + "degrees": { + "type": "String" + } + } + }, + "telemetry_concentrationValue": "{ppm} ppm", + "@telemetry_concentrationValue": { + "placeholders": { + "ppm": { + "type": "String" + } + } + }, + "telemetry_percentageValue": "{percent}%", + "@telemetry_percentageValue": { + "placeholders": { + "percent": { + "type": "String" + } + } + }, + "telemetry_analogValue": "{value}", + "@telemetry_analogValue": { + "placeholders": { + "value": { + "type": "String" + } + } + }, + "telemetry_autoFetchQuantity": "Requests quantity", + "telemetry_error": "Unable to retrieve data", "neighbors_receivedData": "Received Neighbors Data", "neighbors_requestTimedOut": "Neighbors request timed out.", "neighbors_errorLoading": "Error loading neighbors: {error}", diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index b85e7652..f24fb52a 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -33,6 +33,8 @@ "common_remove": "Eliminar", "common_enable": "Activar", "common_disable": "Desactivar", + "common_autoRefresh": "Actualización automática", + "common_interval": "Intervalo", "common_reboot": "Reiniciar", "common_loading": "Cargando...", "common_notAvailable": "—", @@ -1280,6 +1282,43 @@ } } }, + "telemetry_digitalInputLabel": "Entrada digital", + "telemetry_digitalOutputLabel": "Salida digital", + "telemetry_analogInputLabel": "Entrada analógica", + "telemetry_analogOutputLabel": "Salida analógica", + "telemetry_genericLabel": "Sensor genérico", + "telemetry_luminosityLabel": "Luminosidad", + "telemetry_presenceLabel": "Presencia", + "telemetry_humidityLabel": "Humedad", + "telemetry_accelerometerLabel": "Acelerómetro", + "telemetry_pressureLabel": "Presión", + "telemetry_altitudeLabel": "Altitud", + "telemetry_frequencyLabel": "Frecuencia", + "telemetry_percentageLabel": "Porcentaje", + "telemetry_concentrationLabel": "Concentración", + "telemetry_powerLabel": "Potencia", + "telemetry_distanceLabel": "Distancia", + "telemetry_energyLabel": "Energía", + "telemetry_directionLabel": "Dirección", + "telemetry_timeLabel": "Hora", + "telemetry_gyrometerLabel": "Girómetro", + "telemetry_colourLabel": "Color", + "telemetry_gpsLabel": "GPS", + "telemetry_switchLabel": "Interruptor", + "telemetry_polylineLabel": "Polilínea", + "telemetry_altitudeValue": "{meters} m", + "telemetry_frequencyValue": "{hertz} Hz", + "telemetry_pressureValue": "{hpa} hPa", + "telemetry_luminosityValue": "{lux} lx", + "telemetry_powerValue": "{watts} W", + "telemetry_distanceValue": "{meters} m", + "telemetry_energyValue": "{kilowattHours} kWh", + "telemetry_directionValue": "{degrees}°", + "telemetry_concentrationValue": "{ppm} ppm", + "telemetry_percentageValue": "{percent}%", + "telemetry_analogValue": "{value}", + "telemetry_autoFetchQuantity": "Número de solicitudes", + "telemetry_error": "No se pudieron obtener los datos", "telemetry_noData": "No hay datos de telemetría disponibles.", "telemetry_channelTitle": "Canal {channel}", "@telemetry_channelTitle": { diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index fd6b53e0..710ee53a 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -33,6 +33,8 @@ "common_remove": "Supprimer", "common_enable": "Activer", "common_disable": "Désactiver", + "common_autoRefresh": "Actualisation automatique", + "common_interval": "Intervalle", "common_reboot": "Redémarrer", "common_loading": "Chargement...", "common_notAvailable": "—", @@ -1280,6 +1282,43 @@ } } }, + "telemetry_digitalInputLabel": "Entrée numérique", + "telemetry_digitalOutputLabel": "Sortie numérique", + "telemetry_analogInputLabel": "Entrée analogique", + "telemetry_analogOutputLabel": "Sortie analogique", + "telemetry_genericLabel": "Capteur générique", + "telemetry_luminosityLabel": "Luminosité", + "telemetry_presenceLabel": "Présence", + "telemetry_humidityLabel": "Humidité", + "telemetry_accelerometerLabel": "Accéléromètre", + "telemetry_pressureLabel": "Pression", + "telemetry_altitudeLabel": "Altitude", + "telemetry_frequencyLabel": "Fréquence", + "telemetry_percentageLabel": "Pourcentage", + "telemetry_concentrationLabel": "Concentration", + "telemetry_powerLabel": "Puissance", + "telemetry_distanceLabel": "Distance", + "telemetry_energyLabel": "Énergie", + "telemetry_directionLabel": "Direction", + "telemetry_timeLabel": "Heure", + "telemetry_gyrometerLabel": "Gyromètre", + "telemetry_colourLabel": "Couleur", + "telemetry_gpsLabel": "GPS", + "telemetry_switchLabel": "Interrupteur", + "telemetry_polylineLabel": "Polyligne", + "telemetry_altitudeValue": "{meters} m", + "telemetry_frequencyValue": "{hertz} Hz", + "telemetry_pressureValue": "{hpa} hPa", + "telemetry_luminosityValue": "{lux} lx", + "telemetry_powerValue": "{watts} W", + "telemetry_distanceValue": "{meters} m", + "telemetry_energyValue": "{kilowattHours} kWh", + "telemetry_directionValue": "{degrees}°", + "telemetry_concentrationValue": "{ppm} ppm", + "telemetry_percentageValue": "{percent}%", + "telemetry_analogValue": "{value}", + "telemetry_autoFetchQuantity": "Nombre de requêtes", + "telemetry_error": "Impossible de récupérer les données", "telemetry_noData": "Aucune donnée de télémétrie disponible.", "telemetry_channelTitle": "Canal {channel}", "@telemetry_channelTitle": { diff --git a/lib/l10n/app_hu.arb b/lib/l10n/app_hu.arb index d41c62f2..1807fa68 100644 --- a/lib/l10n/app_hu.arb +++ b/lib/l10n/app_hu.arb @@ -27,6 +27,8 @@ "common_remove": "Eltávolít", "common_enable": "Engedélyezés", "common_disable": "Leteteszt", + "common_autoRefresh": "Automatikus frissítés", + "common_interval": "Intervallum", "common_reboot": "Újraindítás", "common_loading": "Betöltés...", "common_notAvailable": "—", @@ -1466,6 +1468,43 @@ } } }, + "telemetry_digitalInputLabel": "Digitális bemenet", + "telemetry_digitalOutputLabel": "Digitális kimenet", + "telemetry_analogInputLabel": "Analóg bemenet", + "telemetry_analogOutputLabel": "Analóg kimenet", + "telemetry_genericLabel": "Általános érzékelő", + "telemetry_luminosityLabel": "Fényerő", + "telemetry_presenceLabel": "Jelenlét", + "telemetry_humidityLabel": "Páratartalom", + "telemetry_accelerometerLabel": "Gyorsulásmérő", + "telemetry_pressureLabel": "Nyomás", + "telemetry_altitudeLabel": "Magasság", + "telemetry_frequencyLabel": "Frekvencia", + "telemetry_percentageLabel": "Százalék", + "telemetry_concentrationLabel": "Koncentráció", + "telemetry_powerLabel": "Teljesítmény", + "telemetry_distanceLabel": "Távolság", + "telemetry_energyLabel": "Energia", + "telemetry_directionLabel": "Irány", + "telemetry_timeLabel": "Idő", + "telemetry_gyrometerLabel": "Giroszkóp", + "telemetry_colourLabel": "Szín", + "telemetry_gpsLabel": "GPS", + "telemetry_switchLabel": "Kapcsoló", + "telemetry_polylineLabel": "Töröttvonal", + "telemetry_altitudeValue": "{meters} m", + "telemetry_frequencyValue": "{hertz} Hz", + "telemetry_pressureValue": "{hpa} hPa", + "telemetry_luminosityValue": "{lux} lx", + "telemetry_powerValue": "{watts} W", + "telemetry_distanceValue": "{meters} m", + "telemetry_energyValue": "{kilowattHours} kWh", + "telemetry_directionValue": "{degrees}°", + "telemetry_concentrationValue": "{ppm} ppm", + "telemetry_percentageValue": "{percent}%", + "telemetry_analogValue": "{value}", + "telemetry_autoFetchQuantity": "Kérések száma", + "telemetry_error": "Nem sikerült lekérni az adatokat", "telemetry_noData": "Nincsenek elérhető telemetriadatok.", "telemetry_channelTitle": "{channel} csatorna", "@telemetry_channelTitle": { diff --git a/lib/l10n/app_it.arb b/lib/l10n/app_it.arb index e60cfc4a..d378d19d 100644 --- a/lib/l10n/app_it.arb +++ b/lib/l10n/app_it.arb @@ -33,6 +33,8 @@ "common_remove": "Elimina", "common_enable": "Abilita", "common_disable": "Disattivare", + "common_autoRefresh": "Aggiornamento automatico", + "common_interval": "Intervallo", "common_reboot": "Riavvia", "common_loading": "Caricamento...", "common_notAvailable": "—", @@ -1280,6 +1282,43 @@ } } }, + "telemetry_digitalInputLabel": "Ingresso digitale", + "telemetry_digitalOutputLabel": "Uscita digitale", + "telemetry_analogInputLabel": "Ingresso analogico", + "telemetry_analogOutputLabel": "Uscita analogica", + "telemetry_genericLabel": "Sensore generico", + "telemetry_luminosityLabel": "Luminosità", + "telemetry_presenceLabel": "Presenza", + "telemetry_humidityLabel": "Umidità", + "telemetry_accelerometerLabel": "Accelerometro", + "telemetry_pressureLabel": "Pressione", + "telemetry_altitudeLabel": "Altitudine", + "telemetry_frequencyLabel": "Frequenza", + "telemetry_percentageLabel": "Percentuale", + "telemetry_concentrationLabel": "Concentrazione", + "telemetry_powerLabel": "Potenza", + "telemetry_distanceLabel": "Distanza", + "telemetry_energyLabel": "Energia", + "telemetry_directionLabel": "Direzione", + "telemetry_timeLabel": "Ora", + "telemetry_gyrometerLabel": "Giroscopio", + "telemetry_colourLabel": "Colore", + "telemetry_gpsLabel": "GPS", + "telemetry_switchLabel": "Interruttore", + "telemetry_polylineLabel": "Polilinea", + "telemetry_altitudeValue": "{meters} m", + "telemetry_frequencyValue": "{hertz} Hz", + "telemetry_pressureValue": "{hpa} hPa", + "telemetry_luminosityValue": "{lux} lx", + "telemetry_powerValue": "{watts} W", + "telemetry_distanceValue": "{meters} m", + "telemetry_energyValue": "{kilowattHours} kWh", + "telemetry_directionValue": "{degrees}°", + "telemetry_concentrationValue": "{ppm} ppm", + "telemetry_percentageValue": "{percent}%", + "telemetry_analogValue": "{value}", + "telemetry_autoFetchQuantity": "Numero di richieste", + "telemetry_error": "Impossibile recuperare i dati", "telemetry_noData": "Nessun dato di telemetria disponibile.", "telemetry_channelTitle": "Canale {channel}", "@telemetry_channelTitle": { diff --git a/lib/l10n/app_ja.arb b/lib/l10n/app_ja.arb index c68fc98d..b525ce41 100644 --- a/lib/l10n/app_ja.arb +++ b/lib/l10n/app_ja.arb @@ -27,6 +27,8 @@ "common_remove": "削除", "common_enable": "有効化する", "common_disable": "無効化する", + "common_autoRefresh": "自動更新", + "common_interval": "間隔", "common_reboot": "再起動", "common_loading": "読み込み中...", "common_notAvailable": "—", @@ -1466,6 +1468,43 @@ } } }, + "telemetry_digitalInputLabel": "デジタル入力", + "telemetry_digitalOutputLabel": "デジタル出力", + "telemetry_analogInputLabel": "アナログ入力", + "telemetry_analogOutputLabel": "アナログ出力", + "telemetry_genericLabel": "汎用センサー", + "telemetry_luminosityLabel": "照度", + "telemetry_presenceLabel": "在室", + "telemetry_humidityLabel": "湿度", + "telemetry_accelerometerLabel": "加速度計", + "telemetry_pressureLabel": "気圧", + "telemetry_altitudeLabel": "高度", + "telemetry_frequencyLabel": "周波数", + "telemetry_percentageLabel": "パーセント", + "telemetry_concentrationLabel": "濃度", + "telemetry_powerLabel": "電力", + "telemetry_distanceLabel": "距離", + "telemetry_energyLabel": "エネルギー", + "telemetry_directionLabel": "方向", + "telemetry_timeLabel": "時刻", + "telemetry_gyrometerLabel": "ジャイロメーター", + "telemetry_colourLabel": "色", + "telemetry_gpsLabel": "GPS", + "telemetry_switchLabel": "スイッチ", + "telemetry_polylineLabel": "ポリライン", + "telemetry_altitudeValue": "{meters} m", + "telemetry_frequencyValue": "{hertz} Hz", + "telemetry_pressureValue": "{hpa} hPa", + "telemetry_luminosityValue": "{lux} lx", + "telemetry_powerValue": "{watts} W", + "telemetry_distanceValue": "{meters} m", + "telemetry_energyValue": "{kilowattHours} kWh", + "telemetry_directionValue": "{degrees}°", + "telemetry_concentrationValue": "{ppm} ppm", + "telemetry_percentageValue": "{percent}%", + "telemetry_analogValue": "{value}", + "telemetry_autoFetchQuantity": "リクエスト数", + "telemetry_error": "データを取得できません", "telemetry_noData": "テレメトリデータは利用できません。", "telemetry_channelTitle": "チャンネル {channel}", "@telemetry_channelTitle": { diff --git a/lib/l10n/app_ko.arb b/lib/l10n/app_ko.arb index 7418068c..8f6781e3 100644 --- a/lib/l10n/app_ko.arb +++ b/lib/l10n/app_ko.arb @@ -27,6 +27,8 @@ "common_remove": "제거", "common_enable": "활성화", "common_disable": "비활성화", + "common_autoRefresh": "자동 새로고침", + "common_interval": "간격", "common_reboot": "재부팅", "common_loading": "로딩 중...", "common_notAvailable": "—", @@ -1466,6 +1468,43 @@ } } }, + "telemetry_digitalInputLabel": "디지털 입력", + "telemetry_digitalOutputLabel": "디지털 출력", + "telemetry_analogInputLabel": "아날로그 입력", + "telemetry_analogOutputLabel": "아날로그 출력", + "telemetry_genericLabel": "일반 센서", + "telemetry_luminosityLabel": "조도", + "telemetry_presenceLabel": "존재 감지", + "telemetry_humidityLabel": "습도", + "telemetry_accelerometerLabel": "가속도계", + "telemetry_pressureLabel": "압력", + "telemetry_altitudeLabel": "고도", + "telemetry_frequencyLabel": "주파수", + "telemetry_percentageLabel": "백분율", + "telemetry_concentrationLabel": "농도", + "telemetry_powerLabel": "전력", + "telemetry_distanceLabel": "거리", + "telemetry_energyLabel": "에너지", + "telemetry_directionLabel": "방향", + "telemetry_timeLabel": "시간", + "telemetry_gyrometerLabel": "자이로미터", + "telemetry_colourLabel": "색상", + "telemetry_gpsLabel": "GPS", + "telemetry_switchLabel": "스위치", + "telemetry_polylineLabel": "폴리라인", + "telemetry_altitudeValue": "{meters} m", + "telemetry_frequencyValue": "{hertz} Hz", + "telemetry_pressureValue": "{hpa} hPa", + "telemetry_luminosityValue": "{lux} lx", + "telemetry_powerValue": "{watts} W", + "telemetry_distanceValue": "{meters} m", + "telemetry_energyValue": "{kilowattHours} kWh", + "telemetry_directionValue": "{degrees}°", + "telemetry_concentrationValue": "{ppm} ppm", + "telemetry_percentageValue": "{percent}%", + "telemetry_analogValue": "{value}", + "telemetry_autoFetchQuantity": "요청 수", + "telemetry_error": "데이터를 가져올 수 없습니다", "telemetry_noData": "텔레메트리 데이터는 제공되지 않습니다.", "telemetry_channelTitle": "채널 {channel}", "@telemetry_channelTitle": { diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index 542b69e4..5a9ef6a5 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -328,6 +328,18 @@ abstract class AppLocalizations { /// **'{percent}%'** String common_percentValue(int percent); + /// No description provided for @common_autoRefresh. + /// + /// In en, this message translates to: + /// **'Autorefresh'** + String get common_autoRefresh; + + /// No description provided for @common_interval. + /// + /// In en, this message translates to: + /// **'Interval'** + String get common_interval; + /// No description provided for @scanner_title. /// /// In en, this message translates to: @@ -5786,6 +5798,228 @@ abstract class AppLocalizations { /// **'{celsius}°C / {fahrenheit}°F'** String telemetry_temperatureValue(String celsius, String fahrenheit); + /// No description provided for @telemetry_digitalInputLabel. + /// + /// In en, this message translates to: + /// **'Digital Input'** + String get telemetry_digitalInputLabel; + + /// No description provided for @telemetry_digitalOutputLabel. + /// + /// In en, this message translates to: + /// **'Digital Output'** + String get telemetry_digitalOutputLabel; + + /// No description provided for @telemetry_analogInputLabel. + /// + /// In en, this message translates to: + /// **'Analog Input'** + String get telemetry_analogInputLabel; + + /// No description provided for @telemetry_analogOutputLabel. + /// + /// In en, this message translates to: + /// **'Analog Output'** + String get telemetry_analogOutputLabel; + + /// No description provided for @telemetry_genericLabel. + /// + /// In en, this message translates to: + /// **'Generic Sensor'** + String get telemetry_genericLabel; + + /// No description provided for @telemetry_luminosityLabel. + /// + /// In en, this message translates to: + /// **'Luminosity'** + String get telemetry_luminosityLabel; + + /// No description provided for @telemetry_presenceLabel. + /// + /// In en, this message translates to: + /// **'Presence'** + String get telemetry_presenceLabel; + + /// No description provided for @telemetry_humidityLabel. + /// + /// In en, this message translates to: + /// **'Humidity'** + String get telemetry_humidityLabel; + + /// No description provided for @telemetry_accelerometerLabel. + /// + /// In en, this message translates to: + /// **'Accelerometer'** + String get telemetry_accelerometerLabel; + + /// No description provided for @telemetry_pressureLabel. + /// + /// In en, this message translates to: + /// **'Pressure'** + String get telemetry_pressureLabel; + + /// No description provided for @telemetry_altitudeLabel. + /// + /// In en, this message translates to: + /// **'Altitude'** + String get telemetry_altitudeLabel; + + /// No description provided for @telemetry_frequencyLabel. + /// + /// In en, this message translates to: + /// **'Frequency'** + String get telemetry_frequencyLabel; + + /// No description provided for @telemetry_percentageLabel. + /// + /// In en, this message translates to: + /// **'Percentage'** + String get telemetry_percentageLabel; + + /// No description provided for @telemetry_concentrationLabel. + /// + /// In en, this message translates to: + /// **'Concentration'** + String get telemetry_concentrationLabel; + + /// No description provided for @telemetry_powerLabel. + /// + /// In en, this message translates to: + /// **'Power'** + String get telemetry_powerLabel; + + /// No description provided for @telemetry_distanceLabel. + /// + /// In en, this message translates to: + /// **'Distance'** + String get telemetry_distanceLabel; + + /// No description provided for @telemetry_energyLabel. + /// + /// In en, this message translates to: + /// **'Energy'** + String get telemetry_energyLabel; + + /// No description provided for @telemetry_directionLabel. + /// + /// In en, this message translates to: + /// **'Direction'** + String get telemetry_directionLabel; + + /// No description provided for @telemetry_timeLabel. + /// + /// In en, this message translates to: + /// **'Time'** + String get telemetry_timeLabel; + + /// No description provided for @telemetry_gyrometerLabel. + /// + /// In en, this message translates to: + /// **'Gyrometer'** + String get telemetry_gyrometerLabel; + + /// No description provided for @telemetry_colourLabel. + /// + /// In en, this message translates to: + /// **'Colour'** + String get telemetry_colourLabel; + + /// No description provided for @telemetry_gpsLabel. + /// + /// In en, this message translates to: + /// **'GPS'** + String get telemetry_gpsLabel; + + /// No description provided for @telemetry_switchLabel. + /// + /// In en, this message translates to: + /// **'Switch'** + String get telemetry_switchLabel; + + /// No description provided for @telemetry_polylineLabel. + /// + /// In en, this message translates to: + /// **'Polyline'** + String get telemetry_polylineLabel; + + /// No description provided for @telemetry_altitudeValue. + /// + /// In en, this message translates to: + /// **'{meters} m'** + String telemetry_altitudeValue(String meters); + + /// No description provided for @telemetry_frequencyValue. + /// + /// In en, this message translates to: + /// **'{hertz} Hz'** + String telemetry_frequencyValue(String hertz); + + /// No description provided for @telemetry_pressureValue. + /// + /// In en, this message translates to: + /// **'{hpa} hPa'** + String telemetry_pressureValue(String hpa); + + /// No description provided for @telemetry_luminosityValue. + /// + /// In en, this message translates to: + /// **'{lux} lx'** + String telemetry_luminosityValue(String lux); + + /// No description provided for @telemetry_powerValue. + /// + /// In en, this message translates to: + /// **'{watts} W'** + String telemetry_powerValue(String watts); + + /// No description provided for @telemetry_distanceValue. + /// + /// In en, this message translates to: + /// **'{meters} m'** + String telemetry_distanceValue(String meters); + + /// No description provided for @telemetry_energyValue. + /// + /// In en, this message translates to: + /// **'{kilowattHours} kWh'** + String telemetry_energyValue(String kilowattHours); + + /// No description provided for @telemetry_directionValue. + /// + /// In en, this message translates to: + /// **'{degrees}°'** + String telemetry_directionValue(String degrees); + + /// No description provided for @telemetry_concentrationValue. + /// + /// In en, this message translates to: + /// **'{ppm} ppm'** + String telemetry_concentrationValue(String ppm); + + /// No description provided for @telemetry_percentageValue. + /// + /// In en, this message translates to: + /// **'{percent}%'** + String telemetry_percentageValue(String percent); + + /// No description provided for @telemetry_analogValue. + /// + /// In en, this message translates to: + /// **'{value}'** + String telemetry_analogValue(String value); + + /// No description provided for @telemetry_autoFetchQuantity. + /// + /// In en, this message translates to: + /// **'Requests quantity'** + String get telemetry_autoFetchQuantity; + + /// No description provided for @telemetry_error. + /// + /// In en, this message translates to: + /// **'Unable to retrieve data'** + String get telemetry_error; + /// No description provided for @neighbors_receivedData. /// /// In en, this message translates to: diff --git a/lib/l10n/app_localizations_bg.dart b/lib/l10n/app_localizations_bg.dart index 88958b0b..ea73e67f 100644 --- a/lib/l10n/app_localizations_bg.dart +++ b/lib/l10n/app_localizations_bg.dart @@ -111,6 +111,12 @@ class AppLocalizationsBg extends AppLocalizations { return '$percent%'; } + @override + String get common_autoRefresh => 'Автоматично обновяване'; + + @override + String get common_interval => 'Интервал'; + @override String get scanner_title => 'MeshCore – Отворена версия'; @@ -3329,6 +3335,139 @@ class AppLocalizationsBg extends AppLocalizations { return '$celsius°C / $fahrenheit°F'; } + @override + String get telemetry_digitalInputLabel => 'Цифров вход'; + + @override + String get telemetry_digitalOutputLabel => 'Цифров изход'; + + @override + String get telemetry_analogInputLabel => 'Аналогов вход'; + + @override + String get telemetry_analogOutputLabel => 'Аналогов изход'; + + @override + String get telemetry_genericLabel => 'Общ сензор'; + + @override + String get telemetry_luminosityLabel => 'Осветеност'; + + @override + String get telemetry_presenceLabel => 'Присъствие'; + + @override + String get telemetry_humidityLabel => 'Влажност'; + + @override + String get telemetry_accelerometerLabel => 'Акселерометър'; + + @override + String get telemetry_pressureLabel => 'Налягане'; + + @override + String get telemetry_altitudeLabel => 'Надморска височина'; + + @override + String get telemetry_frequencyLabel => 'Честота'; + + @override + String get telemetry_percentageLabel => 'Процент'; + + @override + String get telemetry_concentrationLabel => 'Концентрация'; + + @override + String get telemetry_powerLabel => 'Мощност'; + + @override + String get telemetry_distanceLabel => 'Разстояние'; + + @override + String get telemetry_energyLabel => 'Енергия'; + + @override + String get telemetry_directionLabel => 'Посока'; + + @override + String get telemetry_timeLabel => 'Време'; + + @override + String get telemetry_gyrometerLabel => 'Жироскоп'; + + @override + String get telemetry_colourLabel => 'Цвят'; + + @override + String get telemetry_gpsLabel => 'GPS'; + + @override + String get telemetry_switchLabel => 'Превключвател'; + + @override + String get telemetry_polylineLabel => 'Полилиния'; + + @override + String telemetry_altitudeValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_frequencyValue(String hertz) { + return '$hertz Hz'; + } + + @override + String telemetry_pressureValue(String hpa) { + return '$hpa hPa'; + } + + @override + String telemetry_luminosityValue(String lux) { + return '$lux lx'; + } + + @override + String telemetry_powerValue(String watts) { + return '$watts W'; + } + + @override + String telemetry_distanceValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_energyValue(String kilowattHours) { + return '$kilowattHours kWh'; + } + + @override + String telemetry_directionValue(String degrees) { + return '$degrees°'; + } + + @override + String telemetry_concentrationValue(String ppm) { + return '$ppm ppm'; + } + + @override + String telemetry_percentageValue(String percent) { + return '$percent%'; + } + + @override + String telemetry_analogValue(String value) { + return '$value'; + } + + @override + String get telemetry_autoFetchQuantity => 'Брой заявки'; + + @override + String get telemetry_error => 'Неуспешно получаване на данни'; + @override String get neighbors_receivedData => 'Получени данни за съседи'; diff --git a/lib/l10n/app_localizations_de.dart b/lib/l10n/app_localizations_de.dart index 44d82f16..d5919ae9 100644 --- a/lib/l10n/app_localizations_de.dart +++ b/lib/l10n/app_localizations_de.dart @@ -111,6 +111,12 @@ class AppLocalizationsDe extends AppLocalizations { return '$percent%'; } + @override + String get common_autoRefresh => 'Automatische Aktualisierung'; + + @override + String get common_interval => 'Intervall'; + @override String get scanner_title => 'MeshCore – Open-Version'; @@ -3336,6 +3342,139 @@ class AppLocalizationsDe extends AppLocalizations { return '$celsius°C / $fahrenheit°F'; } + @override + String get telemetry_digitalInputLabel => 'Digitaleingang'; + + @override + String get telemetry_digitalOutputLabel => 'Digitalausgang'; + + @override + String get telemetry_analogInputLabel => 'Analogeingang'; + + @override + String get telemetry_analogOutputLabel => 'Analogausgang'; + + @override + String get telemetry_genericLabel => 'Allgemeiner Sensor'; + + @override + String get telemetry_luminosityLabel => 'Helligkeit'; + + @override + String get telemetry_presenceLabel => 'Anwesenheit'; + + @override + String get telemetry_humidityLabel => 'Luftfeuchtigkeit'; + + @override + String get telemetry_accelerometerLabel => 'Beschleunigungsmesser'; + + @override + String get telemetry_pressureLabel => 'Druck'; + + @override + String get telemetry_altitudeLabel => 'Höhe'; + + @override + String get telemetry_frequencyLabel => 'Frequenz'; + + @override + String get telemetry_percentageLabel => 'Prozentsatz'; + + @override + String get telemetry_concentrationLabel => 'Konzentration'; + + @override + String get telemetry_powerLabel => 'Leistung'; + + @override + String get telemetry_distanceLabel => 'Entfernung'; + + @override + String get telemetry_energyLabel => 'Energie'; + + @override + String get telemetry_directionLabel => 'Richtung'; + + @override + String get telemetry_timeLabel => 'Zeit'; + + @override + String get telemetry_gyrometerLabel => 'Gyroskop'; + + @override + String get telemetry_colourLabel => 'Farbe'; + + @override + String get telemetry_gpsLabel => 'GPS'; + + @override + String get telemetry_switchLabel => 'Schalter'; + + @override + String get telemetry_polylineLabel => 'Polylinie'; + + @override + String telemetry_altitudeValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_frequencyValue(String hertz) { + return '$hertz Hz'; + } + + @override + String telemetry_pressureValue(String hpa) { + return '$hpa hPa'; + } + + @override + String telemetry_luminosityValue(String lux) { + return '$lux lx'; + } + + @override + String telemetry_powerValue(String watts) { + return '$watts W'; + } + + @override + String telemetry_distanceValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_energyValue(String kilowattHours) { + return '$kilowattHours kWh'; + } + + @override + String telemetry_directionValue(String degrees) { + return '$degrees°'; + } + + @override + String telemetry_concentrationValue(String ppm) { + return '$ppm ppm'; + } + + @override + String telemetry_percentageValue(String percent) { + return '$percent%'; + } + + @override + String telemetry_analogValue(String value) { + return '$value'; + } + + @override + String get telemetry_autoFetchQuantity => 'Anzahl der Anfragen'; + + @override + String get telemetry_error => 'Daten konnten nicht abgerufen werden'; + @override String get neighbors_receivedData => 'Empfangene Nachbarsdaten'; diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index 389026e0..fcb48802 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -111,6 +111,12 @@ class AppLocalizationsEn extends AppLocalizations { return '$percent%'; } + @override + String get common_autoRefresh => 'Autorefresh'; + + @override + String get common_interval => 'Interval'; + @override String get scanner_title => 'MeshCore Open'; @@ -3266,6 +3272,139 @@ class AppLocalizationsEn extends AppLocalizations { return '$celsius°C / $fahrenheit°F'; } + @override + String get telemetry_digitalInputLabel => 'Digital Input'; + + @override + String get telemetry_digitalOutputLabel => 'Digital Output'; + + @override + String get telemetry_analogInputLabel => 'Analog Input'; + + @override + String get telemetry_analogOutputLabel => 'Analog Output'; + + @override + String get telemetry_genericLabel => 'Generic Sensor'; + + @override + String get telemetry_luminosityLabel => 'Luminosity'; + + @override + String get telemetry_presenceLabel => 'Presence'; + + @override + String get telemetry_humidityLabel => 'Humidity'; + + @override + String get telemetry_accelerometerLabel => 'Accelerometer'; + + @override + String get telemetry_pressureLabel => 'Pressure'; + + @override + String get telemetry_altitudeLabel => 'Altitude'; + + @override + String get telemetry_frequencyLabel => 'Frequency'; + + @override + String get telemetry_percentageLabel => 'Percentage'; + + @override + String get telemetry_concentrationLabel => 'Concentration'; + + @override + String get telemetry_powerLabel => 'Power'; + + @override + String get telemetry_distanceLabel => 'Distance'; + + @override + String get telemetry_energyLabel => 'Energy'; + + @override + String get telemetry_directionLabel => 'Direction'; + + @override + String get telemetry_timeLabel => 'Time'; + + @override + String get telemetry_gyrometerLabel => 'Gyrometer'; + + @override + String get telemetry_colourLabel => 'Colour'; + + @override + String get telemetry_gpsLabel => 'GPS'; + + @override + String get telemetry_switchLabel => 'Switch'; + + @override + String get telemetry_polylineLabel => 'Polyline'; + + @override + String telemetry_altitudeValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_frequencyValue(String hertz) { + return '$hertz Hz'; + } + + @override + String telemetry_pressureValue(String hpa) { + return '$hpa hPa'; + } + + @override + String telemetry_luminosityValue(String lux) { + return '$lux lx'; + } + + @override + String telemetry_powerValue(String watts) { + return '$watts W'; + } + + @override + String telemetry_distanceValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_energyValue(String kilowattHours) { + return '$kilowattHours kWh'; + } + + @override + String telemetry_directionValue(String degrees) { + return '$degrees°'; + } + + @override + String telemetry_concentrationValue(String ppm) { + return '$ppm ppm'; + } + + @override + String telemetry_percentageValue(String percent) { + return '$percent%'; + } + + @override + String telemetry_analogValue(String value) { + return '$value'; + } + + @override + String get telemetry_autoFetchQuantity => 'Requests quantity'; + + @override + String get telemetry_error => 'Unable to retrieve data'; + @override String get neighbors_receivedData => 'Received Neighbors Data'; diff --git a/lib/l10n/app_localizations_es.dart b/lib/l10n/app_localizations_es.dart index 999d9893..a5db08e2 100644 --- a/lib/l10n/app_localizations_es.dart +++ b/lib/l10n/app_localizations_es.dart @@ -111,6 +111,12 @@ class AppLocalizationsEs extends AppLocalizations { return '$percent%'; } + @override + String get common_autoRefresh => 'Actualización automática'; + + @override + String get common_interval => 'Intervalo'; + @override String get scanner_title => 'MeshCore: Versión abierta'; @@ -3323,6 +3329,139 @@ class AppLocalizationsEs extends AppLocalizations { return '$celsius°C / $fahrenheit°F'; } + @override + String get telemetry_digitalInputLabel => 'Entrada digital'; + + @override + String get telemetry_digitalOutputLabel => 'Salida digital'; + + @override + String get telemetry_analogInputLabel => 'Entrada analógica'; + + @override + String get telemetry_analogOutputLabel => 'Salida analógica'; + + @override + String get telemetry_genericLabel => 'Sensor genérico'; + + @override + String get telemetry_luminosityLabel => 'Luminosidad'; + + @override + String get telemetry_presenceLabel => 'Presencia'; + + @override + String get telemetry_humidityLabel => 'Humedad'; + + @override + String get telemetry_accelerometerLabel => 'Acelerómetro'; + + @override + String get telemetry_pressureLabel => 'Presión'; + + @override + String get telemetry_altitudeLabel => 'Altitud'; + + @override + String get telemetry_frequencyLabel => 'Frecuencia'; + + @override + String get telemetry_percentageLabel => 'Porcentaje'; + + @override + String get telemetry_concentrationLabel => 'Concentración'; + + @override + String get telemetry_powerLabel => 'Potencia'; + + @override + String get telemetry_distanceLabel => 'Distancia'; + + @override + String get telemetry_energyLabel => 'Energía'; + + @override + String get telemetry_directionLabel => 'Dirección'; + + @override + String get telemetry_timeLabel => 'Hora'; + + @override + String get telemetry_gyrometerLabel => 'Girómetro'; + + @override + String get telemetry_colourLabel => 'Color'; + + @override + String get telemetry_gpsLabel => 'GPS'; + + @override + String get telemetry_switchLabel => 'Interruptor'; + + @override + String get telemetry_polylineLabel => 'Polilínea'; + + @override + String telemetry_altitudeValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_frequencyValue(String hertz) { + return '$hertz Hz'; + } + + @override + String telemetry_pressureValue(String hpa) { + return '$hpa hPa'; + } + + @override + String telemetry_luminosityValue(String lux) { + return '$lux lx'; + } + + @override + String telemetry_powerValue(String watts) { + return '$watts W'; + } + + @override + String telemetry_distanceValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_energyValue(String kilowattHours) { + return '$kilowattHours kWh'; + } + + @override + String telemetry_directionValue(String degrees) { + return '$degrees°'; + } + + @override + String telemetry_concentrationValue(String ppm) { + return '$ppm ppm'; + } + + @override + String telemetry_percentageValue(String percent) { + return '$percent%'; + } + + @override + String telemetry_analogValue(String value) { + return '$value'; + } + + @override + String get telemetry_autoFetchQuantity => 'Número de solicitudes'; + + @override + String get telemetry_error => 'No se pudieron obtener los datos'; + @override String get neighbors_receivedData => 'Recibidas Datos de Vecinos'; diff --git a/lib/l10n/app_localizations_fr.dart b/lib/l10n/app_localizations_fr.dart index 8aa80d86..38965dc9 100644 --- a/lib/l10n/app_localizations_fr.dart +++ b/lib/l10n/app_localizations_fr.dart @@ -111,6 +111,12 @@ class AppLocalizationsFr extends AppLocalizations { return '$percent%'; } + @override + String get common_autoRefresh => 'Actualisation automatique'; + + @override + String get common_interval => 'Intervalle'; + @override String get scanner_title => 'MeshCore Open'; @@ -3346,6 +3352,139 @@ class AppLocalizationsFr extends AppLocalizations { return '$celsius°C / $fahrenheit°F'; } + @override + String get telemetry_digitalInputLabel => 'Entrée numérique'; + + @override + String get telemetry_digitalOutputLabel => 'Sortie numérique'; + + @override + String get telemetry_analogInputLabel => 'Entrée analogique'; + + @override + String get telemetry_analogOutputLabel => 'Sortie analogique'; + + @override + String get telemetry_genericLabel => 'Capteur générique'; + + @override + String get telemetry_luminosityLabel => 'Luminosité'; + + @override + String get telemetry_presenceLabel => 'Présence'; + + @override + String get telemetry_humidityLabel => 'Humidité'; + + @override + String get telemetry_accelerometerLabel => 'Accéléromètre'; + + @override + String get telemetry_pressureLabel => 'Pression'; + + @override + String get telemetry_altitudeLabel => 'Altitude'; + + @override + String get telemetry_frequencyLabel => 'Fréquence'; + + @override + String get telemetry_percentageLabel => 'Pourcentage'; + + @override + String get telemetry_concentrationLabel => 'Concentration'; + + @override + String get telemetry_powerLabel => 'Puissance'; + + @override + String get telemetry_distanceLabel => 'Distance'; + + @override + String get telemetry_energyLabel => 'Énergie'; + + @override + String get telemetry_directionLabel => 'Direction'; + + @override + String get telemetry_timeLabel => 'Heure'; + + @override + String get telemetry_gyrometerLabel => 'Gyromètre'; + + @override + String get telemetry_colourLabel => 'Couleur'; + + @override + String get telemetry_gpsLabel => 'GPS'; + + @override + String get telemetry_switchLabel => 'Interrupteur'; + + @override + String get telemetry_polylineLabel => 'Polyligne'; + + @override + String telemetry_altitudeValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_frequencyValue(String hertz) { + return '$hertz Hz'; + } + + @override + String telemetry_pressureValue(String hpa) { + return '$hpa hPa'; + } + + @override + String telemetry_luminosityValue(String lux) { + return '$lux lx'; + } + + @override + String telemetry_powerValue(String watts) { + return '$watts W'; + } + + @override + String telemetry_distanceValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_energyValue(String kilowattHours) { + return '$kilowattHours kWh'; + } + + @override + String telemetry_directionValue(String degrees) { + return '$degrees°'; + } + + @override + String telemetry_concentrationValue(String ppm) { + return '$ppm ppm'; + } + + @override + String telemetry_percentageValue(String percent) { + return '$percent%'; + } + + @override + String telemetry_analogValue(String value) { + return '$value'; + } + + @override + String get telemetry_autoFetchQuantity => 'Nombre de requêtes'; + + @override + String get telemetry_error => 'Impossible de récupérer les données'; + @override String get neighbors_receivedData => 'Données des voisins reçues'; diff --git a/lib/l10n/app_localizations_hu.dart b/lib/l10n/app_localizations_hu.dart index 065e011e..4eb35da5 100644 --- a/lib/l10n/app_localizations_hu.dart +++ b/lib/l10n/app_localizations_hu.dart @@ -111,6 +111,12 @@ class AppLocalizationsHu extends AppLocalizations { return '$percent%'; } + @override + String get common_autoRefresh => 'Automatikus frissítés'; + + @override + String get common_interval => 'Intervallum'; + @override String get scanner_title => 'MeshCore nyitott'; @@ -3339,6 +3345,139 @@ class AppLocalizationsHu extends AppLocalizations { return '$celsius °C / $fahrenheit °F'; } + @override + String get telemetry_digitalInputLabel => 'Digitális bemenet'; + + @override + String get telemetry_digitalOutputLabel => 'Digitális kimenet'; + + @override + String get telemetry_analogInputLabel => 'Analóg bemenet'; + + @override + String get telemetry_analogOutputLabel => 'Analóg kimenet'; + + @override + String get telemetry_genericLabel => 'Általános érzékelő'; + + @override + String get telemetry_luminosityLabel => 'Fényerő'; + + @override + String get telemetry_presenceLabel => 'Jelenlét'; + + @override + String get telemetry_humidityLabel => 'Páratartalom'; + + @override + String get telemetry_accelerometerLabel => 'Gyorsulásmérő'; + + @override + String get telemetry_pressureLabel => 'Nyomás'; + + @override + String get telemetry_altitudeLabel => 'Magasság'; + + @override + String get telemetry_frequencyLabel => 'Frekvencia'; + + @override + String get telemetry_percentageLabel => 'Százalék'; + + @override + String get telemetry_concentrationLabel => 'Koncentráció'; + + @override + String get telemetry_powerLabel => 'Teljesítmény'; + + @override + String get telemetry_distanceLabel => 'Távolság'; + + @override + String get telemetry_energyLabel => 'Energia'; + + @override + String get telemetry_directionLabel => 'Irány'; + + @override + String get telemetry_timeLabel => 'Idő'; + + @override + String get telemetry_gyrometerLabel => 'Giroszkóp'; + + @override + String get telemetry_colourLabel => 'Szín'; + + @override + String get telemetry_gpsLabel => 'GPS'; + + @override + String get telemetry_switchLabel => 'Kapcsoló'; + + @override + String get telemetry_polylineLabel => 'Töröttvonal'; + + @override + String telemetry_altitudeValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_frequencyValue(String hertz) { + return '$hertz Hz'; + } + + @override + String telemetry_pressureValue(String hpa) { + return '$hpa hPa'; + } + + @override + String telemetry_luminosityValue(String lux) { + return '$lux lx'; + } + + @override + String telemetry_powerValue(String watts) { + return '$watts W'; + } + + @override + String telemetry_distanceValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_energyValue(String kilowattHours) { + return '$kilowattHours kWh'; + } + + @override + String telemetry_directionValue(String degrees) { + return '$degrees°'; + } + + @override + String telemetry_concentrationValue(String ppm) { + return '$ppm ppm'; + } + + @override + String telemetry_percentageValue(String percent) { + return '$percent%'; + } + + @override + String telemetry_analogValue(String value) { + return '$value'; + } + + @override + String get telemetry_autoFetchQuantity => 'Kérések száma'; + + @override + String get telemetry_error => 'Nem sikerült lekérni az adatokat'; + @override String get neighbors_receivedData => 'Kapott szomszédok adatait'; diff --git a/lib/l10n/app_localizations_it.dart b/lib/l10n/app_localizations_it.dart index a4c98591..1df5bb19 100644 --- a/lib/l10n/app_localizations_it.dart +++ b/lib/l10n/app_localizations_it.dart @@ -111,6 +111,12 @@ class AppLocalizationsIt extends AppLocalizations { return '$percent%'; } + @override + String get common_autoRefresh => 'Aggiornamento automatico'; + + @override + String get common_interval => 'Intervallo'; + @override String get scanner_title => 'MeshCore Open'; @@ -3329,6 +3335,139 @@ class AppLocalizationsIt extends AppLocalizations { return '$celsius°C / $fahrenheit°F'; } + @override + String get telemetry_digitalInputLabel => 'Ingresso digitale'; + + @override + String get telemetry_digitalOutputLabel => 'Uscita digitale'; + + @override + String get telemetry_analogInputLabel => 'Ingresso analogico'; + + @override + String get telemetry_analogOutputLabel => 'Uscita analogica'; + + @override + String get telemetry_genericLabel => 'Sensore generico'; + + @override + String get telemetry_luminosityLabel => 'Luminosità'; + + @override + String get telemetry_presenceLabel => 'Presenza'; + + @override + String get telemetry_humidityLabel => 'Umidità'; + + @override + String get telemetry_accelerometerLabel => 'Accelerometro'; + + @override + String get telemetry_pressureLabel => 'Pressione'; + + @override + String get telemetry_altitudeLabel => 'Altitudine'; + + @override + String get telemetry_frequencyLabel => 'Frequenza'; + + @override + String get telemetry_percentageLabel => 'Percentuale'; + + @override + String get telemetry_concentrationLabel => 'Concentrazione'; + + @override + String get telemetry_powerLabel => 'Potenza'; + + @override + String get telemetry_distanceLabel => 'Distanza'; + + @override + String get telemetry_energyLabel => 'Energia'; + + @override + String get telemetry_directionLabel => 'Direzione'; + + @override + String get telemetry_timeLabel => 'Ora'; + + @override + String get telemetry_gyrometerLabel => 'Giroscopio'; + + @override + String get telemetry_colourLabel => 'Colore'; + + @override + String get telemetry_gpsLabel => 'GPS'; + + @override + String get telemetry_switchLabel => 'Interruttore'; + + @override + String get telemetry_polylineLabel => 'Polilinea'; + + @override + String telemetry_altitudeValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_frequencyValue(String hertz) { + return '$hertz Hz'; + } + + @override + String telemetry_pressureValue(String hpa) { + return '$hpa hPa'; + } + + @override + String telemetry_luminosityValue(String lux) { + return '$lux lx'; + } + + @override + String telemetry_powerValue(String watts) { + return '$watts W'; + } + + @override + String telemetry_distanceValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_energyValue(String kilowattHours) { + return '$kilowattHours kWh'; + } + + @override + String telemetry_directionValue(String degrees) { + return '$degrees°'; + } + + @override + String telemetry_concentrationValue(String ppm) { + return '$ppm ppm'; + } + + @override + String telemetry_percentageValue(String percent) { + return '$percent%'; + } + + @override + String telemetry_analogValue(String value) { + return '$value'; + } + + @override + String get telemetry_autoFetchQuantity => 'Numero di richieste'; + + @override + String get telemetry_error => 'Impossibile recuperare i dati'; + @override String get neighbors_receivedData => 'Ricevute dati vicini'; diff --git a/lib/l10n/app_localizations_ja.dart b/lib/l10n/app_localizations_ja.dart index 5df46482..a230f9f4 100644 --- a/lib/l10n/app_localizations_ja.dart +++ b/lib/l10n/app_localizations_ja.dart @@ -111,6 +111,12 @@ class AppLocalizationsJa extends AppLocalizations { return '$percent%'; } + @override + String get common_autoRefresh => '自動更新'; + + @override + String get common_interval => '間隔'; + @override String get scanner_title => 'MeshCore オープン'; @@ -3147,6 +3153,139 @@ class AppLocalizationsJa extends AppLocalizations { return '$celsius℃ / $fahrenheit°F'; } + @override + String get telemetry_digitalInputLabel => 'デジタル入力'; + + @override + String get telemetry_digitalOutputLabel => 'デジタル出力'; + + @override + String get telemetry_analogInputLabel => 'アナログ入力'; + + @override + String get telemetry_analogOutputLabel => 'アナログ出力'; + + @override + String get telemetry_genericLabel => '汎用センサー'; + + @override + String get telemetry_luminosityLabel => '照度'; + + @override + String get telemetry_presenceLabel => '在室'; + + @override + String get telemetry_humidityLabel => '湿度'; + + @override + String get telemetry_accelerometerLabel => '加速度計'; + + @override + String get telemetry_pressureLabel => '気圧'; + + @override + String get telemetry_altitudeLabel => '高度'; + + @override + String get telemetry_frequencyLabel => '周波数'; + + @override + String get telemetry_percentageLabel => 'パーセント'; + + @override + String get telemetry_concentrationLabel => '濃度'; + + @override + String get telemetry_powerLabel => '電力'; + + @override + String get telemetry_distanceLabel => '距離'; + + @override + String get telemetry_energyLabel => 'エネルギー'; + + @override + String get telemetry_directionLabel => '方向'; + + @override + String get telemetry_timeLabel => '時刻'; + + @override + String get telemetry_gyrometerLabel => 'ジャイロメーター'; + + @override + String get telemetry_colourLabel => '色'; + + @override + String get telemetry_gpsLabel => 'GPS'; + + @override + String get telemetry_switchLabel => 'スイッチ'; + + @override + String get telemetry_polylineLabel => 'ポリライン'; + + @override + String telemetry_altitudeValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_frequencyValue(String hertz) { + return '$hertz Hz'; + } + + @override + String telemetry_pressureValue(String hpa) { + return '$hpa hPa'; + } + + @override + String telemetry_luminosityValue(String lux) { + return '$lux lx'; + } + + @override + String telemetry_powerValue(String watts) { + return '$watts W'; + } + + @override + String telemetry_distanceValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_energyValue(String kilowattHours) { + return '$kilowattHours kWh'; + } + + @override + String telemetry_directionValue(String degrees) { + return '$degrees°'; + } + + @override + String telemetry_concentrationValue(String ppm) { + return '$ppm ppm'; + } + + @override + String telemetry_percentageValue(String percent) { + return '$percent%'; + } + + @override + String telemetry_analogValue(String value) { + return '$value'; + } + + @override + String get telemetry_autoFetchQuantity => 'リクエスト数'; + + @override + String get telemetry_error => 'データを取得できません'; + @override String get neighbors_receivedData => '近隣住民のデータを受信'; diff --git a/lib/l10n/app_localizations_ko.dart b/lib/l10n/app_localizations_ko.dart index 7656e97a..e62b1ea2 100644 --- a/lib/l10n/app_localizations_ko.dart +++ b/lib/l10n/app_localizations_ko.dart @@ -111,6 +111,12 @@ class AppLocalizationsKo extends AppLocalizations { return '$percent%'; } + @override + String get common_autoRefresh => '자동 새로고침'; + + @override + String get common_interval => '간격'; + @override String get scanner_title => 'MeshCore 공개'; @@ -3149,6 +3155,139 @@ class AppLocalizationsKo extends AppLocalizations { return '$celsius°C / $fahrenheit°F'; } + @override + String get telemetry_digitalInputLabel => '디지털 입력'; + + @override + String get telemetry_digitalOutputLabel => '디지털 출력'; + + @override + String get telemetry_analogInputLabel => '아날로그 입력'; + + @override + String get telemetry_analogOutputLabel => '아날로그 출력'; + + @override + String get telemetry_genericLabel => '일반 센서'; + + @override + String get telemetry_luminosityLabel => '조도'; + + @override + String get telemetry_presenceLabel => '존재 감지'; + + @override + String get telemetry_humidityLabel => '습도'; + + @override + String get telemetry_accelerometerLabel => '가속도계'; + + @override + String get telemetry_pressureLabel => '압력'; + + @override + String get telemetry_altitudeLabel => '고도'; + + @override + String get telemetry_frequencyLabel => '주파수'; + + @override + String get telemetry_percentageLabel => '백분율'; + + @override + String get telemetry_concentrationLabel => '농도'; + + @override + String get telemetry_powerLabel => '전력'; + + @override + String get telemetry_distanceLabel => '거리'; + + @override + String get telemetry_energyLabel => '에너지'; + + @override + String get telemetry_directionLabel => '방향'; + + @override + String get telemetry_timeLabel => '시간'; + + @override + String get telemetry_gyrometerLabel => '자이로미터'; + + @override + String get telemetry_colourLabel => '색상'; + + @override + String get telemetry_gpsLabel => 'GPS'; + + @override + String get telemetry_switchLabel => '스위치'; + + @override + String get telemetry_polylineLabel => '폴리라인'; + + @override + String telemetry_altitudeValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_frequencyValue(String hertz) { + return '$hertz Hz'; + } + + @override + String telemetry_pressureValue(String hpa) { + return '$hpa hPa'; + } + + @override + String telemetry_luminosityValue(String lux) { + return '$lux lx'; + } + + @override + String telemetry_powerValue(String watts) { + return '$watts W'; + } + + @override + String telemetry_distanceValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_energyValue(String kilowattHours) { + return '$kilowattHours kWh'; + } + + @override + String telemetry_directionValue(String degrees) { + return '$degrees°'; + } + + @override + String telemetry_concentrationValue(String ppm) { + return '$ppm ppm'; + } + + @override + String telemetry_percentageValue(String percent) { + return '$percent%'; + } + + @override + String telemetry_analogValue(String value) { + return '$value'; + } + + @override + String get telemetry_autoFetchQuantity => '요청 수'; + + @override + String get telemetry_error => '데이터를 가져올 수 없습니다'; + @override String get neighbors_receivedData => '이웃 정보 수집'; diff --git a/lib/l10n/app_localizations_nl.dart b/lib/l10n/app_localizations_nl.dart index 95304df7..f4dcdd1d 100644 --- a/lib/l10n/app_localizations_nl.dart +++ b/lib/l10n/app_localizations_nl.dart @@ -111,6 +111,12 @@ class AppLocalizationsNl extends AppLocalizations { return '$percent%'; } + @override + String get common_autoRefresh => 'Automatisch vernieuwen'; + + @override + String get common_interval => 'Tijdsinterval'; + @override String get scanner_title => 'MeshCore Open'; @@ -3309,6 +3315,139 @@ class AppLocalizationsNl extends AppLocalizations { return '$celsius°C / $fahrenheit°F'; } + @override + String get telemetry_digitalInputLabel => 'Digitale ingang'; + + @override + String get telemetry_digitalOutputLabel => 'Digitale uitgang'; + + @override + String get telemetry_analogInputLabel => 'Analoge ingang'; + + @override + String get telemetry_analogOutputLabel => 'Analoge uitgang'; + + @override + String get telemetry_genericLabel => 'Algemene sensor'; + + @override + String get telemetry_luminosityLabel => 'Lichtsterkte'; + + @override + String get telemetry_presenceLabel => 'Aanwezigheid'; + + @override + String get telemetry_humidityLabel => 'Luchtvochtigheid'; + + @override + String get telemetry_accelerometerLabel => 'Versnellingsmeter'; + + @override + String get telemetry_pressureLabel => 'Druk'; + + @override + String get telemetry_altitudeLabel => 'Hoogte'; + + @override + String get telemetry_frequencyLabel => 'Frequentie'; + + @override + String get telemetry_percentageLabel => 'Percentage'; + + @override + String get telemetry_concentrationLabel => 'Concentratie'; + + @override + String get telemetry_powerLabel => 'Vermogen'; + + @override + String get telemetry_distanceLabel => 'Afstand'; + + @override + String get telemetry_energyLabel => 'Energie'; + + @override + String get telemetry_directionLabel => 'Richting'; + + @override + String get telemetry_timeLabel => 'Tijd'; + + @override + String get telemetry_gyrometerLabel => 'Gyrometer'; + + @override + String get telemetry_colourLabel => 'Kleur'; + + @override + String get telemetry_gpsLabel => 'GPS'; + + @override + String get telemetry_switchLabel => 'Schakelaar'; + + @override + String get telemetry_polylineLabel => 'Polylijn'; + + @override + String telemetry_altitudeValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_frequencyValue(String hertz) { + return '$hertz Hz'; + } + + @override + String telemetry_pressureValue(String hpa) { + return '$hpa hPa'; + } + + @override + String telemetry_luminosityValue(String lux) { + return '$lux lx'; + } + + @override + String telemetry_powerValue(String watts) { + return '$watts W'; + } + + @override + String telemetry_distanceValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_energyValue(String kilowattHours) { + return '$kilowattHours kWh'; + } + + @override + String telemetry_directionValue(String degrees) { + return '$degrees°'; + } + + @override + String telemetry_concentrationValue(String ppm) { + return '$ppm ppm'; + } + + @override + String telemetry_percentageValue(String percent) { + return '$percent%'; + } + + @override + String telemetry_analogValue(String value) { + return '$value'; + } + + @override + String get telemetry_autoFetchQuantity => 'Aantal aanvragen'; + + @override + String get telemetry_error => 'Kan gegevens niet ophalen'; + @override String get neighbors_receivedData => 'Ontvangen Buurdata'; diff --git a/lib/l10n/app_localizations_pl.dart b/lib/l10n/app_localizations_pl.dart index 01be4ec4..877fc934 100644 --- a/lib/l10n/app_localizations_pl.dart +++ b/lib/l10n/app_localizations_pl.dart @@ -111,6 +111,12 @@ class AppLocalizationsPl extends AppLocalizations { return '$percent%'; } + @override + String get common_autoRefresh => 'Automatyczne odświeżanie'; + + @override + String get common_interval => 'Interwał'; + @override String get scanner_title => 'MeshCore – wersja open source'; @@ -3341,6 +3347,139 @@ class AppLocalizationsPl extends AppLocalizations { return '$celsius°C / $fahrenheit°F'; } + @override + String get telemetry_digitalInputLabel => 'Wejście cyfrowe'; + + @override + String get telemetry_digitalOutputLabel => 'Wyjście cyfrowe'; + + @override + String get telemetry_analogInputLabel => 'Wejście analogowe'; + + @override + String get telemetry_analogOutputLabel => 'Wyjście analogowe'; + + @override + String get telemetry_genericLabel => 'Czujnik ogólny'; + + @override + String get telemetry_luminosityLabel => 'Jasność'; + + @override + String get telemetry_presenceLabel => 'Obecność'; + + @override + String get telemetry_humidityLabel => 'Wilgotność'; + + @override + String get telemetry_accelerometerLabel => 'Akcelerometr'; + + @override + String get telemetry_pressureLabel => 'Ciśnienie'; + + @override + String get telemetry_altitudeLabel => 'Wysokość'; + + @override + String get telemetry_frequencyLabel => 'Częstotliwość'; + + @override + String get telemetry_percentageLabel => 'Procent'; + + @override + String get telemetry_concentrationLabel => 'Stężenie'; + + @override + String get telemetry_powerLabel => 'Moc'; + + @override + String get telemetry_distanceLabel => 'Odległość'; + + @override + String get telemetry_energyLabel => 'Energia'; + + @override + String get telemetry_directionLabel => 'Kierunek'; + + @override + String get telemetry_timeLabel => 'Czas'; + + @override + String get telemetry_gyrometerLabel => 'Żyrometr'; + + @override + String get telemetry_colourLabel => 'Kolor'; + + @override + String get telemetry_gpsLabel => 'GPS'; + + @override + String get telemetry_switchLabel => 'Przełącznik'; + + @override + String get telemetry_polylineLabel => 'Polilinia'; + + @override + String telemetry_altitudeValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_frequencyValue(String hertz) { + return '$hertz Hz'; + } + + @override + String telemetry_pressureValue(String hpa) { + return '$hpa hPa'; + } + + @override + String telemetry_luminosityValue(String lux) { + return '$lux lx'; + } + + @override + String telemetry_powerValue(String watts) { + return '$watts W'; + } + + @override + String telemetry_distanceValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_energyValue(String kilowattHours) { + return '$kilowattHours kWh'; + } + + @override + String telemetry_directionValue(String degrees) { + return '$degrees°'; + } + + @override + String telemetry_concentrationValue(String ppm) { + return '$ppm ppm'; + } + + @override + String telemetry_percentageValue(String percent) { + return '$percent%'; + } + + @override + String telemetry_analogValue(String value) { + return '$value'; + } + + @override + String get telemetry_autoFetchQuantity => 'Liczba żądań'; + + @override + String get telemetry_error => 'Nie udało się pobrać danych'; + @override String get neighbors_receivedData => 'Otrzymano dane sąsiedztwa'; diff --git a/lib/l10n/app_localizations_pt.dart b/lib/l10n/app_localizations_pt.dart index 5ca75ce9..585778d9 100644 --- a/lib/l10n/app_localizations_pt.dart +++ b/lib/l10n/app_localizations_pt.dart @@ -111,6 +111,12 @@ class AppLocalizationsPt extends AppLocalizations { return '$percent%'; } + @override + String get common_autoRefresh => 'Atualização automática'; + + @override + String get common_interval => 'Intervalo'; + @override String get scanner_title => 'MeshCore: Versão aberta'; @@ -3322,6 +3328,139 @@ class AppLocalizationsPt extends AppLocalizations { return '$celsius°C / $fahrenheit°F'; } + @override + String get telemetry_digitalInputLabel => 'Entrada digital'; + + @override + String get telemetry_digitalOutputLabel => 'Saída digital'; + + @override + String get telemetry_analogInputLabel => 'Entrada analógica'; + + @override + String get telemetry_analogOutputLabel => 'Saída analógica'; + + @override + String get telemetry_genericLabel => 'Sensor genérico'; + + @override + String get telemetry_luminosityLabel => 'Luminosidade'; + + @override + String get telemetry_presenceLabel => 'Presença'; + + @override + String get telemetry_humidityLabel => 'Humidade'; + + @override + String get telemetry_accelerometerLabel => 'Acelerómetro'; + + @override + String get telemetry_pressureLabel => 'Pressão'; + + @override + String get telemetry_altitudeLabel => 'Altitude'; + + @override + String get telemetry_frequencyLabel => 'Frequência'; + + @override + String get telemetry_percentageLabel => 'Percentagem'; + + @override + String get telemetry_concentrationLabel => 'Concentração'; + + @override + String get telemetry_powerLabel => 'Potência'; + + @override + String get telemetry_distanceLabel => 'Distância'; + + @override + String get telemetry_energyLabel => 'Energia'; + + @override + String get telemetry_directionLabel => 'Direção'; + + @override + String get telemetry_timeLabel => 'Hora'; + + @override + String get telemetry_gyrometerLabel => 'Girómetro'; + + @override + String get telemetry_colourLabel => 'Cor'; + + @override + String get telemetry_gpsLabel => 'GPS'; + + @override + String get telemetry_switchLabel => 'Interruptor'; + + @override + String get telemetry_polylineLabel => 'Polilinha'; + + @override + String telemetry_altitudeValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_frequencyValue(String hertz) { + return '$hertz Hz'; + } + + @override + String telemetry_pressureValue(String hpa) { + return '$hpa hPa'; + } + + @override + String telemetry_luminosityValue(String lux) { + return '$lux lx'; + } + + @override + String telemetry_powerValue(String watts) { + return '$watts W'; + } + + @override + String telemetry_distanceValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_energyValue(String kilowattHours) { + return '$kilowattHours kWh'; + } + + @override + String telemetry_directionValue(String degrees) { + return '$degrees°'; + } + + @override + String telemetry_concentrationValue(String ppm) { + return '$ppm ppm'; + } + + @override + String telemetry_percentageValue(String percent) { + return '$percent%'; + } + + @override + String telemetry_analogValue(String value) { + return '$value'; + } + + @override + String get telemetry_autoFetchQuantity => 'Número de solicitações'; + + @override + String get telemetry_error => 'Não foi possível obter os dados'; + @override String get neighbors_receivedData => 'Dados dos Vizinhos Recebidos'; diff --git a/lib/l10n/app_localizations_ru.dart b/lib/l10n/app_localizations_ru.dart index fb6f20f5..bb312c06 100644 --- a/lib/l10n/app_localizations_ru.dart +++ b/lib/l10n/app_localizations_ru.dart @@ -111,6 +111,12 @@ class AppLocalizationsRu extends AppLocalizations { return '$percent%'; } + @override + String get common_autoRefresh => 'Автообновление'; + + @override + String get common_interval => 'Интервал'; + @override String get scanner_title => 'MeshCore Open'; @@ -3330,6 +3336,139 @@ class AppLocalizationsRu extends AppLocalizations { return '$celsius°C / $fahrenheit°F'; } + @override + String get telemetry_digitalInputLabel => 'Цифровой вход'; + + @override + String get telemetry_digitalOutputLabel => 'Цифровой выход'; + + @override + String get telemetry_analogInputLabel => 'Аналоговый вход'; + + @override + String get telemetry_analogOutputLabel => 'Аналоговый выход'; + + @override + String get telemetry_genericLabel => 'Общий датчик'; + + @override + String get telemetry_luminosityLabel => 'Освещённость'; + + @override + String get telemetry_presenceLabel => 'Присутствие'; + + @override + String get telemetry_humidityLabel => 'Влажность'; + + @override + String get telemetry_accelerometerLabel => 'Акселерометр'; + + @override + String get telemetry_pressureLabel => 'Давление'; + + @override + String get telemetry_altitudeLabel => 'Высота'; + + @override + String get telemetry_frequencyLabel => 'Частота'; + + @override + String get telemetry_percentageLabel => 'Процент'; + + @override + String get telemetry_concentrationLabel => 'Концентрация'; + + @override + String get telemetry_powerLabel => 'Мощность'; + + @override + String get telemetry_distanceLabel => 'Расстояние'; + + @override + String get telemetry_energyLabel => 'Энергия'; + + @override + String get telemetry_directionLabel => 'Направление'; + + @override + String get telemetry_timeLabel => 'Время'; + + @override + String get telemetry_gyrometerLabel => 'Гирометр'; + + @override + String get telemetry_colourLabel => 'Цвет'; + + @override + String get telemetry_gpsLabel => 'GPS'; + + @override + String get telemetry_switchLabel => 'Переключатель'; + + @override + String get telemetry_polylineLabel => 'Полилиния'; + + @override + String telemetry_altitudeValue(String meters) { + return '$meters м'; + } + + @override + String telemetry_frequencyValue(String hertz) { + return '$hertz Гц'; + } + + @override + String telemetry_pressureValue(String hpa) { + return '$hpa гПа'; + } + + @override + String telemetry_luminosityValue(String lux) { + return '$lux лк'; + } + + @override + String telemetry_powerValue(String watts) { + return '$watts Вт'; + } + + @override + String telemetry_distanceValue(String meters) { + return '$meters м'; + } + + @override + String telemetry_energyValue(String kilowattHours) { + return '$kilowattHours кВт⋅ч'; + } + + @override + String telemetry_directionValue(String degrees) { + return '$degrees°'; + } + + @override + String telemetry_concentrationValue(String ppm) { + return '$ppm ppm'; + } + + @override + String telemetry_percentageValue(String percent) { + return '$percent%'; + } + + @override + String telemetry_analogValue(String value) { + return '$value'; + } + + @override + String get telemetry_autoFetchQuantity => 'Количество запросов'; + + @override + String get telemetry_error => 'Не удалось получить данные'; + @override String get neighbors_receivedData => 'Полученные данные о соседях'; diff --git a/lib/l10n/app_localizations_sk.dart b/lib/l10n/app_localizations_sk.dart index 0c3d8b84..317c9399 100644 --- a/lib/l10n/app_localizations_sk.dart +++ b/lib/l10n/app_localizations_sk.dart @@ -111,6 +111,12 @@ class AppLocalizationsSk extends AppLocalizations { return '$percent%'; } + @override + String get common_autoRefresh => 'Automatické obnovenie'; + + @override + String get common_interval => 'Časový interval'; + @override String get scanner_title => 'MeshCore – Verzia pre verejnosť'; @@ -3308,6 +3314,139 @@ class AppLocalizationsSk extends AppLocalizations { return '$celsius°C / $fahrenheit°F'; } + @override + String get telemetry_digitalInputLabel => 'Digitálny vstup'; + + @override + String get telemetry_digitalOutputLabel => 'Digitálny výstup'; + + @override + String get telemetry_analogInputLabel => 'Analógový vstup'; + + @override + String get telemetry_analogOutputLabel => 'Analógový výstup'; + + @override + String get telemetry_genericLabel => 'Všeobecný senzor'; + + @override + String get telemetry_luminosityLabel => 'Osvetlenie'; + + @override + String get telemetry_presenceLabel => 'Prítomnosť'; + + @override + String get telemetry_humidityLabel => 'Vlhkosť'; + + @override + String get telemetry_accelerometerLabel => 'Akcelerometer'; + + @override + String get telemetry_pressureLabel => 'Tlak'; + + @override + String get telemetry_altitudeLabel => 'Nadmorská výška'; + + @override + String get telemetry_frequencyLabel => 'Frekvencia'; + + @override + String get telemetry_percentageLabel => 'Percento'; + + @override + String get telemetry_concentrationLabel => 'Koncentrácia'; + + @override + String get telemetry_powerLabel => 'Výkon'; + + @override + String get telemetry_distanceLabel => 'Vzdialenosť'; + + @override + String get telemetry_energyLabel => 'Energia'; + + @override + String get telemetry_directionLabel => 'Smer'; + + @override + String get telemetry_timeLabel => 'Čas'; + + @override + String get telemetry_gyrometerLabel => 'Gyrometer'; + + @override + String get telemetry_colourLabel => 'Farba'; + + @override + String get telemetry_gpsLabel => 'GPS'; + + @override + String get telemetry_switchLabel => 'Prepínač'; + + @override + String get telemetry_polylineLabel => 'Lomená čiara'; + + @override + String telemetry_altitudeValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_frequencyValue(String hertz) { + return '$hertz Hz'; + } + + @override + String telemetry_pressureValue(String hpa) { + return '$hpa hPa'; + } + + @override + String telemetry_luminosityValue(String lux) { + return '$lux lx'; + } + + @override + String telemetry_powerValue(String watts) { + return '$watts W'; + } + + @override + String telemetry_distanceValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_energyValue(String kilowattHours) { + return '$kilowattHours kWh'; + } + + @override + String telemetry_directionValue(String degrees) { + return '$degrees°'; + } + + @override + String telemetry_concentrationValue(String ppm) { + return '$ppm ppm'; + } + + @override + String telemetry_percentageValue(String percent) { + return '$percent%'; + } + + @override + String telemetry_analogValue(String value) { + return '$value'; + } + + @override + String get telemetry_autoFetchQuantity => 'Počet požiadaviek'; + + @override + String get telemetry_error => 'Nepodarilo sa získať údaje'; + @override String get neighbors_receivedData => 'Obdielo dáta suseda'; diff --git a/lib/l10n/app_localizations_sl.dart b/lib/l10n/app_localizations_sl.dart index c9ccfc0e..6d6a93ba 100644 --- a/lib/l10n/app_localizations_sl.dart +++ b/lib/l10n/app_localizations_sl.dart @@ -111,6 +111,12 @@ class AppLocalizationsSl extends AppLocalizations { return '$percent %'; } + @override + String get common_autoRefresh => 'Samodejno osveževanje'; + + @override + String get common_interval => 'Časovni interval'; + @override String get scanner_title => 'MeshCore – Odprto'; @@ -3303,6 +3309,139 @@ class AppLocalizationsSl extends AppLocalizations { return '$celsius°C / $fahrenheit°F'; } + @override + String get telemetry_digitalInputLabel => 'Digitalni vhod'; + + @override + String get telemetry_digitalOutputLabel => 'Digitalni izhod'; + + @override + String get telemetry_analogInputLabel => 'Analogni vhod'; + + @override + String get telemetry_analogOutputLabel => 'Analogni izhod'; + + @override + String get telemetry_genericLabel => 'Splošni senzor'; + + @override + String get telemetry_luminosityLabel => 'Osvetljenost'; + + @override + String get telemetry_presenceLabel => 'Prisotnost'; + + @override + String get telemetry_humidityLabel => 'Vlažnost'; + + @override + String get telemetry_accelerometerLabel => 'Merilnik pospeška'; + + @override + String get telemetry_pressureLabel => 'Tlak'; + + @override + String get telemetry_altitudeLabel => 'Nadmorska višina'; + + @override + String get telemetry_frequencyLabel => 'Frekvenca'; + + @override + String get telemetry_percentageLabel => 'Odstotek'; + + @override + String get telemetry_concentrationLabel => 'Koncentracija'; + + @override + String get telemetry_powerLabel => 'Moč'; + + @override + String get telemetry_distanceLabel => 'Razdalja'; + + @override + String get telemetry_energyLabel => 'Energija'; + + @override + String get telemetry_directionLabel => 'Smer'; + + @override + String get telemetry_timeLabel => 'Čas'; + + @override + String get telemetry_gyrometerLabel => 'Žiroskop'; + + @override + String get telemetry_colourLabel => 'Barva'; + + @override + String get telemetry_gpsLabel => 'GPS'; + + @override + String get telemetry_switchLabel => 'Stikalo'; + + @override + String get telemetry_polylineLabel => 'Polilinija'; + + @override + String telemetry_altitudeValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_frequencyValue(String hertz) { + return '$hertz Hz'; + } + + @override + String telemetry_pressureValue(String hpa) { + return '$hpa hPa'; + } + + @override + String telemetry_luminosityValue(String lux) { + return '$lux lx'; + } + + @override + String telemetry_powerValue(String watts) { + return '$watts W'; + } + + @override + String telemetry_distanceValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_energyValue(String kilowattHours) { + return '$kilowattHours kWh'; + } + + @override + String telemetry_directionValue(String degrees) { + return '$degrees°'; + } + + @override + String telemetry_concentrationValue(String ppm) { + return '$ppm ppm'; + } + + @override + String telemetry_percentageValue(String percent) { + return '$percent%'; + } + + @override + String telemetry_analogValue(String value) { + return '$value'; + } + + @override + String get telemetry_autoFetchQuantity => 'Število zahtev'; + + @override + String get telemetry_error => 'Podatkov ni bilo mogoče pridobiti'; + @override String get neighbors_receivedData => 'Prejeto podatke o sosedih'; diff --git a/lib/l10n/app_localizations_sv.dart b/lib/l10n/app_localizations_sv.dart index d13a4a99..0b63088a 100644 --- a/lib/l10n/app_localizations_sv.dart +++ b/lib/l10n/app_localizations_sv.dart @@ -111,6 +111,12 @@ class AppLocalizationsSv extends AppLocalizations { return '$percent%'; } + @override + String get common_autoRefresh => 'Automatisk uppdatering'; + + @override + String get common_interval => 'Intervall'; + @override String get scanner_title => 'MeshCore – Öppen version'; @@ -3284,6 +3290,139 @@ class AppLocalizationsSv extends AppLocalizations { return '$celsius°C / $fahrenheit°F'; } + @override + String get telemetry_digitalInputLabel => 'Digital ingång'; + + @override + String get telemetry_digitalOutputLabel => 'Digital utgång'; + + @override + String get telemetry_analogInputLabel => 'Analog ingång'; + + @override + String get telemetry_analogOutputLabel => 'Analog utgång'; + + @override + String get telemetry_genericLabel => 'Allmän sensor'; + + @override + String get telemetry_luminosityLabel => 'Ljusstyrka'; + + @override + String get telemetry_presenceLabel => 'Närvaro'; + + @override + String get telemetry_humidityLabel => 'Luftfuktighet'; + + @override + String get telemetry_accelerometerLabel => 'Accelerometer'; + + @override + String get telemetry_pressureLabel => 'Tryck'; + + @override + String get telemetry_altitudeLabel => 'Höjd'; + + @override + String get telemetry_frequencyLabel => 'Frekvens'; + + @override + String get telemetry_percentageLabel => 'Procent'; + + @override + String get telemetry_concentrationLabel => 'Koncentration'; + + @override + String get telemetry_powerLabel => 'Effekt'; + + @override + String get telemetry_distanceLabel => 'Avstånd'; + + @override + String get telemetry_energyLabel => 'Energi'; + + @override + String get telemetry_directionLabel => 'Riktning'; + + @override + String get telemetry_timeLabel => 'Tid'; + + @override + String get telemetry_gyrometerLabel => 'Gyrometer'; + + @override + String get telemetry_colourLabel => 'Färg'; + + @override + String get telemetry_gpsLabel => 'GPS'; + + @override + String get telemetry_switchLabel => 'Brytare'; + + @override + String get telemetry_polylineLabel => 'Polylinje'; + + @override + String telemetry_altitudeValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_frequencyValue(String hertz) { + return '$hertz Hz'; + } + + @override + String telemetry_pressureValue(String hpa) { + return '$hpa hPa'; + } + + @override + String telemetry_luminosityValue(String lux) { + return '$lux lx'; + } + + @override + String telemetry_powerValue(String watts) { + return '$watts W'; + } + + @override + String telemetry_distanceValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_energyValue(String kilowattHours) { + return '$kilowattHours kWh'; + } + + @override + String telemetry_directionValue(String degrees) { + return '$degrees°'; + } + + @override + String telemetry_concentrationValue(String ppm) { + return '$ppm ppm'; + } + + @override + String telemetry_percentageValue(String percent) { + return '$percent%'; + } + + @override + String telemetry_analogValue(String value) { + return '$value'; + } + + @override + String get telemetry_autoFetchQuantity => 'Antal förfrågningar'; + + @override + String get telemetry_error => 'Det gick inte att hämta data'; + @override String get neighbors_receivedData => 'Mottagna grannars data'; diff --git a/lib/l10n/app_localizations_uk.dart b/lib/l10n/app_localizations_uk.dart index ae67b5d4..3950a433 100644 --- a/lib/l10n/app_localizations_uk.dart +++ b/lib/l10n/app_localizations_uk.dart @@ -111,6 +111,12 @@ class AppLocalizationsUk extends AppLocalizations { return '$percent%'; } + @override + String get common_autoRefresh => 'Автооновлення'; + + @override + String get common_interval => 'Інтервал'; + @override String get scanner_title => 'MeshCore: Відкритий доступ'; @@ -3327,6 +3333,139 @@ class AppLocalizationsUk extends AppLocalizations { return '$celsius°C / $fahrenheit°F'; } + @override + String get telemetry_digitalInputLabel => 'Цифровий вхід'; + + @override + String get telemetry_digitalOutputLabel => 'Цифровий вихід'; + + @override + String get telemetry_analogInputLabel => 'Аналоговий вхід'; + + @override + String get telemetry_analogOutputLabel => 'Аналоговий вихід'; + + @override + String get telemetry_genericLabel => 'Загальний датчик'; + + @override + String get telemetry_luminosityLabel => 'Освітленість'; + + @override + String get telemetry_presenceLabel => 'Присутність'; + + @override + String get telemetry_humidityLabel => 'Вологість'; + + @override + String get telemetry_accelerometerLabel => 'Акселерометр'; + + @override + String get telemetry_pressureLabel => 'Тиск'; + + @override + String get telemetry_altitudeLabel => 'Висота'; + + @override + String get telemetry_frequencyLabel => 'Частота'; + + @override + String get telemetry_percentageLabel => 'Відсоток'; + + @override + String get telemetry_concentrationLabel => 'Концентрація'; + + @override + String get telemetry_powerLabel => 'Потужність'; + + @override + String get telemetry_distanceLabel => 'Відстань'; + + @override + String get telemetry_energyLabel => 'Енергія'; + + @override + String get telemetry_directionLabel => 'Напрямок'; + + @override + String get telemetry_timeLabel => 'Час'; + + @override + String get telemetry_gyrometerLabel => 'Гірометр'; + + @override + String get telemetry_colourLabel => 'Колір'; + + @override + String get telemetry_gpsLabel => 'GPS'; + + @override + String get telemetry_switchLabel => 'Перемикач'; + + @override + String get telemetry_polylineLabel => 'Полілінія'; + + @override + String telemetry_altitudeValue(String meters) { + return '$meters м'; + } + + @override + String telemetry_frequencyValue(String hertz) { + return '$hertz Гц'; + } + + @override + String telemetry_pressureValue(String hpa) { + return '$hpa гПа'; + } + + @override + String telemetry_luminosityValue(String lux) { + return '$lux лк'; + } + + @override + String telemetry_powerValue(String watts) { + return '$watts Вт'; + } + + @override + String telemetry_distanceValue(String meters) { + return '$meters м'; + } + + @override + String telemetry_energyValue(String kilowattHours) { + return '$kilowattHours кВт⋅год'; + } + + @override + String telemetry_directionValue(String degrees) { + return '$degrees°'; + } + + @override + String telemetry_concentrationValue(String ppm) { + return '$ppm ppm'; + } + + @override + String telemetry_percentageValue(String percent) { + return '$percent%'; + } + + @override + String telemetry_analogValue(String value) { + return '$value'; + } + + @override + String get telemetry_autoFetchQuantity => 'Кількість запитів'; + + @override + String get telemetry_error => 'Не вдалося отримати дані'; + @override String get neighbors_receivedData => 'Дані сусідів отримано'; diff --git a/lib/l10n/app_localizations_zh.dart b/lib/l10n/app_localizations_zh.dart index fa626e44..20dc0b1d 100644 --- a/lib/l10n/app_localizations_zh.dart +++ b/lib/l10n/app_localizations_zh.dart @@ -111,6 +111,12 @@ class AppLocalizationsZh extends AppLocalizations { return '$percent%'; } + @override + String get common_autoRefresh => '自动刷新'; + + @override + String get common_interval => '间隔'; + @override String get scanner_title => '连接设备'; @@ -3052,6 +3058,139 @@ class AppLocalizationsZh extends AppLocalizations { return '$celsius°C / $fahrenheit°F'; } + @override + String get telemetry_digitalInputLabel => '数字输入'; + + @override + String get telemetry_digitalOutputLabel => '数字输出'; + + @override + String get telemetry_analogInputLabel => '模拟输入'; + + @override + String get telemetry_analogOutputLabel => '模拟输出'; + + @override + String get telemetry_genericLabel => '通用传感器'; + + @override + String get telemetry_luminosityLabel => '照度'; + + @override + String get telemetry_presenceLabel => '存在检测'; + + @override + String get telemetry_humidityLabel => '湿度'; + + @override + String get telemetry_accelerometerLabel => '加速度计'; + + @override + String get telemetry_pressureLabel => '气压'; + + @override + String get telemetry_altitudeLabel => '高度'; + + @override + String get telemetry_frequencyLabel => '频率'; + + @override + String get telemetry_percentageLabel => '百分比'; + + @override + String get telemetry_concentrationLabel => '浓度'; + + @override + String get telemetry_powerLabel => '功率'; + + @override + String get telemetry_distanceLabel => '距离'; + + @override + String get telemetry_energyLabel => '能量'; + + @override + String get telemetry_directionLabel => '方向'; + + @override + String get telemetry_timeLabel => '时间'; + + @override + String get telemetry_gyrometerLabel => '陀螺仪'; + + @override + String get telemetry_colourLabel => '颜色'; + + @override + String get telemetry_gpsLabel => 'GPS'; + + @override + String get telemetry_switchLabel => '开关'; + + @override + String get telemetry_polylineLabel => '折线'; + + @override + String telemetry_altitudeValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_frequencyValue(String hertz) { + return '$hertz Hz'; + } + + @override + String telemetry_pressureValue(String hpa) { + return '$hpa hPa'; + } + + @override + String telemetry_luminosityValue(String lux) { + return '$lux lx'; + } + + @override + String telemetry_powerValue(String watts) { + return '$watts W'; + } + + @override + String telemetry_distanceValue(String meters) { + return '$meters m'; + } + + @override + String telemetry_energyValue(String kilowattHours) { + return '$kilowattHours kWh'; + } + + @override + String telemetry_directionValue(String degrees) { + return '$degrees°'; + } + + @override + String telemetry_concentrationValue(String ppm) { + return '$ppm ppm'; + } + + @override + String telemetry_percentageValue(String percent) { + return '$percent%'; + } + + @override + String telemetry_analogValue(String value) { + return '$value'; + } + + @override + String get telemetry_autoFetchQuantity => '请求次数'; + + @override + String get telemetry_error => '无法获取数据'; + @override String get neighbors_receivedData => '已接收邻居信息'; diff --git a/lib/l10n/app_nl.arb b/lib/l10n/app_nl.arb index 68d53148..dfcf03b1 100644 --- a/lib/l10n/app_nl.arb +++ b/lib/l10n/app_nl.arb @@ -33,6 +33,8 @@ "common_remove": "Verwijderen", "common_enable": "Activeren", "common_disable": "Uitschakelen", + "common_autoRefresh": "Automatisch vernieuwen", + "common_interval": "Tijdsinterval", "common_reboot": "Herstarten", "common_loading": "Laden...", "common_notAvailable": "—", @@ -1280,6 +1282,43 @@ } } }, + "telemetry_digitalInputLabel": "Digitale ingang", + "telemetry_digitalOutputLabel": "Digitale uitgang", + "telemetry_analogInputLabel": "Analoge ingang", + "telemetry_analogOutputLabel": "Analoge uitgang", + "telemetry_genericLabel": "Algemene sensor", + "telemetry_luminosityLabel": "Lichtsterkte", + "telemetry_presenceLabel": "Aanwezigheid", + "telemetry_humidityLabel": "Luchtvochtigheid", + "telemetry_accelerometerLabel": "Versnellingsmeter", + "telemetry_pressureLabel": "Druk", + "telemetry_altitudeLabel": "Hoogte", + "telemetry_frequencyLabel": "Frequentie", + "telemetry_percentageLabel": "Percentage", + "telemetry_concentrationLabel": "Concentratie", + "telemetry_powerLabel": "Vermogen", + "telemetry_distanceLabel": "Afstand", + "telemetry_energyLabel": "Energie", + "telemetry_directionLabel": "Richting", + "telemetry_timeLabel": "Tijd", + "telemetry_gyrometerLabel": "Gyrometer", + "telemetry_colourLabel": "Kleur", + "telemetry_gpsLabel": "GPS", + "telemetry_switchLabel": "Schakelaar", + "telemetry_polylineLabel": "Polylijn", + "telemetry_altitudeValue": "{meters} m", + "telemetry_frequencyValue": "{hertz} Hz", + "telemetry_pressureValue": "{hpa} hPa", + "telemetry_luminosityValue": "{lux} lx", + "telemetry_powerValue": "{watts} W", + "telemetry_distanceValue": "{meters} m", + "telemetry_energyValue": "{kilowattHours} kWh", + "telemetry_directionValue": "{degrees}°", + "telemetry_concentrationValue": "{ppm} ppm", + "telemetry_percentageValue": "{percent}%", + "telemetry_analogValue": "{value}", + "telemetry_autoFetchQuantity": "Aantal aanvragen", + "telemetry_error": "Kan gegevens niet ophalen", "telemetry_noData": "Geen telemetriedata beschikbaar.", "telemetry_channelTitle": "Kanaal {channel}", "@telemetry_channelTitle": { diff --git a/lib/l10n/app_pl.arb b/lib/l10n/app_pl.arb index f79a589a..2dcdc7d8 100644 --- a/lib/l10n/app_pl.arb +++ b/lib/l10n/app_pl.arb @@ -33,6 +33,8 @@ "common_remove": "Usuń", "common_enable": "Włącz", "common_disable": "Wyłącz", + "common_autoRefresh": "Automatyczne odświeżanie", + "common_interval": "Interwał", "common_reboot": "Uruchom ponownie", "common_loading": "Ładowanie...", "common_notAvailable": "—", @@ -1290,6 +1292,43 @@ } } }, + "telemetry_digitalInputLabel": "Wejście cyfrowe", + "telemetry_digitalOutputLabel": "Wyjście cyfrowe", + "telemetry_analogInputLabel": "Wejście analogowe", + "telemetry_analogOutputLabel": "Wyjście analogowe", + "telemetry_genericLabel": "Czujnik ogólny", + "telemetry_luminosityLabel": "Jasność", + "telemetry_presenceLabel": "Obecność", + "telemetry_humidityLabel": "Wilgotność", + "telemetry_accelerometerLabel": "Akcelerometr", + "telemetry_pressureLabel": "Ciśnienie", + "telemetry_altitudeLabel": "Wysokość", + "telemetry_frequencyLabel": "Częstotliwość", + "telemetry_percentageLabel": "Procent", + "telemetry_concentrationLabel": "Stężenie", + "telemetry_powerLabel": "Moc", + "telemetry_distanceLabel": "Odległość", + "telemetry_energyLabel": "Energia", + "telemetry_directionLabel": "Kierunek", + "telemetry_timeLabel": "Czas", + "telemetry_gyrometerLabel": "Żyrometr", + "telemetry_colourLabel": "Kolor", + "telemetry_gpsLabel": "GPS", + "telemetry_switchLabel": "Przełącznik", + "telemetry_polylineLabel": "Polilinia", + "telemetry_altitudeValue": "{meters} m", + "telemetry_frequencyValue": "{hertz} Hz", + "telemetry_pressureValue": "{hpa} hPa", + "telemetry_luminosityValue": "{lux} lx", + "telemetry_powerValue": "{watts} W", + "telemetry_distanceValue": "{meters} m", + "telemetry_energyValue": "{kilowattHours} kWh", + "telemetry_directionValue": "{degrees}°", + "telemetry_concentrationValue": "{ppm} ppm", + "telemetry_percentageValue": "{percent}%", + "telemetry_analogValue": "{value}", + "telemetry_autoFetchQuantity": "Liczba żądań", + "telemetry_error": "Nie udało się pobrać danych", "telemetry_noData": "Brak dostępnych danych telemetrycznych.", "telemetry_channelTitle": "Kanał {channel}", "@telemetry_channelTitle": { diff --git a/lib/l10n/app_pt.arb b/lib/l10n/app_pt.arb index 994ff8a2..9dff4417 100644 --- a/lib/l10n/app_pt.arb +++ b/lib/l10n/app_pt.arb @@ -33,6 +33,8 @@ "common_remove": "Remover", "common_enable": "Ativar", "common_disable": "Desativar", + "common_autoRefresh": "Atualização automática", + "common_interval": "Intervalo", "common_reboot": "Reiniciar", "common_loading": "Carregando...", "common_notAvailable": "—", @@ -1280,6 +1282,43 @@ } } }, + "telemetry_digitalInputLabel": "Entrada digital", + "telemetry_digitalOutputLabel": "Saída digital", + "telemetry_analogInputLabel": "Entrada analógica", + "telemetry_analogOutputLabel": "Saída analógica", + "telemetry_genericLabel": "Sensor genérico", + "telemetry_luminosityLabel": "Luminosidade", + "telemetry_presenceLabel": "Presença", + "telemetry_humidityLabel": "Humidade", + "telemetry_accelerometerLabel": "Acelerómetro", + "telemetry_pressureLabel": "Pressão", + "telemetry_altitudeLabel": "Altitude", + "telemetry_frequencyLabel": "Frequência", + "telemetry_percentageLabel": "Percentagem", + "telemetry_concentrationLabel": "Concentração", + "telemetry_powerLabel": "Potência", + "telemetry_distanceLabel": "Distância", + "telemetry_energyLabel": "Energia", + "telemetry_directionLabel": "Direção", + "telemetry_timeLabel": "Hora", + "telemetry_gyrometerLabel": "Girómetro", + "telemetry_colourLabel": "Cor", + "telemetry_gpsLabel": "GPS", + "telemetry_switchLabel": "Interruptor", + "telemetry_polylineLabel": "Polilinha", + "telemetry_altitudeValue": "{meters} m", + "telemetry_frequencyValue": "{hertz} Hz", + "telemetry_pressureValue": "{hpa} hPa", + "telemetry_luminosityValue": "{lux} lx", + "telemetry_powerValue": "{watts} W", + "telemetry_distanceValue": "{meters} m", + "telemetry_energyValue": "{kilowattHours} kWh", + "telemetry_directionValue": "{degrees}°", + "telemetry_concentrationValue": "{ppm} ppm", + "telemetry_percentageValue": "{percent}%", + "telemetry_analogValue": "{value}", + "telemetry_autoFetchQuantity": "Número de solicitações", + "telemetry_error": "Não foi possível obter os dados", "telemetry_noData": "Não estão disponíveis dados de telemetria.", "telemetry_channelTitle": "Canal {channel}", "@telemetry_channelTitle": { diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb index 2b0978a6..0ae3eda4 100644 --- a/lib/l10n/app_ru.arb +++ b/lib/l10n/app_ru.arb @@ -39,6 +39,8 @@ "common_notAvailable": "—", "common_voltageValue": "{volts} В", "common_percentValue": "{percent}%", + "common_autoRefresh": "Автообновление", + "common_interval": "Интервал", "scanner_title": "MeshCore Open", "scanner_scanning": "Поиск устройств...", "scanner_connecting": "Подключение...", @@ -686,6 +688,43 @@ "telemetry_voltageValue": "{volts}В", "telemetry_currentValue": "{amps}А", "telemetry_temperatureValue": "{celsius}°C / {fahrenheit}°F", + "telemetry_digitalInputLabel": "Цифровой вход", + "telemetry_digitalOutputLabel": "Цифровой выход", + "telemetry_analogInputLabel": "Аналоговый вход", + "telemetry_analogOutputLabel": "Аналоговый выход", + "telemetry_genericLabel": "Общий датчик", + "telemetry_luminosityLabel": "Освещённость", + "telemetry_presenceLabel": "Присутствие", + "telemetry_humidityLabel": "Влажность", + "telemetry_accelerometerLabel": "Акселерометр", + "telemetry_pressureLabel": "Давление", + "telemetry_altitudeLabel": "Высота", + "telemetry_frequencyLabel": "Частота", + "telemetry_percentageLabel": "Процент", + "telemetry_concentrationLabel": "Концентрация", + "telemetry_powerLabel": "Мощность", + "telemetry_distanceLabel": "Расстояние", + "telemetry_energyLabel": "Энергия", + "telemetry_directionLabel": "Направление", + "telemetry_timeLabel": "Время", + "telemetry_gyrometerLabel": "Гирометр", + "telemetry_colourLabel": "Цвет", + "telemetry_gpsLabel": "GPS", + "telemetry_switchLabel": "Переключатель", + "telemetry_polylineLabel": "Полилиния", + "telemetry_altitudeValue": "{meters} м", + "telemetry_frequencyValue": "{hertz} Гц", + "telemetry_pressureValue": "{hpa} гПа", + "telemetry_luminosityValue": "{lux} лк", + "telemetry_powerValue": "{watts} Вт", + "telemetry_distanceValue": "{meters} м", + "telemetry_energyValue": "{kilowattHours} кВт⋅ч", + "telemetry_directionValue": "{degrees}°", + "telemetry_concentrationValue": "{ppm} ppm", + "telemetry_percentageValue": "{percent}%", + "telemetry_analogValue": "{value}", + "telemetry_autoFetchQuantity": "Количество запросов", + "telemetry_error": "Не удалось получить данные", "neighbors_receivedData": "Полученные данные о соседях", "neighbors_requestTimedOut": "Время ожидания данных о соседях истекло.", "neighbors_errorLoading": "Ошибка загрузки соседей: {error}", diff --git a/lib/l10n/app_sk.arb b/lib/l10n/app_sk.arb index 1a65b35f..3ade2e0d 100644 --- a/lib/l10n/app_sk.arb +++ b/lib/l10n/app_sk.arb @@ -33,6 +33,8 @@ "common_remove": "Odstrániť", "common_enable": "Povolit", "common_disable": "Zakázať", + "common_autoRefresh": "Automatické obnovenie", + "common_interval": "Časový interval", "common_reboot": "Restartovať", "common_loading": "Načítavanie...", "common_notAvailable": "—", @@ -1280,6 +1282,43 @@ } } }, + "telemetry_digitalInputLabel": "Digitálny vstup", + "telemetry_digitalOutputLabel": "Digitálny výstup", + "telemetry_analogInputLabel": "Analógový vstup", + "telemetry_analogOutputLabel": "Analógový výstup", + "telemetry_genericLabel": "Všeobecný senzor", + "telemetry_luminosityLabel": "Osvetlenie", + "telemetry_presenceLabel": "Prítomnosť", + "telemetry_humidityLabel": "Vlhkosť", + "telemetry_accelerometerLabel": "Akcelerometer", + "telemetry_pressureLabel": "Tlak", + "telemetry_altitudeLabel": "Nadmorská výška", + "telemetry_frequencyLabel": "Frekvencia", + "telemetry_percentageLabel": "Percento", + "telemetry_concentrationLabel": "Koncentrácia", + "telemetry_powerLabel": "Výkon", + "telemetry_distanceLabel": "Vzdialenosť", + "telemetry_energyLabel": "Energia", + "telemetry_directionLabel": "Smer", + "telemetry_timeLabel": "Čas", + "telemetry_gyrometerLabel": "Gyrometer", + "telemetry_colourLabel": "Farba", + "telemetry_gpsLabel": "GPS", + "telemetry_switchLabel": "Prepínač", + "telemetry_polylineLabel": "Lomená čiara", + "telemetry_altitudeValue": "{meters} m", + "telemetry_frequencyValue": "{hertz} Hz", + "telemetry_pressureValue": "{hpa} hPa", + "telemetry_luminosityValue": "{lux} lx", + "telemetry_powerValue": "{watts} W", + "telemetry_distanceValue": "{meters} m", + "telemetry_energyValue": "{kilowattHours} kWh", + "telemetry_directionValue": "{degrees}°", + "telemetry_concentrationValue": "{ppm} ppm", + "telemetry_percentageValue": "{percent}%", + "telemetry_analogValue": "{value}", + "telemetry_autoFetchQuantity": "Počet požiadaviek", + "telemetry_error": "Nepodarilo sa získať údaje", "telemetry_noData": "Nejsú dostupné žiadne údaje z telemetrie.", "telemetry_channelTitle": "Kanál {channel}", "@telemetry_channelTitle": { diff --git a/lib/l10n/app_sl.arb b/lib/l10n/app_sl.arb index eff2db17..fa3e2676 100644 --- a/lib/l10n/app_sl.arb +++ b/lib/l10n/app_sl.arb @@ -33,6 +33,8 @@ "common_remove": "Izbrisati", "common_enable": "Omogoči", "common_disable": "Izklopiti", + "common_autoRefresh": "Samodejno osveževanje", + "common_interval": "Časovni interval", "common_reboot": "Ponoviti", "common_loading": "Naložanje...", "common_notAvailable": "—", @@ -1280,6 +1282,43 @@ } } }, + "telemetry_digitalInputLabel": "Digitalni vhod", + "telemetry_digitalOutputLabel": "Digitalni izhod", + "telemetry_analogInputLabel": "Analogni vhod", + "telemetry_analogOutputLabel": "Analogni izhod", + "telemetry_genericLabel": "Splošni senzor", + "telemetry_luminosityLabel": "Osvetljenost", + "telemetry_presenceLabel": "Prisotnost", + "telemetry_humidityLabel": "Vlažnost", + "telemetry_accelerometerLabel": "Merilnik pospeška", + "telemetry_pressureLabel": "Tlak", + "telemetry_altitudeLabel": "Nadmorska višina", + "telemetry_frequencyLabel": "Frekvenca", + "telemetry_percentageLabel": "Odstotek", + "telemetry_concentrationLabel": "Koncentracija", + "telemetry_powerLabel": "Moč", + "telemetry_distanceLabel": "Razdalja", + "telemetry_energyLabel": "Energija", + "telemetry_directionLabel": "Smer", + "telemetry_timeLabel": "Čas", + "telemetry_gyrometerLabel": "Žiroskop", + "telemetry_colourLabel": "Barva", + "telemetry_gpsLabel": "GPS", + "telemetry_switchLabel": "Stikalo", + "telemetry_polylineLabel": "Polilinija", + "telemetry_altitudeValue": "{meters} m", + "telemetry_frequencyValue": "{hertz} Hz", + "telemetry_pressureValue": "{hpa} hPa", + "telemetry_luminosityValue": "{lux} lx", + "telemetry_powerValue": "{watts} W", + "telemetry_distanceValue": "{meters} m", + "telemetry_energyValue": "{kilowattHours} kWh", + "telemetry_directionValue": "{degrees}°", + "telemetry_concentrationValue": "{ppm} ppm", + "telemetry_percentageValue": "{percent}%", + "telemetry_analogValue": "{value}", + "telemetry_autoFetchQuantity": "Število zahtev", + "telemetry_error": "Podatkov ni bilo mogoče pridobiti", "telemetry_noData": "Niso na voljo podatki o telemetriji.", "telemetry_channelTitle": "Kanal {channel}", "@telemetry_channelTitle": { diff --git a/lib/l10n/app_sv.arb b/lib/l10n/app_sv.arb index 044abbc7..1658f186 100644 --- a/lib/l10n/app_sv.arb +++ b/lib/l10n/app_sv.arb @@ -33,6 +33,8 @@ "common_remove": "Ta bort", "common_enable": "Aktivera", "common_disable": "Inaktivera", + "common_autoRefresh": "Automatisk uppdatering", + "common_interval": "Intervall", "common_reboot": "Start om", "common_loading": "Laddar...", "common_notAvailable": "—", @@ -1280,6 +1282,43 @@ } } }, + "telemetry_digitalInputLabel": "Digital ingång", + "telemetry_digitalOutputLabel": "Digital utgång", + "telemetry_analogInputLabel": "Analog ingång", + "telemetry_analogOutputLabel": "Analog utgång", + "telemetry_genericLabel": "Allmän sensor", + "telemetry_luminosityLabel": "Ljusstyrka", + "telemetry_presenceLabel": "Närvaro", + "telemetry_humidityLabel": "Luftfuktighet", + "telemetry_accelerometerLabel": "Accelerometer", + "telemetry_pressureLabel": "Tryck", + "telemetry_altitudeLabel": "Höjd", + "telemetry_frequencyLabel": "Frekvens", + "telemetry_percentageLabel": "Procent", + "telemetry_concentrationLabel": "Koncentration", + "telemetry_powerLabel": "Effekt", + "telemetry_distanceLabel": "Avstånd", + "telemetry_energyLabel": "Energi", + "telemetry_directionLabel": "Riktning", + "telemetry_timeLabel": "Tid", + "telemetry_gyrometerLabel": "Gyrometer", + "telemetry_colourLabel": "Färg", + "telemetry_gpsLabel": "GPS", + "telemetry_switchLabel": "Brytare", + "telemetry_polylineLabel": "Polylinje", + "telemetry_altitudeValue": "{meters} m", + "telemetry_frequencyValue": "{hertz} Hz", + "telemetry_pressureValue": "{hpa} hPa", + "telemetry_luminosityValue": "{lux} lx", + "telemetry_powerValue": "{watts} W", + "telemetry_distanceValue": "{meters} m", + "telemetry_energyValue": "{kilowattHours} kWh", + "telemetry_directionValue": "{degrees}°", + "telemetry_concentrationValue": "{ppm} ppm", + "telemetry_percentageValue": "{percent}%", + "telemetry_analogValue": "{value}", + "telemetry_autoFetchQuantity": "Antal förfrågningar", + "telemetry_error": "Det gick inte att hämta data", "telemetry_noData": "Inga telemetridata tillgängliga.", "telemetry_channelTitle": "Kanal {channel}", "@telemetry_channelTitle": { diff --git a/lib/l10n/app_uk.arb b/lib/l10n/app_uk.arb index 37300095..990ecb90 100644 --- a/lib/l10n/app_uk.arb +++ b/lib/l10n/app_uk.arb @@ -34,6 +34,8 @@ "common_remove": "Прибрати", "common_enable": "Увімкнути", "common_disable": "Вимкнути", + "common_autoRefresh": "Автооновлення", + "common_interval": "Інтервал", "common_reboot": "Перезавантажити", "common_loading": "Завантаження...", "common_notAvailable": "—", @@ -1291,6 +1293,43 @@ } } }, + "telemetry_digitalInputLabel": "Цифровий вхід", + "telemetry_digitalOutputLabel": "Цифровий вихід", + "telemetry_analogInputLabel": "Аналоговий вхід", + "telemetry_analogOutputLabel": "Аналоговий вихід", + "telemetry_genericLabel": "Загальний датчик", + "telemetry_luminosityLabel": "Освітленість", + "telemetry_presenceLabel": "Присутність", + "telemetry_humidityLabel": "Вологість", + "telemetry_accelerometerLabel": "Акселерометр", + "telemetry_pressureLabel": "Тиск", + "telemetry_altitudeLabel": "Висота", + "telemetry_frequencyLabel": "Частота", + "telemetry_percentageLabel": "Відсоток", + "telemetry_concentrationLabel": "Концентрація", + "telemetry_powerLabel": "Потужність", + "telemetry_distanceLabel": "Відстань", + "telemetry_energyLabel": "Енергія", + "telemetry_directionLabel": "Напрямок", + "telemetry_timeLabel": "Час", + "telemetry_gyrometerLabel": "Гірометр", + "telemetry_colourLabel": "Колір", + "telemetry_gpsLabel": "GPS", + "telemetry_switchLabel": "Перемикач", + "telemetry_polylineLabel": "Полілінія", + "telemetry_altitudeValue": "{meters} м", + "telemetry_frequencyValue": "{hertz} Гц", + "telemetry_pressureValue": "{hpa} гПа", + "telemetry_luminosityValue": "{lux} лк", + "telemetry_powerValue": "{watts} Вт", + "telemetry_distanceValue": "{meters} м", + "telemetry_energyValue": "{kilowattHours} кВт⋅год", + "telemetry_directionValue": "{degrees}°", + "telemetry_concentrationValue": "{ppm} ppm", + "telemetry_percentageValue": "{percent}%", + "telemetry_analogValue": "{value}", + "telemetry_autoFetchQuantity": "Кількість запитів", + "telemetry_error": "Не вдалося отримати дані", "telemetry_noData": "Дані телеметрії недоступні.", "telemetry_channelTitle": "Канал {channel}", "@telemetry_channelTitle": { diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 5603034f..170e7212 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -34,6 +34,8 @@ "common_remove": "移除", "common_enable": "启用", "common_disable": "禁用", + "common_autoRefresh": "自动刷新", + "common_interval": "间隔", "common_reboot": "重启", "common_loading": "正在加载...", "common_notAvailable": "—", @@ -1310,6 +1312,43 @@ } } }, + "telemetry_digitalInputLabel": "数字输入", + "telemetry_digitalOutputLabel": "数字输出", + "telemetry_analogInputLabel": "模拟输入", + "telemetry_analogOutputLabel": "模拟输出", + "telemetry_genericLabel": "通用传感器", + "telemetry_luminosityLabel": "照度", + "telemetry_presenceLabel": "存在检测", + "telemetry_humidityLabel": "湿度", + "telemetry_accelerometerLabel": "加速度计", + "telemetry_pressureLabel": "气压", + "telemetry_altitudeLabel": "高度", + "telemetry_frequencyLabel": "频率", + "telemetry_percentageLabel": "百分比", + "telemetry_concentrationLabel": "浓度", + "telemetry_powerLabel": "功率", + "telemetry_distanceLabel": "距离", + "telemetry_energyLabel": "能量", + "telemetry_directionLabel": "方向", + "telemetry_timeLabel": "时间", + "telemetry_gyrometerLabel": "陀螺仪", + "telemetry_colourLabel": "颜色", + "telemetry_gpsLabel": "GPS", + "telemetry_switchLabel": "开关", + "telemetry_polylineLabel": "折线", + "telemetry_altitudeValue": "{meters} m", + "telemetry_frequencyValue": "{hertz} Hz", + "telemetry_pressureValue": "{hpa} hPa", + "telemetry_luminosityValue": "{lux} lx", + "telemetry_powerValue": "{watts} W", + "telemetry_distanceValue": "{meters} m", + "telemetry_energyValue": "{kilowattHours} kWh", + "telemetry_directionValue": "{degrees}°", + "telemetry_concentrationValue": "{ppm} ppm", + "telemetry_percentageValue": "{percent}%", + "telemetry_analogValue": "{value}", + "telemetry_autoFetchQuantity": "请求次数", + "telemetry_error": "无法获取数据", "telemetry_noData": "暂无遥测数据", "telemetry_channelTitle": "频道 {channel}", "@telemetry_channelTitle": { diff --git a/lib/screens/telemetry_screen.dart b/lib/screens/telemetry_screen.dart index 873ca3b1..f277a8e1 100644 --- a/lib/screens/telemetry_screen.dart +++ b/lib/screens/telemetry_screen.dart @@ -1,11 +1,13 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; import '../l10n/l10n.dart'; import '../models/contact.dart'; import '../models/path_selection.dart'; import '../models/app_settings.dart'; +import '../storage/prefs_manager.dart'; import '../connector/meshcore_connector.dart'; import '../connector/meshcore_protocol.dart'; import '../services/app_settings_service.dart'; @@ -16,6 +18,7 @@ import '../helpers/cayenne_lpp.dart'; import '../utils/battery_utils.dart'; import '../helpers/snack_bar_builder.dart'; import '../widgets/sync_progress_overlay.dart'; +import '../widgets/telemetry_location_map.dart'; class TelemetryScreen extends StatefulWidget { final Contact contact; @@ -27,6 +30,13 @@ class TelemetryScreen extends StatefulWidget { } class _TelemetryScreenState extends State { + static const int _autoRefreshDefaultIntervalSeconds = 20; + static const int _autoRefreshDefaultQuantity = 10; + static const int _autoRefreshMinIntervalSeconds = 10; + static const int _autoRefreshMaxIntervalSeconds = 300; + static const int _autoRefreshMinQuantity = 1; + static const int _autoRefreshMaxQuantity = 10; + int _tagData = 0; bool _isLoading = false; @@ -37,6 +47,17 @@ class _TelemetryScreenState extends State { RepeaterCommandService? _commandService; PathSelection? _pendingStatusSelection; List>? _parsedTelemetry; + final TextEditingController _autoRefreshIntervalController = + TextEditingController(text: '$_autoRefreshDefaultIntervalSeconds'); + final TextEditingController _autoRefreshQuantityController = + TextEditingController(text: '$_autoRefreshDefaultQuantity'); + Timer? _autoRefreshTimer; + bool _isAutoRefreshEnabled = false; + bool _activeTelemetryRequestIsAutoRefresh = false; + bool _autoRefreshLastAttemptFailed = false; + int _autoRefreshCurrentAttempt = 0; + int _autoRefreshTotalAttempts = 0; + int _autoRefreshIntervalSeconds = _autoRefreshDefaultIntervalSeconds; int _tripTime = 0; @@ -63,6 +84,7 @@ class _TelemetryScreenState extends State { super.initState(); final connector = Provider.of(context, listen: false); _commandService = RepeaterCommandService(connector); + _loadAutoRefreshSettings(); _setupMessageListener(); _loadTelemetry(); _hasData = false; @@ -82,17 +104,26 @@ class _TelemetryScreenState extends State { _tagData = reader.readUInt32LE(); _tripTime = reader.readUInt32LE(); _statusTimeout?.cancel(); + final isAutoRefreshRequest = _activeTelemetryRequestIsAutoRefresh; _statusTimeout = Timer(Duration(milliseconds: _tripTime), () { if (!mounted) return; setState(() { _isLoading = false; _isLoaded = false; + if (isAutoRefreshRequest && _isAutoRefreshEnabled) { + _autoRefreshLastAttemptFailed = true; + } }); - showDismissibleSnackBar( - context, - content: Text(context.l10n.telemetry_requestTimeout), - backgroundColor: Colors.red, - ); + if (!isAutoRefreshRequest) { + showDismissibleSnackBar( + context, + content: Text(context.l10n.telemetry_requestTimeout), + backgroundColor: Colors.red, + ); + } + if (isAutoRefreshRequest && _isAutoRefreshEnabled) { + _scheduleNextAutoRefreshAttempt(); + } _recordTelemetryResult(false); }); } @@ -134,15 +165,22 @@ class _TelemetryScreenState extends State { ); } if (!mounted) return; + final isAutoRefreshRequest = _activeTelemetryRequestIsAutoRefresh; setState(() { _parsedTelemetry = parsedTelemetry; + if (isAutoRefreshRequest) { + _autoRefreshLastAttemptFailed = false; + } + _activeTelemetryRequestIsAutoRefresh = false; }); - showDismissibleSnackBar( - context, - content: Text(context.l10n.telemetry_receivedData), - backgroundColor: Colors.green, - ); + if (!isAutoRefreshRequest) { + showDismissibleSnackBar( + context, + content: Text(context.l10n.telemetry_receivedData), + backgroundColor: Colors.green, + ); + } _statusTimeout?.cancel(); if (!mounted) return; setState(() { @@ -150,14 +188,18 @@ class _TelemetryScreenState extends State { _isLoaded = true; _hasData = true; }); + if (isAutoRefreshRequest) { + _scheduleNextAutoRefreshAttempt(); + } } - Future _loadTelemetry() async { + Future _loadTelemetry({bool isAutoRefresh = false}) async { if (_commandService == null) return; setState(() { _isLoading = true; _isLoaded = false; + _activeTelemetryRequestIsAutoRefresh = isAutoRefresh; }); try { final connector = Provider.of(context, listen: false); @@ -169,7 +211,7 @@ class _TelemetryScreenState extends State { if (widget.contact.type != advTypeChat) { frame = buildSendBinaryReq( widget.contact.publicKey, - payload: Uint8List.fromList([reqTypeGetTelemetry]), + payload: buildTelemetryBinaryPayload(), ); } else { frame = buildSendTelemetryReq(widget.contact.publicKey); @@ -180,17 +222,76 @@ class _TelemetryScreenState extends State { setState(() { _isLoading = false; _isLoaded = false; + if (isAutoRefresh) { + _autoRefreshLastAttemptFailed = true; + } + _activeTelemetryRequestIsAutoRefresh = false; }); + if (isAutoRefresh) { + _scheduleNextAutoRefreshAttempt(); + } - showDismissibleSnackBar( - context, - content: Text(context.l10n.telemetry_errorLoading(e.toString())), - backgroundColor: Colors.red, - ); + if (!isAutoRefresh) { + showDismissibleSnackBar( + context, + content: Text(context.l10n.telemetry_errorLoading(e.toString())), + backgroundColor: Colors.red, + ); + } } } } + void _loadAutoRefreshSettings() { + final prefs = PrefsManager.instance; + final contactKey = widget.contact.publicKeyHex; + final interval = + (prefs.getInt(_autoRefreshIntervalKey(contactKey)) ?? + _autoRefreshDefaultIntervalSeconds) + .clamp( + _autoRefreshMinIntervalSeconds, + _autoRefreshMaxIntervalSeconds, + ) + .toInt(); + final quantity = + (prefs.getInt(_autoRefreshQuantityKey(contactKey)) ?? + _autoRefreshDefaultQuantity) + .clamp(_autoRefreshMinQuantity, _autoRefreshMaxQuantity) + .toInt(); + + _autoRefreshIntervalSeconds = interval; + _autoRefreshIntervalController.text = interval.toString(); + _autoRefreshQuantityController.text = quantity.toString(); + } + + Future _saveAutoRefreshSettings() async { + final contactKey = widget.contact.publicKeyHex; + final interval = _clampControllerValue( + controller: _autoRefreshIntervalController, + min: _autoRefreshMinIntervalSeconds, + max: _autoRefreshMaxIntervalSeconds, + fallback: _autoRefreshIntervalSeconds, + ); + final quantity = _clampControllerValue( + controller: _autoRefreshQuantityController, + min: _autoRefreshMinQuantity, + max: _autoRefreshMaxQuantity, + fallback: _autoRefreshDefaultQuantity, + ); + + final prefs = PrefsManager.instance; + await prefs.setInt(_autoRefreshIntervalKey(contactKey), interval); + await prefs.setInt(_autoRefreshQuantityKey(contactKey), quantity); + } + + String _autoRefreshIntervalKey(String contactKey) { + return 'telemetry_auto_refresh_interval_$contactKey'; + } + + String _autoRefreshQuantityKey(String contactKey) { + return 'telemetry_auto_refresh_quantity_$contactKey'; + } + void _recordTelemetryResult(bool success) { final selection = _pendingStatusSelection; if (selection == null) return; @@ -206,9 +307,13 @@ class _TelemetryScreenState extends State { @override void dispose() { + unawaited(_saveAutoRefreshSettings()); _frameSubscription?.cancel(); _commandService?.dispose(); _statusTimeout?.cancel(); + _autoRefreshTimer?.cancel(); + _autoRefreshIntervalController.dispose(); + _autoRefreshQuantityController.dispose(); super.dispose(); } @@ -315,7 +420,9 @@ class _TelemetryScreenState extends State { child: CircularProgressIndicator(strokeWidth: 2), ) : const Icon(Icons.refresh), - onPressed: _isLoading ? null : _loadTelemetry, + onPressed: (_isLoading || _isAutoRefreshEnabled) + ? null + : () => _loadTelemetry(), tooltip: l10n.repeater_refresh, ), ], @@ -323,7 +430,8 @@ class _TelemetryScreenState extends State { body: SafeArea( top: false, child: RefreshIndicator( - onRefresh: _loadTelemetry, + onRefresh: () => + _isAutoRefreshEnabled ? Future.value() : _loadTelemetry(), child: ListView( padding: const EdgeInsets.all(16), children: [ @@ -346,6 +454,7 @@ class _TelemetryScreenState extends State { entry['channel'], isImperialUnits, ), + _buildAutoRefreshCard(), ], ), ), @@ -359,7 +468,6 @@ class _TelemetryScreenState extends State { int channel, bool isImperialUnits, ) { - final l10n = context.l10n; return Card( child: Padding( padding: const EdgeInsets.all(16), @@ -384,39 +492,479 @@ class _TelemetryScreenState extends State { ), const Divider(), for (final entry in channelData.entries) - if (entry.key == 'voltage' && channel == 1) - _buildInfoRow( - l10n.telemetry_batteryLabel, - _batteryText(entry.value), - ) - else if (entry.key == 'voltage') - _buildInfoRow( - l10n.telemetry_voltageLabel, - l10n.telemetry_voltageValue(entry.value.toString()), - ) - else if (entry.key == 'temperature' && channel == 1) - _buildInfoRow( - l10n.telemetry_mcuTemperatureLabel, - _temperatureText(entry.value, isImperialUnits), - ) - else if (entry.key == 'temperature') - _buildInfoRow( - l10n.telemetry_temperatureLabel, - _temperatureText(entry.value, isImperialUnits), - ) - else if (entry.key == 'current' && channel == 1) - _buildInfoRow( - l10n.telemetry_currentLabel, - l10n.telemetry_currentValue(entry.value.toString()), - ) - else - _buildInfoRow(entry.key, entry.value.toString()), + _buildTelemetryField(entry, channel, isImperialUnits), ], ), ), ); } + Widget _buildTelemetryField( + MapEntry entry, + int channel, + bool isImperialUnits, + ) { + if (entry.key == 'gps') { + return _buildGpsInfo(entry.value); + } + + final display = _formatTelemetryField( + entry.key, + entry.value, + channel, + isImperialUnits, + ); + return _buildInfoRow(display.label, display.value); + } + + _TelemetryFieldDisplay _formatTelemetryField( + String key, + dynamic value, + int channel, + bool isImperialUnits, + ) { + final l10n = context.l10n; + final text = _telemetryValueText(value); + + switch (key) { + case 'digitalInput': + return _TelemetryFieldDisplay(l10n.telemetry_digitalInputLabel, text); + case 'digitalOutput': + return _TelemetryFieldDisplay(l10n.telemetry_digitalOutputLabel, text); + case 'analogInput': + return _TelemetryFieldDisplay( + l10n.telemetry_analogInputLabel, + l10n.telemetry_analogValue(text), + ); + case 'analogOutput': + return _TelemetryFieldDisplay( + l10n.telemetry_analogOutputLabel, + l10n.telemetry_analogValue(text), + ); + case 'generic': + return _TelemetryFieldDisplay(l10n.telemetry_genericLabel, text); + case 'luminosity': + return _TelemetryFieldDisplay( + l10n.telemetry_luminosityLabel, + l10n.telemetry_luminosityValue(text), + ); + case 'presence': + return _TelemetryFieldDisplay(l10n.telemetry_presenceLabel, text); + case 'temperature': + return _TelemetryFieldDisplay( + channel == 1 + ? l10n.telemetry_mcuTemperatureLabel + : l10n.telemetry_temperatureLabel, + _temperatureText(value, isImperialUnits), + ); + case 'humidity': + return _TelemetryFieldDisplay(l10n.telemetry_humidityLabel, text); + case 'accelerometer': + return _TelemetryFieldDisplay( + l10n.telemetry_accelerometerLabel, + _telemetryAxisText(value), + ); + case 'pressure': + return _TelemetryFieldDisplay( + l10n.telemetry_pressureLabel, + l10n.telemetry_pressureValue(text), + ); + case 'altitude': + return _TelemetryFieldDisplay( + l10n.telemetry_altitudeLabel, + l10n.telemetry_altitudeValue(text), + ); + case 'voltage': + return _TelemetryFieldDisplay( + channel == 1 + ? l10n.telemetry_batteryLabel + : l10n.telemetry_voltageLabel, + channel == 1 + ? _batteryText(value) + : l10n.telemetry_voltageValue(text), + ); + case 'current': + return _TelemetryFieldDisplay( + l10n.telemetry_currentLabel, + l10n.telemetry_currentValue(text), + ); + case 'frequency': + return _TelemetryFieldDisplay( + l10n.telemetry_frequencyLabel, + l10n.telemetry_frequencyValue(text), + ); + case 'percentage': + return _TelemetryFieldDisplay( + l10n.telemetry_percentageLabel, + l10n.telemetry_percentageValue(text), + ); + case 'concentration': + return _TelemetryFieldDisplay( + l10n.telemetry_concentrationLabel, + l10n.telemetry_concentrationValue(text), + ); + case 'power': + return _TelemetryFieldDisplay( + l10n.telemetry_powerLabel, + l10n.telemetry_powerValue(text), + ); + case 'distance': + return _TelemetryFieldDisplay( + l10n.telemetry_distanceLabel, + l10n.telemetry_distanceValue(text), + ); + case 'energy': + return _TelemetryFieldDisplay( + l10n.telemetry_energyLabel, + l10n.telemetry_energyValue(text), + ); + case 'direction': + return _TelemetryFieldDisplay( + l10n.telemetry_directionLabel, + l10n.telemetry_directionValue(text), + ); + case 'time': + return _TelemetryFieldDisplay( + l10n.telemetry_timeLabel, + _telemetryTimeText(value), + ); + case 'gyrometer': + return _TelemetryFieldDisplay( + l10n.telemetry_gyrometerLabel, + _telemetryAxisText(value), + ); + case 'colour': + return _TelemetryFieldDisplay( + l10n.telemetry_colourLabel, + _telemetryColorText(value), + ); + case 'switch': + return _TelemetryFieldDisplay(l10n.telemetry_switchLabel, text); + case 'polyline': + return _TelemetryFieldDisplay( + l10n.telemetry_polylineLabel, + _telemetryMapText(value), + ); + default: + return _TelemetryFieldDisplay(key, text); + } + } + + Widget _buildAutoRefreshCard() { + final l10n = context.l10n; + final counterText = _autoRefreshCounterText(); + + return Card( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Row( + children: [ + Icon( + Icons.autorenew, + color: Theme.of(context).textTheme.headlineSmall?.color, + ), + const SizedBox(width: 8), + Text( + l10n.common_autoRefresh, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + const Divider(), + _buildAutoRefreshNumberField( + controller: _autoRefreshIntervalController, + label: l10n.common_interval, + min: _autoRefreshMinIntervalSeconds, + max: _autoRefreshMaxIntervalSeconds, + fallback: _autoRefreshIntervalSeconds, + ), + const SizedBox(height: 12), + _buildAutoRefreshNumberField( + controller: _autoRefreshQuantityController, + label: l10n.telemetry_autoFetchQuantity, + min: _autoRefreshMinQuantity, + max: _autoRefreshMaxQuantity, + fallback: _autoRefreshDefaultQuantity, + ), + if (counterText != null) ...[ + const SizedBox(height: 12), + Text( + counterText, + textAlign: TextAlign.center, + style: TextStyle( + color: _autoRefreshLastAttemptFailed + ? Theme.of(context).colorScheme.error + : null, + fontWeight: FontWeight.w600, + ), + ), + ], + const SizedBox(height: 12), + FilledButton( + onPressed: _isLoading && !_isAutoRefreshEnabled + ? null + : _toggleAutoRefresh, + child: _isAutoRefreshEnabled + ? SizedBox( + width: double.infinity, + height: 20, + child: Stack( + alignment: Alignment.center, + children: [ + Center(child: Text(l10n.common_disable)), + const Positioned( + right: 0, + child: SizedBox( + width: 18, + height: 18, + child: CircularProgressIndicator( + strokeWidth: 2, + color: Colors.white, + ), + ), + ), + ], + ), + ) + : Text(l10n.common_enable), + ), + ], + ), + ), + ); + } + + Widget _buildAutoRefreshNumberField({ + required TextEditingController controller, + required String label, + required int min, + required int max, + required int fallback, + }) { + return TextField( + controller: controller, + enabled: !_isAutoRefreshEnabled, + keyboardType: TextInputType.number, + inputFormatters: [FilteringTextInputFormatter.digitsOnly], + decoration: InputDecoration( + labelText: label, + border: const OutlineInputBorder(), + isDense: true, + ), + onEditingComplete: () { + _clampControllerValue( + controller: controller, + min: min, + max: max, + fallback: fallback, + ); + unawaited(_saveAutoRefreshSettings()); + FocusScope.of(context).unfocus(); + }, + onSubmitted: (_) => unawaited(_saveAutoRefreshSettings()), + onTapOutside: (_) { + unawaited(_saveAutoRefreshSettings()); + FocusScope.of(context).unfocus(); + }, + ); + } + + String? _autoRefreshCounterText() { + if (!_isAutoRefreshEnabled && _autoRefreshCurrentAttempt == 0) return null; + final counter = '$_autoRefreshCurrentAttempt/$_autoRefreshTotalAttempts'; + if (_autoRefreshLastAttemptFailed) { + return '${context.l10n.telemetry_error}: $counter'; + } + return counter; + } + + void _toggleAutoRefresh() { + if (_isAutoRefreshEnabled) { + _stopAutoRefresh(); + return; + } + _startAutoRefresh(); + } + + void _startAutoRefresh() { + final interval = _clampControllerValue( + controller: _autoRefreshIntervalController, + min: _autoRefreshMinIntervalSeconds, + max: _autoRefreshMaxIntervalSeconds, + fallback: _autoRefreshIntervalSeconds, + ); + final quantity = _clampControllerValue( + controller: _autoRefreshQuantityController, + min: _autoRefreshMinQuantity, + max: _autoRefreshMaxQuantity, + fallback: _autoRefreshDefaultQuantity, + ); + unawaited(_saveAutoRefreshSettings()); + + setState(() { + _isAutoRefreshEnabled = true; + _autoRefreshIntervalSeconds = interval; + _autoRefreshTotalAttempts = quantity; + _autoRefreshCurrentAttempt = 0; + _autoRefreshLastAttemptFailed = false; + }); + _runAutoRefreshAttempt(); + } + + void _stopAutoRefresh() { + _autoRefreshTimer?.cancel(); + _autoRefreshTimer = null; + if (!mounted) return; + setState(() { + _isAutoRefreshEnabled = false; + }); + } + + Future _runAutoRefreshAttempt() async { + if (!_isAutoRefreshEnabled || !mounted) return; + if (_autoRefreshCurrentAttempt >= _autoRefreshTotalAttempts) { + _stopAutoRefresh(); + return; + } + + setState(() { + _autoRefreshCurrentAttempt += 1; + }); + await _loadTelemetry(isAutoRefresh: true); + } + + void _scheduleNextAutoRefreshAttempt() { + if (!_isAutoRefreshEnabled || !mounted) return; + _autoRefreshTimer?.cancel(); + if (_autoRefreshCurrentAttempt >= _autoRefreshTotalAttempts) { + _stopAutoRefresh(); + return; + } + // Start the interval only after the current request has finished: after a + // telemetry response, timeout, or send error. This keeps slow replies from + // shortening the intended pause between requests. + _autoRefreshTimer = Timer( + Duration(seconds: _autoRefreshIntervalSeconds), + _runAutoRefreshAttempt, + ); + } + + int _clampControllerValue({ + required TextEditingController controller, + required int min, + required int max, + required int fallback, + }) { + final parsed = int.tryParse(controller.text); + final value = (parsed ?? fallback).clamp(min, max).toInt(); + controller.text = value.toString(); + controller.selection = TextSelection.collapsed( + offset: controller.text.length, + ); + return value; + } + + Widget _buildGpsInfo(dynamic value) { + final latitude = _readGpsValue(value, 'latitude'); + final longitude = _readGpsValue(value, 'longitude'); + final altitude = _readGpsValue(value, 'altitude'); + final isValidPosition = _isValidGpsPosition(latitude, longitude); + final gpsText = isValidPosition + ? [ + latitude!.toStringAsFixed(5), + longitude!.toStringAsFixed(5), + if (altitude != null) '${altitude.toStringAsFixed(1)} m', + ].join(', ') + : value.toString(); + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildInfoRow(context.l10n.telemetry_gpsLabel, gpsText), + if (isValidPosition) + TelemetryLocationMap( + // The map renders only after bounds validation, keeping malformed + // Cayenne payloads from creating an invalid FlutterMap center. + latitude: latitude!, + longitude: longitude!, + label: widget.contact.name, + contactType: widget.contact.type, + contactPublicKeyHex: widget.contact.publicKeyHex, + ), + ], + ); + } + + double? _readGpsValue(dynamic value, String key) { + if (value is! Map) return null; + final rawValue = value[key]; + if (rawValue is num) return rawValue.toDouble(); + return null; + } + + bool _isValidGpsPosition(double? latitude, double? longitude) { + if (latitude == null || longitude == null) return false; + const double epsilon = 1e-6; + return (latitude.abs() > epsilon || longitude.abs() > epsilon) && + latitude >= -90.0 && + latitude <= 90.0 && + longitude >= -180.0 && + longitude <= 180.0; + } + + String _telemetryValueText(dynamic value) { + if (value == null) return context.l10n.common_notAvailable; + if (value is double) { + return value.toStringAsFixed(value.truncateToDouble() == value ? 0 : 2); + } + if (value is num) { + return value.toString(); + } + return value.toString(); + } + + String _telemetryAxisText(dynamic value) { + if (value is! Map) return _telemetryValueText(value); + final x = _telemetryValueText(value['x']); + final y = _telemetryValueText(value['y']); + final z = _telemetryValueText(value['z']); + return 'X: $x, Y: $y, Z: $z'; + } + + String _telemetryColorText(dynamic value) { + if (value is! Map) return _telemetryValueText(value); + final red = _telemetryValueText(value['red']); + final green = _telemetryValueText(value['green']); + final blue = _telemetryValueText(value['blue']); + return 'R: $red, G: $green, B: $blue'; + } + + String _telemetryMapText(dynamic value) { + if (value is! Map) return _telemetryValueText(value); + return value.entries + .map((entry) => '${entry.key}: ${entry.value}') + .join(', '); + } + + String _telemetryTimeText(dynamic value) { + if (value is! num || value <= 0) return _telemetryValueText(value); + final dateTime = DateTime.fromMillisecondsSinceEpoch( + value.toInt() * 1000, + isUtc: true, + ).toLocal(); + final localizations = MaterialLocalizations.of(context); + final time = localizations.formatTimeOfDay( + TimeOfDay.fromDateTime(dateTime), + ); + return '${localizations.formatFullDate(dateTime)} $time'; + } + Widget _buildInfoRow(String label, String value) { return Padding( padding: const EdgeInsets.symmetric(vertical: 6), @@ -485,3 +1033,10 @@ class _TelemetryScreenState extends State { return '${tempC.toStringAsFixed(1)}°C'; } } + +class _TelemetryFieldDisplay { + final String label; + final String value; + + const _TelemetryFieldDisplay(this.label, this.value); +} diff --git a/lib/widgets/telemetry_location_map.dart b/lib/widgets/telemetry_location_map.dart new file mode 100644 index 00000000..b47d16d1 --- /dev/null +++ b/lib/widgets/telemetry_location_map.dart @@ -0,0 +1,428 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_map/flutter_map.dart'; +import 'package:latlong2/latlong.dart'; +import 'package:provider/provider.dart'; + +import '../connector/meshcore_connector.dart'; +import '../connector/meshcore_protocol.dart'; +import '../l10n/l10n.dart'; +import '../models/app_settings.dart'; +import '../models/contact.dart'; +import '../services/app_settings_service.dart'; +import '../services/map_tile_cache_service.dart'; + +class TelemetryLocationMap extends StatefulWidget { + final double latitude; + final double longitude; + final String label; + final int contactType; + final String contactPublicKeyHex; + + const TelemetryLocationMap({ + super.key, + required this.latitude, + required this.longitude, + required this.label, + required this.contactType, + required this.contactPublicKeyHex, + }); + + @override + State createState() => _TelemetryLocationMapState(); +} + +class _TelemetryLocationMapState extends State { + static const double _initialZoom = 14.0; + static const double _minZoom = 2.0; + static const double _maxZoom = 18.0; + + final MapController _mapController = MapController(); + + LatLng get _position => LatLng(widget.latitude, widget.longitude); + + @override + void dispose() { + _mapController.dispose(); + super.dispose(); + } + + @override + void didUpdateWidget(covariant TelemetryLocationMap oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.latitude == widget.latitude && + oldWidget.longitude == widget.longitude) { + return; + } + + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) { + _mapController.move(_position, _initialZoom); + } + }); + } + + @override + Widget build(BuildContext context) { + final connector = context.watch(); + final settingsService = context.watch(); + final settings = settingsService.settings; + final tileCache = context.read(); + final contacts = _filteredContacts(connector, settings); + final isDesktop = _isDesktopPlatform(defaultTargetPlatform); + + return Padding( + padding: const EdgeInsets.only(top: 8, bottom: 4), + child: ClipRRect( + borderRadius: BorderRadius.circular(8), + child: LayoutBuilder( + builder: (context, constraints) { + final maxHeight = MediaQuery.sizeOf(context).height * 0.75; + final squareHeight = constraints.maxWidth.isFinite + ? constraints.maxWidth + : maxHeight; + // Prefer square sizing by width, but cap only the height so the map + // remains usable on wide screens without growing past the viewport. + final mapHeight = squareHeight > maxHeight + ? maxHeight + : squareHeight; + + return SizedBox( + width: double.infinity, + height: mapHeight, + child: Stack( + children: [ + FlutterMap( + mapController: _mapController, + options: MapOptions( + initialCenter: _position, + initialZoom: _initialZoom, + minZoom: _minZoom, + maxZoom: _maxZoom, + interactionOptions: InteractionOptions( + flags: ~InteractiveFlag.rotate, + scrollWheelVelocity: isDesktop ? 0.012 : 0.005, + cursorKeyboardRotationOptions: + CursorKeyboardRotationOptions.disabled(), + keyboardOptions: isDesktop + ? const KeyboardOptions( + enableArrowKeysPanning: true, + enableWASDPanning: true, + enableRFZooming: true, + ) + : const KeyboardOptions.disabled(), + ), + ), + children: [ + TileLayer( + urlTemplate: kMapTileUrlTemplate, + tileProvider: tileCache.tileProvider, + userAgentPackageName: + MapTileCacheService.userAgentPackageName, + maxZoom: 19, + ), + MarkerLayer( + markers: [ + ...contacts.map(_buildContactMarker), + _buildTelemetryMarker(), + _buildLabelMarker(_position, widget.label), + ], + ), + ], + ), + Positioned( + top: 8, + right: 8, + child: _MapButton( + icon: Icons.filter_list, + tooltip: context.l10n.map_filterNodes, + onPressed: () => + _showFilterDialog(context, settingsService), + ), + ), + Positioned( + left: 8, + top: 8, + child: Column( + children: [ + _MapButton( + icon: Icons.add, + tooltip: 'Zoom in', + onPressed: () => _zoomBy(1), + ), + const SizedBox(height: 6), + _MapButton( + icon: Icons.remove, + tooltip: 'Zoom out', + onPressed: () => _zoomBy(-1), + ), + const SizedBox(height: 6), + _MapButton( + icon: Icons.my_location, + tooltip: 'Center map', + onPressed: () => + _mapController.move(_position, _initialZoom), + ), + ], + ), + ), + ], + ), + ); + }, + ), + ), + ); + } + + List _filteredContacts( + MeshCoreConnector connector, + AppSettings settings, + ) { + final contacts = settings.mapShowDiscoveryContacts + ? connector.allContacts + : connector.allContacts.where((contact) => contact.isActive).toList(); + + return contacts.where((contact) { + if (!contact.hasLocation) return false; + if (contact.publicKeyHex == widget.contactPublicKeyHex) return false; + if (contact.type == advTypeChat) return settings.mapShowChatNodes; + if (contact.type == advTypeRepeater) return settings.mapShowRepeaters; + return settings.mapShowOtherNodes; + }).toList(); + } + + Marker _buildTelemetryMarker() { + return Marker( + point: _position, + width: 44, + height: 44, + child: IgnorePointer( + child: _MarkerBubble( + color: Colors.red, + icon: _getNodeIcon(widget.contactType), + size: 24, + ), + ), + ); + } + + Marker _buildContactMarker(Contact contact) { + return Marker( + point: LatLng(contact.latitude!, contact.longitude!), + width: 34, + height: 34, + child: IgnorePointer( + child: _MarkerBubble( + color: _getNodeColor(contact.type), + icon: _getNodeIcon(contact.type), + size: 18, + ), + ), + ); + } + + Marker _buildLabelMarker(LatLng point, String label) { + return Marker( + point: point, + width: 140, + height: 24, + alignment: Alignment.topCenter, + child: IgnorePointer( + child: Transform.translate( + offset: const Offset(0, -24), + child: FittedBox( + fit: BoxFit.contain, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), + decoration: BoxDecoration( + color: Colors.black54, + borderRadius: BorderRadius.circular(8), + ), + alignment: Alignment.center, + child: Text( + label, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: const TextStyle( + color: Colors.white, + fontSize: 11, + fontWeight: FontWeight.w500, + ), + ), + ), + ), + ), + ), + ); + } + + void _zoomBy(double delta) { + final camera = _mapController.camera; + final nextZoom = (camera.zoom + delta).clamp(_minZoom, _maxZoom).toDouble(); + _mapController.move(camera.center, nextZoom); + } + + bool _isDesktopPlatform(TargetPlatform platform) { + return platform == TargetPlatform.linux || + platform == TargetPlatform.windows || + platform == TargetPlatform.macOS; + } + + Color _getNodeColor(int type) { + switch (type) { + case advTypeChat: + return Colors.blue; + case advTypeRepeater: + return Colors.green; + case advTypeRoom: + return Colors.purple; + case advTypeSensor: + return Colors.orange; + default: + return Colors.grey; + } + } + + IconData _getNodeIcon(int type) { + switch (type) { + case advTypeChat: + return Icons.person; + case advTypeRepeater: + return Icons.router; + case advTypeRoom: + return Icons.meeting_room; + case advTypeSensor: + return Icons.sensors; + default: + return Icons.device_unknown; + } + } + + void _showFilterDialog( + BuildContext context, + AppSettingsService settingsService, + ) { + showDialog( + context: context, + builder: (dialogContext) => AlertDialog( + title: Text(context.l10n.map_filterNodes), + content: SingleChildScrollView( + child: Consumer( + builder: (consumerContext, service, child) { + final settings = service.settings; + // Reuse the global map filters so the telemetry preview and the + // main map stay consistent without another settings model. + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + CheckboxListTile( + title: Text(context.l10n.map_chatNodes), + value: settings.mapShowChatNodes, + onChanged: (value) { + service.setMapShowChatNodes(value ?? true); + }, + contentPadding: EdgeInsets.zero, + ), + CheckboxListTile( + title: Text(context.l10n.map_repeaters), + value: settings.mapShowRepeaters, + onChanged: (value) { + service.setMapShowRepeaters(value ?? true); + }, + contentPadding: EdgeInsets.zero, + ), + CheckboxListTile( + title: Text(context.l10n.map_otherNodes), + value: settings.mapShowOtherNodes, + onChanged: (value) { + service.setMapShowOtherNodes(value ?? true); + }, + contentPadding: EdgeInsets.zero, + ), + CheckboxListTile( + title: Text(context.l10n.map_showDiscoveryContacts), + value: settings.mapShowDiscoveryContacts, + onChanged: (value) { + service.setMapShowDiscoveryContacts(value ?? true); + }, + contentPadding: EdgeInsets.zero, + ), + ], + ); + }, + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(dialogContext), + child: Text(context.l10n.common_close), + ), + ], + ), + ); + } +} + +class _MarkerBubble extends StatelessWidget { + final Color color; + final IconData icon; + final double size; + + const _MarkerBubble({ + required this.color, + required this.icon, + required this.size, + }); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.all(4), + decoration: BoxDecoration( + color: color, + shape: BoxShape.circle, + border: Border.all(color: Colors.white, width: 2), + boxShadow: [ + BoxShadow( + color: Colors.black.withValues(alpha: 0.3), + blurRadius: 4, + offset: const Offset(0, 2), + ), + ], + ), + alignment: Alignment.center, + child: Icon(icon, color: Colors.white, size: size), + ); + } +} + +class _MapButton extends StatelessWidget { + final IconData icon; + final String tooltip; + final VoidCallback onPressed; + + const _MapButton({ + required this.icon, + required this.tooltip, + required this.onPressed, + }); + + @override + Widget build(BuildContext context) { + return Material( + color: Theme.of(context).colorScheme.surface, + elevation: 3, + borderRadius: BorderRadius.circular(8), + clipBehavior: Clip.antiAlias, + child: IconButton( + icon: Icon(icon), + tooltip: tooltip, + onPressed: onPressed, + constraints: const BoxConstraints.tightFor(width: 40, height: 40), + padding: EdgeInsets.zero, + iconSize: 20, + ), + ); + } +}