Flutter封装Coap

news2024/11/23 20:34:32

前言

我们根据Coap数据通信流程写一个公共组件,用户只要在原本的组件外嵌套这个公共组件就可以使用Coap的功能,这样做更加的方便便捷。

具体步骤

封装一个udp函数

  • 创建一个工厂函数,工厂函数初始化时监听广播数据
  • 发送广播函数:入参有发送的内容,目标的ip地址(默认是255.255.255.255)、ip端口(默认端口为1234)
  • import 'dart:async';
    import 'dart:io';
     
    import 'package:my_app/common/value/serve.dart';
     
    class UDPClient {
      factory UDPClient() => _getInstance();
      static UDPClient get instance => _getInstance();
      static UDPClient? _instance;
      late RawDatagramSocket udpSocket;
      final StreamController<List<int>> _getDataController =
          StreamController.broadcast(); //监听数据流的控制器
      StreamController get getDataController => _getDataController; //获取数据流的控制器
     
      //初始化
      static UDPClient _getInstance() {
        _instance ??= UDPClient._internal();
        return _instance!;
      }
     
      //创建一个UDPClient实例
      UDPClient._internal() {
        (InternetAddress.lookup('pool.ntp.org')).then((value) {
          var serverAddress = value.first;
          // print("获取到的数据:----${serverAddress.type}-----${InternetAddress.anyIPv4}");
          RawDatagramSocket.bind(
                  serverAddress.type == InternetAddressType.IPv6
                      ? InternetAddress.anyIPv6
                      : InternetAddress.anyIPv4,
                  0)
              .then((value) {
            udpSocket = value;
            udpSocket.listen(handleUDPDatagram);
            udpSocket.broadcastEnabled = true;
          });
        });
      }
      //断开连接
      void disconnectFromUDP() {
        udpSocket.close();
        _instance = null;
      }
     
      //监听到的数据
      void handleUDPDatagram(RawSocketEvent event) {
        if (event == RawSocketEvent.read) {
          Datagram? datagram = udpSocket.receive();
          if (datagram != null) {
            List<int> data = datagram.data;
            // print("广播接收内容:$data");
            _getDataController.sink.add(data);
          }
        }
      }
     
      //发送数据
      void sendUDPData(
        List<int> data, {
        String ip = '255.255.255.255',
        int port = UDP_PORT,
      }) {
        print("${InternetAddress(ip)}");
        udpSocket.send(data, InternetAddress(ip), port);
      }
    }

封装一个Coap函数

  • 创建一个Coap的工厂函数,可以传入ip地址和端口号
  • 如果ip、port改变了则会创建一个工厂函数
  • 封装Get、post、postBytes、put函数
import 'dart:async';
 
import 'package:coap/coap.dart';
import 'package:my_app/common/value/serve.dart';
import 'package:typed_data/typed_data.dart';
 
import '../value/coap_config.dart';
 
class CoapClientUtil {
  factory CoapClientUtil({String? host, int? port}) =>
      _getInstance(host: host, port: port);
  static CoapClientUtil get instance => _getInstance(host: _currentHost);
  static CoapClientUtil? _instance;
  static CoapClient? client;
  static String _currentHost = COAP_API_URL;
  static int _currentPort = COAP_PORT;
 
  static CoapClientUtil _getInstance({String? host, int? port}) {
    String localHost = host ?? COAP_API_URL;
    int localPort = port ?? COAP_PORT;
    if (_instance == null ||
        _currentHost != localHost ||
        _currentPort != localPort) {
      _instance = CoapClientUtil._internal(localHost, localPort);
      _currentHost = localHost;
      _currentPort = localPort;
    }
    return _instance!;
  }
 
  CoapClientUtil._internal(String host, int port) {
    CoapConfig conf = CoapConfig();
    var baseUri = Uri(scheme: 'coap', host: host, port: port);
    client = CoapClient(baseUri, config: conf);
  }
 
  // 发送GET请求
  Future<CoapResponse?> get(
    final String path, {
    final CoapMediaType? accept,
    final bool confirmable = true,
    final List<Option<Object?>>? options,
    final bool earlyBlock2Negotiation = false,
    final int maxRetransmit = 0,
    final CoapMulticastResponseHandler? onMulticastResponse,
  }) async {
    try {
      var response = await client!.get(
        path,
        accept: accept,
        confirmable: confirmable,
        options: options,
        earlyBlock2Negotiation: earlyBlock2Negotiation,
        maxRetransmit: maxRetransmit,
        onMulticastResponse: onMulticastResponse,
      );
      return response;
    } catch (e) {
      print("错误的内容:${e}");
      return null;
    }
  }
 
