totem_alecto 0.0.3 copy "totem_alecto: ^0.0.3" to clipboard
totem_alecto: ^0.0.3 copied to clipboard

PlatformAndroid

Flutter plugin package for interfacing with Totem Alecto thermal printers, providing native Android support for printing operations

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:async';

import 'package:totem_alecto/totem_alecto.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Totem Alecto Example',
      theme: ThemeData(primarySwatch: Colors.blue, useMaterial3: true),
      home: const PrinterHomePage(),
    );
  }
}

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

  @override
  State<PrinterHomePage> createState() => _PrinterHomePageState();
}

class _PrinterHomePageState extends State<PrinterHomePage> {
  final _printer = TotemAlecto();

  String _status = 'Desconectado';
  bool _isConnected = false;
  List<UsbDeviceInfo> _devices = [];
  UsbDeviceInfo? _selectedDevice;
  StreamSubscription<PrinterEvent>? _eventSubscription;

  final _textController = TextEditingController(
    text: 'Teste de Impressão\nTotem Alecto Plugin\n\n',
  );

  @override
  void initState() {
    super.initState();
    _init();
  }

  @override
  void dispose() {
    _eventSubscription?.cancel();
    _textController.dispose();
    super.dispose();
  }

  Future<void> _init() async {
    // Ouvir eventos da impressora
    _eventSubscription = _printer.printerEvents.listen((event) {
      setState(() {
        switch (event.type) {
          case PrinterEventType.onOpen:
            _status = 'Conectado';
            _isConnected = true;
            break;
          case PrinterEventType.onOpenFailed:
            _status = 'Falha na conexão';
            _isConnected = false;
            break;
          case PrinterEventType.onClose:
            _status = 'Desconectado';
            _isConnected = false;
            break;
          case PrinterEventType.onPrintComplete:
            final success = event.success == true ? 'Sucesso' : 'Falha';
            _showSnackBar('Impressão: $success (código: ${event.resultCode})');
            break;
          default:
            break;
        }
      });
    });

    // Verificar suporte
    final isSupported = await _printer.isSupported();
    if (!isSupported) {
      setState(() {
        _status = 'USB não suportado';
      });
      return;
    }

    // Listar dispositivos
    await _refreshDevices();
  }

  Future<void> _refreshDevices() async {
    final devices = await _printer.listDevices();
    setState(() {
      _devices = devices;
      if (devices.isNotEmpty && _selectedDevice == null) {
        _selectedDevice = devices.first;
      }
    });
  }

  Future<void> _connectDevice() async {
    if (_selectedDevice == null) {
      _showSnackBar('Selecione um dispositivo');
      return;
    }

    setState(() {
      _status = 'Conectando...';
    });

    // Verificar permissão
    // var hasPermission = await _printer.hasPermission(_selectedDevice!.deviceName);
    // if (!hasPermission) {
    //   _showSnackBar('Solicitando permissão USB...');
    //   final granted = await _printer.requestPermission(_selectedDevice!.deviceName);
    //   if (!granted) {
    //     _showSnackBar('Permissão USB negada');
    //     setState(() {
    //       _status = 'Permissão negada';
    //     });
    //     return;
    //   }
    //   hasPermission = true;
    // }

    // Conectar
    await _printer.connectByIds(4070, 33054);
  }

  Future<void> _connect() async {
    if (_selectedDevice == null) {
      _showSnackBar('Selecione um dispositivo');
      return;
    }

    setState(() {
      _status = 'Conectando...';
    });

    // Verificar permissão
    var hasPermission = await _printer.hasPermission(
      _selectedDevice!.deviceName,
    );
    if (!hasPermission) {
      _showSnackBar('Solicitando permissão USB...');
      final granted = await _printer.requestPermission(
        _selectedDevice!.deviceName,
      );
      if (!granted) {
        _showSnackBar('Permissão USB negada');
        setState(() {
          _status = 'Permissão negada';
        });
        return;
      }
      hasPermission = true;
    }

    // Conectar
    if (hasPermission) {
      await _printer.connect(_selectedDevice!.deviceName);
    }
  }

  Future<void> _disconnect() async {
    await _printer.disconnect();
  }

