flutter_nearby_http 0.0.3
flutter_nearby_http: ^0.0.3 copied to clipboard
A package for communication in intermittent connectivity scenarios using a reputation-based mechanism.
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) andbrowser(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:
- Reputation Assessment → Device calculates its own reliability score
- Cooperation Check → System determines if device meets cooperation thresholds
- History Display → Shows reputation evolution over time in a table format
- Reset Capability → Allows clearing metrics and starting fresh
- Safety Warnings → Alerts users when resources are critically low
- Data Exchange → Demonstrates cooperation through real content sharing (images as example)
- Network Monitoring → Tracks performance metrics for reputation updates
- Permission Management → MANDATORY setup for proper functionality
- 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 #
- 📧 [Email Support](mailto:edgar.ladeira@ubi.pt ; mailto:geraldo.cangondo@ubi.pt )
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