ABOUT ME

-

  • DoIP (Diagnostic over Internet Protocol) - TSMaster API C 코드
    카테고리 없음 2025. 4. 11. 15:28

     

    시작하기 전에 

    정비를 하다보면 진단 통신으로 제어기의 상태를 확인하고, 상태에 따라 제어기를 조작하고, 다시 제어기의 상태를 확인하고, 또 다시 상태에 따라 제어기를 조작하는 일을 반복하는 경우가 많다. 이런 경우 미리 프로그램을 작성해두면 편리하다. 

    TSMaster Diagnostic의 Automatic Diagnostic 기능을 이용하여 프로그램을 할 수 있다. TSMaster는 이를 진단 플로우(flow)라고 한다. 

    C나 Python으로 코딩을 하면 더 유연하게 더 복잡한 조작을 프로그램 할 수 있다. 

    C 코드를 이용하여, DoIP 진단 통신하는 방법을 설명한다. 

     

     

    개요

    • DoIP 예제 코드로 방법을 설명한다. 코드는 아래의 구조로 되어있다. 
      • TSMaster 설정
      • 하드웨어 설정
      • 채널 설정
      • DoIP 설정
      • DoIP로 UDS 진단 요청 메시지 전송과 응답 메시지 수신
    • GUI를 이용하여 TSMaster를 사용하는 순서와 다를 바 없다.

     

     

    C 코드

    • 아래 C 코드는 TSMaster의 DoIP 기능을 이용하여 이더넷 진단 통신을 하는 예이다.
    • (#include "TSMaster.h"에서 짐작할 수 있듯이)  이 코드는 TSMaster의 기능들을 이용한다. TSMaster가 설치되어 있어야  정상적으로 실행된다.
    #include <stdio.h>      // Include standard input/output library
    #include <stdint.h>     // Include stdint library for fixed-width integer types
    #include "TSMaster.h"   // Include the TSMaster library header file

    int main()
    {
        // Initialize the TSMaster library with a specific project path
        int32_t ret_1_inistial = initialize_lib_tsmaster_with_project("TSMaster", "D:\6.Other\TSMaster\TSMasterPrj");

        // int32_t ret_inistial = initialize_lib_tsmaster("TSMaster");
        printf("initialize_lib_tsmaster_with_project result=%d\n", ret_1_inistial);

        int32_t devicesCount = -1; // Variable to hold the count of hardware devices

        // Enumerate the hardware devices and get the count
        int32_t ret_2_hw_devices = tsapp_enumerate_hw_devices(&devicesCount);
        printf("tsapp_enumerate_hw_devices result=%d\n", ret_2_hw_devices);
        printf("tsapp_enumerate_hw_devices device-count=%d\n", devicesCount);


        // Get hardware information for each device
        // Loop through each device and retrieve its information
        TLIBHWInfo info; // Structure to hold information about hardware devices
        for(int32_t i = 0; i < devicesCount; ++i) {
            // Get hardware information by index
            int32_t ret_3_get_hw_info = tsapp_get_hw_info_by_index(i, &info);
            printf("tsapp_get_hw_info_by_index result=%d\n", ret_3_get_hw_info);
            printf("tsapp_get_hw_info_by_index index=%d, vendor=%s, devcie=%s, serial=%s\n", info.FDeviceIndex, info.FVendorName, info.FDeviceName, info.FSerialString);
        }

        // Set the count for various communication channels
        tsapp_set_can_channel_count(1); // Set the count for CAN channels
        tsapp_set_lin_channel_count(0); // Set the count for LIN channels
        tsapp_set_canfd_channel_count(0); // Set the count for CAN FD channels
        tsapp_set_flexray_channel_count(0); // Set the count for FlexRay channels

        // Set the count for Ethernet channels
        int32_t ret_4_channel_count = set_ethernet_channel_count(2);
        printf("set_ethernet_channel_count result=%d\n", ret_4_channel_count);

        // Initialize the socket with 2 channels
        int32_t ret_5_initialize = tssocket_initialize(2);
        printf("tssocket_initialize result=%d\n", ret_5_initialize);

        // Define MAC address and network parameters
        uint8_t mac_addr[] = {0xAA,0xBB,0xCC,0xDD,0xEE,0x23};
        uint16_t vlan = 0;
        Tip4_addr_t ip;
        Tip4_addr_t gw;
        Tip4_addr_t netmask;
        int16_t mtu = 1500; // Maximum Transmission Unit

        // Convert string IP addresses to raw socket address format
        rawsocket_aton("172.20.0.36", &ip);
        rawsocket_aton("255.255.255.252", &gw);
        rawsocket_aton("255.255.255.0", &netmask);

        // Add a device to the socket
        int32_t ret_6_add_device = tssocket_add_device(2, mac_addr, &vlan, ip, netmask, gw, mtu);
        printf("tssocket_add_device result=%d\n", ret_6_add_device);

        // Create a mapping structure for CAN channel
        TLIBTSMapping canMapping;
        // TSMaster CAN FD Channel 1 - Vector VIRTUAL 1 CAN FD Channel 1
        memset(canMapping.FAppName, 0x00, 32); // Clear application name
        memcpy(canMapping.FAppName, "TSMaster", sizeof("TSMaster")); // Set application name
        memset(canMapping.FHWDeviceName, 0x00, 32); // Clear hardware device name
        memcpy(canMapping.FHWDeviceName, "Vector VIRTUAL", sizeof("Vector VIRTUAL")); // Set hardware device name

        canMapping.FAppChannelIndex = 0; // Set application channel index
        canMapping.FAppChannelType = (TLIBApplicationChannelType)0; // Set application channel type
        canMapping.FHWDeviceType = (TLIBBusToolDeviceType)2; // Set hardware device type
        canMapping.FHWDeviceSubType = 1; // Set hardware device subtype
        canMapping.FHWIndex = 0; // Set hardware index
        canMapping.FHWChannelIndex = 0; // Set hardware channel index
        canMapping.FMappingDisabled = 0; // Enable mapping

        // Set the mapping for CAN channel
        int32_t ret_7_can_mapping = tsapp_set_mapping(&canMapping);
        printf("tsapp_set_mapping for can result=%d\n", ret_7_can_mapping);

        // Create a mapping structure for Ethernet channel 1
        TLIBTSMapping eth1Mapping;
        // TSMaster Ethernet Channel 1 - TOSUN Ex TE1051 1 Ethernet Channel 1
        memset(eth1Mapping.FAppName, 0x00, 32); // Clear application name
        memcpy(eth1Mapping.FAppName, "TSMaster", sizeof("TSMaster")); // Set application name
        memset(eth1Mapping.FHWDeviceName, 0x00, 32); // Clear hardware device name
        memcpy(eth1Mapping.FHWDeviceName, "TOSUN Ex TE1051", sizeof("TOSUN Ex TE1051")); // Set hardware device name
        eth1Mapping.FAppChannelIndex = 0; // Set application channel index
        eth1Mapping.FAppChannelType = (TLIBApplicationChannelType)3; // Set application channel type
        eth1Mapping.FHWDeviceType = (TLIBBusToolDeviceType)11; // Set hardware device type
        eth1Mapping.FHWDeviceSubType = 27; // Set hardware device subtype
        eth1Mapping.FHWIndex = 0; // Set hardware index
        eth1Mapping.FHWChannelIndex = 0; // Set hardware channel index
        eth1Mapping.FMappingDisabled = 0; // Enable mapping

        // Set the mapping for Ethernet channel 1
        int32_t ret_8_eth1_mapping = tsapp_set_mapping(&eth1Mapping);
        printf("tsapp_set_mapping for eth1 result=%d\n", ret_8_eth1_mapping);

        // TSMaster Ethernet Channel 2
        // Create a mapping structure for Ethernet channel 2
        TLIBTSMapping eth2Mapping;
        memset(eth2Mapping.FAppName, 0x00, 32); // Clear application name
        memcpy(eth2Mapping.FAppName, "TSMaster", sizeof("TSMaster")); // Set application name
        memset(eth2Mapping.FHWDeviceName, 0x00, 32); // Clear hardware device name
        memcpy(eth2Mapping.FHWDeviceName, "Unknown", sizeof("Unknown")); // Set hardware device name
        eth2Mapping.FAppChannelIndex = 1; // Set application channel index
        eth2Mapping.FAppChannelType = (TLIBApplicationChannelType)3; // Set application channel type
        eth2Mapping.FHWDeviceType = (TLIBBusToolDeviceType)0; // Set hardware device type
        eth2Mapping.FHWDeviceSubType = 27; // Set hardware device subtype
        eth2Mapping.FHWIndex = -1; // Set hardware index
        eth2Mapping.FHWChannelIndex = -1; // Set hardware channel index
        // Set the mapping for Ethernet channel 2
        int32_t ret_9_eth2_mapping = tsapp_set_mapping(&eth2Mapping);
        printf("tsapp_set_mapping for eth2 result=%d\n", ret_9_eth2_mapping);

        // Connect to the TSMaster
        int32_t ret_10_connect = tsapp_connect();
        printf("tsapp_connect result=%d\n", ret_10_connect);

        // Start logging to a specified file
        int32_t ret_11_logging_start = tsapp_start_logging("./1.blf");
        printf("tsapp_start_logging result=%d\n", ret_11_logging_start);

        // Define parameters for the DoIP connection
        int32_t udsHandle = 0; // Handle for the UDS connection
        int32_t ToolType = 0; // Type of the tool
        uint32_t ChnIndex = 0; // Channel index
        char *Tester_IP = "172.20.0.36"; // Tester IP address
        uint16_t Tester_PORT = 31281; // Tester port
        char *DUT_IP = "172.20.0.38"; // Device Under Test IP address
        uint16_t DUT_PORT = 13400; // Device Under Test port

        uint32_t req_id = 0x0E00; // Request ID
        uint32_t res_id = 0x0373; // Response ID
        uint32_t func_id = 0x0042; // Function ID

        // Create a DoIP connection
        int32_t ret_12_diop_create = tsdiag_doip_create(&udsHandle, ToolType, ChnIndex,
                                 Tester_IP, Tester_PORT,
                                 DUT_IP, DUT_PORT,
                                 req_id, res_id, func_id);
        printf("tsdiag_doip_create result=%d\n", ret_12_diop_create);

        // Connect using DoIP
        int32_t ret_13_doip_connect = tsdiag_doip_connect(udsHandle);
        printf("tsdiag_doip_connect result=%d\n", ret_13_doip_connect);

        uint8_t activate_type = 0xE2; // Activation type
        bool whether_send_oem_data = true; // Flag to send OEM data
        uint32_t oem_specific_data = 0xFFFFFFFF; // OEM specific data

        // Activate DoIP routing
        int32_t ret_14_doip_routing = tsdiag_doip_routing_activation(udsHandle, activate_type, whether_send_oem_data, oem_specific_data);
        printf("tsdiag_doip_routing_activation result=%d\n", ret_14_doip_routing);

        sleep(2); // Sleep for 2 seconds

        // Define request and response buffers for DoIP
        uint8_t req[2] = {0x10, 0x3}; // Request data. 진단 요청
        int32_t req_size = 2; // Request size

        uint8_t res[10]; // Response buffer. 진단 응답
        int32_t res_size = 10; // Response size

        // Send request and get response
        int32_t ret_15_doip_req_res = tstp_request_and_get_response(udsHandle, req, 2, res, &res_size);
        printf("tsdiag_doip_routing_activation result=%d\n", ret_15_doip_req_res);
        // print(res[0:2])
       
        // Stop logging
        int32_t ret_16_logging_stop = tsapp_stop_logging();
        printf("tsapp_stop_logging result=%d\n", ret_16_logging_stop);
       
        // Disconnect from the TSMaster
        int32_t ret_17_disconnect = tsapp_disconnect();
        printf("tsapp_disconnect result=%d\n", ret_17_disconnect);

        // Finalize the TSMaster library
        finalize_lib_tsmaster();

        return 0; // Return 0 to indicate successful execution
    }

     

     

    하드웨어 설정 부분 코딩 팁

    • 코드에서 하드웨어 설정 부분은 아래 방법으로 작성할 수 있다.
    • 메인 메뉴/ Hardware/ Channel Selection 버튼을 클릭하여 TSMaster Application Channel Selection 창을 연다. 그리고 하드웨어 설정을 한다. 설정을 마친 후, "C" 버튼을 클릭한다. 

    • C 코드 윈도가 열리고, 코드가 클립보드에 복사된다. 코딩 창에 붙여넣기 하면 된다. 

    전체 코드는 아래 코드 블록의 내용과 같다.

     

    initialize_lib_tsmaster("TSMaster");
    tsapp_set_can_channel_count(0);
    tsapp_set_lin_channel_count(0);
    tsapp_set_flexray_channel_count(0);
    tsapp_set_ethernet_channel_count(1);
    tsapp_set_ai_channel_count(0);
    tsapp_set_ao_channel_count(0);
    tsapp_set_di_channel_count(0);
    tsapp_set_do_channel_count(0);
    tsapp_set_gps_channel_count(0);
    
    TLIBTSMapping m;
    
    // TSMaster Ethernet Channel 1 - TS Virtual Device 1 Ethernet Channel 1 
    m.init();
    sprintf_s(m.FAppName, "%s", "TSMaster");
    sprintf_s(m.FHWDeviceName, "%s", "TS Virtual Device");
    m.FAppChannelIndex = 0;
    m.FAppChannelType = (TLIBApplicationChannelType)3;
    m.FHWDeviceType = (TLIBBusToolDeviceType)1;
    m.FHWDeviceSubType = -1;
    m.FHWIndex = 0;
    m.FHWChannelIndex = 0;
    if (0 != tsapp_set_mapping(&m)) { /* handle error */ };
    
    if (0 != tsapp_connect()){ /* handle error */ };
    
    /* do your work here */
    
    tsapp_disconnect();
    finalize_lib_tsmaster();

     

     

    DoIP 설정

    • 코드의 아래 부분은
        // Define parameters for the DoIP connection
        int32_t udsHandle = 0; // Handle for the UDS connection
        int32_t ToolType = 0; // Type of the tool
        uint32_t ChnIndex = 0; // Channel index
        char *Tester_IP = "172.20.0.36"; // Tester IP address
        uint16_t Tester_PORT = 31281; // Tester port
        char *DUT_IP = "172.20.0.38"; // Device Under Test IP address
        uint16_t DUT_PORT = 13400; // Device Under Test port

        uint32_t req_id = 0x0E00; // Request ID
        uint32_t res_id = 0x0373; // Response ID
        uint32_t func_id = 0x0042; // Function ID
    • Diagnostics 창의 Transport Layer 설정에 해당한다. 

    • 아래 코드에서 udsHandle은

       int32_t udsHandle = 0; // Handle for the UDS connection 

    • 아래 코드에서 udsHandle은 메인 메뉴/ Application/ Diagnostic Module 에서 Add Diagnostic 또는 Add DiagnosticDB으로 추가한 "윈도 번호 - 1"한 값이다. 아래 그림에는 윈도가 2개 있다. 번호는 각각 1과 2이다. udsHandle 값은 각각 0과 1이다.

    • 코드의 아래 부분은
        uint8_t activate_type = 0xE2; // Activation type
        bool whether_send_oem_data = true; // Flag to send OEM data
        uint32_t oem_specific_data = 0xFFFFFFFF; // OEM specific data

        // Activate DoIP routing
        int32_t ret_14_doip_routing = tsdiag_doip_routing_activation(udsHandle, activate_type, whether_send_oem_data, oem_specific_data);
        printf("tsdiag_doip_routing_activation result=%d\n", ret_14_doip_routing);

     

    • Diagnostics 창의 Diagnostic Layer 설정에 해당한다. 

     

     

    UDS 진단 요청 송신과 응답 수신

    • DoIP로 진단 요청 메시지를 전송하고 응답 메시지를 수신하는 방법은 아래 코드와 같이 간단하다. 아래 예에서 요청 메시지는 "10 03" (Session Control Extended Diagnostic Session)이다. 
        // Define request and response buffers for DoIP
        uint8_t req[2] = {0x10, 0x3}; // Request data. 진단 요청
        int32_t req_size = 2; // Request size

        uint8_t res[10]; // Response buffer. 진단 응답
        int32_t res_size = 10; // Response size

        // Send request and get response
        int32_t ret_15_doip_req_res = tstp_request_and_get_response(udsHandle, req, 2, res, &res_size);
        printf("tsdiag_doip_routing_activation result=%d\n", ret_15_doip_req_res);
        // print(res[0:2])
       

     

    • 필요에 따라 진단 요청을 변경하며 응답을 해석하는 방법으로 제어기의 진단 기능을 활용할 수 있다. 

     

    UDS 진단 요청과 응답을 조합하여 복잡한 혹은 유연한 서비스 플로우를 프로그램할 수 있을 것이다.  

     

     

     

     

     

    목차 :: hsl's tsmaster 사용기