Flutter Nearby HTTP - ReCoopsys

A Flutter package for cooperative peer-to-peer networking with reputation-based trust system. Enables devices without internet to request data/services from nearby devices with connectivity.

Key Innovation

  • Reputation-based cooperation: Only trustworthy devices participate
  • Automatic role detection: Advertiser (with internet) vs Browser (without)
  • Resource-aware: Protects devices with low battery/storage

Why ReCoopsys?

Traditional P2P solutions don't consider device reliability or resource constraints. ReCoopsys introduces:

βœ… Smart Cooperation: Only devices with good reputation can serve others βœ… Resource Protection: Automatically prevents participation when battery < 6% or storage < 3% βœ… Trust Evolution: Reputation improves/degrades based on actual performance βœ… Universal Application: Works for any data type (images, documents, media, APIs)

Perfect for: Disaster recovery, rural IoT, offline-first apps, edge computing


Features

  • Relay HTTP GET requests through nearby connected peers.
  • Role-based communication: advertiser (with Internet) and browser (without Internet).
  • Node reputation mechanism based on:
    • Battery level
    • Storage availability
    • Interaction history
    • Latency and packet delivery quality
  • Automatic reputation calculation and decision-making.
  • Persistent reputation history with timestamp.
  • Easy integration into existing Flutter apps.

🧠 Reputation Algorithm Explained

Calculation Formula

Reputation = (w1Γ—Battery + w2Γ—Storage + w3Γ—Interactions + w4Γ—History + w5Γ—Quality)

Default Weights

Factor Weight Description
Battery 0.28 Current battery level (0-100%)
Storage 0.14 Available storage (0-100%)
Interactions 0.22 Success rate of past interactions
History 0.20 Long-term reliability track record
Quality 0.16 Network performance (latency, packets)

Cooperation Thresholds

  • With History: 0.40 (Primary Level - PL)
  • Without History: 0.25 (Secondary Level - SL)
  • Critical Resources: Battery <= 6%, Storage < 3%

Decision Tree

Is battery β‰₯ 6% AND storage > 3%?
  β”œβ”€ NO β†’ ❌ Cannot cooperate (resource protection)
  └─ YES β†’ Check reputation threshold
      β”œβ”€ Has history? β†’ Reputation β‰₯ 0.40?
      └─ No history? β†’ Reputation β‰₯ 0.25?

πŸ”„ System Flow Diagram

[Browser Device]     [Advertiser Device]
(No Internet)        (Has Internet)
      β”‚                    β”‚
      β”‚ 1. Request Data     β”‚
      β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€>
      β”‚                    β”‚ 2. Check Reputation
      β”‚                    β”œβ”€ Calculate score
      β”‚                    β”œβ”€ Verify thresholds
      β”‚                    └─ Check resources
      β”‚                    β”‚
      β”‚ 3. Serve Data      β”‚ (if cooperative)
      <──────────────────────
      β”‚                    β”‚
   [Display]          [Update Metrics]

Platform Support

Platform Status Notes
Android βœ… Fully Tested API 24+
iOS ⚠️ Limited Testing iOS 12+
Web ❌ Not Supported Nearby Connections limitation
Desktop ❌ Not Supported Bluetooth API constraints

⚠️ Limitations & Considerations

  • Range: Bluetooth/WiFi Direct range (~10-100m)
  • Battery: Continuous scanning affects battery life
  • Privacy: Device names are visible to nearby devices
  • Security: Data transmission not encrypted by default
  • Performance: Image processing requires device resources
  • Network: Requires location and Bluetooth permissions

πŸ“Š Performance Metrics

Metric Typical Value Notes
Discovery Time 2-10 seconds Depends on device density
Connection Setup 1-5 seconds First-time pairing slower
Reputation Calculation < 100ms Cached after first run
Image Processing 200-2000ms Depends on image size
Throughput 1-10 MB/s Via Bluetooth/WiFi Direct

πŸš€ Getting Started

Installation

Add to your pubspec.yaml:

dependencies:
  flutter_nearby_http: ^0.0.3
  flutter_nearby_connections: ^2.0.0
  device_info_plus: ^9.1.0
  permission_handler: ^11.0.1
  connectivity_plus: ^5.0.1
  path_provider: ^2.1.1
  battery_plus: ^4.0.2
  image: ^4.1.3
  http: ^1.1.0

