メインコンテンツまでスキップ

7. Assetサービス

client.asset() でアクセスします。PlantPulse資産モデルの核心である 企業 > サイト > 区域 > ライン > 設備 の5層ツリーを管理します。

ID規則: 区域 AREA_ · ライン LINE_ · 設備 EQUIPMENT_ (既存の ASSET_ も有効)。asset_id を空にした場合、Platformが発行します。ツリーの層を決定するのはIDではなく asset_type です。詳細は ドメインID規則 を参照してください。

7.1 メソッド一覧​

メソッド戻り値の型HTTPエンドポイント
create(AssetRequestV5)AssetResponseV5 または nullPOST/api/v5/asset
update(asset_id, AssetRequestV5)AssetResponseV5 または nullPUT/api/v5/asset/{id}
delete(asset_id)booleanDELETE/api/v5/asset/{id}
get(asset_id)AssetResponseV5 または nullGET/api/v5/asset/{id}
list()List<AssetResponseV5>GET/api/v5/asset
exists(asset_id)booleanGET/api/v5/asset/{id}/exists
getByExternal(system, external_id)AssetResponseV5 또는 nullGET/api/v5/asset/by-external/{system}/{external_id}
patchProperties(asset_id, 요청)AssetResponseV5 또는 nullPATCH/api/v5/asset/{id}/properties

Assetサービスは簡素化されたCRUDに特化しています。ツリー階層の照会は Pathサービス またはクライアント側でのフィルタリング (list() 後に asset_type フィルタ) を使用してください。

7.2 Asset Type 値​

asset_type意味
E企業 (Enterprise) — インストールにつき1つ、ツリーのルート
Sサイト (Site)
A区域 (Area)
Lライン (Line)
M設備 (Equipment, Machine)

POST /api/v5/asset で作成できるのは A · L · M です。サイトは Siteサービス で作成します。 GET /api/v5/asset は asset_type を指定しない場合は区域・ライン・設備を返し、asset_type=E や S を指定した場合はその層を返します。 E · S を設備としてカウントしないでください。 層はID接頭辞ではなく、この値で判断します。

7.3 AssetRequestV5 / AssetResponseV5​

フィールド型説明
asset_idString資産ID (PK)。空にした場合は発行
asset_nameString表示名
parent_asset_idString親資産ID — 直上の層
asset_orderString兄弟間のソート順
asset_typeStringA/L/M (応答には E·S も)。作成後は変更不可
asset_class_codeString設備分類コード (CNC, INJECTIONなど)。その層の分類である必要があり、そうでない場合は 422
site_idString所属サイト
descriptionString説明 (必須)
operational_status_codeString(応答) 運転状態
external_system / external_idString(応答) 他のシステムがこのノードを呼ぶ番号
insert_date / update_dateString(応答専用) 時刻

単件照会はその層の固有属性まで含み、一覧は共通項目 (operational_status_code · external_system · external_id) のみを返します。

固有属性 — /api/v5/asset/{id}/properties​

層ごとに固有の属性があります。GET で読み取り、PATCH (または PUT) で修正します。送信したキーのみが適用され、null は削除となり、送信しなかったキーは維持されます。

層キー
企業を除く共通operational_status_code, external_system + external_id (両方あるか、両方ないか)
サイト Stimezone, country, site_code, address, lat, lng
区域 Aarea_function_code(PRODUCTION · STORAGE · UTILITY), responsible_employee_id
ライン Lline_kind_code(PRODUCTION_LINE · PROCESS_CELL · PRODUCTION_UNIT), design_rate(時間あたり, 0超) + design_rate_unit_of_measure(UN/ECE Rec 20, 両方あるか、両方ないか), responsible_employee_id
設備 Mmanufacturer, model, serial_number, installed_date, commissioned_date(設置日以降), warranty_end_date(yyyy-MM-dd), criticality_code(A · B · C), functional_location(サイト内で一意)
応答意味
422 asset.invalid.<key>その層にないキー、未知のコード、ペアの不足、日付順序違反
422 asset.invalid.asset_type層を変更しようとした — 層は変更されません
409 asset.duplicate.external_id他のノードが同じ外部番号を使用している
409 asset.duplicate.functional_location同じサイトの別の設備が同じ機能位置を使用している

応答の effective_responsible_employee_id は実際の担当者です。自身の項目が空の場合は、最も近い上位 (ライン → 区域) の担当を継承し、effective_responsible_from_asset_id でどこから継承したかを示します。

GET /api/v5/asset/{id} 応答の qr_payload は QRラベル に印刷するアドレスです。この呼び出しは トークンを生成しません。コンソールでラベルを一度開き、トークンが生成された設備のみが埋められ、まだ存在しないかコンソールアドレスが空の場合は "" となります。

外部番号で検索​

GET /api/v5/asset/by-external/MAXIMO/BEDFORD%2F11430
GET /api/v5/asset/by-external?system=MAXIMO&external_id=BEDFORD/11430

すべての層から検索します。存在しない場合は 404 asset.not_found 、システムと番号のいずれか一方のみが指定された場合は 422 となります。

7.4 使用例​

区域 → ライン → 設備 ツリーの作成​

import plantpulse.api.v5.dto.request.AssetRequestV5;

