from c104 import Client
import time
import logging

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

class EnvisionDataReceiver:
    def __init__(self, server_ip, server_port=2404):
        """
        初始化远景数据接收器
        :param server_ip: 远景系统服务器IP
        :param server_port: IEC104端口，默认2404
        """
        self.server_ip = server_ip
        self.server_port = server_port
        self.client = None

    def on_connect(self, connection):
        """连接成功回调"""
        logger.info(f"成功连接到远景系统 {connection}")

    def on_disconnect(self, connection):
        """断开连接回调"""
        logger.warning(f"与远景系统断开连接 {connection}")

    def on_telemetry(self, asdu_address, io_address, value, quality, time):
        """
        接收遥测数据回调
        :param asdu_address: ASDU地址
        :param io_address: 信息对象地址
        :param value: 值 (归一化值/标度化值/短浮点数)
        :param quality: 质量描述符
        :param time: 时间标签(CP56Time2a格式)
        """
        timestamp = time.to_datetime() if time else None
        logger.info(f"遥测数据 - ASDU:{asdu_address} IO:{io_address} 值:{value:.2f} 质量:{quality} 时间:{timestamp}")

    def on_telecommand(self, asdu_address, io_address, state, quality, time):
        """
        接收遥信数据回调
        :param asdu_address: ASDU地址
        :param io_address: 信息对象地址
        :param state: 状态 (单点/双点)
        :param quality: 质量描述符
        :param time: 时间标签(CP56Time2a格式)
        """
        timestamp = time.to_datetime() if time else None
        logger.info(f"遥信数据 - ASDU:{asdu_address} IO:{io_address} 状态:{state} 质量:{quality} 时间:{timestamp}")

    def start(self):
        """启动客户端连接"""
        try:
            # 创建IEC104客户端
            self.client = Client()
            self.client.add_connection(self.server_ip,self.server_port)

            # 设置回调函数
            self.client.on_connect = self.on_connect
            self.client.on_disconnect = self.on_disconnect
            self.client.on_telemetry = self.on_telemetry
            self.client.on_telecommand = self.on_telecommand

            # 启动连接
            self.client.start()

            logger.info(f"开始连接远景系统 {self.server_ip}:{self.server_port}...")

            # 保持主线程运行
            while True:
                time.sleep(1)

        except KeyboardInterrupt:
            self.stop()
        except Exception as e:
            logger.error(f"发生错误: {str(e)}")
            self.stop()
            raise e

    def stop(self):
        """停止客户端"""
        if self.client:
            self.client.stop()
            logger.info("已停止IEC104客户端")

if __name__ == "__main__":
    # 配置远景系统服务器IP和端口
    ENVISION_IP = "192.168.50.242"  # 替换为远景系统实际IP
    ENVISION_PORT = 2404

    receiver = EnvisionDataReceiver(ENVISION_IP, ENVISION_PORT)
    receiver.start()