{"id":29112143,"url":"https://github.com/jackm/j1939decode","last_synced_at":"2025-06-29T10:04:56.664Z","repository":{"id":54701279,"uuid":"251697655","full_name":"jackm/j1939decode","owner":"jackm","description":"J1939 decode C library","archived":false,"fork":false,"pushed_at":"2021-03-16T01:03:24.000Z","size":96,"stargazers_count":31,"open_issues_count":0,"forks_count":8,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-05-02T02:04:26.124Z","etag":null,"topics":["can","decode","j1939","json"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jackm.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-03-31T18:36:36.000Z","updated_at":"2023-11-22T05:32:35.000Z","dependencies_parsed_at":"2022-08-14T00:30:41.675Z","dependency_job_id":null,"html_url":"https://github.com/jackm/j1939decode","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/jackm/j1939decode","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jackm%2Fj1939decode","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jackm%2Fj1939decode/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jackm%2Fj1939decode/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jackm%2Fj1939decode/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jackm","download_url":"https://codeload.github.com/jackm/j1939decode/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jackm%2Fj1939decode/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262574123,"owners_count":23330779,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["can","decode","j1939","json"],"created_at":"2025-06-29T10:04:46.912Z","updated_at":"2025-06-29T10:04:56.648Z","avatar_url":"https://github.com/jackm.png","language":"C","readme":"# J1939 decode library\n\nDecode J1939 CAN bus messages into a JSON string representation of what the payload data means based on the SAE standard.\n\nThis library by default will attempt to read the file `J1939db.json` from the current directory to load in the J1939 database.\nIf this file cannot be read, J1939 decoding will not be possible.\nThis file name and path can changed by redefining the `J1939DECODE_DB` C macro to point to a different filename.\n\n***See below for how to generate the J1939 database file.***\n\n## Building\n\nCreate a build directory relative to project root, run cmake and then make.\n\n```\nmkdir -p build\ncd build\ncmake ..\nmake -j\n```\n\n## Cleaning\n\nRemove generated directories: `build/`\n\n## Install\n\nTo install first build the library, then run `sudo make install` from within the build directory.\n\n## Uninstall\n\nTo uninstall run `sudo make uninstall` from within the build directory.\n\n## Testing\n\nUnit tests make use of the [Unity testing framework](http://www.throwtheswitch.org/unity) which is used by the [Ceedling](http://www.throwtheswitch.org/ceedling) build system.\n\nTo start all tests run `ceedling test:all`.\n\n## Library usage\n\nCall `j1939decode_init()` first _before_ calling `j1939decode_to_json()`.\n\nWhen done, call `j1939decode_deinit()` to free memory allocated by `j1939decode_init()` and also remember to free the string pointer returned by `j1939decode_to_json()`.\n\n### User-supplied log handler\n\n`j1939decode_set_log_fn()` can be used to set a user-supplied log handler function.\n`j1939decode_set_log_fn()` should be called _before_ calling `j1939decode_init()` since library initialization may generate log messages.\n\nThe replacement log handler should have the following signature:\n\n```c\nvoid custom_log_handler(const char * msg);\n```\n\nIf NULL is supplied for j1939decode_set_log_fn or it is not called at all, then the default logger function will be used, which prints all log messages to stderr.\n\n## J1939 database file generation\n\nThe `J1939db.json` database file is a JSON formatted file that contains all of the PGN, SPN, and SA lookup data needed for decoding J1939 messages.\n\nThis database file can be generated using the `create_j1939db-json.py` script provided by [pretty\\_j1939](https://github.com/nmfta-repo/pretty_j1939) repository.\nA copy of the [SAE J1939 Digital Annex](https://www.sae.org/standards/content/j1939da_201704/) spreadsheet is required.\n\nFor example:\n\n```\ncreate_j1939db-json.py -f J1939DA_201704.xls -w J1939db.json\n```\n\n## JSON format\n\nThe output JSON string generated by `j1939decode_to_json()` contains the following fields.\nWhere possible, the decoder will attempt to decode the CAN message according to the J1939 protocol spec.\n\n* \"_ID_\": CAN identifier\n* \"_Priority_\": message priority\n* \"_PGN_\": parameter group number\n* \"_PGNName_\": parameter group number descriptive name\n* \"_SA_\": source address\n* \"_SAName_\": source address descriptive name\n* \"_DLC_\": data length code\n* \"_DataRaw_\": array of CAN data bytes, MSB first\n* \"_Decoded_\": boolean indicating if J1939 decoding was successful (i.e. one or more SPNs decoded)\n* \"_SPNs_\": object containing all decoded suspect parameter numbers associated with the given PGN\n\nSPN objects use their SPN number as their name, and contain a sub-object with members specific to that SPN.\n\nThe following members are found within an SPN sub-object.\nAll members relate to the specific SPN under which they are found.\n\n* \"_Name_\": suspect parameter number descriptive name\n* \"_DataRange_\": valid data value range as a human-readable string\n* \"_OperationalRange_\": valid data value range (in decoded data value units)\n* \"_OperationalHigh_\": maximum valid data value (in decoded data value units)\n* \"_OperationalLow_\": minimum valid data value (in decoded data value units)\n* \"_StartBit_\": starting bit number of data within 64 bit data field\n* \"_SPNLength_\": length of data in bits\n* \"_Resolution_\": scaling multiplier\n* \"_Offset_\": linear offset\n* \"_ValueRaw_\": raw data value without resolution and offset applied\n* \"_ValueDecoded_\": decoded data value\n* \"_Units_\": units of the decoded data value\n* \"_Valid_\": boolean indicating if the decoded data value is valid (i.e. is within operational data range)\n\nExample JSON object for a fully decoded J1939 CAN message:\n\n```json\n{\n  \"ID\": 217056256,\n  \"Priority\": 3,\n  \"PGN\": 61444,\n  \"PGNName\": \"Electronic Engine Controller 1\",\n  \"SA\": 0,\n  \"SAName\": \"Engine #1\",\n  \"DLC\": 8,\n  \"DataRaw\": [240, 125, 131, 131, 23, 0, 255, 131],\n  \"Decoded\": true,\n  \"SPNs\": {\n    \"190\": {\n      \"Name\": \"Engine Speed\",\n      \"DataRange\": \"0 to 8,031.875 rpm\",\n      \"OperationalRange\": \"\",\n      \"OperationalHigh\": 8031.875,\n      \"OperationalLow\": 0,\n      \"StartBit\": 24,\n      \"SPNLength\": 16,\n      \"Resolution\": 0.125,\n      \"Offset\": 0,\n      \"ValueRaw\": 6019,\n      \"ValueDecoded\": 752.375,\n      \"Units\": \"rpm\",\n      \"Valid\": true\n    },\n    ...\n  }\n}\n```\n\nThe ellipses shows where additional SPN sub-objects would appear.\n\n#### Important notes:\n\n* \"_Decoded_\" boolean should be checked before using the members in the SPN sub-object(s); if it is _false_, then the \"_SPNs_\" object may not even exist\n* \"_Valid_\" boolean from within an SPN sub-object should be checked before using the decoded data value; most often if the decoded data value is not valid, it will be set to the string \"Not Available\"\n* \"_PGNName_\" and \"_SPNName_\" values are found using a simple lookup table based on their number values; if the decoded CAN message is not a real J1939 message these members may still exist if the CAN identifier bits happen to match a value found in the J1939 protocol spec although this does not necessarily mean that the CAN message was a valid J1939 message\n\n## TODO\n\n* Improve speed of J1939 DB lookup.\n  At the moment the processing speed to decode a message is not great and at a high message rate it can lag behind if decoding in real-time.\n  The `hash-tables` branch uses C++ container objects (hash maps) to improve the lookup speed however it is no longer pure C code.\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjackm%2Fj1939decode","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjackm%2Fj1939decode","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjackm%2Fj1939decode/lists"}