Setup

Android

Add the following permissions to android/app/src/main/AndroidManifest.xml:

<!-- Bluetooth Permissions -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />

<!-- Location Permissions -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

<!-- Network Permissions -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

iOS

Add to ios/Runner/Info.plist:

<key>NSBluetoothAlwaysUsageDescription</key>
<string>This app needs Bluetooth for P2P communication</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs location to discover nearby devices</string>
<key>NSLocalNetworkUsageDescription</key>
<string>This app uses the local network to discover and connect to nearby devices</string>

How to Use?

1. Add Dependency

dependencies:
  flutter_nearby_http: ^0.0.3

2. Request Permissions

await PermissionsManager.requestBluetoothPermissions();
await PermissionsManager.requestLocationPermissions();

3. Check Reputation

final repManager = NearbyServiceManager();
final reputation = await repManager.calculateCurrentReputation();
print("Can cooperate: ${reputation.canCooperate()}");

πŸ‘¨β€πŸ’» What You Need to Implement (User Code)

You need to create your own Flutter app that uses the package. Here's the structure:

Required User Implementation

1. Main App Structure

// πŸ“ Your project: lib/main.dart
import 'package:flutter/material.dart';
import 'package:flutter_nearby_http/services/nearby_service_manager.dart';
import 'package:flutter_nearby_http/utils/permissions_manager.dart';
// ... other package imports

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(MaterialApp(home: YourDeviceScreen())); // Your screen name
}

class YourDeviceScreen extends StatefulWidget {
  @override
  _YourDeviceScreenState createState() => _YourDeviceScreenState();
}

2. State Management Variables (You Define)

class _YourDeviceScreenState extends State<YourDeviceScreen> {
  // Your app's state variables
  List<Device> devices = [];
  List<Device> connectedDevices = [];
  DeviceRole? _role;
  late NearbyService nearbyService;
  late StreamSubscription subscription;
  late StreamSubscription receivedDataSubscription;
  
  // Use the package's service manager
  final NearbyServiceManager repManager = NearbyServiceManager(); // βœ… From package
  Future<List<NodeReputation>>? history;
  
  // Your tracking variables
  Map<String, List<int>> delays = HashMap();
  Map<String, int> sentPackets = HashMap();
  Map<String, int> failedPackets = HashMap();
  Map<String, List<DateTime>> startTimes = {};
}

3. Initialization Logic (You Implement)

@override
void initState() {
  super.initState();
  
  // Use package services
  currentReputation = repManager.calculateCurrentReputation(); // βœ… From package
  history = loadHistory(); // Your method using package
  
  _initializeApp(); // Your initialization method
}

Future<void> _initializeApp() async {
  try {
    // Use package utilities
    await _determineRole(); // Your method using PermissionsManager
    await PermissionsManager.requestBluetoothPermissions(); // βœ… From package
    await PermissionsManager.requestLocationPermissions(); // βœ… From package
    await init(); // Your nearby service initialization
  } catch (e) {
    print('Error: $e');
  }
}

Future<void> _determineRole() async {
  // Use package utility
  final hasInternet = await PermissionsManager.checkInternetConnection(); // βœ… From package
  setState(() {
    _role = hasInternet ? DeviceRole.advertiser : DeviceRole.browser; // βœ… DeviceRole from package
  });
}

Optional -- Example

1. UI Implementation (You Build)

@override
Widget build(BuildContext context) {
  if (_role == null) {
    return const Scaffold(
      body: Center(child: CircularProgressIndicator()),
    );
  }
  
  return Scaffold(
    appBar: AppBar(
      title: Text(_role.toString().substring(11).toUpperCase()),
    ),
    body: ListView.builder(
      itemCount: getItemCount(),
      itemBuilder: (context, index) {
        final device = _role == DeviceRole.advertiser
            ? connectedDevices[index]
            : devices[index];
            
        return Container(
          // Your UI design
          child: Column(
            children: [
              // Device info display
              Text(device.deviceName),
              Text(getStateName(device.state)), // Your helper method
              
              // Use package widgets
              GestureDetector(
                onTap: () {
                  showDialog(
                    context: context,
                    builder: (context) => AlertDialog(
                      title: Text("Reputation History"),
                      content: HistoryTable(history: history), // βœ… From package
                      actions: [
                        TextButton(
                          onPressed: () async {
                            // Your reset logic using package services
                            await resetHistory(); // Your method
                            Navigator.pop(context);
                          },
                          child: Text('Reset'),
                        ),
                      ],
                    ),
                  );
                },
                child: Container(
                  // Your button styling
                  child: Text('Cooperation'),
                ),
              ),
            ],
          ),
        );
      },
    ),
  );
}

