You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

7.3 KiB

dpworldapp 호환성 명세서

Web Configurator 교체 시 dpworldapp과의 호환성을 보장하기 위한 계약(Contract) 문서.


1. 개요

dpworldapp(/usr/bin/dpworldapp)은 IoT 장비의 메인 애플리케이션으로, Web Configurator가 저장한 설정을 SQLite DB에서 직접 읽어 사용합니다.

핵심 원칙: dpworldapp은 일체 변경하지 않으므로, 새 Web Configurator는 기존 Java 앱이 생성하는 것과 비트 단위까지 호환되는 데이터를 생성해야 합니다.


2. 공유 인터페이스

2.1 SQLite DB 파일 경로

~/db/dynamic_data.db    (= /home/root/db/dynamic_data.db)
  • 절대 변경 불가: dpworldapp이 이 경로를 하드코딩하고 있을 가능성 높음
  • busy_timeout: 5000ms (동시 접근 시 잠금 대기)

2.2 board_config 테이블

-- 테이블 구조 (변경 불가)
CREATE TABLE board_config (
    key   TEXT PRIMARY KEY NOT NULL,
    value TEXT NOT NULL
);
key 값 역할 쓰기 주체 읽기 주체
device_config 디바이스 네트워크/하드웨어 설정 Web Configurator dpworldapp
protocol_config 프로토콜/매핑 설정 Web Configurator dpworldapp
log_config 로그 관리(auto-compress/cleanup 등) — Python 전용 Web Configurator (dpworldapp 미사용)
net_config Network Apply Engine watchdog 설정(kill-switch 등) — Python 전용 Web Configurator (dpworldapp 미사용)
ap_config Wi-Fi AP(ap0) 설정 — Python 전용 Web Configurator (dpworldapp 미사용)

[!NOTE] board_config 의 전체 허용 키는 위 5개다(db_manager.py:43 ALLOWED_KEYS). dpworldapp 이 읽는 것은 device_config / protocol_config 둘 뿐이고, log_config / net_config / ap_config 는 Web Configurator 자체 기능을 위한 Python 전용 키로 dpworldapp 은 읽지 않는다(별도 key ownership 정책 — dpworldapp 공유 키를 오염시키지 않기 위함). 한편 네트워크 적용 엔진이 dpworldapp 과 byte-exact 호환을 위해 생성하는 network_config.jsonboard_config 행이 아니라 /home/root/network/파일이다(혼동 주의).

2.3 event_history 테이블

CREATE TABLE event_history (
    id   INTEGER PRIMARY KEY AUTOINCREMENT,
    data TEXT NOT NULL
);
역할 쓰기 주체 읽기 주체
이벤트/경고 이력 dpworldapp (선택적 조회 가능)

[!CAUTION] Web Configurator는 event_history절대 쓰지 않습니다. dpworldapp 전용.


3. device_config JSON 스키마

dpworldapp이 읽는 JSON의 정확한 필드명과 타입:

{
  "wifi_static": "on",
  "wifi_ip": "10.227.231.38",
  "wifi_netmask": "255.255.255.0",
  "wifi_gateway": "10.227.231.1",
  "wifi_dns1": "10.226.4.4",
  "wifi_dns2": "10.226.4.5",
  "wifi_country_code": "KR",
  "eth_ip": "192.168.55.44",
  "eth_netmask": "255.255.255.0",
  "eth_gateway": "192.168.55.1",
  "protocol_server_ip": "10.226.22.48",
  "protocol_server_port": 20101,
  "update_server_ip": "10.226.22.244",
  "update_server_port": 9999,
  "rtcm_server_ip": "10.226.22.48",
  "rtcm_server_port": 20104,
  "opc_ua_server_ip": "192.168.55.11",
  "opc_ua_server_port": 53530,
  "modbus_server_ip": "192.168.55.100",
  "modbus_server_port": 502,
  "lte_server_ip": "...",
  "lte_server_port": 0,
  "can_bus_type": "extended",
  "can_baudrate": 1000,
  "rs485_mode": "half",
  "rs485_baudrate": 9600,
  "rs485_parity": "...",
  "lte_ip": "...",
  "lte_netmask": "...",
  "lte_gateway": "...",
  "log_save": "on",
  "log_max_size": 100,
  "log_max_duration": 1,
  "WIFI_SSID": [
    {
      "wifi_ssid": "KROF01-IT-DEV-Y5",
      "wifi_passwd": "password",
      "wifi_security": "wpa/wpa2"
    }
  ]
}