  // 发送POST请求
  Future<CoapResponse?> post(
    final String path, {
    required final String payload,
    final CoapMediaType? format,
    final CoapMediaType? accept,
    final bool confirmable = true,
    final List<Option<Object?>>? options,
    final bool earlyBlock2Negotiation = false,
    final int maxRetransmit = 0,
    final CoapMulticastResponseHandler? onMulticastResponse,
  }) async {
    try {
      var response = await client!.post(
        path,
        payload: payload,
        format: format,
        accept: accept,
        confirmable: confirmable,
        options: options,
        earlyBlock2Negotiation: earlyBlock2Negotiation,
        maxRetransmit: maxRetransmit,
        onMulticastResponse: onMulticastResponse,
      );
      return response;
    } catch (e) {
      print("错误的内容:${e}");
      return null;
    }
  }
 
  /// 发送post请求,且携带的参数为二进制数组
  /// 需要注意的是如果返回的数据也是二进制数组则打印的response中的Payload为<<<< Payload incomplete >>>>>
   这是因为展示的payload走的是res.payloadString,看下发源码可知,转换成utf8抛出异常了,我们只要拿数据的时候使用res.payload即可
  /// String get payloadString {
  ///   final payload = this.payload;
  ///   if (payload.isNotEmpty) {
  ///     try {
  ///       final ret = utf8.decode(payload);
  ///       return ret;
  ///     } on FormatException catch (_) {
  ///       // The payload may be incomplete, if so and the conversion
  ///       // fails indicate this.
  ///       return '<<<< Payload incomplete >>>>>';
  ///     }
  ///   }
  ///   return '';
  /// }
 
  Future<CoapResponse?> postBytes(
    final String path, {
    required final Uint8Buffer payload,
    final CoapMediaType? format,
    final CoapMediaType? accept,
    final bool confirmable = true,
    final List<Option<Object?>>? options,
    final bool earlyBlock2Negotiation = false,
    final int maxRetransmit = 0,
    final CoapMulticastResponseHandler? onMulticastResponse,
  }) async {
    try {
      var response = await client!.postBytes(
        path,
        payload: payload,
        format: format,
        accept: accept,
        confirmable: confirmable,
        options: options,
        earlyBlock2Negotiation: earlyBlock2Negotiation,
        maxRetransmit: maxRetransmit,
        onMulticastResponse: onMulticastResponse,
      );
      return response;
    } catch (e) {
      print("错误的内容:${e}");
      return null;
    }
  }
 
  // 发送PUT请求
  Future<CoapResponse?> put(
    final String path, {
    required final String payload,
    final CoapMediaType? format,
    final CoapMediaType? accept,
    final bool confirmable = true,
    // final List<Uint8Buffer>? etags,
    final MatchEtags matchEtags = MatchEtags.onMatch,
    final List<Option<Object?>>? options,
    final bool earlyBlock2Negotiation = false,
    final int maxRetransmit = 0,
    final CoapMulticastResponseHandler? onMulticastResponse,
  }) async {
    try {
      var response = await client!.put(
        path,
        payload: payload,
        format: format,
        accept: accept,
        confirmable: confirmable,
        // etags: etags,
        matchEtags: matchEtags,
        options: options,
        earlyBlock2Negotiation: earlyBlock2Negotiation,
        maxRetransmit: maxRetransmit,
        onMulticastResponse: onMulticastResponse,
      );
      return response;
    } catch (e) {
      print("错误的内容:${e}");
      return null;
    }
  }
 
  close() {
    client?.close();
  }
 
  disply() {
    client?.close();
    client = null;
    _instance = null;
  }
}

封装一个通用组件

  • 传参内容:mac地址、Widget、key
    • mac地址:因为通信协议中地址需要使用mac地址
    • Widget:要展示的界面
    • key:根据key值调用封装组件中的函数
  • 初始化逻辑:Coap数据通信流程
  • 如果要进行界面跳转
    • 调用setDispose,关闭coap、udp等信息
    • 同步界面跳转
    • 创建一个定时器,定时器中包含初始化udp、coap
import 'dart:async';
import 'dart:convert';
 
import 'package:coap/coap.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter/material.dart';
import 'package:my_app/common/utils/coap.dart';
import 'package:my_app/common/utils/fun.dart';
import 'package:my_app/common/utils/udp.dart';
import 'package:my_app/pages/device_settings/time_switch_addtime/bottom_picker.dart';
import 'package:typed_data/typed_data.dart';
 
