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

More complete examples #25

Open
11 of 36 tasks
rmelian opened this issue Nov 24, 2021 · 3 comments
Open
11 of 36 tasks

More complete examples #25

rmelian opened this issue Nov 24, 2021 · 3 comments
Assignees
Labels
documentation Improvements or additions to documentation

Comments

@rmelian
Copy link

rmelian commented Nov 24, 2021

Documentation checklist (added by @dfieschko):

  • RP1210.py
    • Functions
    • Dicts/constants
    • RP1210Protocol
    • RP1210Device
    • RP1210Config
    • RP1210API
    • RP1210VendorList
    • RP1210Client
  • Commands.py
    • Functions
    • Dicts/constants
  • J1939.py
    • Functions
    • J1939Message
    • DiagnosticMessage
    • DTC
  • CI/test suite

Examples checklist

  • RP1210.py
    • Functions
    • Dicts/constants
    • RP1210Protocol
    • RP1210Device
    • RP1210Config
    • RP1210API
    • RP1210VendorList
    • RP1210Client
  • Commands.py
    • Functions
    • Dicts/constants
  • J1939.py
    • Functions
    • J1939Message
    • DiagnosticMessage
    • DTC
  • CI/test suite

Hi, thank you for putting this together, is looking great so far.

I am trying to follow along and was trying to send a command like for example to get a response from all modules connected to a truck but I'm having a hard time.
NOTE: I'm just a newbie on the protocol and I still need to buy the spec as you mentioned on the readme.

The ask is to create a more complete example for newcomers like me to be able to try all features available.

I am also willing t collaborate on the project.

@dfieschko dfieschko self-assigned this Nov 24, 2021
@dfieschko dfieschko added the documentation Improvements or additions to documentation label Nov 24, 2021
@dfieschko
Copy link
Owner

dfieschko commented Nov 24, 2021

Thanks for the feedback! I'm definitely planning on making some in-depth examples in the future, but I've been holding off because I'm still changing core features and base functionality, and I don't want to have to redo all the examples with every change.

I am assuming you are using this package to receive and transmit J1939 messages, as that is the only protocol I've added functions for at the moment (and because you mentioned trucks).

One very common pitfall for receiving data via RP1210 drivers is that you must set the filters to pass data. If you forget to do this, you won't be able to receive any data, as it all gets filtered out!

Currently, I've got a fairly simple implementation of this package working in an application I'm working on. It's proprietary and belongs to my company, so I can't give you specifics, but here's the general structure:

  • Created a class RP1210VendorList that holds a list of RP1210Config objects that are automatically initialized from RP121032.ini
  • Instantiate RP1210VendorList on startup with name Vendors, have it auto-populate (with exception handling for goofy drivers)
  • Autoconnect to most recent RP1210 adapter, or allow user to choose one from a couple of combo boxes
    • This calls Vendors.getCurrentVendor().api.ClientConnect(deviceID, b"J1939:Baud=Auto") (it's more complicated than this, of course, what with baud options and choosing deviceIDs, but you get the gist)
    • Upon a successful connection, the clientID returned by ClientConnect() is saved, and is used for future function calls.
  • Set J1939 filters to include PGNs I want to listen to
  • Spin off a thread that calls RP1210_ReadMessage in a loop to receive the aforementioned J1939 messages
  • Call RP1210_SendMessage whenever I want to transmit a message

Here's an example for setting J1939 filters:

# this code will allow you to read messages with PGNs 0xDEAD, 0xBEEF, and 0xFECA
cmd_id = 4 # this is the command ID for SET_MESSAGE_FILTERING_FOR_J1939
filter_type = 0x01 # filter by PGN
pgn_list = [0xDEAD, 0xBEEF, 0xFECA] # filter for PGNs DEAD, BEEF, and FECA (FECA is the PGN for DM1 messages; DEAD and BEEF are made up)
for pgn in pgn_list:
   cmd_string = Commands.setJ1939Filters(filter_type, pgn=pgn) # this will generate the proper byte-string to use in SendCommand
   api.SendCommand(cmd_id, clientID, cmd_string) # this will send the command to set the filter
   # 'api' in this example is an RP1210API object. RP1210Config objects contain an RP1210API by default.
   # this can be accessed like so: rp1210config_obj.api.SendCommand()
   # one can access Nexiq USB-Link 2 API via api = RP1210API("NULN2R32") (assuming it's installed)

Now that I will receive messages with PGNs 0xDEAD, 0xBEEF, and 0xFECA, I spin off a thread that calls ReadMessage() or ReadDirect() in a loop. ReadDirect() is quite easy to use (but has the disadvantage of not giving you error codes):

message_bytes = api.ReadDirect(clientID, num_bytes_to_read)
if message_bytes:
   process_j1939_bytes(message_bytes)

You can also send messages via the API and the toJ1939Message convenience function:

# Set J1939 message parameters
pgn = 0x00BEEF # 3 bytes (pgn is always 3 bytes, even if 0xBEEF can be stored as 2 bytes)
priority = 3 # 1 byte
source = 0xDE # 1 byte
destination = 0xAD # 1 byte
data = 0xDEADBEEFDEADBEEF # 8 bytes
# Generate J1939 message from parameters
message_bytes = J1939.toJ1939Message(pgn, priority, source, destination, data) # this will be 14 bytes (3+1+1+1+8)

# Send the J1939 message (let it figure out message size on its own)
api.SendMessage(clientID, message_bytes)

# Send the J1939 message (specify size of message manually)
api.SendMessage(clientID, message_bytes, 14)

I hope these little example snippets helped! If you give me more detail on what you're doing, I might be able to help more.

There are currently plans for an RP1210Client class that will mimic the behavior of the RP1210VendorList class I described in the bullet points above, plus extra functionality for handling commands, different protocols, etc. The goal is to have an implementation that "just works", at least for J1939. That's some time out though, considering work and other obligations.

Edit: something I forgot to mention - some RP1210 drivers may require you to claim a J1939 address before they will allow you to send messages. Copying an example from the README:

# using RP1210.Commands to help w/ claiming a J1939 address
... # assume RP1210Config has been initalized as 'nexiq' and ClientConnect has been called & clientID has been saved
my_address = 42
my_network_mgt_name = 0xDEADBEEF

# generate params
cmd_num = Commands.COMMAND_IDS["PROTECT_J1939_ADDRESS"] # == 19
cmd_data = Commands.protectJ1939Address(my_address, my_network_mgt_name)
# call SendCommand
err_code = nexiq.api.SendCommand(cmd_num, clientID, cmd_data)

While I have tested the protectJ1939Address() for conformity with the RP1210C standard, I have not tested it in an application, so while it should work, there's no guarantee that it does.

Also, for requesting data from components in your truck, the toJ1939Request() function may be of use to you. This function has also been tested for basic conformity with the RP1210C documentation, but hasn't been tested in-application. You will need to have specific PGNs in mind.

@rmelian
Copy link
Author

rmelian commented Nov 27, 2021

this example is great, thank you. I'll give a try and let you know

@dfieschko dfieschko assigned dfieschko and unassigned dfieschko May 25, 2022
@goliva8115
Copy link

Genial

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

No branches or pull requests

3 participants