大家好,我是Edison。

全球电子制造主要集中在中国,面向未来工业4.0、中国制造2025的战略转型升级,互联互通是基础、数据是核心,如何从用户角度来定义设备加工数据的内容完整性、有效性、可扩展性将是工厂通讯连接交换的工作重点。

IPC-CFX是什么?

首先,解释下这两个缩写的意思:IPC是国际电子工业联接协会,CFX是互联工厂数据交换。

IPC-CFX是一个开放式的国际标准,它简化了机器到机器之间的通信。IPC-CFX基于IPC-2591,是全球互联工厂数据交换标准统一定义数据语言格式,我们也可以将其理解为是一个协议,它为制造商、设备、硬件及软件供应商节约沟通和再开发成本,CFX标准的应用将简化并标准化机器设备之间的通信。

总结一下,IPC-CFX就是机器设备之间通信的“统一语言”,是大家都懂的“普通话”而不是“方言”。

话外音:对于IT开发者在追求的DDD(领域驱动设计),其核心思想也是“统一语言”,统一业务和技术之间的语言,提高沟通效率,进而提高软件质量。

IPC-CFX的适用范围

目前IPC-CFX主要在电子制造行业得到应用,特别是在 SMT(表面组装技术)行业,越来越多的SMT设备厂商开始加入CFX联盟,比如SMT检测设备知名厂商Koh Young就是其中一员。

IPC-CFX标准不仅适用于 SMT(表面组装技术)的相关生产,也支持机械装配、定制化、包装和运输等上游环节,甚至电气、机械子部件等上游环节。我们使用基于PC-CFX标准的传输信息来开发一些常见的应用例如设备利用率、生产线效率 和 整体设备效率(OEE)指标等。

IPC-CFX下设备如何通信?

在IPC-CFX的标准下,设备的数据被定义为制造主题(Topic)消息结构(Message)。设备不太需要关注数据发送到哪里,数据来源于哪里,只需要知道在什么时机下发送什么数据,收到什么数据执行什么操作即可。

CFX都定义了哪些标准的Topic呢,如下图所示:

以一个Topic "WorkOrdersScheduled"为例,顾名思义:工单已排程。这个Topic代表会发出一个已经排好执行计划的工单,该工单即将在稍后某个特定时间某条生产线如SMT Line 1开始执行生产,其定义的消息数据体如下所示,还是比较完善的:

{
"ScheduledWorkOrders": [
{
"WorkOrderIdentifier": {
"WorkOrderId": "WO1122334455",
"Batch": null
},
"Scheduler": {
"OperatorIdentifier": "BADGE4486",
"ActorType": "Human",
"LastName": "Doe",
"FirstName": "John",
"LoginName": "john.doe@domain1.com"
},
"WorkArea": "SMT Line 1",
"StartTime": "2018-08-02T11:00:00",
"EndTime": "2018-08-02T15:00:00",
"ReservedResources": [
"L1PRINTER1",
"L1PLACER1",
"L1PLACER2",
"L1OVEN1"
],
"ReservedTools": [
{
"UniqueIdentifier": "UID23890430",
"Name": "TorqueWrench_123"
}
],
"ReservedOperators": [
{
"OperatorIdentifier": "BADGE489435",
"ActorType": "Human",
"LastName": "Smith",
"FirstName": "Joseph",
"LoginName": "joseph.smith@abcdrepairs.com"
}
],
"ReservedMaterials": [
{
"UniqueIdentifier": "UID23849854385",
"InternalPartNumber": "PN4452",
"Quantity": 0.0
},
{
"UniqueIdentifier": "UID23849854386",
"InternalPartNumber": "PN4452",
"Quantity": 0.0
},
{
"UniqueIdentifier": "UID23849854446",
"InternalPartNumber": "PN3358",
"Quantity": 0.0
}
]
}
]
}

又如 "WorkOrdersUnschedule" 这个Topic,代表SMT Line 1的某个工单即将被取消,其数据格式就简单很多:

{
"ScheduledWorkOrderIdentifiers": [
{
"WorkOrderIdentifier": {
"WorkOrderId": "WO1122334455",
"Batch": null
},
"WorkArea": "SMT Line 1"
}
]
}

除此之外,CFX还用一个统一的消息信封来包裹这个消息体,我们可以理解为定义了一个如下所示的统一消息格式:

public class CFXEnvelope
{
public string MessageName {get;set;} // eg. CFX.Produciton.Application.MaterialsApplied
public string Version {get;set;} // eg. 1.7
......
public T MessageBody {get;set;} // 消息体内容:泛型
}

Anyway,这个对于我们IT工程师是比较好理解的,这就跟我们的系统和系统之间通过消息队列(如Kafka)进行发布订阅模式的异步通信一模一样。不过这里呢,是机器与机器,机器与企业之间的通信。

但是,IPC-CFX标准下是基于AMQP协议做消息传输的,每台设备都可以看作是一个AMQP端点,通过发布和订阅实现数据的交互。此外,IPC-CFX还支持点对点(Point-to-Point)的消息模式(请求/响应模式)。

我们都知道,Kafka是不支持AMQP协议的,因此,要使用IPC-CFX就不能直接使用Kafka作为Message Broker,而IPC-CFX官方的案例也都是使用RabbitMQ来写的,虽然我觉得在设备数据交换场景Kafka的性能会更好。

如何开发机台程序?

如何让一台台的设备变成符合IPC-CFX标准的AMQP节点呢?常规做法就是在机台侧开发一个程序,这里IPC-CFX组织为我们提供了一个SDK,其实是一个.NET开发包(Nuget安装即可),所以对咱们.NET开发者是十分友好的。

  • 对于.NET 4.6可以使用 CFX.CFXSDK

  • 对于.NET Core及以上可以使用 CFX.CFXSDK.NetStandard

这个SDK提供了以下功能:

  • 将所有CFX消息的用Class/Object表示。

  • 能够将CFX消息对象序列化和反序列化为JSON格式。

  • 能够通过AMQP传输协议将CFX消息发布到一个或多个目的地。

  • 能够通过AMQP传输协议从一个或多个订阅源接收CFX消息。

  • 完全自动化的网络连接故障管理(即使在网络宕机或其他不可靠的情况下保持AMQP连接)。

  • CFX消息“假脱机”。维护由于网络条件错误而无法传输的CFX消息的持久队列。一旦网络服务恢复,消息将自动按原来的顺序传输。

  • 点对点CFX端点命令(请求/响应)支持。

  • 支持AMQP 1.0 SASL认证和TLS加密。

官方SDK文档传送门:SDK文档

不过,通过学习发现,这个SDK主要还是提供了统一的Topic和Message的数据结构,至于和RabbitMQ的连接,个人感觉不太方便使用,我们完全可以使用其他成熟的RabbitMQ API组件来完成发布和订阅。

接下来,我们来快速实践一下CFX的两种通信方式:发布订阅 和 点对点。

快速开始:搭建一个RabbitMQ

既然IPC-CFX是基于AMQP协议来的,那我们就搭一个RabbitMQ吧。这里我们快速用docker-compose安装一个RabbitMQ。

version: '3'
services:
rabbitmq1:
image: rabbitmq:3.8-management
container_name: rabbit-mq-service
hostname: rabbit-mq-server
ports:
- "5672:5672"
- "15672:15672"
restart: always
environment:
- RABBITMQ_DEFAULT_USER=rabbit # user account
- RABBITMQ_DEFAULT_PASS=EdisonTalk2024 # password
volumes:
- rabbitmq_data:/var/lib/rabbitmq volumes:
rabbitmq_data:
driver: local

然后,通过下面的命令把RabbitMQ Run起来:需要注意的点就是需要手动开启AMQP1.0协议!

docker-compose up -d

#进入RabbitMQ容器
docker exec -it rabbit-mq-service /bin/bash
#开启AMQP1.0协议
rabbitmq-plugins enable rabbitmq_amqp1_0

成功运行起来后,能够成功打开RabbitMQ管理界面:

快速开始:实现基于CFX标准的发布订阅通信

发布者

这里我们通过Visual Studio创建一个控制台应用程序,基于.NET Framework 4.8来实现。

首先,安装Nuget包:

  • CFX.CFXSDK
  • EasyNetQ

其次,完成联接Broker 和 发布Message 的代码:

namespace AMQP.MachineA
{
/// <summary>
/// MachineA: SEWC.SMT.001
/// </summary>
public class Program
{
private const string _machineName = "SDC.SMT.001";
private const string _amqpBroker = "rabbit-mq-server"; // RabbitMQ-Host
private const string _amqpUsername = "rabbit"; // RabbitMQ-User
private const string _amqpPassword = "rabbit-password"; // RabbitMQ-Password public static void Main(string[] args)
{
Console.WriteLine($"Current Machine: {_machineName}");
Console.Write($"Current Role: Publisher {Environment.NewLine}"); var connStr = $"host={_amqpBroker};username={_amqpUsername};password={_amqpPassword}";
using (var amqpBus = RabbitHutch.CreateBus(connStr))
{
while (true)
{
Console.WriteLine($"[Info] Starting to send a message to AMQP broker.");
// Build a CFX Message of MaterialsApplied
var message = new CFXEnvelope(new MaterialsApplied()
{
TransactionId = Guid.NewGuid(),
AppliedMaterials = new List<InstalledMaterial>
{
new InstalledMaterial()
{
QuantityInstalled = 1,
QuantityNonInstalled = 2
}
}
}); amqpBus.PubSub.Publish(message);
Console.WriteLine($"[Info] Finished to send a message to AMQP broker.");
Console.WriteLine("-------------------------------------------------------------------"); Thread.Sleep(1000 * 3);
}
}
}
}
}

Note:这里只是为了快速演示,实际中账号密码以及Broker地址建议写到配置文件中,并使用AMQPS协议联接,否则你的账号密码会被明文在网络中传输。

订阅者

参考发布者,仍然创建一个控制台应用程序,安装两个NuGet包。

然后,实现消费者逻辑:

namespace AMQP.MachineB
{
/// <summary>
/// MachineB: SEWC.SMT.002
/// </summary>
public class Program
{
private const string _machineName = "SDC.SMT.002";
private const string _amqpBroker = "rabbit-mq-server"; // RabbitMQ-Host
private const string _amqpUsername = "rabbit"; // RabbitMQ-User
private const string _amqpPassword = "rabbit-password"; // RabbitMQ-Password public static void Main(string[] args)
{
Console.WriteLine($"Current Machine: {_machineName}");
Console.WriteLine($"Current Role: Subscriber {Environment.NewLine}"); var connStr = $"host={_amqpBroker};username={_amqpUsername};password={_amqpPassword}";
using (var amqpBus = RabbitHutch.CreateBus(connStr))
{
amqpBus.PubSub.Subscribe<CFXEnvelope>(_machineName, message =>
{
if (message.MessageBody is MaterialsApplied)
{
Console.WriteLine($"[Info] Got a message with topic {message.MessageName} :{Environment.NewLine}{message.ToJson(true)}");
Console.WriteLine("-------------------------------------------------------");
}
}); Console.WriteLine("Press any key to exit.");
Console.ReadLine();
}
}
}
}

最终的Demo效果如下图所示:

两个控制台应用程序模拟两个机台程序,实现了基于AMQP协议和CFX标准格式的异步通信。但是整体来讲,实现异步通信并不是重点,而是两个机台采用了所谓的“统一语言”。

快速开始:实现基于CFX标准的点对点通信

基于上面的了解,我们知道基于CFX我们还可以让设备之间实现点对点的通信,也可以不通过Broker转发,而且它仍然是基于AMQP协议的。

在点对点模式下,基于CFX SDK,会自动帮你创建一个基于Socket的通信进程,机台程序之间可以互相应答。

(1)机台A

namespace P2P.MachineA
{
/// <summary>
/// MachineA: SEWC.SMT.001
/// </summary>
public class Program
{
private const string _sendCfxHandle = "SDC.SMT.001"; // Sender
private const string _receiveCfxHandle = "SDC.SMT.002"; // Receiver
private const string _sendRequestUri = "amqp://127.0.0.1:8234"; // Sender
private const string _receiveRequestUri = "amqp://127.0.0.1:8235"; // Receiver public static void Main(string[] args)
{
Console.WriteLine($"Current Machine: {_sendCfxHandle}");
Console.WriteLine($"Current Uri: {_sendRequestUri}");
OpenRequest();
Console.WriteLine("Press Enter Key to start the CFX Sender");
Console.ReadKey(); while (true)
{
SendRequest();
Thread.Sleep(1000 * 5); // Send message every 5 seconds
}
} #region AMQP Sender
private static AmqpCFXEndpoint _sendRequestEndpoint; private static void OpenRequest()
{
if (_sendRequestEndpoint != null)
{
_sendRequestEndpoint.Close();
_sendRequestEndpoint = null;
} _sendRequestEndpoint = new AmqpCFXEndpoint();
Console.WriteLine($"[Debug] SendCFXEndpoint.IsOpen : {_sendRequestEndpoint.IsOpen.ToString()}");
_sendRequestEndpoint.Open(_sendCfxHandle, new Uri(_sendRequestUri));
Console.WriteLine($"[Debug] SendCFXEndpoint.IsOpen : {_sendRequestEndpoint.IsOpen.ToString()}"); AmqpCFXEndpoint.RequestTimeout = TimeSpan.FromSeconds(10 * 2);
} private static void SendRequest()
{
var message = CFXEnvelope.FromCFXMessage(new MaterialsApplied()
{
TransactionId = Guid.NewGuid(),
AppliedMaterials = new List<InstalledMaterial>
{
new InstalledMaterial()
{
QuantityInstalled = 1,
QuantityNonInstalled = 2
}
}
});
message.Source = _sendCfxHandle;
message.Target = _receiveCfxHandle;
message.TimeStamp = DateTime.Now; try
{
Console.WriteLine($"[Info] Starting to send a message to Target Machine {_receiveCfxHandle}.");
var response = _sendRequestEndpoint.ExecuteRequest(_receiveRequestUri, message);
Console.WriteLine($"[Info] Target Machine {_receiveCfxHandle} returns : {Environment.NewLine}{response.ToJson(true)}");
}
catch (Exception ex)
{
Console.WriteLine($"[Error] Exception message: {ex.Message}");
}
finally
{
Console.WriteLine("-------------------------------------------------------");
}
}
#endregion
}
}

Note:既然是点对点,那发送者就必须要知道接收者的位置。

(2)机台B

namespace P2P.MachineB
{
/// <summary>
/// MachineB: SEWC.SMT.002
/// </summary>
public class Program
{
private const string _receiveCfxHandle = "SDC.SMT.002";
private const string _receiveRequestUri = "amqp://127.0.0.1:8235"; public static void Main(string[] args)
{
Console.WriteLine($"Current Machine: {_receiveCfxHandle}");
Console.WriteLine($"Current Uri: {_receiveRequestUri}");
OpenListener();
Console.WriteLine("Press Entery Key to end the CFX Listener"); Console.ReadKey();
} #region AMQP Receiver
private static AmqpCFXEndpoint _receiveRequestEndpoint; private static void OpenListener()
{
if (_receiveRequestEndpoint != null)
{
_receiveRequestEndpoint.Close();
_receiveRequestEndpoint = null;
} _receiveRequestEndpoint = new AmqpCFXEndpoint();
_receiveRequestEndpoint.OnRequestReceived -= CFXMessageOnRequestReceived;
_receiveRequestEndpoint.OnRequestReceived += CFXMessageOnRequestReceived; Console.WriteLine($"[Debug] SendCFXEndpoint.IsOpen: {_receiveRequestEndpoint.IsOpen.ToString()}");
_receiveRequestEndpoint.Open(_receiveCfxHandle, new Uri(_receiveRequestUri));
Console.WriteLine($"[Debug] SendCFXEndpoint.IsOpen: {_receiveRequestEndpoint.IsOpen.ToString()}"); AmqpCFXEndpoint.RequestTimeout = TimeSpan.FromSeconds(10 * 2);
} private static CFXEnvelope CFXMessageOnRequestReceived(CFXEnvelope message)
{
Console.WriteLine($"[Info] Got a message from Source Machine {message.Source} :{Environment.NewLine}{message.ToJson(true)}");
Console.WriteLine("-------------------------------------------------------"); var result = (CFXEnvelope)null;
if (message.MessageBody is WhoIsThereRequest)
{
result = CFXEnvelope.FromCFXMessage(new WhoIsThereResponse()
{
CFXHandle = _receiveCfxHandle,
RequestNetworkUri = _receiveRequestUri,
RequestTargetAddress = "..."
});
}
else if (message.MessageBody is MaterialsApplied)
{
result = CFXEnvelope.FromCFXMessage(new WhoIsThereResponse()
{
CFXHandle = _receiveCfxHandle,
RequestNetworkUri = _receiveRequestUri,
RequestTargetAddress = "..."
});
}
else
{
return null;
} result.Source = _receiveCfxHandle;
result.Target = result.Source;
result.TimeStamp = DateTime.Now;
return result;
}
#endregion
}
}

点对点Demo效果:

小结

本文我们了解了IPC-CFX标准产生的背景 和 用途,它是机器设备之间通信的“统一语言”,是大家都懂的“普通话”而不是“方言”。

首先,IPC-CFX使用AMQP v1.0传输协议实现安全的连接,使用JSON进行数据编码,提供了明确的消息结构和数据内容,确保即插即用。

其次,我们通过两个Demo快速了解了如何实现一个基于CFX标准的机台端应用程序,来实现“统一语言”的设备间通信。

最后,就目前互联网上的资料来看,国内社区对于CFX的应用来看整体都还是不多的,我们也还处于学习阶段,希望未来或许有新的更新分享。

参考资料

IPC CFX 官方文档:Getting Started with SDK

齐开得科技:IPC-CFX在SMT领域的应用

MQTT vs AMQP:物联网通信协议对比

作者:周旭龙

出处:https://edisonchou.cnblogs.com

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

互联工厂数据交换标准:IPC-CFX的更多相关文章

  1. Atitit.常见软件 数据 交换格式 标准

    Atitit.常见软件 数据 交换格式 标准 1. 常见的数据格式txt ,doc ,pic,music ,vodio1 2. 通用格式json yaml phpstr1 3. 专用格式1 4. 用户 ...

  2. Java 常见数据交换格式——xml、json、yaml

    目录 数据交换格式介绍 XML 使用DOM方式解析 使用SAX方式解析 使用DOM4J方式解析 使用JDOM方式解析 JSON 使用JSONObject方式将数据转换为JSON格式 利用JSONObj ...

  3. 两种常用的数据交换格式:XML和JSON

    不同编程语言之间的数据传输,需要一种通用的数据交换格式,它需要简洁.易于数据储存.快速读取,且独立于各种编程语言.我们往往传输的是文本文件,比如我们都知道的csv(comma seperated va ...

  4. 常用两种数据交换格式之XML和JSON的比较

    目前,在web开发领域,主要的数据交换格式有XML和JSON,对于XML相信每一个web developer都不会感到陌生: 相比之下,JSON可能对于一些新步入开发领域的新手会感到有些陌生,也可能你 ...

  5. XML和JSON两种数据交换格式的比较

    在web开发领域,主要的数据交换格式有XML和JSON,对于在 Ajax开发中,是选择XML还是JSON,一直存在着争议,个人还是比较倾向于JSON的.一般都输出Json不输出xml,原因就是因为 x ...

  6. Disruptor——一种可替代有界队列完成并发线程间数据交换的高性能解决方案

    本文翻译自LMAX关于Disruptor的论文,同时加上一些自己的理解和标注.Disruptor是一个高效的线程间交换数据的基础组件,它使用栅栏(barrier)+序号(Sequencing)机制协调 ...

  7. JSON的基本结构和数据交换原理

    0.补充的写在前面的话 2017.03.29 补充内容 最近看到这篇博客的阅读量,想来应该是有部分网友来过想要了解JSON的基本概念,这篇博文写得可能不是那么好,所以现在再补充贴一位老师的文章,希望能 ...

  8. servlet与ajax数据交换(json格式)

    JSON数据格式: JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式. 易于人阅读和编写.同时也易于机器解析和生成. 它基于的一个子集. JSON采用完全独 ...

  9. (77)Wangdao.com第十五天_JavaScript 用于数据交换的文本格式 JSON 对象

    JSON 对象 JSON (JavaScript Object Notation 的缩写) 也是一种数据,是 JavaScript 的原生对象,用来处理 JSON 格式数据.它有两个静态方法:JSON ...

  10. DataStage 九、数据交换到MySQL以及乱码问题

    DataStage序列文章 DataStage 一.安装 DataStage 二.InfoSphere Information Server进程的启动和停止 DataStage 三.配置ODBC Da ...

随机推荐

  1. 基于NXP i.MX 8M Mini开发板规格书(四核ARM Cortex-A53 + 单核ARM Cortex-M4,主频1.6GHz)

     1 评估板简介 创龙科技TLIMX8-EVM-B是一款基于NXP i.MX 8M Mini的四核ARM Cortex-A53 + 单核ARM Cortex-M4异构多核处理器设计的高性能评估板,由核 ...

  2. nginx配置端口转发 并修改swagger路径配置

    项目服务器为linux,仅开放特定外网端口 所以部署的docker服务需要通过nginx 做端口转发 这里的配置使用的是 nginx docker服务 配置步骤: 1. 修改nginx配置文件,我这里 ...

  3. VBA | 统计数组某元素出现的次数,适用于一维、二维数组

    很简单的需求,但是中文网络上基本都是循环的方法,经过查找下面的方法很有效.为了方便用户的使用,进行了如下的整改. 1 Sub Statistics_Number_of_occurrences_test ...

  4. ArkTS基础知识

    [习题]ArkTS基础知识 及格分85/ 满分100   判断题 1. 循环渲染ForEach可以从数据源中迭代获取数据,并为每个数组项创建相应的组件. 正确(True)错误(False) 回答正确 ...

  5. MViT:性能杠杠的多尺度ViT | ICCV 2021

    论文提出了多尺度视觉Transformer模型MViT,将多尺度层级特征的基本概念与Transformer模型联系起来,在逐层扩展特征复杂度同时降低特征的分辨率.在视频识别和图像分类的任务中,MViT ...

  6. 基于Java+Spring+Vue仓储出入库管理系统设计和实现

    \n文末获取源码联系 感兴趣的可以先收藏起来,大家在毕设选题,项目以及论文编写等相关问题都可以给我加好友咨询 系统介绍: 网络的广泛应用给生活带来了十分的便利.所以把仓储出入库管理与现在网络相结合,利 ...

  7. web259(超详细)

    SoapClient看完之后还不是很懂的话就可以去下面的两个网址去补充一下 SoapClient 是 PHP 中用于与 SOAP(Simple Object Access Protocol)服务进行通 ...

  8. Kafka kafka在windows下的安装与配置

    kafka在windows下的安装与配置   By: 授客 QQ:1033553122     1.测试环境.............................................. ...

  9. vue codemirror sql编辑器功能 可自定义提醒(关键字,库名,表名),高亮,主题

    工作中再一次需要开发sql编辑器,优化上篇文章内容 https://www.cnblogs.com/Lu-Lu/p/14388888.html 本次功能是tab页打开多个sql编辑器,效果图: 安装: ...

  10. OkHttp 快速掌握

    OkHttp是一个高效的HTTP库,它提供了许多优化和便利功能,使得我们能够更高效地使用HTTP协议进行通信. 一些主要特性包括: 支持SPDY协议:SPDY协议是Google开发的一种HTTP传输协 ...