// 1) Area
AssetRequestV5 area = new AssetRequestV5();
area.setSite_id("SITE_DJ");
area.setParent_asset_id("SITE_DJ");
area.setAsset_name("조립구역");
area.setAsset_type("A");
client.asset().create(area);

// asset_id 를 비워 두면 플랫폼이 발급합니다 — 응답에서 AREA_000001 을 받습니다

// 2) Line
AssetRequestV5 line = new AssetRequestV5();
line.setSite_id("SITE_DJ");
line.setParent_asset_id("AREA_000001");
line.setAsset_name("1번 조립 라인");
line.setAsset_type("L");
client.asset().create(line);

// 3) Equipment (CNC 머신)
AssetRequestV5 cnc = new AssetRequestV5();
cnc.setSite_id("SITE_DJ");
cnc.setParent_asset_id("LINE_000001");
cnc.setAsset_name("CNC #1");
cnc.setAsset_type("M");
cnc.setAsset_class_code("CNC");
cnc.setDescription("DMG MORI NLX-2500");
client.asset().create(cnc);

単件照会​

import plantpulse.api.v5.dto.response.AssetResponseV5;

AssetResponseV5 cnc = client.asset().get("EQUIPMENT_000001");
if (cnc != null) {
System.out.println(cnc.getAsset_name() + " (" + cnc.getAsset_type() + ")");
System.out.println("부모: " + cnc.getParent_asset_id());
}

全件一覧 + タイプ別フィルタリング​

サーバー側フィルタは GET /api/v5/asset?asset_type=M · operational_status_code= · external_system= です。Javaクライアントの list() はフィルタを受け取らないため、受信後にフィルタリングを行います。

import java.util.List;
import java.util.stream.Collectors;

List<AssetResponseV5> all = client.asset().list();

// Equipment만
List<AssetResponseV5> equipments = all.stream()
.filter(a -> "M".equals(a.getAsset_type()))
.collect(Collectors.toList());

// 대전공장의 Line만
List<AssetResponseV5> djLines = all.stream()
.filter(a -> "SITE_DJ".equals(a.getSite_id()))
.filter(a -> "L".equals(a.getAsset_type()))
.collect(Collectors.toList());

ツリー再構成 (クライアント側)​

import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;

// asset_id 인덱스
Map<String, AssetResponseV5> byId = new HashMap<>();
for (AssetResponseV5 a : client.asset().list()) {
byId.put(a.getAsset_id(), a);
}

// 부모-자식 매핑
Map<String, List<AssetResponseV5>> children = new HashMap<>();
for (AssetResponseV5 a : byId.values()) {
children
.computeIfAbsent(a.getParent_asset_id(), k -> new ArrayList<>())
.add(a);
}

// 사이트(SITE_DJ) 산하 트리 출력
printTree(children, "SITE_DJ", 0);

static void printTree(Map<String, List<AssetResponseV5>> children, String id, int depth) {
List<AssetResponseV5> kids = children.getOrDefault(id, List.of());
for (AssetResponseV5 c : kids) {
System.out.println(" ".repeat(depth) + c.getAsset_id() + " — " + c.getAsset_name());
printTree(children, c.getAsset_id(), depth + 1);
}
}

資産修正​

AssetRequestV5 update = new AssetRequestV5();
update.setSite_id("SITE_DJ");
update.setParent_asset_id("LINE_000001");
update.setAsset_id("EQUIPMENT_000001");
update.setAsset_name("CNC #1 (보수 후)");
update.setAsset_type("M");
update.setAsset_class_code("CNC");
update.setDescription("2026-05-10 베어링 교체 완료");

client.asset().update("EQUIPMENT_000001", update);

資産削除​

⚠️ 資産を削除する前に、その資産に接続されているすべてのタグ・下位資産を先に削除する必要があります。

boolean ok = client.asset().delete("EQUIPMENT_OLD");

7.5 活用シナリオ​

シナリオ — サイトの設備一覧と各タグ数​

String siteId = "SITE_DJ";

List<AssetResponseV5> equipments = client.asset().list().stream()
.filter(a -> siteId.equals(a.getSite_id()))
.filter(a -> "M".equals(a.getAsset_type()))
.collect(Collectors.toList());

for (AssetResponseV5 eq : equipments) {
long tagCount = client.tag().countByAsset(eq.getAsset_id());
System.out.printf("%s — Tag %d개%n", eq.getAsset_name(), tagCount);
}

シナリオ — ライン単位のOEEダッシュボードデータ収集​

// 1) Line 목록
List<AssetResponseV5> lines = client.asset().list().stream()
.filter(a -> "L".equals(a.getAsset_type()))
.filter(a -> "SITE_DJ".equals(a.getSite_id()))
.collect(Collectors.toList());

// 2) 각 Line 산하 Equipment 조회 → 자산 경로 → 작업지시 → KPI 집계
for (AssetResponseV5 line : lines) {
List<AssetResponseV5> machines = client.asset().list().stream()
.filter(a -> line.getAsset_id().equals(a.getParent_asset_id()))
.collect(Collectors.toList());

for (AssetResponseV5 m : machines) {
long now = System.currentTimeMillis();
// 현재 작업지시는 Order 서비스로 조회
// ...
}
}

次のステップ​