当前位置: 首页 > news >正文

Android 实现MQTT客户端,用于门禁消息推送

添加MQTT依赖

implementation ‘org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.2’
implementation ‘org.eclipse.paho:org.eclipse.paho.android.service:1.1.1’

在Manifest清单文件中添加服务

<service android:name="org.eclipse.paho.android.service.MqttService" />

两种实现方法


MqttClient的实现方式

MQTT初始化连接线程,实现与服务器的连接、订阅、发布消息

    private class ConnectTask extends AsyncTask<Void, String, Boolean> {//MQTT连接线程,实现与服务器的连接、订阅、发布消息/*** 异步任务:AsyncTask<Params, Progress, Result>* 1.Params:UI线程传过来的参数。* 2.Progress:发布进度的类型。* 3.Result:返回结果的类型。耗时操作doInBackground的返回结果传给执行之后的参数类型。** 执行流程:* 1.onPreExecute()* 2.doInBackground()-->onProgressUpdate()* 3.onPostExecute()*/@Overrideprotected void onPreExecute() //执行耗时操作之前处理UI线程事件{super.onPreExecute();isConnecting = true;connectionStatusTextView.setText("Connecting...");}@Overrideprotected Boolean doInBackground(Void... voids){//在此方法执行耗时操作,耗时操作中收发MQTT服务器的数据//MQTT服务器地址String brokerUrl = "tcp://www.10086.com:1883";//客户端ID,用于在MQTT服务器上String clientId = MqttClient.generateClientId();try {mqttClient = new MqttClient(brokerUrl, clientId, new MemoryPersistence());} catch (MqttException e) {throw new RuntimeException(e);}MqttConnectOptions connectOptions = new MqttConnectOptions();connectOptions.setCleanSession(true);//mqtt服务器用户名和密码connectOptions.setUserName("username");connectOptions.setPassword("password".toCharArray());connectOptions.setWill("断线消息主题","断线消息内容".getBytes(),1,true);connectOptions.setConnectionTimeout(10);connectOptions.setKeepAliveInterval(20);try {mqttClient.connect(connectOptions);mqttClient.setCallback(new MqttCallback() {@Overridepublic void connectionLost(Throwable throwable) {Log.e(TAG, "连接丢失");//连接丢失的时候可以在这里进行重新连接publishProgress("Connection lost, reconnecting...");new ReconnectTask().execute();}@Overridepublic void messageArrived(String topic, MqttMessage message) throws Exception {Log.i(TAG, "收到消息:"+message.toString());if (topic.equals("sensors/temperature")) {// Update temperature readingpublishProgress("Temperature: " + message.toString());} else if (topic.equals("sensors/humidity")) {// Update humidity readingpublishProgress("Humidity: " + message.toString());} else if (topic.equals("leds/led1/status")) {// Update LED 1 statusif (message.toString().equals("on")) {publishProgress("LED 1 is on");ledStatusImageView.setText("LED 1 is on");} else {publishProgress("LED 1 is off");ledStatusImageView.setText("LED 1 is off");}} else if (topic.equals("leds/led2/status")) {// Update LED 2 statusif (message.toString().equals("on")) {publishProgress("LED 2 is on");ledStatusImageView.setText("LED 2 is on");} else {publishProgress("LED 2 is off");ledStatusImageView.setText("LED 2 is off");}}}@Overridepublic void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {Log.i(TAG, "成功发送");}});//这里是订阅的话题/*** subscribe的第二个参数如果是消息等级,其代表的意义是:** qos = 0 : 消息最多发送一次,在客户端离线等不可用的情况下客户端将会丢失这条消息。** qos = 1 : 消息至少发送一次,能保证客户端能收到该条消息。** qos = 2 : 消息仅传送一次。*/mqttClient.subscribe("zhyj/temperature",1);mqttClient.subscribe("zhyj/mj1/status",1);mqttClient.subscribe("zhyj/mj22/status",1);} catch (MqttException e) {Log.e(TAG, "Error connecting to MQTT broker: " + e.getMessage());publishProgress("Error connecting to MQTT broker: " + e.getMessage());return false;}return true;}@Overrideprotected void onProgressUpdate(String... values) {//用于在主线程处理doInBackground()方法执行完毕后的结果,更新UI或者执行其它操作super.onProgressUpdate(values);connectionStatusTextView.setText(values[0]);}@Overrideprotected void onPostExecute(Boolean aBoolean){//用于在主线程处理doInBackground()方法执行完毕后的结果,更新UI或者执行其它操作super.onPostExecute(aBoolean);isConnecting = false;if (aBoolean) {connectionStatusTextView.setText("Connected");}}}

MQTT重连

    private class ReconnectTask extends AsyncTask<Void, String, Boolean> {@Overrideprotected void onPreExecute() {super.onPreExecute();isConnecting = true;connectionStatusTextView.setText("Reconnecting...");}@Overrideprotected Boolean doInBackground(Void... voids) {if (mqttClient != null && mqttClient.isConnected()) {try {mqttClient.disconnect();} catch (MqttException e) {Log.e(TAG, "Error disconnecting from MQTT broker: " + e.getMessage());}}return new ConnectTask().doInBackground();}@Overrideprotected void onPostExecute(Boolean aBoolean) {super.onPostExecute(aBoolean);isConnecting = false;if (aBoolean) {connectionStatusTextView.setText("Connected");}}}

MQTT断开

 private class DisconnectTask extends AsyncTask<Void, Void, Void> {@Overrideprotected void onPreExecute() {super.onPreExecute();connectionStatusTextView.setText("Disconnecting...");}@Overrideprotected Void doInBackground(Void... voids) {if (mqttClient != null && mqttClient.isConnected()) {try {mqttClient.disconnect();} catch (MqttException e) {Log.e("dbj", "Error disconnecting from MQTT broker: " + e.getMessage());}}return null;}@Overrideprotected void onPostExecute(Void aVoid) {super.onPostExecute(aVoid);connectionStatusTextView.setText("Disconnected");ledStatusImageView.setText("Disconnected");}}

发送消息

private class ToggleLedTask extends AsyncTask<String, Void, Void> {@Overrideprotected Void doInBackground(String... strings) {if (mqttClient != null && mqttClient.isConnected()) {String topic = "zhyj/" + strings[0] + "/control";MqttMessage message = new MqttMessage();if (ledStatusImageView.getText().toString().contains("on")) {message.setPayload("off".getBytes());} else {message.setPayload("on".getBytes());}try {//publish()的第三个参数和subscribe的第二个参数的qos同理mqttClient.publish(topic, message);} catch (MqttException e) {Log.e(TAG, "Error publishing message: " + e.getMessage());}}return null;}}

MqttAndroidClient service的实现方式

配置文件添加 MQTTService

public class MQTTService extends Service {public static final String TAG = "dxj";private static MqttAndroidClient client;private MqttConnectOptions conOpt;private String host = "tcp://www.10086.com:1883";private String userName = "";private String passWord = "";private static String myTopic = "zhyj_mj";      //要订阅的主题private String clientId = "";//客户端标识private IGetMessageCallBack IGetMessageCallBack;@Overridepublic void onCreate() {super.onCreate();Log.e(getClass().getName(), "onCreate");init();}public static void publish(String msg) {try {if (client != null) {client.publish(myTopic, msg.getBytes(), 1, false);}} catch (MqttException e) {e.printStackTrace();Log.e(TAG, "Error connecting to MQTT broker: " + e.getMessage());}}private void init() {// 服务器地址(协议+地址+端口号)String uri = host;client = new MqttAndroidClient(this, uri, clientId);// 设置MQTT监听并且接受消息client.setCallback(mqttCallback);conOpt = new MqttConnectOptions();// 这个标志是标志客户端,服务端是否要保持持久化的一个标志。默认是true//设置客户端和服务端重启或重连后是否需要记住之前的状态conOpt.setCleanSession(false);// 设置超时时间,单位:秒conOpt.setConnectionTimeout(10);// 心跳包发送间隔,单位:秒conOpt.setKeepAliveInterval(20);//连接丢失的情况下,客户端将尝试重新连接到服务器。// 在尝试重新连接之前,它最初将等待1秒,对于每次失败的重新连接尝试,// 延迟将加倍,直到达到2分钟,此时延迟将保持在2分钟
//        conOpt.setAutomaticReconnect(true);// 用户名conOpt.setUserName(userName);// 密码conOpt.setPassword(passWord.toCharArray());     //将字符串转换为字符串数组// last will messageboolean doConnect = true;String message = "{\"terminal_uid\":\"" + clientId + "\"}";Log.e(getClass().getName(), "message是:" + message);String topic = myTopic;// 最后的遗嘱// MQTT本身就是为信号不稳定的网络设计的,所以难免一些客户端会无故的和Broker断开连接。//当客户端连接到Broker时,可以指定LWT,Broker会定期检测客户端是否有异常。//当客户端异常掉线时,Broker就往连接时指定的topic里推送当时指定的LWT消息。try {conOpt.setWill(topic, message.getBytes(), 1, false);} catch (Exception e) {Log.i(TAG, "Exception Occured", e);doConnect = false;iMqttActionListener.onFailure(null, e);}if (doConnect) {doClientConnection();}}@Overridepublic void onDestroy() {stopSelf();try {if (isAlreadyConnected()) {client.disconnect();client.unregisterResources();}IGetMessageCallBack.setStatus("断开连接");} catch (MqttException e) {e.printStackTrace();Log.e(TAG, "Error connecting to MQTT broker: " + e.getMessage());}super.onDestroy();}/*** 连接MQTT服务器*/private void doClientConnection() {if (!isAlreadyConnected() && isConnectIsNormal()) {try {client.connect(conOpt, null, iMqttActionListener);} catch (MqttException e) {e.printStackTrace();Log.e(TAG, "Error connecting to MQTT broker: " + e.getMessage());}}}// MQTT是否连接成功private IMqttActionListener iMqttActionListener = new IMqttActionListener() {@Overridepublic void onSuccess(IMqttToken arg0) {try {/*** subscribe的第二个参数如果是消息等级,其代表的意义是:** qos = 0 : 消息最多发送一次,在客户端离线等不可用的情况下客户端将会丢失这条消息。** qos = 1 : 消息至少发送一次,能保证客户端能收到该条消息。** qos = 2 : 消息仅传送一次。*/client.subscribe("zhyj/mj/status", 1);IGetMessageCallBack.setStatus("连接成功");} catch (MqttException e) {e.printStackTrace();IGetMessageCallBack.setStatus("连接失败");Log.e(TAG, "Error connecting to MQTT broker: " + e.getMessage());}}@Overridepublic void onFailure(IMqttToken arg0, Throwable arg1) {arg1.printStackTrace();// 连接失败,重连Log.e(TAG, "Error publishing message: " + arg0.toString());IGetMessageCallBack.setStatus("连接失败");}};// MQTT监听并且接受消息private MqttCallback mqttCallback = new MqttCallback() {@Overridepublic void messageArrived(String topic, MqttMessage message) throws Exception {IGetMessageCallBack.setStatus("收到消息");String str1 = new String(message.getPayload());if (IGetMessageCallBack != null) {IGetMessageCallBack.setMessage(str1);}String str2 = topic + ";qos:" + message.getQos() + ";retained:" + message.isRetained();Log.i(TAG, "messageArrived:" + str1);Log.i(TAG, str2);}@Overridepublic void deliveryComplete(IMqttDeliveryToken arg0) {IGetMessageCallBack.setStatus("成功发送");}@Overridepublic void connectionLost(Throwable arg0) {// 失去连接,重连Log.e(TAG, "连接丢失 isAlreadyConnected=" + isAlreadyConnected());IGetMessageCallBack.setStatus("连接丢失");}};/*** 判断网络是否连接*/private boolean isConnectIsNormal() {ConnectivityManager connectivityManager = (ConnectivityManager) this.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);NetworkInfo info = connectivityManager.getActiveNetworkInfo();if (info != null && info.isAvailable()) {String name = info.getTypeName();Log.e(TAG, "MQTT当前网络名称:" + name);return true;} else {Log.e(TAG, "MQTT 没有可用网络");return false;}}@Overridepublic IBinder onBind(Intent intent) {Log.e(getClass().getName(), "onBind");return new CustomBinder();}public void setIGetMessageCallBack(IGetMessageCallBack IGetMessageCallBack) {this.IGetMessageCallBack = IGetMessageCallBack;}public class CustomBinder extends Binder {public MQTTService getService() {Log.e(getClass().getName(), "CustomBinder");return MQTTService.this;}}public void toCreateNotification(String message) {PendingIntent pendingIntent = PendingIntent.getActivity(this, 1, new Intent(this, MQTTService.class), PendingIntent.FLAG_UPDATE_CURRENT);NotificationCompat.Builder builder = new NotificationCompat.Builder(this);//3、创建一个通知,属性太多,使用构造器模式Notification notification = builder.setTicker("test_title").setSmallIcon(R.mipmap.ic_launcher).setContentTitle("").setContentText(message).setContentInfo("").setContentIntent(pendingIntent)//点击后才触发的意图,“挂起的”意图.setAutoCancel(true)        //设置点击之后notification消失.build();NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);startForeground(0, notification);notificationManager.notify(0, notification);}public boolean isAlreadyConnected() {if (client != null) {try {boolean result = client.isConnected();if (result) {return true;} else {return false;}} catch (Exception e) {e.printStackTrace();return false;}} else {return false;}}
}
为了方便Service与Acitivity之间的通信,创建一个工具类作为桥梁
public class MyServiceConnection implements ServiceConnection {private MQTTService mqttService;private IGetMessageCallBack IGetMessageCallBack;@Overridepublic void onServiceConnected(ComponentName componentName, IBinder iBinder) {mqttService = ((MQTTService.CustomBinder)iBinder).getService();mqttService.setIGetMessageCallBack(IGetMessageCallBack);}@Overridepublic void onServiceDisconnected(ComponentName componentName) {}public MQTTService getMqttService(){return mqttService;}public void setIGetMessageCallBack(IGetMessageCallBack IGetMessageCallBack){this.IGetMessageCallBack = IGetMessageCallBack;}
几个重要的参数
MqttConnectOptions.setAutomaticReconnect(true)

true表示支持自动重连
连接丢失的情况下,客户端将尝试重新连接到服务器。
在尝试重新连接之前,它最初将等待1秒,对于每次失败的重新连接尝试,
延迟将加倍,直到达到2分钟,此时延迟将保持在2分钟

MqttConnectOptions.setCleanSession(true)

官方注释:
如果设置为false,则客户端和服务器将在重新启动客户端、服务器和连接时保持状态。当状态保持时:
即使重新启动客户端、服务器或连接,消息传递也将可靠地满足指定的QOS。
服务器会将订阅视为持久订阅。
如果设置为true,则客户端和服务器将不会在重新启动客户端、服务器或连接时保持状态。这意味着
如果重新启动客户端、服务器或连接,则无法维持向指定QOS的消息传递

这个标志是标志客户端,服务端是否要保持持久化的一个标志。默认是true
设置客户端和服务端重启或重连后是否需要记住之前的状态。
当setCleanSession为true时,客户端掉线或服务端重启后,服务端和客户端会清掉之前的 session, 重连后客户端会有一个新的session。离线期间发来QoS=0,1,2的消息一律接收不到,且所有之前订阅的topic需要重新订阅。
··························································································
当setCleanSession为false时, 客户端掉线或服务端重启后,服务端和客户端不会清除之前的session。重连后session将会恢复,客户端不用重新订阅主题。且离线期间发来QoS=0,1,2的消息仍然可以接收到。

这里有个需要注意的地方,即setCleanSession为true时,掉线后客户端设置了setAutomaticReconnect为true才会自动重连。为当setCleanSession为false时。不管setAutomaticReconnect为true或者false都会自动重连。

MqttConnectOptions.setKeepAliveInterval(30);

心跳包发送间隔,单位:秒
MQTT客户端(client)在没有收到或发布任何消息时仍然是保持连接的。服务端(the broker)需要跟踪客户端的连接状态。 所有需要发送心跳包来确定客户端是否是连接状态。心跳包发送的时间间隔就是keepalive设置的。
服务端会维持一个timer。当这个timer记录的时间超过1.5倍keepalive值时,服务端会将这个客户端标记为断开连接,并发送Last Will and Testament (LWT)遗言广播。
每次客户端发送或接收一个消息, 服务端会重置这个timer。

按具体业务场景修改使用即可

相关文章:

Android 实现MQTT客户端,用于门禁消息推送

添加MQTT依赖 implementation ‘org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.2’ implementation ‘org.eclipse.paho:org.eclipse.paho.android.service:1.1.1’ 在Manifest清单文件中添加服务 <service android:name"org.eclipse.paho.android.service.Mq…...

跨境电商的广告推广怎么做?7个方法

在跨境电商竞争日趋激烈的市场环境下&#xff0c;跨境电商店铺引流成了制胜关键点。这里给大家分享一套引流推广的方法。 一、搜索引擎营销推广 搜索引擎有两个最大的优点是更灵活、更准确。搜索引擎营销的目标定位更精确&#xff0c;且不受时间和地理位置上的限制&#xff0…...

《Java-SE-第二十八章》之CAS

前言 在你立足处深挖下去,就会有泉水涌出!别管蒙昧者们叫嚷:“下边永远是地狱!” 博客主页&#xff1a;KC老衲爱尼姑的博客主页 博主的github&#xff0c;平常所写代码皆在于此 共勉&#xff1a;talk is cheap, show me the code 作者是爪哇岛的新手&#xff0c;水平很有限&…...

git之reflog分析

写在前面 本文一起看下reflog命令。 1&#xff1a;场景描述 在开发的过程中&#xff0c;因为修改错误&#xff0c;想要通过git reset命令恢复到之前的某个版本&#xff0c;但是选择提交ID错误&#xff0c;导致多恢复了一个版本&#xff0c;假定&#xff0c;该版本对应的内容…...

《吐血整理》进阶系列教程-拿捏Fiddler抓包教程(18)-Fiddler如何接口测试,妈妈再也不担心我不会接口测试了

1.简介 Fiddler最大的优势在于抓包&#xff0c;我们大部分使用的功能也在抓包的功能上&#xff0c;fiddler做接口测试也是非常方便的。 领导或者开发给你安排接口测试的工作任务&#xff0c;但是没有给你接口文档&#xff08;由于开发周期没有时间出接口文档&#xff09;&…...

Oracle open JDK和 Amazon Corretto JDK的区别

Oracle OpenJDK和Amazon Corretto JDK都是基于Java开放源代码项目的发行版&#xff0c;它们之间有一些区别。 1. 来源&#xff1a;Oracle OpenJDK是由Oracle公司领导和支持的&#xff0c;它是Java的官方参考实现之一。而Amazon Corretto JDK是由亚马逊公司开发和支持的&#xf…...

Spark写PGSQL分区表

这里写目录标题 需求碰到的问题格式问题分区问题&#xff08;重点&#xff09; 解决完整代码效果 需求 spark程序计算后的数据需要往PGSQL中的分区表进行写入。 碰到的问题 格式问题 使用了字符串格式&#xff0c;导致插入报错。 val frame df.withColumn("insert_t…...

Git 命令行登录

有时候登录命令行版本的git会出现这个错误 1remote: Support for password authentication was removed on August 13, 2021. 2remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for …...

性能分析记录

4实例压测TPS浮动在200-300 1.TPS浮动200-300&#xff0c;ART浮动的可能性是10-20ms&#xff0c;链路复杂是可接受的&#xff0c;链路简单则需要分析原因。 1&#xff09;缓存没命中&#xff0c;对某些账号缓存没命中&#xff0c;或缓存失效后导致隔段时间耗时升高。 2&…...

Java反射学习(大综合)

第一天 Java反射及动态代理... 2 一、 Java反射... 2 1、什么是反射&#xff1a;... 2 2、反射的原理... 2 3、反射的优缺点&#xff1a;... 2 4、反射的用途&#xff1a;... 3 5、反射机制常用的类&#xff1a;... 3 1、获得Class&#xff1a;主要有三…...

Vite+Vue3 开发UI组件库并发布到npm

一直对开源UI组件库比较感兴趣&#xff0c;摸索着开发了一套&#xff0c;虽然还只是开始&#xff0c;但是从搭建到发布这套流程基本弄明白了&#xff0c;现在分享给大家&#xff0c;希望对同样感兴趣的同学有所帮助。 目前我的这套名为hasaki-ui的组件库仅有两个组件&#xff0…...

vue- form动态表单验证规则-表单验证

前言 以element官网的form表单的-动态增减表单项为例讲解表单验证规则 动态的功能就是v-model配合push v-for 便利来实现的 我们需要熟知2个知识点prop表单验证需要跟v-model绑定的值是一样的&#xff0c; 如果是一个数组便利的表单&#xff0c;那就需要绑定这个数组每一项…...

FPGA学习—通过数码管实现电子秒表模拟

文章目录 一、数码管简介二、项目分析三、项目源码及分析四、实现效果五、总结 一、数码管简介 请参阅博主以前写过的一篇电子时钟模拟&#xff0c;在此不再赘述。 https://blog.csdn.net/qq_54347584/article/details/130402287 二、项目分析 项目说明&#xff1a;本次项目…...

区块链媒体发稿:区块链媒体宣发常见问题解析

据统计&#xff0c;由于区块链应用和虚拟货币的兴起&#xff0c;越来越多媒体对区块链领域开展报导&#xff0c;特别是世界各国媒体宣发全是热火朝天。但是&#xff0c;随着推卸责任媒体宣发的五花八门&#xff0c;让很多人因而上当受骗&#xff0c;乃至伤害一大笔资产。身为投…...

openGauss学习笔记-28 openGauss 高级数据管理-NULL值

文章目录 openGauss学习笔记-28 openGauss 高级数据管理-NULL值28.1 IS NOT NULL28.2 IS NULL openGauss学习笔记-28 openGauss 高级数据管理-NULL值 NULL值代表未知数据。无法比较NULL和0&#xff0c;因为它们是不等价的。 创建表时&#xff0c;可以指定列可以存放或者不能存…...

DAO和XML文件参数和返回值

①MyBatis中resultType和resultMap的区别 1.使用MyBatis查询数据库记录时&#xff0c;返回类型常用的有两种&#xff1a;resultType和resultMap。那么两者之间有什么区别呢&#xff1f; 如果只是返回一个值&#xff0c;简单类型&#xff0c;比如说String或者int&#xff0c;那…...

vue 浏览器右侧可拖拽小组件

目录 0. 使用场景 1. 动图示例 2. 实现方式 2.1 创建drag.js 2.2 使用v-drag 3. 结尾 0. 使用场景 很多网页在浏览器右侧有"导航"或者“智能助手”的悬浮小气泡框&#xff0c;比如我们的csdn☞ 作为页面友好型的引导标注&#xff0c;某些场景下这些小气泡可以…...

SpringMvc学习笔记五

Restful 风格路由 1. 配置类 1.1、SpringMvcConfig配置类 Configuration ComponentScan({"com.itheima.controller", "com.itheima.config"}) 方式1.2 添加com.itheima.config 扫描目录 EnableWebMvc public class SpringMvcConfig { } 1.2、ServletCo…...

ORACLE-DG总结

述 当主库的某些日志没有成功传送到备库,那么这时候就发生了归档裂缝(Archive Gap)。目前Oracle提供了两种日志GAP的检测和处理机制,分别是自动GAP处理(Automatic Gap Resolution)和FAL进程GAP处理(FAL Gap Resolution)。自动GAP处理即主库上的ARCn进程会每分钟检查备库…...

机器学习中的 K-均值聚类算法及其优缺点

K-均值聚类算法是一种常用的无监督学习算法&#xff0c;用于将相似的数据点分组为聚类。 其步骤如下&#xff1a; 1. 初始化&#xff1a;选择聚类数K&#xff0c;随机选取K个聚类中心。 2. 计算距离&#xff1a;计算每个数据点与K个聚类中心的距离&#xff0c;将其分配到距离最…...

文生图模型Z-Image:低配电脑也能玩的AI绘画工具

文生图模型Z-Image&#xff1a;低配电脑也能玩的AI绘画工具 1. 项目介绍 1.1 什么是Z-Image-GGUF&#xff1f; Z-Image-GGUF是一个基于阿里巴巴通义实验室Z-Image模型的文生图AI工具。它最大的特点是通过GGUF量化技术&#xff0c;大幅降低了硬件要求&#xff0c;让普通配置的…...

用公司组织架构模式读懂AI大模型、OpenClaw、Claude Code、Agent、Prompt、MCP、Skill、Token、多智能体、具身智能到底啥关系?

公司最小的信息颗粒是 Token&#xff1b;老板 AI大模型 通过 Prompt 听汇报做决策&#xff1b;公司规定所有业务系统必须按 MCP 标准接入&#xff1b;HR 给员工发 Skill 手册&#xff1b;单个 Agent 员工领命干活&#xff1b;遇到大项目就组个 多智能体 团队&#xff1b;OpenCl…...

从零到一:在Vitis平台上构建ZYNQ PS-SPI Flash驱动

1. 环境准备与硬件连接 在开始构建ZYNQ PS-SPI Flash驱动之前&#xff0c;我们需要准备好开发环境和硬件平台。我推荐使用Xilinx官方提供的Vitis 2022.1版本&#xff0c;这个版本对ZYNQ系列的支持比较稳定。硬件方面&#xff0c;你需要一块带有SPI Flash的ZYNQ开发板&#xff0…...

Flux.1-Dev深海幻境助力学术研究:为论文生成假设验证过程的可视化图表

Flux.1-Dev深海幻境助力学术研究&#xff1a;为论文生成假设验证过程的可视化图表 1. 引言 写论文最头疼的环节是什么&#xff1f;对很多理工科的研究者来说&#xff0c;可能不是实验&#xff0c;也不是数据分析&#xff0c;而是如何把脑子里那个复杂的理论模型或验证过程&am…...

常州别墅大宅设计装修行业头部企业精选评估报告

当前&#xff0c;常州别墅大宅设计装修技术已成为高端家装领域增长的核心驱动力&#xff0c;随着高净值人群需求升级&#xff0c;市场呈现出“设计个性化、施工精细化、服务全案化、品质高端化”的趋势&#xff0c;但同时也存在设计同质化严重、施工管控难度大、全案交付能力不…...

解决Ubuntu浏览器认证校园网址无法打开的

清理 WebKit 缓存rm -rf ~/.cache/WebKit/ rm -rf ~/.cache/gnome-shell/portal-helper/重启网络管家sudo systemctl restart NetworkManager...

科研进展 | JAG: 大光斑高光谱激光雷达遥感辐射传输模型从垂直视角解锁森林叶绿素分布密码

大光斑高光谱激光雷达辐射传输模型: 垂直视角解锁叶绿素分布密码当森林的 “健康密码” 藏在垂直分层的枝叶间&#xff0c;传统遥感技术难以触及森林冠层中下层的生化奥秘&#xff1f; 近日&#xff0c;电子科技大学定量遥感团队白杰副研究员&#xff08;师资博士后&#xff09…...

Notepad++深度解析:免费开源轻量高效的程序员必备代码编辑器

摘要 本文由拥有20年经验的全栈工程师撰写&#xff0c;深度解析Notepad这款免费开源代码编辑器的核心技术优势、功能特性与全流程实操指南&#xff0c;覆盖语法高亮、插件扩展等核心能力&#xff0c;适配多语言开发场景&#xff0c;为开发者提供高效稳定的文本编辑解决方案。 访…...

如何解决APT仓库体系结构不匹配问题:以amd64和i386为例

1. 当APT仓库遇到体系结构不匹配时会发生什么 第一次在树莓派上执行sudo apt-get update时看到"不支持amd64体系结构"的红色警告&#xff0c;我差点以为系统崩溃了。实际上这是Linux系统在提醒你&#xff1a;当前仓库和你的设备"语言不通"。就像带着英文菜…...

被“圈养”的Java开发者:当AI浪潮来袭,你还在用手写HttpClient调大模型吗?

写在前面 2026年&#xff0c;AI早已不是算法工程师的专属领域。每个后端开发者都被卷入了这场浪潮——无论你愿不愿意。 “两年前&#xff0c;大部分Java团队面对大模型浪潮的反应是&#xff1a;‘我们用HTTP调OpenAI的API不就行了&#xff1f;’” 但到了2026年&#xff0c;如…...