본문 바로가기
스마트폰 (Mobile)

Nintendo Switch Online 서비스 게임정보 및 친구상태 활동센서 구성

by 날으는물고기 2024. 10. 14.

Nintendo Switch Online 서비스 게임정보 및 친구상태 활동센서 구성

Home Assistant에서 Nintendo Switch App Sensor를 설정하여 Ring Fit Adventure 활동 시간을 추적하는 방법입니다. 홈브루(homebrew) 활성화된 Nintendo Switch와 Home Assistant를 갖추고 있으며, Python과 YAML 구성에 대한 기본 지식이 필요합니다.

Step 1: Nintendo Switch에 SwitchPresence-Rewritten 설치 및 설정

  1. 홈브루 활성화: Nintendo Switch에서 홈브루를 활성화합니다.
  2. SwitchPresence-Rewritten 설치
    • SwitchPresence-Rewritten sysmodule을 다운로드합니다.
    • SD 카드에 sysmodule 파일을 복사합니다.
    • 홈브루 매니저를 사용하여 sysmodule이 활성화되었는지 확인합니다.

Step 2: Home Assistant용 Python 스크립트 생성

Home Assistant에서 Nintendo Switch에 연결하고 현재 게임 제목을 가져오는 Python 스크립트를 만듭니다.

  1. 스크립트 생성
    • 다음 스크립트를 switch_presence.py로 저장하고 Home Assistant 구성 디렉토리에 위치시킵니다.
      import socket
      import struct
      import json
      
      TCP_PORT = 0xCAFE
      SWITCH_IP = '192.168.1.100'  # 여기서 Switch의 IP 주소로 변경하세요
      PACKETMAGIC = 0xFFAADD23
      
      # 타이틀 패킷 정의
      class Title:
          def __init__(self, raw_data):
              unpacker = struct.Struct('2L612s')
              enc_data = unpacker.unpack(raw_data)
              self.magic = int(enc_data[0])
              if int(enc_data[1]) == 0:
                  self.pid = int(enc_data[1])
                  self.name = 'Home Menu'
              else:
                  self.pid = int(enc_data[1])
                  self.name = enc_data[2].decode('utf-8', 'ignore').split('\x00')[0]
      
      def main():
          switch_server_address = (SWITCH_IP, TCP_PORT)
          sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
          sock.settimeout(10)
          try:
              sock.connect(switch_server_address)
              data = sock.recv(628)
              title = Title(data)
              sensorJson = {
                  "state": "on",
                  "id": str(hex(title.pid)).replace("x",""),
                  "title": title.name
              }
              sensorString = json.dumps(sensorJson)
              print(sensorString)
          except:
              sensorJson = {
                  "state": "off",
                  "id": -1,
                  "title": "unknown"
              }
              sensorString = json.dumps(sensorJson)
              print(sensorString)
          finally:
              sock.close()
      
      if __name__ == '__main__':
          main()

Step 3: Home Assistant 설정

Home Assistant의 configuration.yaml 파일에 명령 줄 센서와 히스토리 통계 센서를 추가합니다.

  1. 명령 줄 센서
    command_line:
      - sensor:
          name: "Switch Presence Python"
          command: python3 /config/scripts/switch_presence.py
          json_attributes:
            - id
            - title
          value_template: '{{ value_json.state }}'
          scan_interval: 15
  2. 템플릿 센서
    sensor:
      - platform: template
        sensors:
          nintendo_switch_status_python:
            friendly_name: "Nintendo Switch Status Python"
            value_template: '{{ states("sensor.switch_presence_python") }}'
            entity_picture_template: '{{ "/local/nintendo_switch_thumbnails/" ~ state_attr("sensor.switch_presence_python","id") ~ ".jpg" }}'
            attribute_templates:
              media_content_type: music
              media_title: '{{ state_attr("sensor.switch_presence_python","title") }}'
  3. Ring Fit Adventure 활동 시간 추적을 위한 히스토리 통계 센서
    sensor:
      - platform: history_stats
        name: Ring Fit Duration
        entity_id: sensor.switch_presence_python
        state: "Ring Fit Adventure"
        type: time
        start: "{{ now().replace(hour=0, minute=0, second=0) }}"
        end: "{{ now() }}"

Step 4: 미디어 플레이어 설정

추가 기능을 위해 미디어 플레이어 엔티티를 설정할 수 있습니다.

media_player:
  - platform: universal
    name: Nintendo Switch Python
    children:
      - sensor.nintendo_switch_status_python

Step 5: 이미지 전송

게임에 대한 맞춤형 이미지를 사용하려면 Switch에서 Home Assistant로 이미지를 전송해야 합니다.

  1. SwitchPresence-Rewritten-Manager.nro를 사용하여 Switch에서 이미지를 덤프합니다.
  2. Switch의 SDMC://Images 폴더의 내용을 Home Assistant의 /config/www/nintendo_switch_thumbnails/ 디렉토리에 전송합니다.

