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,一经查实,立即删除!

相关文章

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;广…

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;颜色&#…

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;轮廓出来后这些导览线就会被擦除。 我画了一个…

【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、在终端窗口中输入如下…

业务架构、数据架构、应用架构和技术架构

TOGAF(The Open Group Architecture Framework)是一个广泛应用的企业架构框架&#xff0c;旨在帮助组织高效地进行架构设计和管理。 TOGAF 的核心就是由我们熟知的四大架构领域组成:业务架构、数据架构、应用架构和技术架构。 企业数字化架构设计中的最常见要素是4A 架构。 4…

苹果Siri将搭载大型语言模型,近屿智能抢占AIGC大模型人才培养高地

据媒体报道&#xff0c;苹果公司正在研发一款全新升级、更加智能且对话能力显著提升的Siri&#xff0c;意在超越OpenAI的ChatGPT及其他语音服务。 报道指出&#xff0c;新一代Siri将搭载更为先进的大型语言模型&#xff08;LLM&#xff09;&#xff0c;苹果期望其能够进行连续…

【1.4 Getting Started--->Support Matrix】

主页&#xff1a;支持矩阵 这些支持矩阵概述了 TensorRT API、解析器和层支持的平台、特性和硬件功能。 Support Matrix Abstract 这些支持矩阵概述了 TensorRT API、解析器和层所支持的平台、功能和硬件功能。 有关之前发布的 TensorRT 文档&#xff0c;请参阅 TensorRT 档…

WPF中如何让Textbox显示为一条直线

由于Textbox直接使用是一条直线 设置如下代码 可以让Textbox变为直线输入 <Style TargetType"TextBox"x:Key"UsernameTextBoxStyle"><Setter Property"Template"><Setter.Value><ControlTemplate TargetType"{x:Typ…

Mac 修改默认jdk版本

当前会话生效 这里演示将 Java 17 版本降低到 Java 8 查看已安装的 Java 版本&#xff1a; 在终端&#xff08;Terminal&#xff09;中运行以下命令&#xff0c;查看已安装的 Java 版本列表 /usr/libexec/java_home -V设置默认 Java 版本&#xff1a; 找到 Java 8 的安装路…

K8S + Jenkins 做CICD

前言 这里会做整体CICD的思路和流程的介绍&#xff0c;会给出核心的Jenkins pipeline脚本&#xff0c;最后会演示一下 实验/实操 结果 由于整体内容较多&#xff0c;所以不打算在这里做每一步的详细演示 - 本文仅作自己的实操记录和日后回顾用 要看保姆式教学的可以划走了&…

使用 前端技术 创建 QR 码生成器 API1

前言 QR码&#xff08;Quick Response Code&#xff09;是一种二维码&#xff0c;于1994年开发。它能快速存储和识别数据&#xff0c;包含黑白方块图案&#xff0c;常用于扫描获取信息。QR码具有高容错性和快速读取的优点&#xff0c;广泛应用于广告、支付、物流等领域。通过扫…

基于Java Springboot高校工作室管理系统

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue、Element-ui 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse 数据…