Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How do I assign J1939 standard to a message? #574

Open
rotschaedel opened this issue Jun 1, 2023 · 10 comments
Open

How do I assign J1939 standard to a message? #574

rotschaedel opened this issue Jun 1, 2023 · 10 comments

Comments

@rotschaedel
Copy link

rotschaedel commented Jun 1, 2023

Hello,

I want to create a dbc file with a J1939 message. But after i save the file and open it with another program the message just shows CAN Extended as ID Format. Could anyone explain to me why it is not working?

Here a short code example:

                                 is_signed=True, scale=1, offset=0, unit=None, spn=1586)

frame1 = cantools.db.can.Message(name="Msg1", frame_id=0x16fd3b09, protocol="j1939",
                                 is_extended_frame=True, length=8, signals=[signal1],
                                 cycle_time=50, senders=["A"])

db_cantools = cantools.db.can.Database(messages=[frame1])

cantools.db.dump_file(db_cantools, "test_db.dbc")

And a picture how it looks like in CANdb:
VJXsD

@andlaus
Copy link
Member

andlaus commented Jun 1, 2023

I'm in no way an expert when it comes to J1939, but I suspect that the DBC writing code simply does not consider its peculiarities. do you know anything about this @juleq?

@juleq
Copy link
Collaborator

juleq commented Jun 1, 2023

There is only minimal support of j1939 in cantools.

That said, what was your expectation? I do not remember if CANdb++ does interpret j1939 specifics. But note that the ID remains extended, it is just interpreted according to j1939 by upper layers. We have the Vector tooling with j1939 option, but I am not sure if the CANdb++ variant is any different.

@rotschaedel
Copy link
Author

That said, what was your expectation?

I have a different DBC file where it is like this:
image
image

There i can choose between those three for the ID Format/Type. Yes it remains extended but by creating the DBC file i can lose some information.

For this DBC file which has the j1939 type in it, i can also find with

db.dbc.attributes

this dict of attributes of the database:

OrderedDict([('ProtocolType', attribute('ProtocolType', J1939)),...)

I don't know if that would be the key, to create this attribute, but I also don't know how i do that. Also in the attributes of the messages i find j1939 but same problem (don't know how to create them).

@geo4711
Copy link
Contributor

geo4711 commented Jun 3, 2023

Hi,
there are some special conditions in a dbc for full J1939 support, I can only remember a few (like the ProtocolType, maybe also the BusType, and of course the frame type).
I don't know an official specification for that. But I know that some tools (CANoe, CANalyzer, vSignalzer, ...) rely on a certain "DBC style" (the "Vector Style"). I have observed different strang effects with J1939 files that do not stick to the Vector style, e. g.:

  • Using different enums for frametype lets vSignalyzer fail decoding some frames with dynamic priority field (however, CANoe/CANalyzer do fine

So, creating a J1939 DBC file from scratch might be very hard (and frustrating). For your use case this:

  • Create a new DBC with CANdb++, based on the J1939 template. Save this to an "empty" DBC --> CANdb++ cares about all the special enum definitions etc.
  • with cantools:
    -- load this blueprint file
    -- add your messages
    -- dump to a new file

I hope this helps! Good luck!

P.S.: If you need CAN FD together with J1939, checkout the latest version of CANdb++. The version I currently have does not support having both CAN FD and J1939 frames in the same file. My CANdb++ version is older than the related SAE documents. Maybe Vector has updated the CANdb++ in the meanwhile.

@rotschaedel
Copy link
Author

rotschaedel commented Jun 7, 2023

Hi @geo4711,
thanks for your answer. I tried it now and it works (almost too good). Now all messages turn into J1939, even if i give the message the attribute protocol=None (I have some messages which still use CAN Standard or CAN Extended). Do you know if there is a way how i could fix that?

Edit: Or is it possible to create two databases (one j1939 and a normal one) and merge them together before i dump them into a new file?

BR

@geo4711
Copy link
Contributor

geo4711 commented Jun 9, 2023

Hi @rotschaedel,
I just had a try and can confirm your observation: cantools does not reflect the frame type when dumping the database to a file. I guess it's not a big effort to add/fix this functionality, but currently I won't manage to do this by my own.
If you're familiar with the source code, you could give it a try and create a pull request.
About your "merging" question: I think to plan merging with cantools: I don't expect that to work, as a merge function in general has not been implemented yet. And the problem in this case is caring about attributes that have different default values in the two dbcs. So it's not just concatenating two lists of message :-(
BR

@geo4711
Copy link
Contributor

geo4711 commented Jun 9, 2023

Hi @rotschaedel,
I found a quick workaround which might help you. An explanation first:

  • every attribute in a dbc file needs a default value. For the frame type in a J1939 dbc, the default value is "J1939" (you might change this, but that's how it is in my files)
  • If you don't specify an attribute's value for an object (e. g. a message), the default value applies. If an objects shall use the default value, there's no need to write this explicitely. However, it is allowed.
  • cantools considers the frametype when reading dbcs, but it does not write the frametype (in fact it keeps the original value unchanged)
  • if you create new objects (e. g. messages) with cantools, the attribute won't be written --> the default value will apply

Now here's the workaround:

  • prepare your template dbc so that it contains a dummy frame defined as "Extended CAN"
  • use the frame setting (located in a nested object hierarchy) and copy it to your new frames

Example code:

import copy
...
db = cantools.database.load_file(<your_template_dbc>)
my_template_msg_ext_frame = db.get_message_by_name(<your_ext_frame_message>)

# "save" the frame type:
att_tmpl_extFrame = copy.deepcopy(my_template_msg_ext_frame)

new_extFrame = cantools.database.Message(frame_id=0x1, name="new_ext_frame", is_extended_frame=True, protocol=None, length=8, signals=[])

# apply the frame type:
new_extFrame.dbc = att_tmpl_extFrame

db.messages.append(new_extFrame)

This worked for me, hope it does for you as well. Of course you can try to assign the attributes from scratch. But I found that quite tricky due to the nested object hierarchy.

BR
Martin

P.S.: Implementing a proper fix would be a bigger effort (to be backwards compatible for dbcs not using J1939 etc.).

@rotschaedel
Copy link
Author

rotschaedel commented Jun 14, 2023

Hi @geo4711 ,

thanks for the workaround! I will try to implement it in the next days. But one question if i understand it correctly: I should create in my j1939 template a dummy message which i use for not j1939 messages?

Sadly I'm not really into the source code, so I'm probably not able to create this pull request. But thanks again for your help!

BR

Edit: When trying your workaround i receive the error message when dumping the file: AttributeError: 'Message' object has no attribute 'attributes' :(

@geo4711
Copy link
Contributor

geo4711 commented Jun 15, 2023

Hi @rotschaedel,
you could try with a template dbc like this:

image

VERSION ""


NS_ : 
	NS_DESC_
	CM_
	BA_DEF_
	BA_
	VAL_
	CAT_DEF_
	CAT_
	FILTER
	BA_DEF_DEF_
	EV_DATA_
	ENVVAR_DATA_
	SGTYPE_
	SGTYPE_VAL_
	BA_DEF_SGTYPE_
	BA_SGTYPE_
	SIG_TYPE_REF_
	VAL_TABLE_
	SIG_GROUP_
	SIG_VALTYPE_
	SIGTYPE_VALTYPE_
	BO_TX_BU_
	BA_DEF_REL_
	BA_REL_
	BA_DEF_DEF_REL_
	BU_SG_REL_
	BU_EV_REL_
	BU_BO_REL_
	SG_MUL_VAL_

BS_:

BU_:


BO_ 2348941054 a_standard_frame: 8 Vector__XXX

BO_ 2348875518 a_J1939_pgn: 8 Vector__XXX



BA_DEF_ BO_  "FsJ1939UseCrcAndCounter" STRING ;
BA_DEF_ BO_  "FsJ1939NeedsSHM" ENUM  "No","Yes";
BA_DEF_ BO_  "FsJ1939Delay" INT 0 1000;
BA_DEF_ BO_  "TpJ1939VarDlc" ENUM  "No","Yes";
BA_DEF_ SG_  "SigType" ENUM  "Default","Range","RangeSigned","ASCII","Discrete","Control","ReferencePGN","DTC","StringDelimiter","StringLength","StringLengthControl","MessageCounter","MessageChecksum";
BA_DEF_ SG_  "GenSigEVName" STRING ;
BA_DEF_ SG_  "GenSigILSupport" ENUM  "No","Yes";
BA_DEF_ SG_  "GenSigSendType" ENUM  "Cyclic","OnWrite","OnWriteWithRepetition","OnChange","OnChangeWithRepetition","IfActive","IfActiveWithRepetition","NoSigSendType";
BA_DEF_ BO_  "GenMsgFastOnStart" INT 0 100000;
BA_DEF_ SG_  "GenSigInactiveValue" INT 0 0;
BA_DEF_ BO_  "GenMsgCycleTimeFast" INT 0 3600000;
BA_DEF_ BO_  "GenMsgNrOfRepetition" INT 0 1000000;
BA_DEF_ SG_  "GenSigStartValue" INT 0 2147483647;
BA_DEF_ BO_  "GenMsgDelayTime" INT 0 1000;
BA_DEF_ BO_  "GenMsgILSupport" ENUM  "No","Yes";
BA_DEF_ BO_  "GenMsgStartDelayTime" INT 0 100000;
BA_DEF_ BU_  "NodeLayerModules" STRING ;
BA_DEF_ BU_  "ECU" STRING ;
BA_DEF_ BU_  "NmJ1939SystemInstance" INT 0 15;
BA_DEF_ BU_  "NmJ1939System" INT 0 127;
BA_DEF_ BU_  "NmJ1939ManufacturerCode" INT 0 2047;
BA_DEF_ BU_  "NmJ1939IndustryGroup" INT 0 7;
BA_DEF_ BU_  "NmJ1939IdentityNumber" INT 0 2097151;
BA_DEF_ BU_  "NmJ1939FunctionInstance" INT 0 7;
BA_DEF_ BU_  "NmJ1939Function" INT 0 255;
BA_DEF_ BU_  "NmJ1939ECUInstance" INT 0 3;
BA_DEF_ BU_  "NmJ1939AAC" INT 0 1;
BA_DEF_ BU_  "NmStationAddress" INT 0 255;
BA_DEF_ BO_  "GenMsgSendType" ENUM  "cyclic","NotUsed","IfActive","NotUsed","NotUsed","NotUsed","NotUsed","NotUsed","noMsgSendType";
BA_DEF_ BO_  "GenMsgRequestable" INT 0 1;
BA_DEF_ BO_  "GenMsgCycleTime" INT 0 3600000;
BA_DEF_ SG_  "SPN" INT 0 524287;
BA_DEF_  "DBName" STRING ;
BA_DEF_  "BusType" STRING ;
BA_DEF_  "ProtocolType" STRING ;
BA_DEF_ BO_  "VFrameFormat" ENUM  "StandardCAN","ExtendedCAN","reserved","J1939PG";
BA_DEF_DEF_  "FsJ1939UseCrcAndCounter" "";
BA_DEF_DEF_  "FsJ1939NeedsSHM" "No";
BA_DEF_DEF_  "FsJ1939Delay" 0;
BA_DEF_DEF_  "TpJ1939VarDlc" "No";
BA_DEF_DEF_  "SigType" "Default";
BA_DEF_DEF_  "GenSigEVName" "Env@Nodename_@Signame";
BA_DEF_DEF_  "GenSigILSupport" "Yes";
BA_DEF_DEF_  "GenSigSendType" "NoSigSendType";
BA_DEF_DEF_  "GenMsgFastOnStart" 0;
BA_DEF_DEF_  "GenSigInactiveValue" 0;
BA_DEF_DEF_  "GenMsgCycleTimeFast" 0;
BA_DEF_DEF_  "GenMsgNrOfRepetition" 0;
BA_DEF_DEF_  "GenSigStartValue" 0;
BA_DEF_DEF_  "GenMsgDelayTime" 0;
BA_DEF_DEF_  "GenMsgILSupport" "Yes";
BA_DEF_DEF_  "GenMsgStartDelayTime" 0;
BA_DEF_DEF_  "NodeLayerModules" "";
BA_DEF_DEF_  "ECU" "";
BA_DEF_DEF_  "NmJ1939SystemInstance" 0;
BA_DEF_DEF_  "NmJ1939System" 0;
BA_DEF_DEF_  "NmJ1939ManufacturerCode" 0;
BA_DEF_DEF_  "NmJ1939IndustryGroup" 0;
BA_DEF_DEF_  "NmJ1939IdentityNumber" 0;
BA_DEF_DEF_  "NmJ1939FunctionInstance" 0;
BA_DEF_DEF_  "NmJ1939Function" 0;
BA_DEF_DEF_  "NmJ1939ECUInstance" 0;
BA_DEF_DEF_  "NmJ1939AAC" 0;
BA_DEF_DEF_  "NmStationAddress" 254;
BA_DEF_DEF_  "GenMsgSendType" "noMsgSendType";
BA_DEF_DEF_  "GenMsgRequestable" 1;
BA_DEF_DEF_  "GenMsgCycleTime" 0;
BA_DEF_DEF_  "SPN" 0;
BA_DEF_DEF_  "DBName" "";
BA_DEF_DEF_  "BusType" "CAN";
BA_DEF_DEF_  "ProtocolType" "J1939";
BA_DEF_DEF_  "VFrameFormat" "J1939PG";
BA_ "DBName" "mixed_J1939";
BA_ "VFrameFormat" BO_ 2348941054 1;
BA_ "VFrameFormat" BO_ 2348875518 3;

BR
Martin

@rotschaedel
Copy link
Author

@geo4711

There i get the same error message. I think the problem is dump_file. When i remove it, the program runs without errors.

BR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants