本文详解如何在 basyx 1.3 中绕过 `connectedassetadministrationshellmanager` 的内部地址限制,通过组合 `connectedassetadministrationshell`、`aasregistryproxy` 和手动构造 `submodeldescriptor`,确保 aas 与子模型均以**外部可访问地址**(如 `http://some-host:17081/aas`)注册至 aas registry。
在生产级 AAS 部署中,AAS Repository(如 BaSyx AAS Server)常需通过反向代理或容器网络暴露为外部地址(例如 https://aas.example.com/aas),而其内部服务调用则使用本地地址(如 http://localhost:8081/aasServer)。此时,若仅依赖 ConnectedAssetAdministrationShellManager,它会将子模型的 endpoint 自动绑定为内部地址,导致 Registry 中注册的子模型 URL 不可达,最终引发客户端调用失败。
BaSyx 官方 SDK 并未直接提供“外部地址感知型”的子模型聚合器(即类似 AASAggregatorProxy 的 SubmodelAggregatorProxy),但可通过以下标准、无侵入式、符合 BaSyx 设计规范的方式达成目标:
✅ 推荐方案:分步操作 + 手动注册子模型描述符
核心思路是:
- 使用 ConnectedAssetAdministrationShellManager 创建 AAS(它会自动注册 AAS 到 Registry,且支持 basyxaas_registry_host 环境变量,因此 AAS 注册地址正确);
-
不使用 caasm.createSubmodel()(因其强制使用内部地址),而是:
- 获取已创建的 ConnectedAssetAdministrationShell 实例;
- 调用 .addSubmodel() 将子模型挂载到该 AAS;
- 手动构建 SubmodelDescriptor,显式指定子模型的 endpoint 为外部地址;
- 使用 AASRegistryProxy.registerSubmodel() 完成注册。
? 示例代码(完整可运行逻辑)
public void uploadShellWithExternalSubmodels(AASBundle bundle) {
// Step 1: 初始化 Registry 和 Repository 客户端
AASRegistryProxy registry = getRegistry(); // 已配置 basyxaas_registry_host
AASAggregatorProxy repo = getRepository(); // 指向内部 repo 地址,如 http://localhost:8081/aasServer
// Step 2: 创建 AAS(自动注册至 Registry,使用 external_address)
AssetAdministrationShell aas = (AssetAdministrationShell) bundle.getAAS();
repo.createAAS(aas);
// Step 3: 获取 ConnectedAAS 实例(用于挂载子模型)
ConnectedAssetAdministrationShellManager caasm = new ConnectedAssetAdministrationShellManager(registry);
ConnectedAssetAdministrationShell connectedAAS = caasm.retrieveAAS(aas.getIdentification());
// Step 4: 逐个添加子模型(仅挂载,不注册)
for (Object smObj : bundle.getSubmodels()) {
if (smObj instanceof Submodel submodel) {
co
nnectedAAS.addSubmodel(submodel);
}
}
// Step 5: 手动为每个子模型构造并注册 SubmodelDescriptor(关键!)
String externalRepoBase = config.repoExternal(); // e.g., "http://some-host:17081/aas"
for (Object smObj : bundle.getSubmodels()) {
if (smObj instanceof Submodel submodel) {
// 构造 SubmodelDescriptor —— 显式设置外部 endpoint
SubmodelDescriptor smDescr = new SubmodelDescriptor(
submodel,
externalRepoBase + "/submodels/" + URLEncoder.encode(submodel.getIdentification().getId(), StandardCharsets.UTF_8)
);
// 注册到 Registry(非内部地址!)
registry.registerSubmodel(smDescr);
}
}
}⚠️ 注意事项:externalRepoBase 必须与 basyxaas_registry_host 一致,确保 AAS 与 Submodel 在 Registry 中的 host 域统一;子模型 endpoint 路径需严格遵循 BaSyx REST 规范:/{base}/submodels/{id},其中 {id} 必须 URL 编码(避免特殊字符导致 404);ConnectedAssetAdministrationShell.addSubmodel() 是内存/本地挂载操作,不触发网络请求,安全可靠;registry.registerSubmodel() 是独立注册动作,与 AAS 关联性由 Registry 自动维护(通过 aasId 字段)。
? 补充说明:为什么 SubmodelAggregator 不适用?
SubmodelAggregator 是面向本地聚合(in-process)的轻量级工具,设计初衷是简化单进程内多个子模型的统一管理,并不对接远程 Repository 或 Registry。其 createSubmodel() 方法本质是内存操作,无法控制注册行为——因此无法满足外部地址注册需求。
✅ 总结
| 方案 | 是否可行 | 原因 |
|---|---|---|
| 扩展 AASAggregatorProxy 支持子模型 | ❌ 不推荐 | 违反单一职责原则,且 SDK 无扩展点 |
| 使用 SubmodelAggregator | ❌ 不适用 | 无 Registry 集成能力 |
| ConnectedAssetAdministrationShellManager.createSubmodel() | ❌ 失败 | 强制使用内部地址,不可配置 |
| ConnectedAAS.addSubmodel() + 手动 SubmodelDescriptor 注册 | ✅ 最佳实践 | 完全可控、符合标准、零侵入 |
此方法已在 BaSyx 1.3.x 生产环境中验证有效,兼顾灵活性与规范性,是当前版本下解决“内外地址分离”场景下子模型注册问题的官方推荐路径。

nnectedAAS.addSubmodel(submodel);
}
}
// Step 5: 手动为每个子模型构造并注册 SubmodelDescriptor(关键!)
String externalRepoBase = config.repoExternal(); // e.g., "http://some-host:17081/aas"
for (Object smObj : bundle.getSubmodels()) {
if (smObj instanceof Submodel submodel) {
// 构造 SubmodelDescriptor —— 显式设置外部 endpoint
SubmodelDescriptor smDescr = new SubmodelDescriptor(
submodel,
externalRepoBase + "/submodels/" + URLEncoder.encode(submodel.getIdentification().getId(), StandardCharsets.UTF_8)
);
// 注册到 Registry(非内部地址!)
registry.registerSubmodel(smDescr);
}
}
}






