from typing import Any, Callable, Optional, TypeVar, Dict, List, Union, Literal, Iterable, overload
from enum import Enum
from threading import Timer, Lock
from dataclasses import dataclass, field
import math

from typing_extensions import deprecated
import requests


T = TypeVar('T')


class enumConnectionType(Enum):
    TCP          = "TCP"
    UDP          = "UDP"
    MULTICAST    = "MULTICAST"


class _C4:
    NOTHING = math.inf
    ERROR   = 40
    WARNING = 30
    INFO    = 20
    DEBUG   = 10
    NOTSET  = 0


    class BreakException(Exception):
        """用于中断执行流程的异常

        Args:
            message: 异常信息
            level: 异常级别, 默认为 WARING
        """


    class StateChangeMode(Enum):
        # 状态变化模式
        AUTO = 1
        MANUAL = 2


    @dataclass
    class Song:
        """
        歌曲信息类

        Attributes:
            title: 歌曲名
            artist: 歌手名
            album: 专辑名
            genre: 歌曲风格
            duration: 歌曲时长（秒）
            image_url: 歌曲封面图片URL
            custom_data: 自定义数据
        """
        title: str
        artist: str = None
        album: str = None
        genre: str = None
        duration: int = None
        image_url: str = None
        custom_data: Dict[str, Any] = field(default_factory=dict)

        def to_dict(self) -> Dict[str, Union[str, int, Dict[str, Any]]]:
            """
            将歌曲信息类转换为字典

            Returns:
                歌曲信息字典
            """

        def to_json(self) -> str:
            """
            将歌曲信息序列化为JSON字符串

            Returns:
                JSON格式的歌曲信息
            """

        @classmethod
        def from_dict(cls, data: Dict[str, Any]) -> '_C4.Song':
            """
            从字典创建Song对象

            Args:
                data: 包含歌曲信息的字典

            Returns:
                Song对象
            """

        @classmethod
        def from_json(cls, json_str: str) -> '_C4.Song':
            """
            从JSON字符串创建Song对象

            Args:
                json_str: JSON格式的歌曲信息

            Returns:
                Song对象
            """


    @dataclass
    class SongList:
        """
        歌单，播放列表对象

        Attributes:
            name: 歌单名
            songs: 歌曲列表
            custom_data: 自定义数据
        """
        name: str = None
        songs: List['_C4.Song'] = field(default_factory=list)
        custom_data: Dict[str, Any] = field(default_factory=dict)

        def to_dict(self) -> Dict[str, Union[str, int, Dict[str, Any]]]:
            """
            将歌曲信息类转换为字典

            Returns:
                歌曲信息字典
            """

        def to_json(self) -> str:
            """
            将歌曲信息序列化为JSON字符串

            Returns:
                JSON格式的歌曲信息
            """

        @classmethod
        def from_dict(cls, data: Dict[str, Any]) -> '_C4.SongList':
            """
            从字典创建SongList对象

            Args:
                data: 包含歌单信息的字典

            Returns:
                SongList对象
            """

        @classmethod
        def from_json(cls, json_str: str) -> '_C4.SongList':
            """
            从JSON字符串创建SongList对象

            Args:
                json_str: JSON格式的歌单信息

            Returns:
                SongList对象
            """


    class PlayMode:
        """播放模式"""

        SEQUENTIAL = "SEQUENTIAL"
        """顺序播放"""

        LOOP = "LOOP"
        """循环播放"""

        RANDOM = "RANDOM"
        """随机播放"""

        SINGLE = "SINGLE"
        """单曲循环"""

        VALID_MODES = {SEQUENTIAL, LOOP, RANDOM, SINGLE}

    # ---------------------- base ----------------------

    def SetPropertyAttribs(self, key, hidden: bool):
        """设置前端属性可见性，hidden=false显示,true隐藏"""

    def UpdateProperty(self, key, value):
        """更新属性表中对应设备属性键值"""

    def InvalidateState(self):
        """保存持久化数据"""

    def FireEvent(self, event_name):
        """触发用户自定义事件，传递参数为自定义事件名称"""

    def GetDeviceID(self):
        """获取设备ID"""

    def GetProxyID(self, idBinding):
        """根据绑定ID获取代理ID"""

    def GetDeviceDisplayName(self, DeviceID=None):
        """根据device_id获取设备显示名称，显示的为第一个设备名称"""
        """根据device_id获取设备显示名称，显示的为第一个设备名称"""

    def GetProxyDisplayName(self, ProxyID):
        """根据proxy_id获取设备显示名称"""

    def ModifyProxyDisplayName(self, name: str, idBinding: int = None) -> bool:
        """
        修改设备显示名称。
        :param self
        :param name: 新的设备显示名称，不能为空且长度不能超过32个字符。
        :param idBinding: 代理设备的绑定ID，如果未提供，则修改主设备的名称。
        :return: 修改成功返回True，否则返回False。
        """

    def GetDriverConfigInfo(self, key):
        """根据xml标签名称返回对应的xml标签内容"""

    def RoomGetID(self):
        """获取此设备的默认房间ID(项目树中房间节点的ID)"""

    def RoomGetVisibleID(self, ProxyID):
        """获取此设备显示在对应房间的ID,非项目树中房间节点的ID"""

    def RoomGetFloorID(self, RoomID):
        """获取房间所在楼层ID"""

    @deprecated('使用 C4.pub_log(...) 代替')
    def Log(self, message, level="INFO", is_display=True):
        """记录日志, is_display=False时不在页面日志显示"""

    def SetLogLevel(self, level: str = "INFO"):
        """设置日志级别 DEBUG, INFO, WARN, ERROR, FATAL, 默认为INFO"""

    def SetHostSerialParameters(self, BindingID: int, SerialParameters: dict):
        """
        若设备对应的BindingID与主机串口绑定，则可设置主机对应的串口参数
        SerialParameters格式为{"baud_rate": 9600, "data_bits": 8, "stop_bits": 1, "parity": 0}
        baud_rate波特率取值为{110, 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200}
        data_bits数据位取值为{8}
        stop_bits停止位取值为{1}
        parity校验位取值为{0,1,2}分别标识[none,even,odd]
        其中返回值只有当返回True才表示设置成功
        """

    def AddBindingConnection(self, idDevice1: int, idBinding1: int, idDevice2: int, idBinding2: int) -> bool:
        """
        添加两个设备之间的绑定连接
        :param self:
        :param idDevice1: 要连接的设备1的ID
        :param idBinding1: 要连接的设备1的绑定ID
        :param idDevice2: 要连接的设备2的ID
        :param idBinding2: 要连接的设备2的绑定ID
        :return: 连接成功返回True, 失败返回False
        """

    def AddDevice(self, device_file: str, parent_id: int, init_data: dict = None) -> int | None:
        """
        添加设备到项目树中
        :param self:
        :param device_file: 要添加的设备驱动文件名
        :param parent_id: 要添加到的房间ID
        :param init_data: 驱动OnInit函数传入的初始化数据，字典格式，会进行解包传入
        :return: 添加成功返回设备DeviceID, 失败返回None
        """

    def AddRoom(self, name: str, parent_id: int) -> int | None:
        """
        添加房间到项目树中(若同楼层已有同名房间，则会直接返回该房间的ID)
        :param self:
        :param name: 房间名称
        :param parent_id: 父节点楼层id
        :return: 添加成功返回房间DeviceID, 失败返回None
        """

    def DelDevice(self, proxy_ids: list) -> bool:
        """
        从项目树中删除设备
        :param self:
        :param proxy_ids: 要删除的设备代理ID列表
        :return: 成功返回True, 失败返回False
        """

    def HiddenDevice(self, room_id: int, proxy_id: int) -> None:
        """
        在房间中隐藏设备
        :param self:
        :param room_id: 房间ID
        :param proxy_id: 要隐藏的设备代理ID
        :return:
        """

    def SetDeviceType(self, binding_id: int, device_type: str) -> bool:
        """
        设置设备类型
        :param self:
        :param binding_id: 设备绑定ID
        :param device_type: 要设置的设备类型
        设备类型包括：['开闭灯','调光灯', '双色温灯', '彩灯'...]
        :return: True/False
        """

    def GetDeviceSharedData(self, device_id: int):
        """获取对应设备中的共享数据SharedData"""

    def ModifyDeviceXML(self, path: str, value: Any, attribute: str = None):
        """修改设备的xml配置（支持属性和文本内容）
        :param self:
        :param path: XML路径
        :param value: 要设置的值（文本或XML字符串，当为XML字符串时，将完全替换节点内容）
        :param attribute: 需要设置的属性名
        :return: 修改后的完整XML数据
        """

    def GetDeviceXML(self, path: str, device_id: int = None, attribute: str = None, as_xml: bool = False):
        """
        获取对应设备的xml配置（支持属性和文本内容）
        :param self:
        :param path: XML路径，若传递'.'，则获取整个XML数据
        :param device_id: 设备ID,默认为当前设备ID
        :param attribute: 需要获取的属性名
        :param as_xml: 是否返回XML字符串
        :return:
        """

    def InitButtonInfo(self, button_number: int, pattern_number: int = 1) -> Optional[dict]:
        """
        初始化按键设备信息，自动生成按键模式与按键ID对应的按键名称
        :param self:
        :param button_number: 按键数量
        :param pattern_number: 按键模式数量，默认为1
        :return: 创建成功后的按键信息, 若为None则表示创建失败
        """

    def ModifyButtonInfo(self, button_id: int, name: str, pattern_id: int = 1) -> Optional[dict]:
        """
        修改按键名称
        :param self:
        :param button_id: 按键ID
        :param name: 修改后的按键名称
        :param pattern_id: 按键模式ID，默认为1
        :return: 修改后的按键信息, 若为None则表示修改失败
        """

    def NotifyPlayer(self, event: str, data: Any = None):
        """
        驱动用于通知音乐播放器数据变化
        :param self:
        :param event: 事件类型，playlist/next
        :param data: 数据
        :return:
        """

    def AddRtsp(self, rtsp_url: str) -> str | None:
        """
        添加RTSP地址到设备
        :param self:
        :param rtsp_url: rtsp地址
        :return: 摄像头唯一链接ID
        """

    def DAHCalculate(self, msg_type: str, timestamp: int, data: dict[str, Any]) -> str:
        """
        计算数据完整性校验码
        :param self:
        :param msg_type:  报文类型
        :param timestamp:  时间戳
        :param data:  数据
        :return: 数据完整性校验码
        """

    def DAHVerify(self, msg_type: str, timestamp: int, data: dict[str, Any], checksum: str) -> bool:
        """
        验证数据完整性
        :param self:
        :param msg_type: 报文类型
        :param timestamp: 时间戳
        :param data: 数据
        :param checksum: 数据完整性校验码
        :return: 成功True, 失败False
        """

    def GetSceneDevice(self, scene_id: int):
        """
        获取场景下所有设备
        :param self:
        :param scene_id: 场景ID
        :return:
        """

    def GetAllScenes(self) -> dict:
        """
        获取项目下所有场景信息
        :param self:
        :return:
        """

    def GetDeviceProperty(self, device_id: int, property_name: str) -> str | None:
        """
        获取设备属性
        :param self:
        :param device_id: 设备ID
        :param property_name: 属性名称
        :return:
        """

    def ShowConnection(self, id: int) -> None:
        """
        显示当前设备XML中对应的ID连接
        :param self:
        :param id: XML中连接对应的ID
        """

    def HideConnection(self, id: int) -> None:
        """
        隐藏当前设备XML中对应的ID连接
        :param self:
        :param id: XML中连接对应的ID
        """

    # ---------------------- base64 ----------------------

    def Base64Decode(self, data: str) -> str:
        """将 Base64 编码的字符串解码为原始数据。"""

    def Base64DEncode(self, data: str) -> str:
        """将原始数据编码为 Base64 编码的字符串。"""

    def JsonDecode(self, data: str) -> object:
        """将 JSON 字符串解码为 Python 对象。"""

    def JsonEncode(self, data: object) -> str:
        """将 Python 对象编码为 JSON 字符串。"""

    # ---------------------- Device_Interface ----------------------

    @deprecated('使用 "CreateServer"、"ServerSend"、"StopServer"、"CreateClient"、"ClientSend"、"StopClient" 代替')
    def CreateNetworkConnection(self, BindID, NetworkAdds, ConnectionType:enumConnectionType="TCP",Options={}) -> bool:
        """创建发送端 TCP/UDP/MULTICAST"""

    @deprecated('使用 "CreateServer"、"ServerSend"、"StopServer"、"CreateClient"、"ClientSend"、"StopClient" 代替')
    def DestroyNetworkConnection(self, BindID) -> bool:
        """删除发送端"""

    @deprecated('使用 "CreateServer"、"ServerSend"、"StopServer"、"CreateClient"、"ClientSend"、"StopClient" 代替')
    def NetPortOptions(self, BindID, Port, ConnectionType:enumConnectionType="TCP", tPortParams={}):
        """修改发送端配置"""

    @deprecated('使用 "CreateServer"、"ServerSend"、"StopServer"、"CreateClient"、"ClientSend"、"StopClient" 代替')
    def NetConnect(self, BindID, nPort, type=None, nGrowBytes=0, strStart=None , strEnd=None, bSuppressConnectionEvents=None):
        """连接"""

    @deprecated('使用 "CreateServer"、"ServerSend"、"StopServer"、"CreateClient"、"ClientSend"、"StopClient" 代替')
    def SendToNetwork(self, BindID, Port, Message):
        """发送端发送 TCP/UDP 数据"""

    @deprecated('使用 "CreateServer"、"ServerSend"、"StopServer"、"CreateClient"、"ClientSend"、"StopClient" 代替')
    def SendBroadcast(self, BindID, Port, Message):
        """发送端发送 MULTICAST 数据"""

    @deprecated('使用 "CreateServer"、"ServerSend"、"StopServer"、"CreateClient"、"ClientSend"、"StopClient" 代替')
    def NetDisconnect(self, BindID, Port):
        """断开连接"""

    # ---------------------- net ----------------------

    def is_port_in_use(self, port):
        """判断端口是否被占用"""

    def GetRandomPort(self):
        """获取随机可用端口"""

    def get_local_ip(self) -> str:
        """获取本机IP地址"""

    def CreateServer(self, port: int, protocol: enumConnectionType = "TCP", host: str = "0.0.0.0", callback: callable = None) -> str | None:
        """
        创建与本设备绑定的Server端服务
        :param self:
        :param port:端口号
        :param protocol:协议类型
        :param callback:回调函数
        :param host:主机地址
        :return:
        """

    def ServerSend(self, server_id: str, data: str | bytes, handle: tuple[str, int]) -> None:
        """
        服务端发送数据
        :param self:
        :param server_id:服务ID
        :param data:要发送的数据
        :param handle:客户端句柄
        :return:
        """

    def StopServer(self, server_id: str) -> None:
        """
        停止与本设备绑定的Server端服务
        :param self:
        :param server_id:服务ID
        :return:
        """

    def CreateClient(self, address: str, port: int, protocol: enumConnectionType = "TCP", callback=None, options=None) -> str | None:
        """
        创建Client模式的网络连接
        :param self:
        :param port: 网络端口
        :param address: 网络地址
        :param protocol: 连接类型，TCP,UDP,MULTICAST
        :param callback: 网络接收时的回调函数
        :param options: 连接参数
        :return:
        """

    def ClientSend(self, client_id: str, data: str | bytes) -> bool:
        """
        发送数据到对应服务器
        :param self:
        :param client_id: 客户端ID
        :param data: 发送数据
        :return:
        """

    def StopClient(self, client_id: str) -> bool:
        """
        断开对应网络的服务器的连接
        :param self:
        :param client_id: 客户端ID
        :return:
        """

    def GetControllerNetworkAddress(self):
        """none"""

    def SendToProxy(self, idBinding, Command, Params, message=None, allowEmptyValues=None) -> None:
        """发送数据到设备"""

    def SendUIRequest(self):
        pass

    def GetBoundConsumerDevices(self, id, idBinding):
        pass

    def GetUniqueMAC(self):
        '''
        Returns
        string
        Example
            print("Unique mac is " .. C4:GetUniqueMAC())
            Output: Unique mac is 000FFF102F73
        Note
            The unique MAC may not be the active MAC if multiple NICs are present. For example, for systems using a wireless interface the MAC returned will be the MAC of the wired Eth
        '''

    def SendToDevice(self, idDevice, CommandType, Command, Params=None):
        """
        如果 CommandType 是 ReceivedFromProxy 则对应驱动的接收接口函数是ReceivedFromProxy()，
        如果 CommandType 是 ExecuteCommand 则对应的驱动接收接口函数是ExecuteCommand()
        """

    def GetConnectionInfo(self, idBinding) -> list[dict]:
        """
        获取当前设备绑定ID对应的连接设备信息

        返回的数据格式：
        [{'device_id':1,'binding_id':1,'classname':'','consumer':true},]
        device_id: 连接设备ID
        binding_id: 连接设备的绑定ID
        classname: 连接的类型
        consumer: true为输入，false为输出
        """

    # ---------------------- Remote_Control ----------------------

    def get_floor_info(self):
        """获取楼层信息"""

    def get_room_info(self, floor_id):
        """根据楼层获取房间信息"""

    def get_device_info(self, room_id):
        """根据房间获取显示在房间的设备信息，根据设备大类分组"""

    def get_all_devices(self) -> list[dict[str, Any]]:
        """获取显示在房间中设备的设备信息，房间信息以及楼层信息"""

    def get_position_in_tree(self, proxy_id: int) -> dict:
        """获取项目树中设备所在房间，楼层信息和获取房间所在楼层信息

        返回的数据格式：
            `{'floor_id':1,'floor_name':'xxx','room_id':'2','room_name':'xxx'}`
        """

    def get_all_room_property(self):
        """获取所有房间的属性信息"""

    def get_room_video(self, room_id):
        """获取房间视频源"""

    def get_room_audio_device(self, room_id) -> list | None:
        """获取房间音频连接设备的device_id"""

    def set_room_volume(self, room_id: int, cmd: str, param: dict = None):
        """通过房间音频音量和视频音量连接发送设置音量命令到对应的设备上
        room_id: 房间ID
        cmd: 音量控制命令，VOLUME_UP|VOLUME_DOWN|VOLUME_LEVEL，需要确保对应的设备具有此命令
        param: 当命令为VOLUME_LEVEL时，传递具体音量值{'LEVEL':100}
        """

    def get_states(self, proxy_id) -> dict | None:
        """获取指定设备的状态"""

    def SetDriverState(self, proxy_id, key, value):
        """设置指定设备的状态"""

    def get_scenes(self) -> list[dict[str, Any]]:
        """获取场景列表"""

    def ExecuteScene(scene_id: int, command: str = 'EXECUTE'):
        """执行场景，command为EXECUTE时，则为执行场景操作；command为TOGGLE时，反转场景，默认执行场景"""

    @deprecated('使用 C4.SendToDevice(...) 代替')
    def send_command(self, proxy_id, command, params=None):
        """给指定设备发送指令控制"""

    def RegisterDevice(self, device_list):
        """遥控器注册要监听的设备"""

    def RegisterScene(self, scene_list: list[int]) -> None:
        """
        当前设备要监听的场景，需要实现OnSceneStateChange(scene_id, state)方法, state 1为激活，2为非激活, 3为设备变化
        """

    def FireRoomEvent(self, room_id, event_name='ROOM_OFF'):
        """手动触发房间编程事件，默认为触发关闭房间事件"""

    def RegisterDiscover(self, mac: str) -> bool:
        """注册此状态机设备至discover表中，成功返回True，失败返回False"""

    def UnRegisterDiscover(self, mac: str) -> bool:
        """删除discover表中对应mac的记录，成功返回True，失败返回False"""

    def IsInDiscover(self, mac: str) -> bool:
        """查询设备mac是否在discover表中，存在返回True，不存在返回False"""

    def GetDeviceIPByDiscover(self) -> str | None:
        """根据本设备发现协议mac信息查询IP地址"""

    def GetRoomVisible(self, room_id: int) -> dict:
        """获取房间中显示的设备列表和场景列表"""

    def SetSceneProxyDevice(self, device_id: int):
        """设置当前设备的场景执行代理设备，若设置了代理设备则执行场景时调用代理设备的ReceivedFromScene接口"""

    def GetAllRoomDevices(self) -> list[dict[str, str | int]]:
        """
        获取项目下所有房间显示设备的所有信息
        :param self:
        :return:
        """

    def RegisterScheduler(self, scheduler_list: list[int]) -> None:
        """
        注册监听定时计划，若定时计划执行，则会通知对应注册的驱动，需要实现OnSchedulerRun
        """

    # ---------------------- timer ----------------------

    def AddTimer(self, nInterval=None, strUnits=None, bRepeat=False, idTimer=None) -> int:
        """
        添加定时器
        :param self:
        :param nInterval: 间隔时间
        :param strUnits: 定时类型：MILLISECONDS、SECONDS、MINUTES、HOURS
        :param bRepeat: 是否重复
        :param idTimer: 定时器ID
        :return:
        """

    def KillTimer(self, idTimer:int) -> None:
        """删除定时器"""

    # ---------------------- driver_public ----------------------

    def pub_func_log(self: '_C4', log_level = 20) -> Callable:
        """装饰器，打印函数调用日志

        Args:
            log_level (int, optional): 日志级别. 默认为 20.

        Returns:
            function: 装饰器函数。
        """

    def pub_func_catch(self: '_C4', is_raise: bool = False, on_except: Callable[[Exception], None] | None = None) -> Callable:
        """装饰器，捕获函数异常并打印日志

        Args:
            is_raise (bool, optional): 是否抛出异常. 默认为 False.
            on_except (Callable[[Exception], None] | None, optional): 异常回调函数. 默认为 None.

        Returns:
            function: 装饰器函数。
        """

    def pub_class_catch[T](self: '_C4', cls: T, is_raise: bool = False, on_except: Callable[[Exception], None] | None = None) -> T:
        """装饰器，捕获类方法执行异常，并输出日志

        Args:
            is_raise (bool, optional): 是否抛出异常. 默认为 False.
            on_except (Callable[[Exception], None] | None, optional): 异常回调函数. 默认为 None.
        """

    def pub_func_hook(self: '_C4', hook) -> Callable:
        """装饰器，在函数调用前后执行 hook 函数

        Args:
            hook (_type_): 钩子函数，参数为 ('before', *args, **kwargs) 或 ('after', *args, **kwargs)
                : `before` 返回 True 则不执行函数
                : `after` 置函数返回值为关键字参数 `__result`, 返回非 `None` 值替换函数返回值

        Returns:
            function: 装饰器函数。
        """

    def pub_func_cache(self: '_C4', timeout: float = 0) -> Callable:
        """装饰器，缓存函数返回值

        Args:
            timeout (float, optional): 缓存超时时间，单位秒，为 `0` 时表示永不过期. 默认为 `0`.

        Returns:
            function: 装饰器函数。
                property: `clear` (lambda) 清除缓存
        """

    def pub_func_debounced(self: '_C4', delay: float | Callable[[tuple, dict], float], diff_params: bool = False):
        """装饰器，给函数添加防抖功能

        Args:
            delay (float | Callable[[tuple, dict], float]): 延迟时间 (秒)
            diff_params (bool, optional): 是否对参数进行比较, 相同参数才会进行防抖. 默认为 False.
        """

    @deprecated('框架内部自动调用，请勿手动调用')
    def pub_init(self: '_C4', PersistData: dict, **kwargs) -> None:
        """初始化公共函数库，并将持久化数据推送到前端（忽略以 _ 开头的属性）"""

    def pub_set_log_level(self: '_C4', level: int | str) -> None:
        """设置日志级别 0 无 10 调试 20 信息 30 警告 40 错误"""

    def pub_log(self: '_C4', *args, level: int | Iterable[int] = 20, sep: str = ' ') -> None:
        """输出日志；若 level 整除 10，则输出 >= level 级别的日志，否则输出 == level 级别的日志"""

    def pub_get_PD(self: '_C4', key: str, default: Optional[T] = None) -> Optional[T]:
        """获取持久化数据"""

    def pub_set_PD(self: '_C4', key: str, value) -> None:
        """更新持久化数据"""

    def pub_save_PD(self: '_C4') -> None:
        """保存持久化数据到数据库"""

    def pub_update_property(self: '_C4', key: str, value, log: str | None = None) -> None:
        """更新设备状态, 并推送到前端"""

    def pub_hide_property(self: '_C4', property: str) -> None:
        """隐藏属性"""

    def pub_show_property(self: '_C4', property: str) -> None:
        """显示属性"""

    def pub_uuid() -> str:
        """获取随机 uuid"""

    def pub_sleep(self: '_C4', seconds: float) -> None:
        """让当前线程休眠指定秒数"""

    def pub_str_time(self: '_C4') -> str:
        """获取当前时间字符串"""

    def pub_time(self: '_C4') -> float:
        """获取当前时间戳 (秒)"""

    def pub_pass_time(self: '_C4', time: float) -> float:
        """返回当前时间戳与指定时间戳的差值 (秒)"""

    def pub_set_interval(self: '_C4', interval: float, unit: str = 'SECONDS') -> int:
        """添加一个定时器，返回定时器 id"""

    def pub_clear_interval(self: '_C4', timer_id: int) -> None:
        """清除一个定时器"""

    def pub_set_timeout(self: '_C4', interval: float, function: Callable, args: Any | None = None, kwargs: Any | None = None) -> Timer:
        """定时 n 秒后执行函数"""

    def pub_clear_timeout(self: '_C4', timer: Timer) -> None:
        """清除一个定时器"""

    def pub_retry(self: '_C4', target: Callable, args: tuple = (), kwargs: dict | None = None, *, condition: Callable, msg: str | None = None, max_retry: int = 3, timeout: float = 3, interval: float = 0.1) -> bool:
        """重试执行函数，直到满足条件或达到最大重试次数

        Args:
            target (Callable): 要执行的函数
            args (tuple, optional): 位置参数. 默认为 ().
            kwargs (dict, optional): 关键字参数. 默认为 None.
            condition (Callable): 条件函数，返回 True 则停止重试.
            msg (str, optional): 重试提示文本.
            max_retry (int, optional): 最大重试次数. 默认为 3 秒.
            timeout (float, optional): 超时时间. 默认为 3 秒.
            interval (float, optional): 条件检查间隔. 默认为 0.1 秒.

        Returns:
            bool: 成功或失败
        """

    def pub_get_lock(self: '_C4', lock_name: str = 'default_lock') -> Lock:
        """获取一个线程锁，若没有则创建

        Args:
            lock_name (str): 锁名称, 默认为 'default_lock'

        Returns:
            Lock: 线程锁对象
        """

    def pub_task(self: '_C4', target: Callable, args: tuple | None = None, kwargs: dict | None = None, *, delay_before: float = 0, delay_after: float = 0, group: str = 'default') -> None:
        """创建后台任务

        Args:
            target (Callable): 任务函数
            args (tuple | None, optional): 任务参数. 默认为 None.
            kwargs (dict | None, optional): 任务关键字参数. 默认为 None.
            delay_before (float, optional): 任务前延时, 单位毫秒. 默认为 0.
            delay_after (float, optional): 任务后延时, 单位毫秒. 默认为 0.
            group (str, optional): 任务分组. 默认为 'default'.
        """

    def pub_clear_task(self: '_C4', group: str = 'default') -> None:
        """清空指定任务组的任务"""

    def pub_xor_sum(self: '_C4', data: bytes) -> int:
        """计算异或校验和

        Args:
            data (bytes): 数据

        Returns:
            int: 校验和
        """

    def pub_crc16_xmodem(self: '_C4', data: bytes, polynomial = 0x1021) -> int:
        """
        计算给定数据的 CRC-16-XMODEM 校验值。

        :param data: 需要计算CRC的字节数据。
        :param polynomial: CRC-16-XMODEM 多项式。
        :return: 计算得到的CRC-16-XMODEM校验值。
        """

    def pub_crc16_modbus(self: '_C4', data: bytes, polynomial = 0xA001) -> int:
        """计算指定数据的 CRC-16-MODBUS 校验值。

        Args:
            data (bytes): 需要计算CRC的字节数据。
            polynomial (_type_, optional): CRC-16-MODBUS 多项式. Defaults to 0xA001.

        Returns:
            int: 计算得到的 CRC-16-MODBUS 校验值。
        """

    def pub_RC4(self: '_C4', key: str | bytes, data: str | bytes, encoding: str = 'utf-8') -> bytes:
        """使用 RC4 算法加密或解密数据

        Args:
            key (str | bytes): 秘钥
            data (str | bytes): 数据
            encoding (str, optional): 编码. 默认为 'utf-8'.

        Returns:
            bytes: 加密或解密后的结果
        """

    def pub_with_default(self: '_C4', data: dict, default: dict) -> dict:
        """将 `data` 中的 `None` 值替换为 `default` 中的值"""

    @overload
    def pub_make_jsonrpc(self: '_C4', *, dump: Literal[True] = True, **kw) -> str:
        ...

    @overload
    def pub_make_jsonrpc(self: '_C4', *, dump: Literal[False] = False, **kw) -> dict:
        ...

    def pub_make_jsonrpc(self: '_C4', *, dump: bool = False, **kw) -> str | dict:
        """生成 jsonrpc 格式的请求数据，自动递增 id

        默认:
        ```python
            {
                'jsonrpc': '2.0',
                'id': xxx,
            }
        ```
        """

    def pub_table_dumps(self: '_C4', table: list[dict[str, Any]]) -> str:
        """将字典列表转换为表格字符串"""

    def pub_json_loads(self: '_C4', s: str | bytes | bytearray) -> dict:
        """将 json 格式的字符串转换为字典"""

    def pub_json_dumps(self: '_C4', data: dict, indent: int = 4) -> str:
        """将字典数据转换为 json 格式"""

    def pub_ishex(self: '_C4', text: str):
        """判断字符串是否为 16 进制字符串"""

    def pub_format_hex(self: '_C4', hex_str: str, reverse: bool = False) -> str:
        """格式化 16 进制字符串，每 8 位插入一个空格。

        Args:
            hex_str (str): 16 进制字符串。

        Returns:
            str: 格式化后的 16 进制字符串。
        """

    def pub_percent_hex(self: '_C4', percent: int | float) -> str:
        """将百分比转换为 16 进制字符串形式"""

    def pub_dispercent_hex(self: '_C4', hex_str: str) -> float:
        """将 16 进制字符串转换为百分比形式"""

    def pub_bounds(self: '_C4', num: int | float, _min: int | float, _max: int | float):
        """将 num 限定在 [_min:_max]"""

    def pub_percent(self: '_C4', num: int | float, _min: int | float, _max: int | float) -> float:
        """将数值转换为百分比形式"""

    def pub_dispercent(self: '_C4', num: int | float, _min: int | float, _max: int | float) -> int | float:
        """将百分比转换为数值形式"""

    def pub_int_key(self: '_C4', data: dict):
        """将字典的 key 转换为整数"""

    def pub_int_to_bin(self: '_C4', num: int, length: int = 8) -> str:
        """将整数转换为指定长度的2进制字符串形式

        Args:
            num (int): 数字
            length (int, optional): 长度（位，一字节 8 个 2 进制字符）. Defaults to 8.

        Returns:
            str: 2 进制字符串（例：8 -> '00001000'）
        """

    def pub_int_to_hex(self: '_C4', num: int, length: int = 1) -> str:
        """将整数转换为指定长度的16进制字符串形式

        Args:
            num (int): 数字
            length (int, optional): 长度（字节，一字节 2 个 16 进制字符）. Defaults to 1.

        Returns:
            str: 16 进制字符串（例：10 -> '0A'）
        """

    def pub_ip_to_hex(self: '_C4', ip: str) -> str:
        """将IP地址转为16进制字符串形式"""

    def pub_hex_to_ip(self: '_C4', hex_string: str) -> str:
        """将16进制字符串形式的IP地址转为IP地址形式"""

    def pub_hex_to_mac(self: '_C4', hex_str: str) -> str:
        """十六进制字符串转为 MAC 地址"""

    def pub_mac_to_hex(self: '_C4', mac_str: str) -> str:
        """MAC 地址转为十六进制字符串"""

    def pub_xml_to_dict(self: '_C4', xml: str, default = ...) -> dict:
        """将xml字符串转换为字典"""

    def pub_dict_to_xml(self: '_C4', data: dict, root_name: str | None = None, encoding: str = 'unicode') -> str:
        """将字典数据转换为xml格式"""

    def pub_fetch_get(self: '_C4', host, port, path, params = None, protocol = 'http', timeout = 3, **kwargs) -> requests.Response | None:
        """requests.get 封装"""

    def pub_fetch_post(self: '_C4', host, port, path, params = None, data = None, json = None, protocol='http', timeout = 3, **kwargs) -> requests.Response | None:
        """requests.post 封装"""

    def pub_knx_connect(self: '_C4', addr: tuple[str, int], rate_limit: int = 20) -> None:
        """创建 KNX 连接"""

    def pub_knx_disconnect(self: '_C4') -> None:
        """断开 KNX 连接"""

    def pub_knx_rate_limit(self: '_C4', rate_limit: int) -> None:
        """设置 KNX 报文队列的发送速率，单位毫秒"""

    def pub_knx_send(self: '_C4', group_address: str, value, value_type) -> None:
        """向 KNX 设备发送数据"""

    def pub_knx_is_alive(self: '_C4') -> bool:
        """判断 KNX 连接是否存活"""

    def pub_knx_check_addr(self: '_C4', addr: str):
        """验证 KNX 地址是否合法"""

    def pub_create_connection(self: '_C4', type: Literal['TC', 'UC', 'MC', 'TS', 'US', 'MS'], port: int, host: str | None = None, pretreatment: Callable | None = None) -> str | None:
        """建立指定连接

        Args:
            type (str): 连接类型
                - 'TC'  TCP 客户端
                - 'UC'  UDP 客户端
                - 'MC'  多播客户端
                - 'TS'  TCP 服务端
                - 'US'  UDP 服务端
                - 'MS'  多播服务端
            port (int): 端口号
            host (str): ip 地址 (服务端为可选项)
            pretreatment (Callable, optional): 预处理函数, 默认为 None.

        Returns:
            str: 连接 ID
        """

    def pub_destroy_connection(self: '_C4', id: str) -> None:
        """关闭指定连接

        Args:
            id (str): 连接 ID
        """

    def pub_send_to_network(self: '_C4', id: str, data: str | bytes, target: tuple[str, int] | None = None, retry: int = 3, interval: float = 3) -> bool:
        """发送网络数据

        Args:
            id (str): 连接 ID
            data (str | bytes): 要发送的数据
            target (tuple[str, int], optional): 目标地址 (服务端连接时有效)
            retry (int, optional): 重试次数. 默认为 3.
            interval (float, optional): 重试间隔. 默认为 3.

        Returns:
            bool: 是否发送成功
        """

    @deprecated('使用 "pub_send_to_network" 代替')
    def pub_send_to_multicast(self: '_C4', channel: int, port: int, message: str) -> None:
        """向对应端口发送多播数据"""

    def pub_send_to_serial(self: '_C4', hex_data: str | list, interval: float = 0.1, to_hex: bool = False, channel: int = 3001) -> None:
        """发送串口数据，内部格式：{ hex_data: str, interval: float }

        Args:
            hex_data (str | list): 要发送的串口数据
            interval (float, optional): 发送间隔. 默认为 0.1.
            to_hex (bool, optional): 是否将数据转换为十六进制格式. 默认为 False.
        """

    def pub_send_to_ir(self: '_C4', code: str | list, count: int = 1, to_hex: bool = False, channel: int = 3000) -> None:
        """发送红外数据，内部格式：{ code: str, count: int }

        Args:
            code (str | list): 要发送的红外码
            count (int, optional): 发送次数. 默认为 1.
            to_hex (bool, optional): 是否将数据转换为十六进制格式. 默认为 False.
        """

    def pub_send_to_internal(self: '_C4', command: str, params: dict, channel: int = 5001) -> None:
        """向内部通道发送命令，改变设备状态"""

    def pub_send_to_device(self: '_C4', cmd: str, params: dict | str, device_id: int) -> None:
        """向指定设备发送命令

        Args:
            cmd (str): 命令
            params (dict | str): 参数
            device_id (int): 设备 ID
        """

    def pub_send_to_master(self: '_C4', cmd: str, params: dict | str, target: int | str = '4000') -> None:
        """向主控设备发送数据

        Args:
            cmd (str): 命令
            params (dict | str): 参数
            target (int | str, optional): 通道号 (str, 群发) 或 设备 ID (int). 默认为 '4000'.
        """

    def pub_send_to_slave(self: '_C4', cmd: str, params: dict | str, target: int | str = '4000') -> None:
        """向从控设备发送数据

        Args:
            cmd (str): 命令
            params (dict | str): 参数
            target (int | str, optional): 通道号 (str, 群发) 或 设备 ID (int). 默认为 '4000'.
        """

    def pub_get_broadcast_ip(self: '_C4') -> str:
        """获取广播地址"""

    def pub_broadcast(self: '_C4', message: bytes, port: int | None = None, channel: int = 3999):
        """发送广播数据"""

    def pub_WOL(self: '_C4', mac: str):
        """发送 WOL 包，实现网络唤醒"""

    def pub_data_pipe(self: '_C4', data: bytes, len_size: int = 2, *, filter: Callable[[bytes], bool] | None = None) -> list[bytes]:
        """解析带长度前缀的数据，可以应对粘包拆包问题

        Args:
            data (bytes): 带长度前缀的数据
            len_size (int, optional): 长度前缀的字节数. 默认为 2.
            filter (Callable[[bytes], bool] | None, optional): 过滤函数。整包或拆包的第一个包返回 `True`；非拆包的第一个包返回 `False`，将放入 `buffer` 等待接收到足够长度的数据. 默认为 None.

        Attrs:
            buffer (bytes): 缓存数据
            extract (Callable[[bytes, int], tuple[list[bytes], bytes]]): 提取数据包
            clear (Callable[[], None]): 清空缓存

        Returns:
            list[bytes]: 解析后的包列表
        """

    def pub_longdown_task(self: '_C4', send_to_proxy: Callable, cmd: str, params: dict, delay: float, interval: float = 0.5) -> None:
        """创建长按任务"""

    def pub_mute_switch(self: '_C4', cmd: Literal['MUTE_ON', 'MUTE_OFF', 'MUTE_TOGGLE']) -> Literal['MUTE_ON', 'MUTE_OFF'] | None:
        """处理静音开关的情况"""

    def pub_mute_toggle(self: '_C4', cmd: Literal['MUTE_ON', 'MUTE_OFF', 'MUTE_TOGGLE']) -> Literal['MUTE_TOGGLE'] | None:
        """处理静音切换的情况"""


C4: _C4 = ...
PersistData: dict[str, Any] = ...
SharedData: Any = ...