///macStr 是测试的,后期要改
class CoapClientPackage extends StatefulWidget {
  const CoapClientPackage({
    super.key,
    this.mac = '11:22:33:44:55:66',
    required this.widget,
  });
  final String mac;
  final Widget widget;
 
  @override
  State<CoapClientPackage> createState() => CoapClientPackageState();
}
 
class CoapClientPackageState extends State<CoapClientPackage> {
  StreamSubscription? _networkStatusSubscription; //监听设备的网络类型
  CoapClientUtil? coapClient;
 
  //udp获取到的数据
  UDPClient? udpClient;
  StreamSubscription? _sacnSubscription;
  bool isCoap = false;
  Timer? timer;
  @override
  void initState() {
    super.initState();
    // initUDP();
 
    // //监听移动终端联网方式
    // _listenNetworkStatus();
    getinitState();
  }
 
  getinitState() {
    print("初始化");
    initUDP();
    //监听移动终端联网方式
    _listenNetworkStatus();
  }
 
  setDispose() {
    print("移除");
    _networkStatusSubscription?.cancel(); //取消监听
    coapClient?.disply(); //关闭coap连接
    udpClient?.disconnectFromUDP(); //关闭udp连接
    _sacnSubscription?.cancel(); //取消监听
    timer?.cancel(); //取消定时器
  }
 
  @override
  void dispose() {
    setDispose();
    super.dispose();
  }
 
  initUDP() {
    udpClient = UDPClient.instance;
    _sacnSubscription?.cancel();
    _sacnSubscription = udpClient?.getDataController.stream.listen((data) {
      if (data is List<int>) {
        print("这是哪个数据:$data");
        setState(() {
          isCoap = false;
        });
        switch (data[2]) {
          case 129: //
            if (data[0] == 170 && data.length == 15 && data[14] == 85) {
              //将从data[7]开始截取数组
              // List macArr = data.sublist(3, 9); //截取mac地址
              // //将十进制数组转换成十六进制mac并添加:
              // String macStr =
              //     macArr.map((e) => e.toRadixString(16).padLeft(2, '0')).join(':');
              // print("macArr:$macArr -----${macStr}");
              timer?.cancel();
              String serverIp =
                  "${data[9]}.${data[10]}.${data[11]}.${data[12]}";
 
              print("获取到了ip地址:$serverIp");
              //创建一个coap服务
              coapClient = CoapClientUtil(
                host: serverIp,
                port: 5683,
              );
              setState(() {
                isCoap = true;
              });
            }
 
            break;
          default:
        }
      }
    });
  }
 
  //监听移动终端联网方式
  void _listenNetworkStatus() async {
    _networkStatusSubscription?.cancel(); //取消之前的监听
    bool isWif = await isWifi();
    if (isWif) {
      isWifiAfter();
    } else {
      _networkStatusSubscription = Connectivity()
          .onConnectivityChanged
          .listen((ConnectivityResult result) {
        if (result == ConnectivityResult.wifi) {
          //当前的类型是WiFi
          isWifiAfter();
        } else {
          setState(() {
            isCoap = false;
          });
        }
      });
    }
  }
 
  isWifiAfter() {
    print('当前的类型是WiFi');
 
    //这里需要在发送mac地址,这里使用模拟的数据
    String macStr = widget.mac;
    // String macStr = '11:22:33:44:55:66';
 
    //将macStr装换成List<int>
    List<int> macArr =
        macStr.split(':').map((e) => int.parse(e, radix: 16)).toList();
    List<int> sendData = sendCoapData('01', macArr);
    print("-----=====------macArr:${sendData},macStr");
    Timer(Duration(seconds: 1), () {
      udpClient?.sendUDPData(sendData, port: 1234);
    });
    timer?.cancel();
    timer = Timer.periodic(Duration(seconds: 3), (timer) {
      if (udpClient != null) {
        try {
          udpClient?.sendUDPData(sendData, port: 1234);
        } catch (e) {
          print("发送出现了问题:${e}");
        }
      } else {
        print("为空");
      }
    });
  }
 
  //发送coap请求
  Future<CoapResponse?> sendCoap(String payload) async {
    String macStr = widget.mac;
    // String macStr = '11:22:33:44:55:66';
    var res = await coapClient?.post('/api/v1/$macStr/rpc',
        accept: CoapMediaType.applicationJson, payload: payload);
    return res;
  }
 
