
from ULAN.UBusCommLibWrapper import *
import time
import sys

mFlexrayClusterParameter = FlexrayClusterParameter_t()
mFlexrayNodeParameter = FlexrayNodeParameter_t()
mFlexrayCCParameter = FlexrayCCParameter_t()
gFlexrayMsgBufferParameter= [FlexrayMsgBufferParameter_t () for _ in range(20)]
mFlexrayClusterParameter_ptr = ctypes.pointer(mFlexrayClusterParameter)
mFlexrayNodeParameter_ptr = ctypes.pointer(mFlexrayNodeParameter)
mFlexrayCCParameter_ptr = ctypes.pointer(mFlexrayCCParameter)
gFlexrayMsgBufferParameter_ptr = []


for i in range(20):
    gFlexrayMsgBufferParameter_ptr.append(ctypes.pointer(gFlexrayMsgBufferParameter[i]))

def Sleep(msec):
    sec = msec / 1000.0
    time.sleep(sec)

if __name__ == '__main__':
    # 设置目标 IP 地址和端口号
    target_ip = "192.168.0.8"
    m_UBusCommLibWrapper = UBusCommLibWrapper()
    # 打开设备
    instance = m_UBusCommLibWrapper.OpenDevice(target_ip)
    if instance <= 0:
        print(f"Open flexray device fail!{instance}")
        sys.exit(0)
    print("Open flexray device OK!")
# 支持中文路径
    result = m_UBusCommLibWrapper.Fibex_Open("E:\\UL-FlexRay-Python\\FlexRayPython中文路径\\FlexRayDemo(python3.7.3)V1.0.1\\FlexRayDemo(python3.7.3)V1.0.1\\demo2\\File\\BackboneFR-demo.xml")

    if result == CMD_SUCCESS:
        print("UFr_Fibex_Open OK!")
        #输入cluster名称和ECU名称，如果函数执行成功，参数将保存在对应的结构体中
        result = m_UBusCommLibWrapper.Fibex_GetParameter("BackboneFR", "VDDM",  mFlexrayClusterParameter_ptr,mFlexrayNodeParameter_ptr, mFlexrayCCParameter_ptr) #需要更改参数为指针
        if result != CMD_SUCCESS:
            print(f"UFr_Fibex_GetParameter fail{result})!")
        else:
            print("UFr_Fibex_GetParameter OK!")
    else:
        print(f"UFr_Fibex_Open fail{result}!")