  Future<void> _printText() async {
    if (!_isConnected) {
      _showSnackBar('Impressora não conectada');
      return;
    }

    final text = _textController.text;
    if (text.isEmpty) {
      _showSnackBar('Digite um texto para imprimir');
      return;
    }

    final result = await _printer.printText(
      text,
      alignment: TextAlignment.center,
      cutPaper: true,
    );

    _showSnackBar(
      result.success ? 'Enviado para impressão' : 'Erro ao imprimir',
    );
  }

  Future<void> _printImage() async {
    if (!_isConnected) {
      _showSnackBar('Impressora não conectada');
      return;
    }

    // Carregar a imagem do ativo
    final byteData = await rootBundle.load('assets/images/epoc_logo.png');
    final bytes = byteData.buffer.asUint8List();

    final result = await _printer.printPicture(
      bytes,
      alignment: TextAlignment.center,
      cutPaper: false,
    );

    _showSnackBar(
      result.success
          ? 'Imagem enviada para impressão'
          : 'Erro ao imprimir imagem',
    );
  }

  Future<void> _printFormatted() async {
    if (!_isConnected) {
      _showSnackBar('Impressora não conectada');
      return;
    }

    // Exemplo de texto formatado
    await _printer.printTextFormatted(
      '=== TOTEM ALECTO ===\n',
      alignment: TextAlignment.center,
      fontAttributes: const FontAttributes(bold: true, doubleHeight: true),
      cutPaper: false,
    );

    await _printer.printText(
      '\nData: ${DateTime.now()}\n',
      alignment: TextAlignment.left,
      cutPaper: false,
    );

    await _printer.printTextFormatted(
      '\n*** FIM DO TESTE ***\n\n\n',
      alignment: TextAlignment.center,
      fontAttributes: const FontAttributes(bold: true),
      cutPaper: false,
    );
    await _printer.printTextFormatted(
      '\n*** FIM DO TESTE ***\n\n\n',
      alignment: TextAlignment.center,
      fontAttributes: const FontAttributes(bold: true),
      cutPaper: false,
    );
    await _printer.printTextFormatted(
      '\n*** FIM DO TESTE ***\n\n\n',
      alignment: TextAlignment.center,
      fontAttributes: const FontAttributes(bold: true),
      cutPaper: false,
    );
    await _printer.printTextFormatted(
      '\n*** FIM DO TESTE ***\n\n\n',
      alignment: TextAlignment.center,
      fontAttributes: const FontAttributes(bold: true),
      cutPaper: false,
    );
    await _printer.printTextFormatted(
      '\n*** FIM DO TESTE ***\n\n\n',
      alignment: TextAlignment.center,
      fontAttributes: const FontAttributes(bold: true),
      cutPaper: false,
    );
    await _printer.printTextFormatted(
      '\n*** FIM DO TESTE ***\n\n\n',
      alignment: TextAlignment.center,
      fontAttributes: const FontAttributes(bold: true),
      cutPaper: false,
    );

    _showSnackBar('Impressão formatada enviada');
  }

  Future<void> _openDrawer() async {
    if (!_isConnected) {
      _showSnackBar('Impressora não conectada');
      return;
    }

    await _printer.openCashDrawer();
    _showSnackBar('Gaveta aberta');
  }

  Future<void> _beep() async {
    if (!_isConnected) {
      _showSnackBar('Impressora não conectada');
      return;
    }

    await _printer.beep(times: 3, duration: 100);
  }