2. Helper Methods

// Your utility methods
String getStateName(SessionState state) {
  switch (state) {
    case SessionState.notConnected: return "disconnected";
    case SessionState.connecting: return "waiting";
    default: return "connected";
  }
}

Color getStateColor(SessionState state) {
  switch (state) {
    case SessionState.notConnected: return Colors.black;
    case SessionState.connecting: return Colors.grey;
    default: return Colors.green;
  }
}

int getItemCount() {
  return _role == DeviceRole.advertiser 
      ? connectedDevices.length 
      : devices.length;
}

3. Data Handling Methods (You Implement)

Future<List<NodeReputation>> loadHistory() async {
  // Use package service
  final historyRaw = await repManager.readHistory(); // βœ… From package
  return historyRaw.map((map) => NodeReputation.fromMap(map)).toList(); // βœ… From package
}

Future<void> resetHistory() async {
  setState(() {
    history = Future.value(<NodeReputation>[]);
  });
  
  // Use package services
  repManager.resetPacketCounters(); // βœ… From package
  
  // Your file handling logic
  final dir = await getApplicationDocumentsDirectory();
  final file = File('${dir.path}/reputation_deviceId.txt');
  if (await file.exists()) {
    await file.writeAsString('');
  }
}

4. Image Handling (You Implement)

void sendImageBackToDevice(String deviceId, String imageUrl) async {
  final startTime = DateTime.now();
  startTimes.putIfAbsent(deviceId, () => []).add(startTime);

  try {
    // Use package services
    Uint8List imageBytes = await ImageService.downloadImage(imageUrl); // βœ… From package
    String base64Image = base64Encode(await ImageService.resizeImage(imageBytes)); // βœ… From package
    
    // Your device finding logic
    Device foundDevice = connectedDevices.firstWhere((device) => device.deviceId == deviceId);
    
    // Your nearby service call
    nearbyService.sendMessage(foundDevice.deviceId, base64Image);
    
    // Use package dialog
    ReputationDialogs.showImageDialog(context, imageBytes); // βœ… From package
    
    // Update reputation using package
    await repManager.calculateCurrentReputation(); // βœ… From package
    
  } catch (e) {
    // Your error handling
    print('Error: $e');
  }
}

πŸ§‘β€πŸ’» Usage Examples

πŸ“ Note: The image processing example below demonstrates the package's capabilities, but the same principles apply to any type of data sharing or service request. The package evaluates device reputation and cooperation eligibility regardless of the content being shared.

How the Package Works in Practice

The package implements a cooperative networking system where devices must prove their reliability before participating in data sharing. Here's the complete flow:

  1. Reputation Assessment β†’ Device calculates its own reliability score
  2. Cooperation Check β†’ System determines if device meets cooperation thresholds
  3. History Display β†’ Shows reputation evolution over time in a table format
  4. Reset Capability β†’ Allows clearing metrics and starting fresh
  5. Safety Warnings β†’ Alerts users when resources are critically low
  6. Data Exchange β†’ Demonstrates cooperation through real content sharing (images as example)
  7. Network Monitoring β†’ Tracks performance metrics for reputation updates
  8. Permission Management β†’ MANDATORY setup for proper functionality
  9. Status Display β†’ Shows current reputation and cooperation status

1. Calculate Reputation and Check Cooperation

This is the core mechanism that determines if a device can participate in the network based on battery, storage, interaction history, and network performance.

final repManager = NearbyServiceManager();

// Calculate current device reputation
final NodeReputation rep = await repManager.calculateCurrentReputation();

// Check if device can cooperate
if (rep.canCooperate()) {
  print("βœ… Device can cooperate");
  print("Reputation: ${rep.reputation.toStringAsFixed(3)}");
  print("Battery: ${rep.battery.toStringAsFixed(1)}%");
  print("Storage: ${rep.storage.toStringAsFixed(1)}%");
} else {
  print("❌ Device cannot cooperate");
  final threshold = rep.hasHistory ? rep.PL : rep.SL;
  print("Reputation: ${rep.reputation.toStringAsFixed(3)} < Threshold: ${threshold.toStringAsFixed(2)}");
}

