Flutter封装Coap

前言

我们根据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;@overrideState<CoapClientPackage> createState() => CoapClientPackageState();
}class CoapClientPackageState extends State<CoapClientPackage> {StreamSubscription? _networkStatusSubscription; //监听设备的网络类型CoapClientUtil? coapClient;//udp获取到的数据UDPClient? udpClient;StreamSubscription? _sacnSubscription;bool isCoap = false;Timer? timer;@overridevoid initState() {super.initState();// initUDP();// //监听移动终端联网方式// _listenNetworkStatus();getinitState();}getinitState() {print("初始化");initUDP();//监听移动终端联网方式_listenNetworkStatus();}setDispose() {print("移除");_networkStatusSubscription?.cancel(); //取消监听coapClient?.disply(); //关闭coap连接udpClient?.disconnectFromUDP(); //关闭udp连接_sacnSubscription?.cancel(); //取消监听timer?.cancel(); //取消定时器}@overridevoid 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) {//当前的类型是WiFiisWifiAfter();} 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;}@overrideWidget build(BuildContext context) {return widget.widget;}
}

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

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

相关文章

探索 Vue.js:构建交互式前端的强大工具

在当今的 web 开发领域&#xff0c;前端技术日新月异&#xff0c;而 Vue.js 作为一款备受瞩目的 JavaScript 框架&#xff0c;以其简洁易用、高效灵活的特点&#xff0c;赢得了众多开发者的青睐。今天&#xff0c;就让我们深入了解一下 Vue.js 的相关知识&#xff0c;同时也探讨…

Java方法中的可变参数列表

在Java中&#xff0c;可变参数列表&#xff08;Variable Argument List&#xff09;允许方法接受不定数量的参数。可变参数列表通过在方法参数类型后加上三个点&#xff08;...&#xff09;来定义。可变参数列表实际上是一个数组&#xff0c;因此可以在方法内部像操作数组一样操…

PVE的优化与温度监控(二)—无法识别移动硬盘S.M.A.R.T信息的思考并解决

前情提要&#xff1a;空闲2.5英寸机械硬盘&#xff0c;直接放到PVE上测试NAS 使用&#xff0c;通过SATA线的方式让小主机不太美观&#xff0c;并且失去了前期调试的安全性。购入移动硬盘盒&#xff0c;缺点&#xff0c;USB 连接&#xff0c;会失去一些特性。比如本文中遇到的问…

嵌入式硬件实战基础篇(二)-稳定输出3.3V的太阳能电池-无限充放电

引言&#xff1a;本内容主要用作于学习巩固嵌入式硬件内容知识&#xff0c;用于想提升下述能力&#xff0c;针对学习稳压芯片和电容以及电池之间的运用&#xff0c;对于硬件PCB以及原理图的练习和前面硬件篇的实际运用&#xff1b;太阳能是一种清洁、可再生的能源&#xff0c;广…

Word和Excel使用有感

1.画图 折线图&#xff1a;适用于多个y值的画图 散点图&#xff1a;适合需要对x轴进行自定义时使用 2.word和excel的联动 1&#xff09;excel中的数据导入word直接复制即可 若是表格中的数据要导入word 则先将表格中的数据拆分出来&#xff0c;再直接复制到word中 2&#…

OpenCV相机标定与3D重建(3)校正鱼眼镜头畸变的函数calibrate()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::fisheye::calibrate 函数是 OpenCV 中用于校正鱼眼镜头畸变的一个重要函数。该函数通过一系列棋盘格标定板的图像来计算相机的内参矩阵和畸变…

【过程控制系统】第6章 串级控制系统

目录 6. l 串级控制系统的概念 6.1.2 串级控制系统的组成 6.l.3 串级控制系统的工作过程 6.2 串级控制系统的分析 6.2.1 增强系统的抗干扰能力 6.2.2 改善对象的动态特性 6.2.3 对负荷变化有一定的自适应能力 6.3 串级控制系统的设计 6.3.1 副回路的选择 2.串级系…

24/11/22 项目拆解 艺术风格转移

我们有时候想把两种艺术风格整合&#xff0c;创造更具艺术特色的艺术品&#xff0c;人很难办到&#xff0c;但是人工智能可以,比如下面将艺术画的风格转移到照片上。 我们先来初步了解一下实现上述功能的数学原理 所谓艺术风格&#xff0c;其实就是边缘&#xff0c;颜色&#…

中断的详细流程

一、中断请求 中断请求是中断过程的起始阶段&#xff0c;由需要CPU服务的外设&#xff08;中断源&#xff09;向CPU发出请求信号。这个信号可以是电平信号或边沿信号&#xff0c;具体取决于中断系统的设计和中断源的类型。 二、中断判优 当系统中存在多个中断源时&#xff0…

