Source code for toio.cube.api.indicator

# -*- coding: utf-8 -*-
# ************************************************************
#
#     indicator.py
#
#     Copyright 2022 Sony Interactive Entertainment Inc.
#
# ************************************************************

from __future__ import annotations

import struct
from dataclasses import dataclass

from typing_extensions import List, Sequence, Union

from ...device_interface import CubeInterface, GattReadData
from ...logger import get_toio_logger
from ...toio_uuid import ToioUuid
from ...utility import clip
from ..api.base_class import CubeCharacteristic, CubeCommand
from ..notification_handler_info import NotificationReceivedDevice

logger = get_toio_logger(__name__)


[docs]@dataclass class Color: """ Indicator color in RGB """ r: int """R value (0 - 255)""" g: int """G value (0 - 255)""" b: int """B value (0 - 255)"""
[docs] def flatten(self): """ Return the tuple representation of this dataclass """ r = clip(self.r, 0, 255) g = clip(self.g, 0, 255) b = clip(self.b, 0, 255) return r, g, b
[docs]@dataclass class IndicatorParam: """ Indicator color and lighting period """ duration_ms: int """ | Duration of lighting: | Any fraction less than 10ms will be truncated. | 0 - 9: no time limit | 10 - 2550: duration [ms] """ color: Color """ | RGB value """
[docs] @staticmethod def from_int(duration_ms: int, r: int, g: int, b: int) -> IndicatorParam: return IndicatorParam(duration_ms=duration_ms, color=Color(r=r, g=g, b=b))
[docs] def flatten(self): duration = clip(int(self.duration_ms / 10), 0, 255) return duration, 0x01, 0x01, *self.color.flatten()
[docs]class TurningOnAndOff(CubeCommand): """ Indicator turning on / off command References: https://toio.github.io/toio-spec/en/docs/ble_light#turning-the-indicator-on-and-off """ _payload_id = 0x03 _converter = struct.Struct("<BBBBBBB")
[docs] def __init__(self, param: IndicatorParam): self.param = param
[docs] def __bytes__(self) -> bytes: return self._converter.pack(self._payload_id, *self.param.flatten())
[docs]class RepeatedTurningOnAndOff(CubeCommand): """ Repeated indicator turning on /off command References: https://toio.github.io/toio-spec/en/docs/ble_light#repeated-turning-on-and-off-of-indicator """ _payload_id = 0x04 _converter = struct.Struct("<BBB") REPEAT_INFINITE = 0
[docs] def __init__( self, repeat: int, param_list: Sequence[IndicatorParam], ) -> None: self.repeat = repeat self.param_list = param_list
[docs] def __bytes__(self) -> bytes: byte_representation = self._converter.pack( self._payload_id, self.repeat, len(self.param_list) ) for param in self.param_list: byte_representation = byte_representation + struct.pack( "<BBBBBB", *param.flatten() ) return byte_representation
[docs]class TurnOffAll(CubeCommand): """ Indicator all off command References: https://toio.github.io/toio-spec/en/docs/ble_light#turn-off-all-indicators """ _payload_id = 0x01
[docs] def __init__(self) -> None: pass
[docs] def __bytes__(self) -> bytes: return bytes((self._payload_id,))
[docs]class TurnOff(CubeCommand): """ Indicator off command References: https://toio.github.io/toio-spec/en/docs/ble_light#turn-off-a-specific-indicator """ _payload_id = 0x02 _converter = struct.Struct("<BBB")
[docs] def __init__(self, indicator_id: int) -> None: self.indicator_id = indicator_id
[docs] def __bytes__(self) -> bytes: return self._converter.pack(self._payload_id, 0x01, self.indicator_id)
[docs]class Indicator(CubeCharacteristic): """ Indicator characteristic References: https://toio.github.io/toio-spec/en/docs/ble_light """
[docs] @staticmethod def is_my_data(_payload: GattReadData) -> None: return None
[docs] def __init__(self, interface: CubeInterface, device: NotificationReceivedDevice): self.interface = interface super().__init__(interface, ToioUuid.Light.value, device)
[docs] async def turn_on(self, param: Union[IndicatorParam, Sequence[int]]) -> None: """ Send indicator turn on / off command Args: param (Union[IndicatorParam, Sequence[int]]): Indicator parameter References: https://toio.github.io/toio-spec/en/docs/ble_light#repeated-turning-on-and-off-of-indicator """ if isinstance(param, Sequence): param = IndicatorParam.from_int(*param) turn_on = TurningOnAndOff(param) await self._write(bytes(turn_on))
[docs] async def repeated_turn_on( self, repeat: int, param_list: Union[Sequence[IndicatorParam], Sequence[Sequence[int]]], ) -> None: """ Send repeated indicator turning on / off command Args: repeat (int): Number of repetitions param_list (Union[Sequence[IndicatorParam], Sequence[Sequence[int]]]): List of indicator parameters References: https://toio.github.io/toio-spec/en/docs/ble_light#repeated-turning-on-and-off-of-indicator """ params: List[IndicatorParam] = [] for param in param_list: if isinstance(param, Sequence): params.append(IndicatorParam.from_int(*param)) elif isinstance(param, IndicatorParam): params.append(param) else: raise ValueError("wrong value is found in param_list: %s", str(param)) repeated = RepeatedTurningOnAndOff(repeat, params) await self._write(bytes(repeated))
[docs] async def turn_off_all(self) -> None: """ Send all off command References: https://toio.github.io/toio-spec/en/docs/ble_light#turn-off-all-indicators """ turn_off = TurnOffAll() await self._write(bytes(turn_off))
[docs] async def turn_off(self, indicator_id: int) -> None: """ Send off command Args: indicator_id (int): Indicator ID References: https://toio.github.io/toio-spec/en/docs/ble_light#turn-off-a-specific-indicator """ turn_off = TurnOff(indicator_id) await self._write(bytes(turn_off))