nebula_flutter_plugin 1.0.3 copy "nebula_flutter_plugin: ^1.0.3" to clipboard
nebula_flutter_plugin: ^1.0.3 copied to clipboard

PlatformAndroid

Flutter wrapper for PAX Nebula SDK: connect to PAX POS terminals and perform Sale, Refund, Void, Settlement and custom txn transactions easily over WIFI, USB, BLuetooth and Cloud

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:nebula_flutter_plugin/nebula_flutter_plugin.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Nebula Plugin Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
        useMaterial3: true,
      ),
      home: const HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final NebulaFlutterPlugin _plugin = NebulaFlutterPlugin();
  final List<String> _logs = [];
  bool _isConnected = false;

  @override
  void initState() {
    super.initState();
    _plugin.setOnConnectionStatusCallback((connected) {
      setState(() {
        _isConnected = connected;
        _addLog('Connection status changed: ${connected ? "Connected" : "Disconnected"}');
      });
    });
    _plugin.setOnMessageReceivedCallback((packageName, message) {
      _addLog('Message received: pkg=$packageName, msg=$message');
    });
    _plugin.setOnChooseAppCallback((apps) async {
      return await showDialog<String>(
        context: context,
        barrierDismissible: false,
        builder: (context) {
          return SimpleDialog(
            title: const Text('Select Application'),
            children: apps.map((app) {
              return SimpleDialogOption(
                onPressed: () {
                  Navigator.pop(context, app['packageName']);
                },
                child: Text(app['appName'] ?? (app['packageName'] ?? 'Unknown App')),
              );
            }).toList(),
          );
        },
      );
    });
  }

  Future<Map<String, String>?> _showInputsDialog(
      String title, Map<String, String> defaultValues) async {
    final controllers = <String, TextEditingController>{};
    for (var entry in defaultValues.entries) {
      controllers[entry.key] = TextEditingController(text: entry.value);
    }

    return await showDialog<Map<String, String>>(
      context: context,
      builder: (context) {
        return AlertDialog(
          title: Text(title),
          content: SingleChildScrollView(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: defaultValues.keys.map((key) {
                return Padding(
                  padding: const EdgeInsets.only(bottom: 8.0),
                  child: TextField(
                    controller: controllers[key],
                    decoration: InputDecoration(
                      labelText: key,
                      border: const OutlineInputBorder(),
                    ),
                  ),
                );
              }).toList(),
            ),
          ),
          actions: [
            TextButton(
              onPressed: () => Navigator.pop(context, null),
              child: const Text('Cancel'),
            ),
            FilledButton(
              onPressed: () {
                final result = <String, String>{};
                for (var key in controllers.keys) {
                  result[key] = controllers[key]!.text;
                }
                Navigator.pop(context, result);
              },
              child: const Text('OK'),
            ),
          ],
        );
      },
    );
  }

  void _addLog(String log) {
    setState(() {
      _logs.insert(0, '[${DateTime.now().toString().substring(11, 19)}] $log');
      if (_logs.length > 100) _logs.removeLast();
    });
  }

  Future<void> _connectTcp() async {
    final inputs = await _showInputsDialog('TCP Connect', {
      'host': '192.168.8.101',
      'port': '30999',
    });
    if (inputs == null) return;

    _addLog('Connecting via TCP to ${inputs['host']}:${inputs['port']}...');
    try {
      final result = await _plugin.connectTcp(
        inputs['host']!,
        port: int.tryParse(inputs['port']!) ?? 30999,
        timeout: 20000,
      );
      _addLog('TCP Connection result: $result');
    } catch (e) {
      _addLog('TCP Connection failed: $e');
    }
  }

  Future<void> _connectBluetooth() async {
    final inputs = await _showInputsDialog('Bluetooth Connect', {
      'identifier': 'A0:44:B7:DC:3E:0D',
    });
    if (inputs == null) return;

    _addLog('Connecting via Bluetooth to ${inputs['identifier']}...');
    try {
      final result = await _plugin.connectBluetooth(
        inputs['identifier']!,
        timeout: 20000,
      );
      _addLog('Bluetooth Connection result: $result');
    } catch (e) {
      _addLog('Bluetooth Connection failed: $e');
    }
  }

  Future<void> _connectUsb() async {
    _addLog('Connecting via USB...');
    try {
      final result = await _plugin.connectUsb(timeout: 20000);
      _addLog('USB Connection result: $result');
    } catch (e) {
      _addLog('USB Connection failed: $e');
    }
  }

  Future<void> _bindCloud() async {
    final inputs = await _showInputsDialog('Bind Cloud', {
      'baseUrl': 'https://uat.posnebula.com/nebula-acs/',
      'bindCode': '62719',
      'eid': '495572',
      'appId': '600052',
    });
    if (inputs == null) return;

    _addLog('Binding via Cloud...');
    try {
      final config = CloudConfig(
        baseUrl: inputs['baseUrl']!,
        bindCode: inputs['bindCode']!,
        eid: inputs['eid']!,
        appId: inputs['appId']!,
      );
      final result = await _plugin.bindDeviceByCloud(config, timeout: 20000);
      _addLog('Cloud Bind result: $result');
    } catch (e) {
      _addLog('Cloud Bind failed: $e');
    }
  }

  Future<void> _connectCloud() async {
    _addLog('Connecting via Cloud...');
    try {
      final result = await _plugin.connectCloud(timeout: 20000);
      _addLog('Cloud Connection result: $result');
    } catch (e) {
      _addLog('Cloud Connection failed: $e');
    }
  }

  Future<void> _sendSaleTransaction() async {
    final inputs = await _showInputsDialog('Sale Transaction', {
      'amount': '1000',
    });

    if (inputs == null) return;

    final amount = int.tryParse(inputs['amount'] ?? '');

    if (amount == null) {
      _addLog('Invalid amount entered');
      return;
    }

    _addLog('Sending Sale transaction...');
    try {
      final request = SaleRequest(
        amount: amount,
        tipAmount: 0,
        currencyCode: 'BDT',
      );
      final response = await _plugin.startSaleTransaction(request);
      _addLog('Sale Transaction result: $response');
    } catch (e) {
      _addLog('Sale Transaction failed: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);

    return Scaffold(
      appBar: AppBar(
        title: const Text('Nebula Plugin Demo'),
        backgroundColor: theme.colorScheme.inversePrimary,
        actions: [
          Padding(
            padding: const EdgeInsets.only(right: 16),
            child: Row(
              children: [
                Icon(
                  Icons.circle,
                  size: 12,
                  color: _isConnected ? Colors.green : Colors.red,
                ),
                const SizedBox(width: 6),
                Text(
                  _isConnected ? 'Connected' : 'Disconnected',
                  style: TextStyle(
                    fontSize: 14,
                    color: _isConnected ? Colors.green : Colors.red,
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
      body: Column(
        children: [
          // Button area
          Padding(
            padding: const EdgeInsets.all(16),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                Row(
                  children: [
                    Expanded(
                      child:_buildButton(
                        icon: Icons.usb,
                        label: 'USB Connect',
                        onPressed: _connectUsb,
                        color: Colors.teal,
                      ),
                    ),
                    const SizedBox(width: 8),
                    Expanded(
                      child: _buildButton(
                        icon: Icons.bluetooth,
                        label: 'BT Connect',
                        onPressed: _connectBluetooth,
                        color: Colors.indigo,
                      ),
                    ),
                  ],
                ),
                const SizedBox(height: 8),
                Row(
                  children: [
                    Expanded(
                      child: _buildButton(
                        icon: Icons.cloud_outlined,
                        label: 'Bind Cloud',
                        onPressed: _bindCloud,
                        color: Colors.deepPurple,
                      ),
                    ),
                    const SizedBox(width: 8),
                    Expanded(
                      child: _buildButton(
                        icon: Icons.cloud_done,
                        label: 'Connect Cloud',
                        onPressed: _connectCloud,
                        color: Colors.blueGrey,
                      ),
                    ),
                  ],
                ),
                const SizedBox(height: 8),
                
                const SizedBox(height: 12),
                _buildButton(
                  icon: Icons.payment,
                  label: 'Send Sale Transaction',
                  onPressed: _sendSaleTransaction,
                  color: Colors.orange,
                ),
                if (_isConnected) ...[
                  const SizedBox(height: 8),
                  OutlinedButton.icon(
                    onPressed: () async {
                      await _plugin.disconnect();
                      _addLog('Disconnected');
                    },
                    icon: const Icon(Icons.link_off),
                    label: const Text('Disconnect'),
                    style: OutlinedButton.styleFrom(
                      foregroundColor: Colors.red,
                      side: const BorderSide(color: Colors.red),
                      padding: const EdgeInsets.symmetric(vertical: 12),
                    ),
                  ),
                ],
              ],
            ),
          ),
          const Divider(height: 1),
          // Log area
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Text(
                  'Logs',
                  style: theme.textTheme.titleMedium?.copyWith(
                    fontWeight: FontWeight.bold,
                  ),
                ),
                TextButton(
                  onPressed: () => setState(() => _logs.clear()),
                  child: const Text('Clear'),
                ),
              ],
            ),
          ),
          Expanded(
            child: _logs.isEmpty
                ? const Center(
                    child: Text(
                      'No Logs Available',
                      style: TextStyle(color: Colors.grey),
                    ),
                  )
                : ListView.builder(
                    padding: const EdgeInsets.symmetric(horizontal: 16),
                    itemCount: _logs.length,
                    itemBuilder: (context, index) {
                      return Padding(
                        padding: const EdgeInsets.only(bottom: 4),
                        child: Text(
                          _logs[index],
                          style: const TextStyle(
                            fontSize: 13,
                            fontFamily: 'monospace',
                          ),
                        ),
                      );
                    },
                  ),
          ),
        ],
      ),
    );
  }

  Widget _buildButton({
    required IconData icon,
    required String label,
    required VoidCallback onPressed,
    required Color color,
  }) {
    return ElevatedButton.icon(
      onPressed: onPressed,
      icon: Icon(icon, size: 18),
      label: Text(label),
      style: ElevatedButton.styleFrom(
        backgroundColor: color,
        foregroundColor: Colors.white,
        padding: const EdgeInsets.symmetric(vertical: 12),
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(8),
        ),
      ),
    );
  }
}
1
likes
160
points
147
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Flutter wrapper for PAX Nebula SDK: connect to PAX POS terminals and perform Sale, Refund, Void, Settlement and custom txn transactions easily over WIFI, USB, BLuetooth and Cloud

Homepage

License

MIT-0 (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on nebula_flutter_plugin

Packages that implement nebula_flutter_plugin