이 단계를 따르면 Home Assistant에서 Ring Fit Adventure 활동을 추적하는 Nintendo Switch 센서를 설정할 수 있습니다. Switch IP가 정확하게 설정되어 있고 SwitchPresence-Rewritten sysmodule이 Switch에서 실행 중인지 확인하세요. 문제가 발생하면 Home Assistant의 로그를 확인하거나 Python 스크립트를 디버깅하여 연결 문제를 해결할 수 있습니다.

Nintendo Switch Online Integration for Home Assistant

이 커스텀 컴포넌트는 Home Assistant에서 Nintendo Switch Online 사용자의 상태를 가져와 그들이 온라인인지 여부와 어떤 게임을 플레이 중인지 표시합니다.

 

기능

이 컴포넌트는 nso-api 라이브러리를 기반으로 하며, Nintendo의 서버에 계정으로 연결하여 해당 계정의 친구 상태를 가져옵니다. 그러나 Nintendo Switch API의 제한으로 인해 자신의 상태는 가져올 수 없고, 친구의 상태만 가져올 수 있습니다. 따라서 이 컴포넌트를 사용하려면 보조 계정을 생성하고 상태를 확인하고자 하는 사용자를 친구로 추가해야 합니다.

 

설치

이 컴포넌트는 HACS를 통해 설치할 수 있습니다.

  1. Home Assistant 인스턴스를 열고 Home Assistant Community Store에서 저장소를 엽니다.
  2. 또는 수동으로 Home Assistant 구성 폴더에 다운로드할 수 있습니다.

설정

설치 후 다음 단계를 따라 설정합니다.

  1. Settings -> Devices & Services -> Add Integration으로 이동하고 "Nintendo Switch"를 검색합니다.
  2. 마법사는 로그인 계정 링크를 요청합니다.
  3. 지정된 URL로 이동하여 사용자 계정으로 로그인합니다. 그런 다음 "Select this person"을 오른쪽 클릭하고 해당 버튼의 링크를 복사합니다.
  4. 복사한 링크를 요청된 필드에 붙여넣습니다.

사용법

계정을 추가하면 계정에 있는 친구 수만큼 바이너리 센서가 생성되며, 친구가 게임을 플레이 중이라면 "game" 속성에 그들이 플레이 중인 게임 이름이 표시됩니다. 데이터는 30초마다 업데이트됩니다.

 

새로운 친구 추가

새로운 친구를 추가하면 통합을 다시 로드해야 합니다. 이는 통합 화면에서 직접 할 수 있거나 Home Assistant를 재시작하여 수행할 수 있습니다.

 

주의사항

주 계정에 영향을 미칠 수 있는 잠재적 위험을 줄이기 위해 보조 Nintendo 계정을 사용하는 것이 권장됩니다.

상세 구현 방법

1. Home Assistant 커스텀 컴포넌트 디렉토리 구조

config/
└── custom_components/
    └── nintendo_switch/
        ├── __init__.py
        ├── manifest.json
        ├── sensor.py
        └── nso_api.py

2. __init__.py

from homeassistant.helpers import discovery
import logging

DOMAIN = "nintendo_switch"
_LOGGER = logging.getLogger(__name__)

async def async_setup(hass, config):
    """Set up the Nintendo Switch integration."""
    hass.async_create_task(
        discovery.async_load_platform(hass, "sensor", DOMAIN, {}, config)
    )
    return True

3. manifest.json

{
  "domain": "nintendo_switch",
  "name": "Nintendo Switch",
  "documentation": "https://github.com/your-repo/nintendo_switch",
  "dependencies": [],
  "codeowners": ["@your_github_username"],
  "requirements": ["nso-api==1.0.0"]
}

4. sensor.py

import logging
import asyncio
from homeassistant.helpers.entity import Entity
from .nso_api import NintendoSwitchAPI

_LOGGER = logging.getLogger(__name__)

async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
    """Set up the Nintendo Switch sensor platform."""
    sensors = []
    api = NintendoSwitchAPI(config['username'], config['password'])
    friends = await api.get_friends()

    for friend in friends:
        sensors.append(NintendoSwitchSensor(friend))

    async_add_entities(sensors, True)

class NintendoSwitchSensor(Entity):
    """Representation of a Nintendo Switch sensor."""

    def __init__(self, friend):
        """Initialize the sensor."""
        self._state = None
        self._friend = friend
        self._name = f"NSW {friend['name']}"
        self._game = None

    @property
    def name(self):
        """Return the name of the sensor."""
        return self._name

    @property
    def state(self):
        """Return the state of the sensor."""
        return self._state

    @property
    def extra_state_attributes(self):
        """Return the state attributes."""
        return {"game": self._game}

    async def async_update(self):
        """Fetch new state data for the sensor."""
        status = await self._friend.get_status()
        self._state = status['online']
        self._game = status['game']

5. nso_api.py

import aiohttp

class NintendoSwitchAPI:
    def __init__(self, username, password):
        self.username = username
        self.password = password
        self.session = aiohttp.ClientSession()

    async def get_friends(self):
        # 로그인하고 친구 목록 가져오기
        async with self.session.post("https://example.com/api/login", data={"username": self.username, "password": self.password}) as response:
            data = await response.json()
            return data["friends"]

    async def close(self):
        await self.session.close()

