Advertisement
wemersonrv

Implementação TCP socket com loop

Jul 13th, 2019
129
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Dart 7.57 KB | None | 0 0
  1. // ************************
  2. // ****** SocketBloc ******
  3. // ************************
  4.  
  5. enum SocketState {
  6.   IDLE,
  7.   CREATING,
  8.   CREATE_FAIL,
  9.   READY,
  10.   GET_DATA,
  11.   GET_DATA_FAIL,
  12.   SET_INCREMENT,
  13.   SET_INCREMENT_FAIL,
  14. }
  15.  
  16. class SocketBloc extends BlocBase {
  17.   Socket _socket;
  18.   DateTime _lastDone;
  19.   SettingsBloc _settingsBloc = SettingsBloc();
  20.   String _ip;
  21.   int _port;
  22.  
  23.   // Fluxo de estado
  24.   final _stateController =
  25.       BehaviorSubject<SocketState>(seedValue: SocketState.IDLE);
  26.  
  27.   Stream<SocketState> get outState => _stateController.stream;
  28.  
  29.   Sink<SocketState> get inState => _stateController.sink;
  30.  
  31.   // Construtor padrão
  32.   SocketBloc() {
  33.     _log("SocketBloc Construtor", "Instanciado", "Inicializando...");
  34.  
  35.     _stateController.listen((SocketState state) {
  36.       switch (state) {
  37.         case SocketState.CREATING:
  38.           _closeSocket();
  39.           _createSocket();
  40.           break;
  41.         case SocketState.READY:
  42.           _getAbastecimento();
  43.           break;
  44.         case SocketState.SET_INCREMENT: // TODO: SET_INCREMENT
  45.         case SocketState.IDLE: // TODO: IDLE
  46.         case SocketState.CREATE_FAIL: // TODO: CREATE_FAIL
  47.         case SocketState.GET_DATA: // TODO: GET_DATA
  48.         case SocketState.GET_DATA_FAIL: // TODO: GET_DATA_FAIL
  49.         case SocketState.SET_INCREMENT_FAIL: // TODO: SET_INCREMENT_FAIL
  50.       }
  51.     });
  52.  
  53.     _settingsBloc.outConnection.listen((data) {
  54.       bool setingsChanged = false;
  55.       if (_ip != data["ip"]) {
  56.         _ip = data["ip"];
  57.         setingsChanged = true;
  58.       }
  59.       if (_port != data["port"]) {
  60.         _port = data["port"];
  61.         setingsChanged = true;
  62.       }
  63.  
  64.       if (setingsChanged) {
  65.         _log("SocketBloc Construtor", "IP/PORTA",
  66.             "FLAG para tentar criar canal com Socket");
  67.         _stateController.add(SocketState.CREATING);
  68.       }
  69.     });
  70.   }
  71.  
  72.   Future<void> _createSocket() async {
  73.     try {
  74.       _socket = await Socket.connect(_ip, _port,
  75.           timeout: Duration(milliseconds: 2000));
  76.  
  77.       _log("_createSocket", "Canal aberto",
  78.           "Canal com socket aberto, ADICIONAR LISTENERS");
  79.       _addListeners();
  80.  
  81.       _stateController.add(SocketState.READY);
  82.     } catch (e) {
  83.       print("Falha ao criar o socket: $e");
  84.       _stateController.add(SocketState.CREATE_FAIL);
  85.       _log("_createSocket", "Falha na criação do canal ",
  86.           "Tentar criar novamente 10 segundos",
  87.           jump: false);
  88.  
  89.       Future.delayed(Duration(seconds: 10)).then((_) {
  90.         _createSocket();
  91.       });
  92.     }
  93.   }
  94.  
  95.   void _addListeners() {
  96.     _log("_addListeners", "Socket ok, adicionar listener",
  97.         "listeners adicionados no canal");
  98.  
  99.     _socket.listen(dataHandler, onError: errorHandler);
  100.   }
  101.  
  102.   void dataHandler(data) {
  103.     String result = _stringChecked(data);
  104.  
  105.     // TODO: Verificar conteúdo da string quando não tem mais ponteiros com registros válidos, pois vem uma string com algum conteúdo
  106.     _log("dataHandler", "String de resultado",
  107.         "Resposta OK, validar string de $result",
  108.         jump: false);
  109.  
  110.     if (result != "" && result != SWC_NO_CONTENT) {
  111.       String pointer = result.substring(8, 14);
  112.  
  113.       _log("dataHandler", "Validou string",
  114.           "Ponteiro atual: $pointer  String Válida: $result");
  115.  
  116.       switch (_stateController.stream.value) {
  117.         // *** Dados de abastecimento
  118.         case SocketState.GET_DATA:
  119.           // TODO: Ponteiro não existe no BD (Grava SQLite)
  120.  
  121.           _setIncrement();
  122.           break;
  123.  
  124.         // *** Confirmação de incremento do ponteiro
  125.         case SocketState.SET_INCREMENT:
  126.           print(
  127.               "------------------------------------------------------------\n\n");
  128.           _setReady();
  129.           break;
  130.         default:
  131.       }
  132.     } else {
  133.       // *** Buffer de dados incorreto ou truncado, repetir na próxima iteração
  134.       _log("dataHandler", "String Inválida",
  135.           "String não é válida (ou não tem dados registrados)... tenta de novo na próxima iteração");
  136.       _setReady();
  137.     }
  138.   }
  139.  
  140.   void errorHandler(error, StackTrace trace) {
  141.     print(error);
  142.     _log("errorHandler", "Falha ao receber",
  143.         "Falha ao buscar informações no canal, tenta recriar socket...");
  144.  
  145.     _stateController.add(SocketState.CREATING);
  146.   }
  147.  
  148.   void _getAbastecimento() {
  149.     try {
  150.       _stateController.add(SocketState.GET_DATA);
  151.       _socket.write(GET_ABASTECIMENTO_STRING);
  152.     } catch (e) {
  153.       print("Falha ao consultar abastecimento: $e");
  154.       _stateController.add(SocketState.GET_DATA_FAIL);
  155.     }
  156.   }
  157.  
  158.   void _setIncrement() {
  159.     try {
  160.       _stateController.add(SocketState.SET_INCREMENT);
  161.       _socket.write(SET_INCREMENT_POINTER_STRING);
  162.     } catch (e) {
  163.       print("Falha incrementar ponteiro de abastecimento: $e");
  164.       _stateController.add(SocketState.SET_INCREMENT_FAIL);
  165.     }
  166.   }
  167.  
  168.   void _setReady() {
  169.     Future.delayed(SWC_DELAY_INTERVAL).then((_) {
  170.       _stateController.add(SocketState.READY);
  171.     });
  172.   }
  173.  
  174.   String _stringChecked(List<int> buff) {
  175.     // Verificação de estrutura do buffer
  176.     // 5+ posições, sendo:
  177.     //    - 1º caractere ">" (ASCII 62)
  178.     //    - Último caractere "\n" (ASCII 13)
  179.     //    - Penúltimo e antepenúltimo: CHECKSUM
  180.     //    - posições de conteúdo, totalizando + de 4 posições no mínimo
  181.     if (buff.length <= 4) return "";
  182.     if (buff[0] != 62 || buff[buff.length - 1] != 13) return "";
  183.  
  184.     // 4 Validar Checksum
  185.     int checksum = 0;
  186.     for (int i = 1; i < buff.length - 3; i++) {
  187.       checksum += buff[i];
  188.       if (checksum > 256) checksum -= 256;
  189.     }
  190.  
  191.     String str = String.fromCharCodes(buff).trim();
  192.     String check = checksum.toRadixString(16).toUpperCase();
  193.     print(
  194.         "Checksum: $checksum  - Check: $check / ${str.substring(str.length - 2)}");
  195.     return check == str.substring(str.length - 2) ? str : "";
  196.   }
  197.  
  198.   DateTime get lastDone => _lastDone;
  199.  
  200.   @override
  201.   void dispose() {
  202.     _stateController.close();
  203.  
  204.     _closeSocket();
  205.   }
  206.  
  207.   void _closeSocket() {
  208.     try {
  209.       if (_socket != null) _socket.close();
  210.     } catch (e) {
  211.       _socket = null;
  212.     }
  213.   }
  214.  
  215.   void _log(String method, String location, String message, {bool jump: true}) {
  216.     print("------| LOG |------");
  217.     print("\t- Socket: $_socket");
  218.     print("\t- SocketState: ${_stateController.stream.value}");
  219.     print("\t- Método: $method ( $location )");
  220.     print("\t- Resultado: $message${jump ? "\n\n" : ""}");
  221.   }
  222. }
  223.  
  224.  
  225.  
  226. // ****************************
  227. // ****** SocketWrapper  ******
  228. // ****************************
  229. class SocketWrapper extends StatefulWidget {
  230.   @override
  231.   _SocketWrapperState createState() => _SocketWrapperState();
  232. }
  233.  
  234. class _SocketWrapperState extends State<SocketWrapper> {
  235.   SocketBloc _socketBloc = SocketBloc();
  236.  
  237.   @override
  238.   Widget build(BuildContext context) {
  239.     final bloc = BlocProvider.of<SettingsBloc>(context);
  240.     return StreamBuilder<SettingsState>(
  241.       stream: bloc.outState,
  242.       builder: (context, snapshot) {
  243.         if (snapshot.data != SettingsState.DONE) {
  244.           return Center(
  245.             child: CircularProgressIndicator(),
  246.           );
  247.         }
  248.  
  249.         return HomeScreen();
  250.       },
  251.     );
  252.   }
  253.  
  254.   @override
  255.   void dispose() {
  256.     _socketBloc.dispose();
  257.     super.dispose();
  258.   }
  259. }
  260.  
  261.  
  262. // ************************
  263. // ****** LOGS ******
  264. // ************************
  265.  
  266. 1. Conexão 100%: https://pastebin.com/vr6qXh0F
  267. 2. Conexão 100% em seguida falha: https://pastebin.com/hvXqb1y7
  268. 3. Falha direto depois restabelece: https://pastebin.com/cRabGrZy
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement