{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://dpworld/schemas/protocol_v2.json", "title": "Protocol configuration (schema v2 — flat 정규화)", "description": "Web Configurator ↔ dpworldapp 합의 schema. 옵션 B (Medium): boolean/integer 정규화 + naming 일관 (MEID→meid) + enum 명시.", "type": "object", "required": ["schema_version", "dev_type", "protocol"], "additionalProperties": false, "properties": { "schema_version": { "type": "integer", "const": 2, "description": "본 schema 버전." }, "dev_type": { "type": "string", "enum": ["RTLS"], "default": "RTLS", "description": "디바이스 종류. 향후 enum 확장 가능." }, "version": { "type": "string", "pattern": "^v\\d+\\.\\d+(\\.\\d+)?$", "default": "v1.0", "description": "Configuration 버전 string (free-form, schema_version 과 별개)." }, "dr_on": { "type": "boolean", "default": true, "description": "Dead Reckoning 활성. v1 의 \"on\"/\"off\" → v2 의 true/false." }, "odo_on": { "type": "boolean", "default": false, "description": "Odometer 활성." }, "heading_on": { "type": "boolean", "default": true, "description": "Heading 계산 활성." }, "heading_imu_on": { "type": "boolean", "default": false, "description": "IMU 기반 heading 활성." }, "fix_mode_on": { "type": "boolean", "default": true, "description": "Fix mode 활성." }, "can_input": { "type": "boolean", "default": false, "description": "CAN 입력 활성." }, "speed_data": { "type": "string", "enum": ["CAN", "HW", "OPC-UA", "MODBUS"], "description": "속도 데이터 source. odo_on=true 시 사용 가능 source 결정." }, "equipment": { "type": "string", "enum": ["ITV", "FL", "CR"], "description": "장비 종류. ★ 협의 항목: dpworldapp 팀 enum 전체 list 확정 필요 (spec §8 Q1)." }, "equipment_id": { "type": "string", "pattern": "^\\d{2}$", "description": "장비 ID (zero-padded 2-digit)." }, "meid": { "type": "integer", "minimum": 0, "description": "MEID. v1 의 'MEID' upper-case (int) → v2 의 meid snake_case (int). default file 의 int 형식이 정답." }, "protocol": { "type": "string", "enum": ["OPC-UA", "MODBUS", "CAN-BUS", "NONE"], "description": "활성 protocol. 'NONE' 시 OPC_UA/CAN/MODBUS array 보존 (data loss 방지)." }, "two_byte_order": { "type": "string", "enum": ["big", "little"], "default": "big", "description": "2-byte field 의 byte order." }, "four_byte_order": { "type": "string", "enum": ["big", "little", "bigSwap", "littleSwap"], "default": "big", "description": "4-byte field 의 byte order." }, "analog_input_level": { "type": "string", "enum": ["2", "4", "6"], "description": "Analog input voltage level. string 으로 유지 — device 계약 정합." }, "ai0": {"type": "boolean", "default": false, "description": "Analog Input 0 활성. v1 의 \"1\"/\"0\" → v2 의 true/false."}, "ai1": {"type": "boolean", "default": false, "description": "Analog Input 1 활성."}, "ai2": {"type": "boolean", "default": false, "description": "Analog Input 2 활성."}, "ai3": {"type": "boolean", "default": false, "description": "Analog Input 3 활성."}, "di0": {"type": "boolean", "default": false, "description": "Digital Input 0 활성."}, "di1": {"type": "boolean", "default": false, "description": "Digital Input 1 활성."}, "di2": {"type": "boolean", "default": false, "description": "Digital Input 2 활성."}, "di3": {"type": "boolean", "default": false, "description": "Digital Input 3 활성."}, "odo_speed": { "$ref": "#/$defs/OdoField", "description": "Odometer speed 필드 정의." }, "odo_direction": { "$ref": "#/$defs/OdoField", "description": "Odometer direction 필드 정의." }, "OPC_UA": { "type": "array", "description": "OPC-UA register mapping 목록. ★ 협의: array name 도 lowercase 통일 'opc_ua' 가능 (옵션 C 부분).", "items": {"$ref": "#/$defs/OpcUaRegister"} }, "CAN": { "type": "array", "description": "CAN-BUS register mapping 목록.", "items": {"$ref": "#/$defs/CanRegister"} }, "MODBUS": { "type": "array", "description": "Modbus register mapping 목록.", "items": {"$ref": "#/$defs/ModbusRegister"} } }, "$defs": { "OdoField": { "type": "object", "required": ["source"], "additionalProperties": false, "properties": { "source": { "type": "string", "enum": ["CAN", "HW", "OPC-UA", "MODBUS"], "description": "Odometer 데이터 source." }, "id": { "type": "string", "pattern": "^0x[0-9a-fA-F]+$", "description": "CAN ID (hex string, source='CAN' 시 사용). 가독성을 위해 hex string 유지." }, "shift": { "type": "integer", "minimum": 0, "maximum": 63, "description": "비트 shift. v1 의 string \"8\" → v2 의 integer 8." }, "mask": { "type": "string", "pattern": "^0x[0-9a-fA-F]+$", "description": "비트 mask (hex string). 가독성을 위해 hex string 유지." }, "expr": { "type": "string", "maxLength": 256, "description": "변환 expression DSL (`x*0.05+10.0`). forbidden chars 정책: v1.4.8 Stage 4 참조." } } }, "OpcUaRegister": { "type": "object", "required": ["field", "ns", "addr", "odt"], "additionalProperties": false, "properties": { "field": {"type": "string", "description": "Logical field 이름."}, "ns": {"type": "integer", "minimum": 0, "description": "OPC-UA namespace. v1 의 string \"3\" → v2 의 integer 3."}, "addr": {"type": "integer", "minimum": 0, "description": "OPC-UA node address. v1 의 string \"1001\" → v2 의 integer."}, "odt": { "type": "string", "enum": ["integer", "float", "float64", "boolean", "string"], "description": "Output data type. ★ float64/float/string 은 v1.5.5+ 시점 dpworldapp 처리에 결함 — handoff doc 참조." }, "dv": {"type": "integer", "description": "Default value. v1 의 string → v2 의 integer."}, "expr": {"type": "string", "maxLength": 256, "description": "변환 expression."} } }, "CanRegister": { "type": "object", "required": ["field", "id", "shift", "mask", "odt"], "additionalProperties": false, "properties": { "field": {"type": "string"}, "id": {"type": "string", "pattern": "^0x[0-9a-fA-F]+$", "description": "CAN ID (hex string)."}, "shift": {"type": "integer", "minimum": 0, "maximum": 63}, "mask": {"type": "string", "pattern": "^0x[0-9a-fA-F]+$"}, "odt": {"type": "string", "enum": ["integer", "float", "float64", "boolean", "string"]}, "dv": {"type": "integer"}, "expr": {"type": "string", "maxLength": 256} } }, "ModbusRegister": { "type": "object", "required": ["field", "addr", "odt"], "additionalProperties": false, "properties": { "field": {"type": "string"}, "addr": {"type": "integer", "minimum": 0, "description": "Modbus register address."}, "odt": {"type": "string", "enum": ["integer", "float", "float64", "boolean", "string"]}, "dv": {"type": "integer"}, "expr": {"type": "string", "maxLength": 256} } } } }