Unity图形学之CubeMap立方体贴图

1.CubeMap&#xff1a;有六个面的贴图组成 2. 假反射&#xff1a;反射天空盒子 &#xff08;1&#xff09;正常UV采样&#xff1a; &#xff08;2&#xff09;Cube的采样&#xff1a;利用反射角采样&#xff0c;反射角X和Cube的交点采样 Shader "Custom/TestReflect"…

LLM Inference Unveiled

题目&#xff1a;LLM Inference Unveiled: Survey and Roofline Model Insights 链接&#xff1a;https://arxiv.org/abs/2402.16363 这也是一篇推理加速的综述&#xff0c;重点关注一下它的组织结构吧&#xff0c;也就是它对推理加速方法的分类 论文给的全文结构图&#xff…

Cesium的ClearCommand的流程

ClearCommand是在每帧渲染前可以将显存的一些状态置为初始值&#xff0c;就如同把擦黑板。当然也包括在绘制过程中擦掉部分的数据&#xff0c;就如同画家在开始绘制的时候会画导览线&#xff08;如透视线&#xff09;&#xff0c;轮廓出来后这些导览线就会被擦除。 我画了一个…

【系统架构设计师】真题论文: 论企业应用系统的分层架构风格 (包括解题思路和素材)

更多内容请见: 备考系统架构设计师-专栏介绍和目录 文章目录 真题题目(2013年 试题1)解题思路论文素材参考常见分层架构模式分层架构风格的优势分层架构风格在企业应用系统中的应用案例真题题目(2013年 试题1) 软件架构风格是描述一类特定应用领域中系统组织方式的惯用模…

【Linux】重定向,dup

目录 文件描述符分配规则 重定向 dup ​编辑 输出重定向 追加重定向 输入重定向。 重定向会影响后面的程序替换吗&#xff1f; 1号文件和2号文件 2号文件输出重定向 下标之间的重定向 文件描述符分配规则 重定向 把显示器文件关闭后&#xff0c;本来应该写给显示器…

大语言模型---梯度的简单介绍;梯度的定义;梯度计算的方法

1. 梯度介绍 如果我们在一座山上&#xff08;一个山的坡度有很多&#xff0c;陡峭的&#xff0c;平缓的&#xff09;&#xff0c;想要从山顶下山。而梯度就像告诉我们如何沿着最陡的下坡路线走&#xff0c;以尽快到达山脚&#xff08;最低点&#xff09;。 2. 梯度的定义 梯度…

【JAVA】一次操蛋的nginx镜像之旅

一、前言 由于我们的项目中使用到了nginx&#xff0c;同时我们的nginx是通过docker镜像进行安装的&#xff0c;由于nginx出现了问题&#xff0c;需要重新安装。于是。。。 二、通过docker进行安装 docker pull nginx:latest 1.5.2 脚本文件 在/home/docker/script路径下创…

ubuntu24挂载硬盘记录

1、显示硬盘及所属分区情况。在终端窗口中输入如下命令&#xff1a; sudo fdisk -l 找到自己硬盘的分区 我的地址/dev/sda 2、显示硬盘及所属分区情况。在终端窗口中输入如下命令&#xff0c;格式化自己硬盘&#xff1a; sudo mkfs -t ext4 /dev/sda 3、在终端窗口中输入如下…

力扣第 60 题 “第 k 个排列”

题目描述 给定整数 n 和 k&#xff0c;返回由 1 到 n 组成的排列中第 k 个排列。 所有排列按字典序排列。1 ≤ n ≤ 9&#xff0c;1 ≤ k ≤ n!。 解题思路 要快速找到第 k 个排列&#xff0c;可以利用数学方法而不是生成所有排列&#xff1a; 1. 知识点&#xff1a;阶乘与…

springcloud读取nacos配置中心的json文件

由于业务需要&#xff0c;将一些json数据存放到了nacos配置中心上 ①服务启动读取nacos进行数据初始化 Slf4j Component Data public class NacosJsonInitializeRunner implements ApplicationRunner{//以下属性都是nacos相关的Value("${nacos.config.server-addr}&quo…

大模型呼入机器人系统如何建设?

大模型呼入机器人系统如何建设&#xff1f; 作者&#xff1a;开源呼叫中心系统 FreeIPCC, Github地址&#xff1a;https://github.com/lihaiya/freeipcc 大模型呼叫中心呼入机器人系统的建设是一个涉及多个环节和领域的综合性工程。以下是一个详细的步骤指南&#xff0c;涵盖了…