configuration.yaml 파일에 다음을 추가하여 통합을 설정합니다.

nintendo_switch:
  username: "your_secondary_account_username"
  password: "your_secondary_account_password"

Home Assistant를 재시작한 후 Settings -> Devices & Services -> Add Integration에서 "Nintendo Switch"를 검색하여 통합을 추가합니다. 로그인 계정 링크를 입력하면 설정이 완료됩니다. 이제 Home Assistant에서 Nintendo Switch 친구의 온라인 상태와 그들이 플레이 중인 게임을 모니터링할 수 있습니다.

nso-api: A Python Library for Nintendo Switch Online Service

nso-api는 Nintendo Switch Online 서비스와 통신할 수 있도록 지원하는 Python 라이브러리입니다. 이 라이브러리를 사용하면 Nintendo의 서버에 연결하여 계정 및 게임 정보를 가져올 수 있습니다.

  • Nintendo Switch Online 서비스와의 통신 지원
  • 계정 상태 확인 및 게임 정보 요청
  • 세션 토큰 설정 및 게임 서비스 토큰 요청

 

nso-api는 pip를 통해 설치할 수 있습니다. 다음 명령어를 사용하여 설치하세요.

pip3 install nso-api

리포지토리에서 직접 설치할 수도 있습니다.

  1. GitHub에서 리포지토리를 클론합니다. git clone https://github.com/Jetsurf/nso-api.git
  2. 클론한 디렉토리에서 pip를 사용하여 설치합니다. pip3 install .

다음은 nso-api를 사용하여 세션 토큰을 설정하고, 게임 서비스 토큰을 요청하며, 기본 데이터를 가져오는 간단한 예제입니다.

 

example.py

import nso
import asyncio

async def main():
    # Nintendo 계정 자격 증명
    email = 'your_email@example.com'
    password = 'your_password'

    # Nintendo 계정 세션 초기화
    session = nso.NintendoSession(email, password)

    # 세션 토큰 요청
    await session.request_session_token()

    # 게임 서비스 토큰 요청
    game_token = await session.get_game_service_token()

    # 기본 데이터 가져오기
    friends = await session.get_friends()

    for friend in friends:
        print(f"{friend['name']} is {'online' if friend['online'] else 'offline'}")
        if friend['online']:
            print(f"Playing {friend['game']}")

# asyncio 이벤트 루프 실행
loop = asyncio.get_event_loop()
loop.run_until_complete(main())

NintendoSession 클래스

  • __init__(self, email, password): 이메일과 비밀번호로 세션 초기화.
  • request_session_token(self): 세션 토큰 요청.
  • get_game_service_token(self): 게임 서비스 토큰 요청.
  • get_friends(self): 친구 목록 가져오기.

사용 예시

  1. 세션 초기화session = nso.NintendoSession(email, password)
  2. 세션 토큰 요청await session.request_session_token()
  3. 게임 서비스 토큰 요청game_token = await session.get_game_service_token()
  4. 친구 목록 가져오기friends = await session.get_friends()

커스텀 컴포넌트와의 통합

위의 nso-api 예제를 활용하여 Home Assistant 커스텀 컴포넌트와 통합할 수 있습니다. 앞서 설명한 커스텀 컴포넌트 디렉토리 구조 및 sensor.py 파일에 nso-api를 활용하여 친구 상태를 가져오는 로직을 추가합니다.

 

sensor.py 예제

import logging
import asyncio
from homeassistant.helpers.entity import Entity
from .nso_api import NintendoSession

_LOGGER = logging.getLogger(__name__)

async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
    """Set up the Nintendo Switch sensor platform."""
    sensors = []
    email = config['email']
    password = config['password']
    session = NintendoSession(email, password)

    await session.request_session_token()
    friends = await session.get_friends()

    for friend in friends:
        sensors.append(NintendoSwitchSensor(friend))

    async_add_entities(sensors, True)

class NintendoSwitchSensor(Entity):
    """Representation of a Nintendo Switch sensor."""

    def __init__(self, friend):
        """Initialize the sensor."""
        self._state = None
        self._friend = friend
        self._name = f"NSW {friend['name']}"
        self._game = None

    @property
    def name(self):
        """Return the name of the sensor."""
        return self._name

    @property
    def state(self):
        """Return the state of the sensor."""
        return self._state

    @property
    def extra_state_attributes(self):
        """Return the state attributes."""
        return {"game": self._game}

    async def async_update(self):
        """Fetch new state data for the sensor."""
        status = await self._friend.get_status()
        self._state = status['online']
        self._game = status['game']

configuration.yaml 파일에 다음을 추가하여 통합을 설정합니다.

nintendo_switch:
  email: "your_email@example.com"
  password: "your_password"

nso-api 라이브러리를 사용하면 Nintendo Switch Online 서비스와 통신하여 친구의 상태와 게임 정보를 가져올 수 있습니다. 이를 통해 Home Assistant와 같은 플랫폼에서 Nintendo Switch의 다양한 데이터를 통합하고 활용할 수 있습니다.

728x90

댓글