# 配置cluster参数
    if m_UBusCommLibWrapper.Set_Cluster_Parameter(instance, 0, mFlexrayClusterParameter_ptr) != CMD_SUCCESS:
        print("Set_Cluster_Parameter fail!")
        exit(0)
    print("Set_Cluster_Parameter OK!")
    # 配置节点参数
    if m_UBusCommLibWrapper.Set_Node_Parameter(instance, 0, mFlexrayNodeParameter_ptr) != CMD_SUCCESS:
        print("UFr_Set_Node_Parameter fail!")
        exit(0)
    print("UFr_Set_Node_Parameter OK!")

    # 配置CC参数
    if m_UBusCommLibWrapper.Set_CC_Parameter(instance, 0, mFlexrayCCParameter_ptr) != CMD_SUCCESS:
        print("UFr_Set_CC_Parameter fail!")
        exit(0)
    print("UFr_Set_CC_Parameter OK!")

     # 配置发送、接收时隙参数
    FrameNameStrArray = ctypes.c_char * 100
    FrameNameStr = FrameNameStrArray()
    isFirstGet = False
    isFirstGet_ptr = ctypes.pointer(ctypes.c_bool(isFirstGet))
    ret = m_UBusCommLibWrapper.Fibex_GetFrameName_BySignalName("RoadInclnRoadIncln", FrameNameStr, isFirstGet_ptr)
    if ret == CMD_SUCCESS:
        print(f"Frame Name is: {FrameNameStr.value}")

    # 从fibex文件获取一个发送帧的配置信息
    ret = m_UBusCommLibWrapper.Fibex_Set_Slot_Parameter(instance, 0, "BcmVddmBackBoneFr00", True, False)
    if ret != CMD_SUCCESS:
        print(f"UFr_Fibex_Set_Slot_Parameter_Wrapper FAIL [{ret}]!")
        sys.exit(0)

    #从fibex文件获取一个接收帧的配置信息
    ret = m_UBusCommLibWrapper.Fibex_Set_Slot_Parameter(instance, 0, "BbmBcmBackBoneFr01", False, False)
    if ret != CMD_SUCCESS:
        print(f"UFr_Fibex_Set_Slot_Parameter_Wrapper FAIL [{ret}]!")
        sys.exit(0)

    #从fibex文件获取一个接收帧的配置信息
    ret = m_UBusCommLibWrapper.Fibex_Set_Slot_Parameter(instance, 0, "BbmBcmBackBoneFr02", False, False)
    if ret != CMD_SUCCESS:
        print(f"UFr_Fibex_Set_Slot_Parameter_Wrapper FAIL [{ret}]!!")
        sys.exit(0)

    # 配置使能
    if m_UBusCommLibWrapper.Configure_Node(instance, 0) != CMD_SUCCESS:
        print("UFr_Configure_Node fail!")
        sys.exit(0)      
    print("UFr_Configure_Node OK!")

    # 启动接收数据上传操作
    if m_UBusCommLibWrapper.StartFrRxUpload(instance, 0) != CMD_SUCCESS:
        print("UFr_StartFrRxUpload fail!")
        sys.exit(0)
    print("UFr_StartFrRxUpload OK! ")

    # 启动节点，进入总线建立连接状态
    ret = m_UBusCommLibWrapper.Start_Node(instance, 0)
    if ret != CMD_SUCCESS:
        print(f"UFr_Start_Node fail[{ret}]!")
        sys.exit(0)
    print("UFr_Start_Node OK!")

    while True:
        # 获得节点的状态
        # frnodeState, curCycle = pyuflex.FlexRayNodeState(), pyuflex.CycleCount()
        frnodeState = ctypes.c_int8(0)
        frnodeState_ptr = ctypes.pointer(frnodeState)
        curCycle = ctypes.c_int8(0)
        curCycle_ptr = ctypes.pointer(curCycle)
        m_UBusCommLibWrapper.GetFrNodeState(instance, 0, frnodeState_ptr, curCycle_ptr)
        frnodeState = frnodeState.value
        while True:
            if frnodeState == FR_POCSTATE_DEFAULT_CONFIG:
                print("FlexRay Node is in status [defconfig]")
                break
            if frnodeState == FR_POCSTATE_CONFIG:
                print("FlexRay Node is in status [config]")
                break
            if frnodeState == FR_POCSTATE_WAKEUP:
                print("FlexRay Node is in status [wakeup]")
                break
            if frnodeState == FR_POCSTATE_READY:
                print("FlexRay Node is in status [ready]")
                break
            if frnodeState == FR_POCSTATE_NORMAL_ACTIVE:
                print("FlexRay Node is in status [normal active]")
                break
            if frnodeState == FR_POCSTATE_NORMAL_PASSIVE:
                print("FlexRay Node is in status [normal passive]")
                break
            if frnodeState == FR_POCSTATE_HALT:
                print("FlexRay Node is in status [halt]")
                break
            if frnodeState == FR_POCSTATE_STARTUP:
                print("FlexRay Node is in status [startup]")
                break

        if frnodeState == FR_POCSTATE_NORMAL_ACTIVE:
            print("FlexRay bus connect created! You can start recieve and Transmit!")
            break
        # print(f"FlexRay Node is in status [{frnodeState}]")
        time.sleep(1)

    # 发送一帧数据
    mFlexrayFrame = uFlexrayFrame_t()
    mFlexrayFrame_data_ptr = (ctypes.c_uint16 * len(mFlexrayFrame.data))(*mFlexrayFrame.data)
    mFlexrayFrame.payloadLength = mFlexrayClusterParameter.gPayloadLengthStatic
    RcvArray = ctypes.c_uint16 * 127
    mFlexrayFrame.data = RcvArray()

    for i in range(mFlexrayFrame.payloadLength):
        mFlexrayFrame.data[i] = 0x1234 + i

    if m_UBusCommLibWrapper.Fibex_Transmit(instance, 0, "BcmVddmBackBoneFr00",  mFlexrayFrame.data, mFlexrayFrame.payloadLength*2) != CMD_SUCCESS:
        print("UFr_Transmit fail!")
    else:
        print("UFr_Transmit OK!")

    # 接收并处理数据
    rcvcount = 0
    sigval1 = ctypes.c_float(0)
    sigval1_ptr = ctypes.pointer(sigval1)
    sigval2 = ctypes.c_float(0)
    sigval2_ptr = ctypes.pointer(sigval2)
    signal3 = ctypes.c_float(0.01)
    # 借用C库建立可被C动态库调用的数组
    RcvArray = ctypes.c_uint16*127
    rcvData = RcvArray()
    uFlexrayFrameHead = uFlexrayFrameHead_t()
    uFlexrayFrameHead_ptr = ctypes.pointer(uFlexrayFrameHead)
    while True:
        ret = m_UBusCommLibWrapper.Receive(instance, uFlexrayFrameHead_ptr, rcvData, 1000)
        if ret == CMD_SUCCESS:
            framenameArray = ctypes.c_char * 100
            framename = framenameArray()
            ret = m_UBusCommLibWrapper.Fibex_GetFrameName( uFlexrayFrameHead_ptr, framename)
            if ret == CMD_SUCCESS:
                print(f"FrameName = {framename.value}")
           #解析信号
            if framename == b"BbmBcmBackBoneFr01":

                ret = m_UBusCommLibWrapper.Fibex_decodeSignal(uFlexrayFrameHead_ptr,rcvData,"BrkPedlTrvlTar",sigval1_ptr)
                if ret == CMD_SUCCESS:
                    print(f"signal: BrkPedlTrvlTar= {sigval1.value}")
                else:
                    print(f"signal: BrkPedlTrvlTar can't be decode{ret}!")

                ret = m_UBusCommLibWrapper.Fibex_decodeSignal(uFlexrayFrameHead_ptr, rcvData, "BrkPedlTrvlChks", sigval2_ptr)
                if ret == CMD_SUCCESS:
                    print(f"signal: BrkPedlTrvlChks= {ctypes.c_uint32(sigval2.value)}")
                else:
                    print(f"signal: BrkPedlTrvlChks can't be decode{ret}!")

            if framename == b"BbmBcmBackBoneFr02":
                ret = m_UBusCommLibWrapper.Fibex_decodeSignal( uFlexrayFrameHead_ptr,rcvData, "JBkpSig1aAY", sigval1_ptr)
                if ret == CMD_SUCCESS:
                    print(f"signal: JBkpSig1aAY= {sigval1.value}")
                else:
                    print(f"signal: JBkpSig1aAY can't be decode{ret}!")

            rcvcount += 1
            print(
                f"sn={uFlexrayFrameHead.serial_number} time={uFlexrayFrameHead.timestamp_s}.{uFlexrayFrameHead.timestamp_us} channel={uFlexrayFrameHead.Channel} ID={uFlexrayFrameHead.frameID} Cycle={uFlexrayFrameHead.cycleCount} Length={uFlexrayFrameHead.payloadLength} slotstatus={uFlexrayFrameHead.slotStatus} startup={uFlexrayFrameHead.startupFrameIndicator} sync={uFlexrayFrameHead.syncFrameIndicator} NFI={uFlexrayFrameHead.nullFrameIndicator} PPI={uFlexrayFrameHead.payloadPreambleIndicator} headCRC={uFlexrayFrameHead.headerCrc} data:",
                end=" ")
            for i in range(uFlexrayFrameHead.payloadLength):
                print(f"{rcvData[i]:04X}", end=" ")
                
            ret = m_UBusCommLibWrapper.Fibex_encodeSignal("RoadInclnRoadIncln", signal3, rcvData, 32)
            if ret == CMD_SUCCESS:
                print("signal: RoadInclnRoadIncln encode ok!")
            else:
                print(f"signal: RoadInclnRoadIncln encode fail{ret}!")

            signal3.value = signal3.value + 0.01
            ret = m_UBusCommLibWrapper.Fibex_encodeSignal("EpbStsCntr", sigval2, rcvData, 32)
            if ret == CMD_SUCCESS:
                print("signal: EpbStsCntr encode ok!")
            else:
                print(f"signal: EpbStsCntr encode fail{ret}!")

            #将接收到的flexray帧的数据部分通过发送时隙发送出去
            if m_UBusCommLibWrapper.Fibex_Transmit(instance, 0, "BcmVddmBackBoneFr00", rcvData, uFlexrayFrameHead.payloadLength * 2) != CMD_SUCCESS:
                print("UFr_Transmit fail!")
            else:
                print("UFr_Transmit ok!")

            time.sleep(0.01)
        # 如果退出程序，退出程序前应stop和close设备，否则需要重新启动设备才能进行配置, 该Demo为了做演示没有关闭设备，使用者请在实践工程的适当位置关闭
        #     ret = m_UBusCommLibWrapper.StopFrRxUpload(instance, 0)
        #     if ret != CMD_SUCCESS:
        #         printf("UFr_StopFrRxUpload fail!")
        #     ret = m_UBusCommLibWrapper.Stop(instance, 0)
        #     if ret != CMD_SUCCESS:
        #         printf("UFr_Stop fail!")
        #     ret = m_UBusCommLibWrapper.CloseDevice(instance)
        #     if ret != CMD_SUCCESS:
        #         printf("UFr_Close fail!")