  //发送透传数据
  Future<CoapResponse?> sendTranCoap(String payload) async {
    String macStr = widget.mac;
    // String macStr = '11:22:33:44:55:66';
    var res = await coapClient?.post('/api/v1/$macStr/trans',
        accept: CoapMediaType.applicationJson, payload: payload);
    return res;
  }
 
  //发送透传数据
  Future<CoapResponse?> sendTranCoap1(Uint8Buffer payload) async {
    String macStr = widget.mac;
    // String macStr = '11:22:33:44:55:66';
    var res = await coapClient?.postBytes('/api/v1/$macStr/trans',
        accept: CoapMediaType.applicationJson, payload: payload);
    return res;
  }
 
  @override
  Widget build(BuildContext context) {
    return widget.widget;
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2246230.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python 数据分析核心库大全!

&#xff08;欢迎关注我的视频号&#xff09; &#x1f447;我的小册 45章教程:(小白零基础用Python量化股票分析小册) ,原价299&#xff0c;限时特价2杯咖啡&#xff0c;满100人涨10元。 大家好&#xff01;我是菜鸟哥&#xff01; 今天我们来聊点干货&#xff1a;Python 数据…

跨境出海安全:如何防止PayPal账户被风控?

今天咱们聊聊那些让人头疼的事儿——PayPal账户被风控。不少跨境电商商家反馈&#xff0c;我们只是想要安安静静地在网上做个小生意&#xff0c;结果不知道为什么&#xff0c;莫名其妙账户就被冻结了。 但其实每个封禁都是有原因的&#xff0c;今天就来给大家分享分享可能的原…

39页PDF | 毕马威_数据资产运营白皮书(限免下载)

一、前言 《毕马威数据资产运营白皮书》探讨了数据作为新型生产要素在企业数智化转型中的重要性&#xff0c;提出了数据资产运营的“三要素”&#xff08;组织与意识、流程与规范、平台与工具&#xff09;和“四重奏”&#xff08;数据资产盘点、评估、治理、共享&#xff09;…

数据科学与SQL:组距分组分析 | 区间分布问题

目录 0 问题描述 1 数据准备 2 问题分析 3 小结 0 问题描述 绝对值分布分析也可以理解为组距分组分析。对于某个指标而言&#xff0c;一个记录对应的指标值的绝对值&#xff0c;肯定落在所有指标值的绝对值的最小值和最大值构成的区间内&#xff0c;根据一定的算法&#x…

使用 PyTorch-BigGraph 构建和部署大规模图嵌入的完整教程

当涉及到图数据时&#xff0c;复杂性是不可避免的。无论是社交网络中的庞大互联关系、像 Freebase 这样的知识图谱&#xff0c;还是推荐引擎中海量的数据量&#xff0c;处理如此规模的图数据都充满挑战。 尤其是当目标是生成能够准确捕捉这些关系本质的嵌入表示时&#xff0c;…

23种设计模式-模板方法(Template Method)设计模式

文章目录 一.什么是模板方法模式&#xff1f;二.模板方法模式的特点三.模板方法模式的结构四.模板方法模式的应用场景五.模板方法模式的优缺点六.模板方法模式的C实现七.模板方法模式的JAVA实现八.代码解析九.总结 类图&#xff1a; 模板方法设计模式类图 一.什么是模板方法模…

.net的winfrom程序 窗体透明打开窗体时出现在屏幕右上角

窗体透明&#xff0c; 将Form的属性Opacity&#xff0c;由默认的100% 调整到 80%(尽量别低于50%)&#xff0c;这个数字越小越透明&#xff01; 打开窗体时出现在屏幕右上角 //构造函数 public frmCalendarList() {InitializeComponent();//打开窗体&#xff0c;窗体出现在屏幕…

DRNN 神经网络的Jacobian 信息辨识

DRNN 神经网络的 Jacobian 信息辨识 1. 基本原理 Jacobian 矩阵用于描述多输入多输出系统中输入和输出之间的偏导关系&#xff0c;其形式为&#xff1a; 对于 DRNN&#xff08;Dynamic Recurrent Neural Network&#xff09;&#xff0c;其动态特性使得 y(t)\mathbf{y}(t)y(t…

iptables网络安全服务详细使用

iptables防火墙概念说明 开源的基于数据包过滤的网络安全策略控制工具。 centos6.9 --- 默认防火墙工具软件iptables centos7 --- 默认防火墙工具软件firewalld&#xff08;zone&#xff09; iptables主要工作在OSI七层的二、三、四层&#xff0c;如果重新编译内核&…

《DAMA 数据管理知识体系指南》读书笔记 - 第 2 章 数据处理伦理

文章目录 1. 章节概述2. 核心概念与定义3. 重要方法与实践步骤4. 理论与实际结合5. 重点6. 理解与记忆要点7. 复习思考题标题图——书籍图片 WPS AI生成的XMind链接&#xff08;不用要源文件&#xff0c;下载不了&#xff09;&#xff1a; 【金山文档 | WPS云文档】 第2章 数据…

《线性代数的本质》

之前收藏的一门课&#xff0c;刚好期末复习&#xff0c;顺便看一看哈哈 课程链接&#xff1a;【线性代数的本质】合集-转载于3Blue1Brown官方双语】 向量究竟是什么 线性代数中最基础、最根源的组成部分就是向量&#xff0c;需要先明白什么是向量 不同专业对向量的看法 物理专…

AI 大模型如何重塑软件开发流程?——技术革新与未来展望

人工智能的蓬勃发展为许多领域注入了强劲动力&#xff0c;而在软件开发这一关键技术领域&#xff0c;AI 大模型的应用正在彻底改变传统流程。从代码自动生成到智能测试&#xff0c;再到协同开发和流程优化&#xff0c;AI 正逐步成为软件开发者的得力助手&#xff0c;也推动企业…

三季度业绩亮点多元,宝尊全域经营走向破茧成蝶

电商行业的变革从未停止&#xff0c;始终反映着网络消费和品牌发展的趋势&#xff0c;以及未来的想象空间&#xff0c;因此令赛道上的相关公司备受关注。 那么&#xff0c;当前赛道正在发生哪些变化&#xff1f;11月21日&#xff0c;行业龙头宝尊电商发布截至2024年9月30日的2…

机器学习day7-线性回归3、逻辑回归、聚类、SVC

7欠拟合与过拟合 1.欠拟合 模型在训练数据上表现不佳&#xff0c;在新的数据上也表现不佳&#xff0c;常发生在模型过于简单无法处理数据中的复杂模式时。 特征&#xff1a; 训练误差较高 测试误差也高 模型过于简化&#xff0c;不能充分学习训练数据中的模式 2.过拟合 …

【云计算】腾讯云架构高级工程师认证TCP--考纲例题,知识点总结

【云计算】腾讯云架构高级工程师认证TCCP–知识点总结&#xff0c;排版整理 文章目录 1、云计算架构概论1.1 五大版块知识点&#xff08;架构设计&#xff0c;基础服务&#xff0c;高阶技术&#xff0c;安全&#xff0c;上云&#xff09;1.2 课程详细目录1.3 云基础架构设计1.4…

proto3语法详解

proto3语法详解 字段规则消息类型的定义与使⽤定义使用 enum类型定义与使用定义规则定义时注意事项 Any类型Any类型介绍Any类型使用 oneof类型oneof类型的介绍oneof类型的使用 map类型map类型的介绍map类型的使用 默认值更新消息更新规则保留字段reserved 未知字段未知字段获取…

【STM32】在 STM32 USB 设备库添加新的设备类

说实话&#xff0c;我非常想吐槽 STM32 的 USB device library&#xff0c;总感觉很混乱。 USB Device library architecture 根据架构图&#xff1a; Adding a custom class 如果你想添加新的设备类&#xff0c;必须修改的文件有 usbd_desc.cusbd_conf.cusb_device.c 需要…

怎么编译OpenWrt镜像?-基于Widora开发板

1.准备相应的环境&#xff0c;我使用的环境是VMware16ubuntu20.04&#xff0c;如图1所示安装编译所需的依赖包&#xff1b; sudo apt-get install build-essential asciidoc binutils bzip2 gawk gettext git libncurses5-dev libz-dev patch python3 python2.7 unzip zlib1g-…

神经网络问题之一:梯度消失(Vanishing Gradient)

梯度消失&#xff08;Vanishing Gradient&#xff09;问题是深度神经网络训练中的一个关键问题&#xff0c;它主要发生在反向传播过程中&#xff0c;导致靠近输入层的权重更新变得非常缓慢甚至几乎停滞&#xff0c;严重影响网络的训练效果和性能。 图1 在深度神经网络中容易出现…

JavaWeb之综合案例

前言 这一节讲一个案例 1. 环境搭建 然后就是把这些数据全部用到sql语句中执行 2.查询所有-后台&前台 我们先写后台代码 2.1 后台 2.2 Dao BrandMapper&#xff1a; 注意因为数据库里面的名称是下划线分割的&#xff0c;我们类里面是驼峰的&#xff0c;所以要映射 …