12 KiB
12 KiB
Validação de Sinal Mobile e Armazenamento Offline
Visão Geral
Sistema inteligente que monitora a qualidade do sinal de conexão mobile (4G/5G) e automaticamente ativa o modo offline quando o sinal está abaixo de 30%, garantindo que os dados sejam salvos localmente e sincronizados quando a conexão melhorar.
🎯 Funcionalidades Principais
1. Monitoramento de Sinal em Tempo Real
- Detecção automática do tipo de conexão (WiFi, 4G, 5G, 3G, 2G)
- Estimativa da intensidade do sinal baseada na geração da rede
- Atualização contínua do status de conexão
2. Ativação Automática do Modo Offline
- Trigger: Sinal abaixo de 30% ou sem conexão
- Comportamento: Salva dados localmente em vez de enviar para API
- Notificação: Alerta o usuário sobre a mudança de modo
3. Armazenamento Local Inteligente
- Dados organizados por tipo (entregas, fotos, assinaturas, status)
- Fila de sincronização para operações pendentes
- Sistema de retry com limite de tentativas
4. Sincronização Automática
- Detecta quando a conexão melhora
- Sincroniza dados pendentes automaticamente
- Limpa dados locais após sincronização bem-sucedida
🏗️ Arquitetura do Sistema
Componentes Principais
1. useMobileSignal Hook
// Monitora conexão e estima força do sinal
const { signalInfo, checkConnection } = useMobileSignal();
// signalInfo contém:
{
isConnected: boolean;
connectionType: 'wifi' | 'cellular' | 'none' | 'unknown';
isMobile: boolean;
signalStrength: number; // 0-100%
shouldUseOffline: boolean;
carrier?: string;
details?: {
cellularGeneration?: '2g' | '3g' | '4g' | '5g';
isConnectionExpensive?: boolean;
};
}
2. MobileSignalIndicator Component
// Interface visual do status de conexão
<MobileSignalIndicator
showDetails={true} // Mostrar detalhes completos
compact={false} // Modo compacto ou expandido
onPress={() => {}} // Ação ao tocar
/>
3. OfflineStorage Service
// Gerencia armazenamento local
const offlineStorage = new OfflineStorageService();
// Salvar dados offline
await offlineStorage.saveOfflineData('delivery', deliveryData);
// Adicionar à fila de sincronização
await offlineStorage.addToSyncQueue({
action: 'create',
endpoint: '/v1/delivery/create',
data: deliveryData
});
4. OfflineContext
// Contexto global para estado offline
const {
isOfflineMode,
offlineStats,
saveOfflineData,
syncOfflineData
} = useOffline();
📱 Interface Visual
Indicador de Sinal Mobile
Modo Expandido (showDetails={true})
┌─────────────────────────────────────┐
│ 📶 WiFi 80% 🔄 │
│ ████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ │
│ ● Modo Online │
│ Rede: 5G │
│ Conexão cara │
└─────────────────────────────────────┘
Modo Compacto (compact={true})
📶 ████
Cores e Estados
| Estado | Cor | Descrição |
|---|---|---|
| Excelente (70-100%) | 🟢 Verde | Conexão estável, modo online |
| Bom (40-69%) | 🟡 Amarelo | Conexão aceitável, modo online |
| Fraco (0-39%) | 🔴 Vermelho | Modo offline ativado |
🔄 Fluxo de Funcionamento
1. Monitoramento Contínuo
App Inicia → useMobileSignal → NetInfo Listener → Atualiza signalInfo
2. Decisão de Modo
signalInfo.signalStrength < 30% → shouldUseOffline = true → Modo Offline
signalInfo.signalStrength >= 30% → shouldUseOffline = false → Modo Online
3. Armazenamento Offline
Dados → Validação → Salva Localmente → Adiciona à Fila de Sync
4. Sincronização
Conexão Melhora → Detecta Mudança → Sincroniza Dados → Limpa Local
💾 Tipos de Dados Armazenados
1. Entregas (delivery)
{
outId: number;
transactionId: number;
deliveryDate: string;
receiverDoc: string;
receiverName: string;
lat: number | null;
lng: number | null;
broken: boolean;
devolution: boolean;
reasonDevolution: string;
deliveryImages: Array<{ type: string; url: string }>;
userId: number;
}
2. Fotos (photo)
{
file: string; // URI local da foto
transactionId: number;
timestamp: number;
}
3. Assinaturas (signature)
{
file: string; // URI local da assinatura
transactionId: number;
timestamp: number;
}
4. Status (status)
{
outId: number;
customerId: number;
status: 'pending' | 'in_progress' | 'delivered' | 'failed';
lat: number | null;
lng: number | null;
notes?: string;
}
🚀 Como Usar
1. Implementação Básica
import { useMobileSignal } from '../hooks/useMobileSignal';
import { useOffline } from '../contexts/OfflineContext';
const MyComponent = () => {
const { signalInfo } = useMobileSignal();
const { isOfflineMode, saveOfflineData } = useOffline();
const handleSaveData = async (data: any) => {
if (isOfflineMode) {
// Salvar offline
await saveOfflineData('delivery', data);
} else {
// Enviar para API
await api.createDelivery(data);
}
};
return (
<View>
<MobileSignalIndicator showDetails={true} />
{/* Resto da interface */}
</View>
);
};
2. Integração com CompleteDeliveryScreen
const handleSubmit = async () => {
try {
if (isOfflineMode) {
// Salvar dados offline
const offlineId = await saveOfflineData('delivery', deliveryData);
await addToSyncQueue({
action: 'create',
endpoint: '/v1/delivery/create',
data: deliveryData
});
Alert.alert(
'Dados Salvos Offline',
'Os dados foram salvos localmente e serão sincronizados quando a conexão melhorar.'
);
} else {
// Enviar para API normalmente
await api.createMultipleDeliveries([deliveryData]);
}
} catch (error) {
console.error('Erro ao salvar dados:', error);
}
};
3. Verificação de Status
const checkOfflineStatus = async () => {
const stats = await offlineStorage.getOfflineStats();
if (stats.totalSize > 0) {
console.log('Dados pendentes para sincronização:', stats);
// Mostrar indicador visual
setHasOfflineData(true);
setOfflineDataCount(stats.totalSize);
}
};
📊 Estatísticas e Monitoramento
Estatísticas Offline
const stats = await offlineStorage.getOfflineStats();
// Retorna:
{
deliveries: 5, // Entregas pendentes
photos: 12, // Fotos pendentes
signatures: 3, // Assinaturas pendentes
status: 2, // Status pendentes
syncQueue: 8, // Itens na fila de sync
totalSize: 30 // Total de itens pendentes
}
Logs de Debug
=== DEBUG: INFORMAÇÕES DE SINAL MOBILE ===
Tipo de conexão: cellular
Conectado: true
Força do sinal estimada: 25%
Deve usar offline: true
Detalhes: { cellularGeneration: '4g', isConnectionExpensive: false }
=== DEBUG: MODO OFFLINE ATUALIZADO ===
Sinal: 25%
Tipo de conexão: cellular
Deve usar offline: true
Modo offline ativo: true
=== DEBUG: DADOS SALVOS OFFLINE ===
Tipo: delivery
ID: delivery_1703123456789_abc123
Timestamp: 2023-12-21T10:30:56.789Z
🔧 Configuração e Personalização
1. Threshold de Sinal
// Em useMobileSignal.ts
const shouldUseOfflineMode = (strength: number, connectionType: string): boolean => {
// Personalizar threshold (padrão: 30%)
const OFFLINE_THRESHOLD = 30;
return strength < OFFLINE_THRESHOLD || connectionType === 'none';
};
2. Estimativa de Força de Sinal
// Personalizar estimativas por tipo de rede
const estimateSignalStrength = (netInfo: NetInfoState): number => {
if (netInfo.type === 'cellular' && netInfo.details?.cellularGeneration) {
switch (netInfo.details.cellularGeneration) {
case '5g': return 95; // Ajustar valores
case '4g': return 80; // Ajustar valores
case '3g': return 60; // Ajustar valores
case '2g': return 30; // Ajustar valores
}
}
return 60;
};
3. Tempo de Retry
// Em OfflineStorageService
const MAX_RETRIES = 5; // Aumentar tentativas
const RETRY_DELAY = 5000; // Delay entre tentativas (ms)
🧪 Testes e Validação
1. Teste de Conexão Fraca
# Simular sinal fraco
# Verificar ativação do modo offline
# Confirmar salvamento local
# Verificar notificação ao usuário
2. Teste de Sincronização
# Salvar dados offline
# Melhorar conexão
# Verificar sincronização automática
# Confirmar limpeza dos dados locais
3. Teste de Recuperação
# Simular falha na sincronização
# Verificar sistema de retry
# Confirmar limite de tentativas
# Verificar tratamento de erro
🚨 Tratamento de Erros
1. Erro de Armazenamento
try {
await saveOfflineData('delivery', data);
} catch (error) {
console.error('Erro ao salvar offline:', error);
// Fallback: tentar enviar para API mesmo com sinal fraco
try {
await api.createDelivery(data);
} catch (apiError) {
Alert.alert('Erro', 'Não foi possível salvar os dados. Tente novamente.');
}
}
2. Erro de Sincronização
try {
await syncOfflineData();
} catch (error) {
console.error('Erro na sincronização:', error);
// Manter dados offline para próxima tentativa
Alert.alert(
'Erro na Sincronização',
'Alguns dados não puderam ser sincronizados. Eles permanecerão salvos localmente.'
);
}
📈 Métricas e Performance
Indicadores de Performance
- Tempo de resposta: < 100ms para detecção de mudança de sinal
- Uso de memória: < 50MB para dados offline
- Tempo de sincronização: < 5s para 100 itens
- Taxa de sucesso: > 95% para operações offline
Monitoramento
- Logs detalhados para debug
- Estatísticas de uso offline
- Métricas de sincronização
- Alertas de erro em tempo real
🔮 Melhorias Futuras
1. Cache Inteligente
- Compressão de dados offline
- Limpeza automática de dados antigos
- Priorização de dados críticos
2. Sincronização Incremental
- Sync apenas de dados modificados
- Resolução de conflitos automática
- Merge inteligente de dados
3. Análise de Padrões
- Machine learning para prever qualidade de sinal
- Otimização automática de threshold
- Recomendações de sincronização
4. Backup em Nuvem
- Backup automático de dados críticos
- Sincronização cross-device
- Recuperação de dados perdidos
📚 Referências Técnicas
Bibliotecas Utilizadas
- @react-native-community/netinfo: Monitoramento de rede
- @react-native-async-storage/async-storage: Armazenamento local
- React Context API: Gerenciamento de estado global
APIs Nativas
- NetInfo: Informações de conectividade
- AsyncStorage: Armazenamento persistente
- FileSystem: Gerenciamento de arquivos
Padrões de Design
- Observer Pattern: Monitoramento de mudanças de rede
- Strategy Pattern: Alternância entre modos online/offline
- Queue Pattern: Fila de sincronização
- Retry Pattern: Tentativas de sincronização
✅ Conclusão
O sistema de validação de sinal mobile e armazenamento offline oferece:
- Confiabilidade: Dados nunca são perdidos, mesmo com conexão instável
- Transparência: Usuário sempre sabe o status da conexão
- Automação: Mudança de modo transparente e automática
- Performance: Operações offline são instantâneas
- Escalabilidade: Sistema preparado para crescimento futuro
Este sistema garante que o aplicativo funcione perfeitamente em qualquer condição de rede, proporcionando uma experiência consistente para o usuário final.