타입 규칙

필드 패턴 타입 예시
*_port Integer (JSON number) 20101
*_baudrate Integer 9600
log_max_size, log_max_duration Integer 100
wifi_static, log_save String ("on" / "off") "on"
나머지 String "192.168.55.44"

[!NOTE] dpworldapp-owned 필드 (Web Configurator 미작성): imu_remap_x / imu_remap_x_sign / imu_remap_y / imu_remap_y_sign / imu_remap_z / imu_remap_z_sign 6개 IMU remap 필드는 v1.4.5 부터 Web Configurator 가 더 이상 작성하지 않는다(UI 에서 제거됨, src 에 참조 0). dpworldapp 이 자체적으로 소유·관리하는 값이므로 위 스키마 예시에서 의도적으로 제외했다. Web Configurator 의 partial-merge POST 는 기존 행을 통째로 덮어쓰지 않으므로 (/setting/device 부분 병합), dpworldapp 이 기록한 이 키들은 보존된다.


4. protocol_config JSON 스키마

{
  "dev_type": "RTLS",
  "equipment": "ITV",
  "equipment_id": "01",
  "MEID": "7000",
  "protocol": "OPC_UA",
  "version": "v1.0",
  "can_input": "on",
  "speed_data": "CAN",
  "dr_on": "on",
  "heading_on": "on",
  "heading_imu_on": "on",
  "fix_mode_on": "on",
  "analog_input_level": "6",
  "ai0": "0", "ai1": "1", "ai2": "0", "ai3": "0",
  "di0": "0", "di1": "0", "di2": "0", "di3": "0",
  "two_byte_order": "big",
  "four_byte_order": "big",
  "CAN": [
    {
      "field": "CAN1",
      "id": "0x18FEFC28",
      "shift": 0,
      "mask": "0xffff",
      "expr": "x*0.05+10.0",
      "odt": "integer",
      "dv": "-9"
    }
  ],
  "OPC_UA": [
    {
      "field": "TMP1",
      "ns": "3",
      "addr": "1001",
      "shift": 0,
      "expr": "x*10.0",
      "odt": "float64",
      "dv": "-9"
    }
  ],
  "MODBUS": [
    {
      "field": "TEMP",
      "addr": "100",
      "idt": "integer",
      "odt": "float64",
      "dv": "-9",
      "shift": 0,
      "expr": "x*0.1",
      "mask": "0xffff"
    }
  ]
}

프로토콜별 조건부 필드 존재 규칙

조건 결과
protocol == "OPC_UA" OPC_UA[] 포함, MODBUS 제외 (null → JSON에서 생략)
protocol == "MODBUS" MODBUS[] 포함, OPC_UA 제외
protocol == "NONE" 둘 다 제외
can_input == "on" CAN[] 포함
can_input == "off" CAN 제외

5. 호환성 체크리스트

배포 전 필수 확인

  • ~/db/dynamic_data.db 경로 동일
  • board_config 테이블 구조 동일
  • key 값 문자열 동일 ("device_config", "protocol_config")
  • JSON 필드명 snake_case 동일
  • Integer 필드가 JSON number 타입으로 저장
  • null/None 필드가 JSON에서 제외됨
  • MEID가 항상 문자열로 저장
  • 비활성 프로토콜 매핑이 JSON에서 제외됨
  • busy_timeout=5000 설정됨
  • event_history 테이블에 쓰기 없음

검증 방법

# 1. 기존 Java 앱으로 설정 저장 후 DB 덤프
sqlite3 ~/db/dynamic_data.db "SELECT value FROM board_config WHERE key='device_config'" > java_device.json

# 2. 새 Python 앱으로 동일 설정 저장 후 DB 덤프
sqlite3 ~/db/dynamic_data.db "SELECT value FROM board_config WHERE key='device_config'" > python_device.json

# 3. JSON 비교 (필드 순서 무시)
python3 -c "
import json
a = json.loads(open('java_device.json').read())
b = json.loads(open('python_device.json').read())
print('MATCH' if a == b else 'MISMATCH')
print('Diff keys:', set(a.keys()) ^ set(b.keys()))
"