  void _showSnackBar(String message) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text(message), duration: const Duration(seconds: 2)),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Totem Alecto'),
        actions: [
          IconButton(
            icon: const Icon(Icons.refresh),
            onPressed: _refreshDevices,
            tooltip: 'Atualizar dispositivos',
          ),
        ],
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            // Status Card
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  children: [
                    Icon(
                      _isConnected ? Icons.print : Icons.print_disabled,
                      size: 48,
                      color: _isConnected ? Colors.green : Colors.grey,
                    ),
                    const SizedBox(height: 8),
                    Text(
                      _status,
                      style: Theme.of(context).textTheme.titleLarge,
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 16),

            // Device Selection
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Dispositivos USB',
                      style: Theme.of(context).textTheme.titleMedium,
                    ),
                    const SizedBox(height: 8),
                    if (_devices.isEmpty)
                      const Text('Nenhum dispositivo encontrado')
                    else
                      DropdownButton<UsbDeviceInfo>(
                        isExpanded: true,
                        value: _selectedDevice,
                        items: _devices.map((device) {
                          return DropdownMenuItem(
                            value: device,
                            child: Text(device.displayName),
                          );
                        }).toList(),
                        onChanged: (device) {
                          setState(() {
                            _selectedDevice = device;
                          });
                        },
                      ),
                    const SizedBox(height: 16),
                    Row(
                      children: [
                        Expanded(
                          child: ElevatedButton.icon(
                            onPressed: _isConnected ? null : _connect,
                            icon: const Icon(Icons.usb),
                            label: const Text('Conectar'),
                          ),
                        ),

                        Expanded(
                          child: ElevatedButton.icon(
                            onPressed: _isConnected ? null : _connectDevice,
                            icon: const Icon(Icons.usb),
                            label: const Text('Conectar Via Device'),
                          ),
                        ),
                        const SizedBox(width: 8),
                        Expanded(
                          child: ElevatedButton.icon(
                            onPressed: _isConnected ? _disconnect : null,
                            icon: const Icon(Icons.usb_off),
                            label: const Text('Desconectar'),
                            style: ElevatedButton.styleFrom(
                              backgroundColor: Colors.red,
                              foregroundColor: Colors.white,
                            ),
                          ),
                        ),
                      ],
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 16),

            // Print Section
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Impressão',
                      style: Theme.of(context).textTheme.titleMedium,
                    ),
                    const SizedBox(height: 8),
                    TextField(
                      controller: _textController,
                      maxLines: 4,
                      decoration: const InputDecoration(
                        border: OutlineInputBorder(),
                        hintText: 'Digite o texto para imprimir...',
                      ),
                    ),
                    const SizedBox(height: 16),
                    Row(
                      children: [
                        Expanded(
                          child: ElevatedButton.icon(
                            onPressed: _isConnected ? _printText : null,
                            icon: const Icon(Icons.print),
                            label: const Text('Imprimir'),
                          ),
                        ),
                        const SizedBox(width: 8),
                        Expanded(
                          child: ElevatedButton.icon(
                            onPressed: _isConnected ? _printFormatted : null,
                            icon: const Icon(Icons.text_format),
                            label: const Text('Formatado'),
                          ),
                        ),
                      ],
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 16),
            const SizedBox(width: 8),

            Image.asset('assets/images/epoc_logo.png', height: 48),
            SizedBox(
              width: 200,
              child: ElevatedButton.icon(
                onPressed: _isConnected ? _printImage : null,
                icon: const Icon(Icons.text_format),
                label: const Text('Imprimir imagem'),
              ),
            ),
            // Actions Section
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Ações',
                      style: Theme.of(context).textTheme.titleMedium,
                    ),
                    const SizedBox(height: 8),
                    Wrap(
                      spacing: 8,
                      runSpacing: 8,
                      children: [
                        ElevatedButton.icon(
                          onPressed: _isConnected ? _openDrawer : null,
                          icon: const Icon(Icons.inventory_2),
                          label: const Text('Gaveta'),
                        ),
                        ElevatedButton.icon(
                          onPressed: _isConnected ? _beep : null,
                          icon: const Icon(Icons.volume_up),
                          label: const Text('Beep'),
                        ),
                        ElevatedButton.icon(
                          onPressed: _isConnected
                              ? () => _printer.feedPaper(lines: 3)
                              : null,
                          icon: const Icon(Icons.arrow_downward),
                          label: const Text('Avançar'),
                        ),
                        ElevatedButton.icon(
                          onPressed: _isConnected
                              ? () => _printer.cutPaper()
                              : null,
                          icon: const Icon(Icons.content_cut),
                          label: const Text('Cortar'),
                        ),
                      ],
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
2
likes
160
points
22
downloads

Documentation

API reference

Publisher

verified publishermarcus.brasizza.com

Weekly Downloads

Flutter plugin package for interfacing with Totem Alecto thermal printers, providing native Android support for printing operations

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on totem_alecto

Packages that implement totem_alecto