diff --git a/app/(tabs)/beneficiaries/[id]/equipment.tsx b/app/(tabs)/beneficiaries/[id]/equipment.tsx
index 7200910..bc78dd4 100644
--- a/app/(tabs)/beneficiaries/[id]/equipment.tsx
+++ b/app/(tabs)/beneficiaries/[id]/equipment.tsx
@@ -296,16 +296,11 @@ export default function EquipmentScreen() {
Sensors
-
-
-
-
-
-
+
{/* Simulator Warning */}
@@ -361,7 +356,7 @@ export default function EquipmentScreen() {
{apiSensors.length === 0 ? (
-
+
No Sensors Connected
@@ -515,19 +510,6 @@ const styles = StyleSheet.create({
placeholder: {
width: 32,
},
- headerRight: {
- flexDirection: 'row',
- alignItems: 'center',
- gap: Spacing.xs,
- },
- addButton: {
- width: 40,
- height: 40,
- borderRadius: BorderRadius.md,
- backgroundColor: AppColors.primaryLighter,
- justifyContent: 'center',
- alignItems: 'center',
- },
content: {
flex: 1,
},
diff --git a/app/(tabs)/beneficiaries/[id]/setup-wifi.tsx b/app/(tabs)/beneficiaries/[id]/setup-wifi.tsx
index 6dd49a3..aad28d7 100644
--- a/app/(tabs)/beneficiaries/[id]/setup-wifi.tsx
+++ b/app/(tabs)/beneficiaries/[id]/setup-wifi.tsx
@@ -13,6 +13,7 @@ import { Ionicons } from '@expo/vector-icons';
import { SafeAreaView } from 'react-native-safe-area-context';
import { router, useLocalSearchParams } from 'expo-router';
import * as Device from 'expo-device';
+import AsyncStorage from '@react-native-async-storage/async-storage';
import { useBLE } from '@/contexts/BLEContext';
import { api } from '@/services/api';
import type { WiFiNetwork } from '@/services/ble';
@@ -110,7 +111,19 @@ export default function SetupWiFiScreen() {
const setupInProgressRef = useRef(false);
const shouldCancelRef = useRef(false);
+ // Load saved WiFi password on mount
useEffect(() => {
+ const loadSavedPassword = async () => {
+ try {
+ const savedPassword = await AsyncStorage.getItem('LAST_WIFI_PASSWORD');
+ if (savedPassword) {
+ setPassword(savedPassword);
+ }
+ } catch (error) {
+ console.log('[SetupWiFi] Failed to load saved password:', error);
+ }
+ };
+ loadSavedPassword();
loadWiFiNetworks();
}, []);
@@ -233,14 +246,22 @@ export default function SetupWiFiScreen() {
updateSensorStatus(deviceId, 'attaching');
if (!isSimulator && wellId) {
+ console.log('[SetupWiFi] Attaching device to beneficiary:', {
+ beneficiaryId: id,
+ wellId,
+ ssid,
+ });
const attachResponse = await api.attachDeviceToBeneficiary(
id!,
wellId,
ssid,
pwd
);
+ console.log('[SetupWiFi] Attach response:', attachResponse);
if (!attachResponse.ok) {
- throw new Error('Failed to register sensor');
+ const errorDetail = attachResponse.error || 'Unknown API error';
+ console.error('[SetupWiFi] Attach FAILED:', errorDetail);
+ throw new Error(`Failed to register sensor: ${errorDetail}`);
}
}
updateSensorStep(deviceId, 'attach', 'completed');
@@ -364,7 +385,7 @@ export default function SetupWiFiScreen() {
}, [sensors, currentIndex, selectedNetwork, password, isPaused, processSensor]);
// Start batch setup
- const handleStartBatchSetup = () => {
+ const handleStartBatchSetup = async () => {
if (!selectedNetwork) {
Alert.alert('Error', 'Please select a WiFi network');
return;
@@ -374,6 +395,14 @@ export default function SetupWiFiScreen() {
return;
}
+ // Save password for next time
+ try {
+ await AsyncStorage.setItem('LAST_WIFI_PASSWORD', password);
+ console.log('[SetupWiFi] Password saved for future use');
+ } catch (error) {
+ console.log('[SetupWiFi] Failed to save password:', error);
+ }
+
// Initialize sensor states
const initialStates = selectedDevices.map(createSensorState);
setSensors(initialStates);
diff --git a/app/(tabs)/dashboard.tsx b/app/(tabs)/dashboard.tsx
index e2c51c1..720e8f9 100644
--- a/app/(tabs)/dashboard.tsx
+++ b/app/(tabs)/dashboard.tsx
@@ -9,6 +9,10 @@ import { FullScreenError } from '@/components/ui/ErrorMessage';
const DASHBOARD_URL = 'https://react.eluxnetworks.net/dashboard';
+// BUILD VERSION INDICATOR - видно на экране для проверки версии
+const BUILD_VERSION = 'v2.1.0';
+const BUILD_TIMESTAMP = '2026-01-27 17:05';
+
export default function DashboardScreen() {
const webViewRef = useRef(null);
const [isLoading, setIsLoading] = useState(true);
@@ -64,6 +68,13 @@ export default function DashboardScreen() {
+ {/* Build Version Indicator - ALWAYS VISIBLE */}
+
+
+ {BUILD_VERSION} • {BUILD_TIMESTAMP}
+
+
+
{/* WebView */}
= 3) {
+ const [currentSsid] = parts[2].split(',');
+ if (currentSsid && currentSsid.trim().toLowerCase() === ssid.toLowerCase()) {
+ console.log('[BLE] Sensor is ALREADY connected to target WiFi:', ssid);
+ console.log('[BLE] Skipping W| command - returning success');
+ return true;
+ }
+ console.log('[BLE] Sensor connected to different network or not connected:', currentSsid || 'none');
+ }
+ } catch (statusError) {
+ console.warn('[BLE] Failed to check WiFi status, continuing with config:', statusError);
+ }
+
// Step 2: Set WiFi credentials
const command = `${BLE_COMMANDS.SET_WIFI}|${ssid},${password}`;
console.log('[BLE] Step 2: Sending WiFi credentials...');
@@ -426,8 +449,28 @@ export class RealBLEManager implements IBLEManager {
return true;
}
- // WiFi config failed - throw detailed error
+ // WiFi config failed - check if sensor is still connected (using old credentials)
if (setResponse.includes('|W|fail')) {
+ console.log('[BLE] W|fail received. Checking if sensor still connected to WiFi...');
+
+ try {
+ const recheckResponse = await this.sendCommand(deviceId, BLE_COMMANDS.GET_WIFI_STATUS);
+ const parts = recheckResponse.split('|');
+ if (parts.length >= 3) {
+ const [currentSsid, rssiStr] = parts[2].split(',');
+ const rssi = parseInt(rssiStr, 10);
+
+ // If connected to target SSID (using old credentials), consider it success
+ if (currentSsid && currentSsid.trim().toLowerCase() === ssid.toLowerCase() && rssi < 0) {
+ console.log('[BLE] Sensor IS connected to target WiFi (using saved credentials):', currentSsid, 'RSSI:', rssi);
+ console.log('[BLE] Password may be wrong but sensor works - returning success');
+ return true;
+ }
+ }
+ } catch (recheckError) {
+ console.warn('[BLE] Failed to recheck WiFi status after W|fail');
+ }
+
throw new Error('WiFi credentials rejected by sensor. Check password.');
}