```dart
final repManager = NearbyServiceManager();

// Calculate current device reputation
final NodeReputation rep = await repManager.calculateCurrentReputation();

// Check if device can cooperate
if (rep.canCooperate()) {
  print("βœ… Device can cooperate");
  print("Reputation: ${rep.reputation.toStringAsFixed(3)}");
  print("Battery: ${rep.battery.toStringAsFixed(1)}%");
  print("Storage: ${rep.storage.toStringAsFixed(1)}%");
} else {
  print("❌ Device cannot cooperate");
  final threshold = rep.hasHistory ? rep.PL : rep.SL;
  print("Reputation: ${rep.reputation.toStringAsFixed(3)} < Threshold: ${threshold.toStringAsFixed(2)}");
}

2. View and Manage Reputation History

The reputation history table (as shown in the example code) displays the evolution of device reliability over time, helping users understand cooperation patterns.

// Load reputation history
final historyData = await repManager.readHistory();
final history = historyData.map((map) => NodeReputation.fromMap(map)).toList();

// Display history
history.forEach((rep) {
  print("${rep.timestamp}: reputation=${rep.reputation.toStringAsFixed(2)}, "
        "battery=${rep.battery}%, cooperates=${rep.canCooperate()}");
});

// Show history in UI using package widget
showDialog(
  context: context,
  builder: (context) => AlertDialog(
    title: Text("Reputation History"),
    content: HistoryTable(history: Future.value(history)), // βœ… Package widget
    actions: [
      TextButton(
        onPressed: () => Navigator.pop(context),
        child: Text('Close'),
      ),
    ],
  ),
);

3. Reset Metrics and History

Provides the ability to clear all counters and reputation history, allowing devices to start fresh in the cooperation system.

// Reset packet counters
repManager.resetPacketCounters();

// Reset reputation history file
final currentRep = await repManager.calculateCurrentReputation();
await currentRep.resetHistory();

print("πŸ“Š All metrics and history reset");

4. Automatic Status Check with UI Feedback

Critical safety mechanism that prevents cooperation when resources are too low (battery < 6% or storage ≀ 3%). This bypasses reputation calculation entirely to protect device health.

// Trigger comprehensive device status check
// This will show a dialog if cooperation is denied
await DeviceStatusUtils.checkDeviceStatus(context, repManager.getService());

// Manual cooperation check
final canCooperate = await repManager.canCooperate();
if (!canCooperate) {
  print("⚠️ Device denied cooperation - check battery, storage, or reputation");
}

5. Handle Data Exchange (Image Example)

Practical demonstration of the cooperation system in action. A device without internet requests an image from a device with internet connection. The internet-connected device will only serve the image if it has good reputation and proper connectivity.

πŸ”„ Use Case Flow: Browser device β†’ requests image URL β†’ Advertiser device β†’ checks own reputation β†’ downloads image if cooperative β†’ processes & sends image bytes β†’ Browser receives & displays image

// Download and process image
Future<void> handleImageRequest(String imageUrl) async {
  try {
    // βœ… Use package service
    final imageBytes = await ImageService.downloadImage(imageUrl);
    final resizedBytes = await ImageService.resizeImage(
      imageBytes, 
      width: 600, 
      height: 400
    );
    
    // Show image using package dialog
    ReputationDialogs.showImageDialog(context, resizedBytes);
    
    print("πŸ“Έ Image processed: ${resizedBytes.length} bytes");
  } catch (e) {
    print("❌ Image processing failed: $e");
  }
}

6. Monitor Network Metrics

Performance tracking that monitors packet success/failure rates and network latency. These metrics feed back into the reputation calculation, creating a feedback loop for cooperation assessment.

// Update metrics after network activity
void updateNetworkMetrics(String deviceId, bool success, int delay) {
  final service = NearbyHttpService();
  
  if (success) {
    service.sentPackets.update(deviceId, (v) => v + 1, ifAbsent: () => 1);
  } else {
    service.failedPackets.update(deviceId, (v) => v + 1, ifAbsent: () => 1);
  }
  
  service.delays.putIfAbsent(deviceId, () => []).add(delay);
  
  // Update reputation manager
  repManager.updateMetrics(
    sent: service.sentPackets,
    failed: service.failedPackets,
    delays: service.delays,
    metrics: service.packetMetricsTable,
  );
}

7. Permission Handling (MANDATORY)

⚠️ REQUIRED SETUP - These permissions are essential for the package to function properly. Without them, device discovery and P2P communication will fail.

// Check and request all necessary permissions
Future<void> setupPermissions() async {
  try {
    // Check internet connectivity
    final hasInternet = await PermissionsManager.checkInternetConnection();
    print("Internet available: $hasInternet");
    
    // Request Bluetooth permissions
    await PermissionsManager.requestBluetoothPermissions();
    print("βœ… Bluetooth permissions requested");
    
    // Request location permissions
    await PermissionsManager.requestLocationPermissions();
    print("βœ… Location permissions requested");
    
  } catch (e) {
    print("❌ Permission setup failed: $e");
  }
}

8. Display Device Reputation Status

Individual device assessment - Shows the reputation and cooperation status for each device in the network, helping users understand the reliability of their peers.

// Show detailed cooperation status
Future<void> showCooperationStatus(BuildContext context) async {
  final lastRecord = await loadLastRecord(); // Your method
  final cooperationStatus = NodeReputation.cooperationStatusString(lastRecord);
  
  // βœ… Use package dialog
  ReputationDialogs.showLastRecordPopup(context, cooperationStatus, lastRecord);
}

Advanced Features

Reputation Algorithm

The reputation system uses a weighted formula considering:

// Reputation weights (default)
final weights = [0.28, 0.14, 0.22, 0.20, 0.16];
// [battery, storage, interaction, history, qDelivery]

// Cooperation thresholds
final double PL = 0.40;  // Primary threshold (with history)
final double SL = 0.25;  // Secondary threshold (no history)

// Critical resource thresholds
final batteryThreshold = 6;   // Below 6% battery = no cooperation
final storageThreshold = 3;   // Below 3% storage = no cooperation

πŸ—οΈ Complete Example Template

Here's a complete template of what you need to implement:

// πŸ“ Your project: lib/main.dart
import 'dart:typed_data';
import 'dart:async';
import 'dart:collection';
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_nearby_connections/flutter_nearby_connections.dart';
import 'package:path_provider/path_provider.dart';
import 'package:device_info_plus/device_info_plus.dart';

// βœ… Import the package components
import 'package:flutter_nearby_http/services/nearby_service_manager.dart';
import 'package:flutter_nearby_http/services/nearby_http_service.dart';
import 'package:flutter_nearby_http/services/nearby_service_instance.dart';
import 'package:flutter_nearby_http/services/image_service.dart';
import 'package:flutter_nearby_http/utils/permissions_manager.dart';
import 'package:flutter_nearby_http/utils/device_status_utils.dart';
import 'package:flutter_nearby_http/models/node_reputation.dart';
import 'package:flutter_nearby_http/models/packet_metrics.dart';
import 'package:flutter_nearby_http/widgets.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(MaterialApp(home: DevicesListScreen()));
}

class DevicesListScreen extends StatefulWidget {
  @override
  _DevicesListScreenState createState() => _DevicesListScreenState();
}

class _DevicesListScreenState extends State<DevicesListScreen> {
  // πŸ‘€ Your app state variables
  List<Device> devices = [];
  List<Device> connectedDevices = [];
  late NearbyService nearbyService;
  late StreamSubscription subscription;
  late StreamSubscription receivedDataSubscription;
  DeviceRole? _role;
  bool _isInitialized = false;
  
  // βœ… Use package services
  final NearbyServiceManager repManager = NearbyServiceManager();
  Future<List<NodeReputation>>? history;
  
  // πŸ‘€ Your tracking variables
  Map<String, List<int>> delays = HashMap();
  Map<String, int> sentPackets = HashMap();
  Map<String, int> failedPackets = HashMap();
  Map<String, List<DateTime>> startTimes = {};

  @override
  void initState() {
    super.initState();
    // βœ… Use package services
    history = loadHistory();
    _checkStatus();
    _initializeApp();
  }

  // πŸ‘€ Your initialization method
  Future<void> _initializeApp() async {
    try {
      await _determineRole();
      // βœ… Use package utilities
      await PermissionsManager.requestBluetoothPermissions();
      await PermissionsManager.requestLocationPermissions();
      await init();
    } catch (e) {
      print('Error: $e');
    }
  }

  // πŸ‘€ Your role determination method
  Future<void> _determineRole() async {
    try {
      // βœ… Use package utility
      final hasInternet = await PermissionsManager.checkInternetConnection();
      setState(() {
        _role = hasInternet ? DeviceRole.advertiser : DeviceRole.browser;
      });
    } catch (e) {
      setState(() {
        _role = DeviceRole.browser;
      });
    }
  }

  // πŸ‘€ Your status check method
  Future<void> _checkStatus() async {
    // βœ… Use package utility
    final nearbyHttpService = repManager.getService();
    await DeviceStatusUtils.checkDeviceStatus(context, nearbyHttpService);
  }

  // πŸ‘€ Your history loading method
  Future<List<NodeReputation>> loadHistory() async {
    // βœ… Use package service
    final historyRaw = await repManager.readHistory();
    return historyRaw.map((map) => NodeReputation.fromMap(map)).toList();
  }

  @override
  Widget build(BuildContext context) {
    // πŸ‘€ Your UI implementation
    if (_role == null) {
      return const Scaffold(
        body: Center(child: CircularProgressIndicator()),
      );
    }
    
    return Scaffold(
      appBar: AppBar(
        title: Text(_role.toString().substring(11).toUpperCase()),
      ),
      body: ListView.builder(
        itemCount: devices.length,
        itemBuilder: (context, index) {
          final device = devices[index];
          return ListTile(
            title: Text(device.deviceName),
            subtitle: Text(device.state.toString()),
            trailing: ElevatedButton(
              onPressed: () {
                // πŸ‘€ Your connection logic
                nearbyService.invitePeer(
                  deviceID: device.deviceId,
                  deviceName: device.deviceName,
                );
              },
              child: Text('Connect'),
            ),
            onTap: () {
              // βœ… Use package widget
              showDialog(
                context: context,
                builder: (context) => AlertDialog(
                  title: Text("Reputation History"),
                  content: HistoryTable(history: history),
                  actions: [
                    TextButton(
                      onPressed: () => Navigator.pop(context),
                      child: Text('Close'),
                    ),
                  ],
                ),
              );
            },
          );
        },
      ),
    );
  }

  // πŸ‘€ Your nearby service initialization
  Future<void> init() async {
    if (_isInitialized) return;
    
    nearbyService = NearbyServiceInstance().service; // βœ… From package
    
    // πŸ‘€ Your device info logic
    String devInfo = '';
    DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
    if (Platform.isAndroid) {
      AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
      devInfo = androidInfo.model;
    }
    
    // πŸ‘€ Your nearby service setup
    await nearbyService.init(
      serviceType: 'mp-connection',
      deviceName: devInfo,
      strategy: Strategy.P2P_CLUSTER,
      callback: (isRunning) async {
        if (isRunning) {
          await _handleDeviceRole();
          _isInitialized = true;
        }
      },
    );
    
    // πŸ‘€ Your subscription setup
    setupSubscriptions();
  }

  // πŸ‘€ Your role handling method
  Future<void> _handleDeviceRole() async {
    if (_role == DeviceRole.advertiser) {
      await nearbyService.startAdvertisingPeer();
    } else if (_role == DeviceRole.browser) {
      await nearbyService.startBrowsingForPeers();
    }
  }

  // πŸ‘€ Your subscription setup
  void setupSubscriptions() {
    subscription = nearbyService.stateChangedSubscription(callback: (devicesList) {
      setState(() {
        devices = devicesList;
        connectedDevices = devicesList
            .where((d) => d.state == SessionState.connected)
            .toList();
      });
    });

    receivedDataSubscription = nearbyService.dataReceivedSubscription(callback: (data) async {
      // πŸ‘€ Your data processing logic
      Map<String, dynamic> jsonMap = jsonDecode(jsonEncode(data));
      String message = jsonMap['message'];
      
      if (message.startsWith('http')) {
        // Handle image URL
        // βœ… Use package services
        Uint8List imageBytes = await ImageService.downloadImage(message);
        ReputationDialogs.showImageDialog(context, imageBytes);
      } else {
        // Handle base64 image
        Uint8List imageBytes = base64Decode(message);
        // βœ… Use package dialog
        ReputationDialogs.showImageDialog(context, imageBytes);
      }
      
      // βœ… Update reputation using package
      await repManager.calculateCurrentReputation();
      setState(() {
        history = loadHistory();
      });
    });
  }

  @override
  void dispose() {
    subscription.cancel();
    receivedDataSubscription.cancel();
    nearbyService.stopBrowsingForPeers();
    nearbyService.stopAdvertisingPeer();
    super.dispose();
  }
}

Automatic Status Checking

import 'package:flutter_nearby_http/utils/device_status_utils.dart';

// Automatic device status evaluation
await DeviceStatusUtils.checkDeviceStatus(context, nearbyHttpService);

Network Performance Metrics

// Calculate throughput for device packets
double throughput = calculateThroughput(packetMetrics);

// Get average delay for device
double avgDelay = calculateAverageDelay(delays);

// Normalize values for reputation calculation
double normalizedValue = normalize(value, min, max);

Data Models

NodeReputation

class NodeReputation {
  final String deviceId;
  final double battery;              // Battery percentage (0-100)
  final double storage;              // Available storage percentage
  final int successfulInteractions;  // Count of successful operations
  final int totalInteractions;       // Total interaction attempts
  final int requestedPackets;        // Packets requested from network
  final int deliveredPackets;        // Successfully delivered packets
  final double avgLatency;           // Average response time (ms)
  final int diversity;               // Number of different peers interacted with
  final int daysSinceLastInteraction; // Recency factor
  final List<double> weights;        // Algorithm weights [0.28, 0.14, 0.22, 0.20, 0.16]
  
  double reputation = 0.0;           // Calculated reputation score (0-1)
  bool hasHistory = false;           // Whether device has interaction history
  
  // Cooperation decision logic
  bool canCooperate() {
    final threshold = hasHistory ? PL : SL;
    return (battery >= 6 && storage > 3 && reputation >= threshold);
  }
}

PacketMetrics

class PacketMetrics {
  final String deviceId;      // Target device identifier
  final bool packetSent;      // Whether packet was transmitted
  final bool packetDiscarded; // Whether packet was lost/dropped
  final int delay;            // Round-trip time in milliseconds
  final DateTime dateTime;    // Timestamp of transmission
  final int packetSize;       // Packet size in bytes
}

Device Roles

Advertiser Role

  • Condition: Device has internet connectivity
  • Behavior: Serves content, advertises availability
  • Responsibilities: Download images, process requests, serve data

Browser Role

  • Condition: Device lacks internet connectivity
  • Behavior: Requests content from advertisers
  • Responsibilities: Discover advertisers, request resources, display content

πŸ“ Package Structure

lib/
β”œβ”€β”€ flutter_nearby_cooperation.dart     # Main library
β”œβ”€β”€ models/
β”‚   β”œβ”€β”€ node_reputation.dart            # Reputation calculation and storage
β”‚   └── packet_metrics.dart             # Network performance tracking
β”œβ”€β”€ services/
β”‚   β”œβ”€β”€ nearby_http_service.dart        # Core P2P networking service
β”‚   β”œβ”€β”€ nearby_service_manager.dart     # Reputation and metrics management
β”‚   β”œβ”€β”€ nearby_service_instance.dart    # Singleton service instance
β”‚   └── image_service.dart              # Image processing utilities
└── utils/
    β”œβ”€β”€ permissions_manager.dart        # Permission handling
    β”œβ”€β”€ device_status_utils.dart        # Device capability assessment
    └── network_utils.dart              # Network calculation utilities

πŸ“š Additional Information

  • For detailed examples, see the example/ folder.
  • Issues and feature requests are welcome via GitHub.
  • Contributions are encouraged! Feel free to submit a pull request.

πŸ›  Author & License

Developed by:

Licensed under the MIT License.

πŸ“¦ Third-Party Licenses

This project uses flutter_nearby_connections, licensed under the BSD 2-Clause License. See LICENSES_THIRD_PARTY for details.

Support

Acknowledgments

  • Universidade da Beira Interior (UBI) for supporting this research and development
  • Instituto de TelecomunicaΓ§Γ΅es (IT) for providing the research infrastructure and expertise
  • Flutter Nearby Connections for P2P networking foundation