LUMOS 프로젝트에서 가장 까다로웠던 부분 중 하나는 SmartThings의 기기 제어 명령 구조였음.
같은 기기 타입이라도 어떤 건 switchLevel, 어떤 건 fanSpeed, 또 어떤 건 아예 구조가 다름.
그래서 기기 상태를 SmartThings 명령(JSON)으로 자동 변환해주는 파서를 따로 만들었음.
"어떤 데이터를 내가 원하는 형식으로 바꿔주는 변환기" 정도로 보면 됨.
예를 들어,
SmartThings에 기기 상태를 보내려면 이런 JSON 명령어가 필요함:
{
"component": "main",
"capability": "switchLevel",
"command": "setLevel",
"arguments": [70]
}
하지만 사용자가 앱에서 설정하는 건 이런 구조임:
LightState(isOn = true, brightness = 70)
→ 문제는 이 두 구조가 다르다는 점.
→ 매번 일일이 capability, command, arguments를 다룰 순 없었음.
그래서 상태를 → JSON 명령어로 바꾸는 전용 파서 클래스를 기기별로 따로 만든 것.
LightState(isOn = true, brightness = 70)
[
{
"capability": "switch",
"command": "on"
},
{
"capability": "switchLevel",
"command": "setLevel",
"arguments": [70]
}
]
이걸 자동으로 변환해주는 클래스가 바로 LightCommandParser 같은 거.
interface CommandParser {
fun parse(state: Any): List<Command>
}
class LightCommandParser : CommandParser {
override fun parse(state: Any): List<Command> {
val lightState = state as LightState
return buildList {
if (lightState.isOn) add(Command("switch", "on"))
add(Command("switchLevel", "setLevel", listOf(lightState.brightness)))
}
}
}
val parser = LightCommandParser()
val commands = parser.parse(brightness = 70, isOn = true)
val json = gson.toJson(commands)
| 이유 | 설명 |
|---|---|
| 재사용성 | 기기별로 로직 분리하니까 유지보수 용이 |
| 확장성 | 새로운 기기 추가할 때 파서만 만들면 됨 |
| 안정성 | 상태 → 명령 변환 과정에서의 예외 케이스에 유연하게 대응 가능 |
사용자 입력 (예: 밝기 70, 전원 ON)
↓
기기별 파서 클래스에서 Command 리스트로 가공
↓
gson.toJson(commands)로 JSON 문자열 변환
↓
SmartThings API에 전송
기기마다 명령 구조(capability/command)가 다르니까
JSON을 바로 만들면 실수하기 쉽고, 구조가 복잡해짐
그래서 기기별로 명령 객체(Command)를 만들어두고 → 나중에 통일된 방식으로 JSON 변환하는 것!
SmartThings의 명령 구조는 기기마다 제각각이라,
"파서"라는 중간 추상화를 도입해서 코드 구조를 깔끔하게 유지할 수 있었음.
LUMOS에서 LightCommandParser, AirPurifierCommandParser, SpeakerCommandParser처럼
기기별로 파서를 분리해 관리하면서 제어 명령을 안전하고 일관되게 생성할 수 있었던 게 큰 성과 중 하나였음.