Mit SocketCAN Daten lesen



  • Hallo liebes c++-Team,

    ich bin neu und hoffe, dass ich hier richtig bin.

    Ich soll mich mit dem SocketCAN auseinandersetzen und Daten vom CAN lesen.

    Ich habe dazu folgendes bekommen bzw. gefunden:

    https://www.kernel.org/doc/Documentation/networking/can.txt

    http://www.brownhat.org/docs/socketcan/llcf-api.html#SECTION00060000000000000000

    Allerdings möchte ich kein RAW-Socket sondern ein BroadcastManager Socket.

    Darauf aufbauend hab ich mir folgendes zusammengebaut:

    /* includes */
    #include <iostream>
    #include <fstream>
    #include <sstream>
    #include <string>
    
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <sys/ioctl.h>
    #include <net/if.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <linux/can.h>
    #include <linux/can/bcm.h>
    
    using namespace std;
    
    typedef struct {
    		struct bcm_msg_head msg_head;
    		struct can_frame frame;
    } bcm_msg;
    
    int main(){
    
       /* Create the socket */
       int skt = socket( PF_CAN, SOCK_DGRAM, CAN_BCM );
       cout << "Socket anlegen endete mit " << skt << endl;
    
    	bcm_msg msg;
    	struct can_frame frame;
    
       /* Locate the interface you wish to use */
       struct ifreq ifr;
       strcpy(ifr.ifr_name, "can0");
       ioctl(skt, SIOCGIFINDEX, &ifr); /* ifr.ifr_ifindex gets filled
                                        * with that device's index */
    
       /* Select that CAN interface, and bind the socket to it. */
       struct sockaddr_can addr;
       addr.can_family = AF_CAN;
       addr.can_ifindex = ifr.ifr_ifindex;
       int nr = connect( skt, (struct sockaddr*)&addr, sizeof(addr) );
       cout << "connect() endete mit " << nr << endl;
    
    	msg.msg_head.opcode  = RX_SETUP;
    	msg.msg_head.can_id  = 0x1a0;
    	msg.msg_head.flags   = RX_FILTER_ID;
    	msg.msg_head.ival1.tv_sec  = 0;
    	msg.msg_head.ival1.tv_usec = 0;
    	msg.msg_head.ival2.tv_sec  = 0;
    	msg.msg_head.ival2.tv_usec = 0;
    	msg.msg_head.nframes = 1; /* frame data not necessary */
    	msg.frame.can_dlc = 8;
    	msg.frame.can_id = 0xa10;
    
    	msg.msg_head.flags &= ~(STARTTIMER); /* allow reuse of the same msg buffer */
    
       msg.frame.can_id = 0x1a0;
       strcpy( (char*)msg.frame.data, "foo" );
       frame.can_dlc = strlen( (char*)frame.data );
       cout << "strlen..." << endl;
    
       /* Read a message back from the CAN bus */
       int bytes_read = recv( skt, &frame, sizeof(frame), NULL);
    
    	cout << "Gelesene Bytes: " << bytes_read << endl;
    
    	return 0;
    }
    

    Ich bekomme keine Fehler, aber er hängt im read()-Befehl fest und tut nichts mehr.

    In meinem Beispiel möchte ich das Signal mit ID 0x1A0 mit der Länge 8 Bytes lesen.

    Mit candump hab ich überprüft, dass wirklich Daten kommen 😉

    Wisst ihr wo mein Fehler liegt ? 😕



  • Ergänzung:

    Ich meine er hängt im recv() fest.
    Ich hatte es vorher mit read() und dachte mit recv() würde es gehen



  • Ich denke ich kann hier vielleicht nicht mehr dem Autor helfen, aber vielleicht stolpert jemand anderes noch über das Problem.
    Ich hatte auch das Problem, dass in meinem Testprogramm mein Programm im read() hängen geblieben ist und bei eingehenden Nachrichten nicht mehr weiter gemacht hat.

    Für mich hat es gereicht das "using namespace std;" raus zu schmeißen. Vermutlich gibt es hier irgendeinen Konflikt.

    Ich hoffe ich kann damit, noch irgendwem helfen 🙂


Anmelden zum Antworten