[
  {
    "path": ".travis.yml",
    "content": "dist: trusty\nsudo: required\nlanguage: cpp\n\naddons:\n  apt:\n    sources:\n      - ubuntu-toolchain-r-test\n    packages:\n      - g++-6\n      - libgtest-dev\n      - protobuf-compiler\n      - libprotobuf-dev\n      \ninstall:\n  - pushd ~\n  - git clone https://github.com/open-source-parsers/jsoncpp.git\n  - pushd jsoncpp\n  - cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON \n  - sudo make install\n  - popd\n  - popd\n  - pushd ~\n  - git clone https://github.com/warmcat/libwebsockets.git\n  - pushd libwebsockets\n  - cmake .\n  - sudo make install\n  - popd\n  - popd\n  - pushd /usr/src/gtest\n  - sudo env \"PATH=$PATH\" cmake CMakeLists.txt\n  - sudo make\n  - sudo cp *.a /usr/lib\n  - popd\n  \n\nscript:\n  - CXX=/usr/bin/g++-6 CC=/usr/bin/gcc-6 cmake .\n  - cmake --build .\n  - ./Tests/execTests\n"
  },
  {
    "path": "BinTest/AccelCCVS/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.5)\n\nproject(accelCCVS)\n\nset(CMAKE_BUILD_TYPE Debug)    #For debug purposes\n\nfind_package(J1939Framework REQUIRED)\n\nadd_definitions(-DDATABASE_PATH=\"${J1939_Database}\")\n\nset(CMAKE_CXX_STANDARD 11)\n\nadd_executable(accelCCVS \n    src/accelCCVS.cpp\n)\n\n\ntarget_link_libraries(accelCCVS\n    PUBLIC\n        J1939 Can rt -rdynamic\n)\n\n\ninstall (TARGETS accelCCVS\n    DESTINATION bin)\n"
  },
  {
    "path": "BinTest/AccelCCVS/src/accelCCVS.cpp",
    "content": "#ifndef DATABASE_PATH\n#define DATABASE_PATH\t\t\"/etc/j1939/frames.json\"\n#endif\n\n#include <getopt.h>\n\n#include <memory>\n#include <chrono>\n#include <thread>\n\n#include <CanEasy.h>\n\n#include <SPN/SPNNumeric.h>\n#include <J1939Frame.h>\n#include <GenericFrame.h>\n#include <J1939Factory.h>\n\n\n#define BAUD_250K\t\t\t250000\n#define MAX_ACCEL_VALUE\t\t2 /*m/s²*/\n#define DIFF_ACCEL\t\t\t0.5\n\n\nusing namespace J1939;\nusing namespace Can;\nusing namespace Utils;\n\n\nint\nmain (int argc, char **argv)\n{\n\n\tCanEasy::initialize(BAUD_250K);\n\n\tstd::set<std::string> interfaces = CanEasy::getCanIfaces();\n\n\n\tstd::shared_ptr<ICanSender> sender = CanEasy::getSender(\"vcan0\");\n\n\tif(!sender) {\n\t\tstd::cerr << \"Cannot send through the interface\" << std::endl;\n\t\treturn -1;\n\t}\n\n\t//Read database if available\n\tif(!J1939Factory::getInstance().registerDatabaseFrames(DATABASE_PATH)) {\n\t\tstd::cerr << \"Database not found in \" << DATABASE_PATH << std::endl;\n\t\texit(-2);\n\t}\n\t\n\tstd::unique_ptr<J1939Frame> myFrame = J1939Factory::getInstance().getJ1939Frame(\"CCVS\");\n\n\tif(!myFrame)\t\treturn -3;\n\n\tGenericFrame *ccvsFrame = static_cast<GenericFrame *>(myFrame.get());\n\n\tSPNNumeric *spnSpeed = static_cast<SPNNumeric*>(ccvsFrame->getSPN(84));\n\n\tccvsFrame->setPriority(3);\n\tccvsFrame->setSrcAddr(0x20);\n\n\n\tCanFrame frame(true, ccvsFrame->getIdentifier());\n\n\tsender->sendFrame(frame, 100, [ccvsFrame](u32 id, std::string& data) {\t\t//We need to modify speed dynamically\n\n\t\tsize_t length = ccvsFrame->getDataLength();\n\t\tu8* buff = new u8[length];\n\n\t\tccvsFrame->encode(id, buff, length);\n\n\t\t//Set data\n\t\tdata.append((char*)buff, length);\n\n\t\tdelete[] buff;\n\n\t});\n\n\tdouble diffAccel = DIFF_ACCEL;\n\tbool inc = true;\n\n\tdouble accel = /*0*/MAX_ACCEL_VALUE;\n\tdouble speed = 2;\n\tdouble coef = 1;\n\n\twhile(true) {\n\n\t\t//Simulate acceleration\n\t\tspeed += accel*36/100;\n\t\tstd::cout << \"Accel: \" << accel << std::endl;\n\t\tstd::cout << \"Speed: \" << speed << std::endl;\n\n\t\tspnSpeed->setFormattedValue(speed);\n\n\t\t//modify accel\n\n\t\t\n\t\tif(inc) {\n\t\t\taccel += diffAccel * coef;\n\t\t} else {\n\t\t\taccel -= diffAccel * coef;\n\t\t}\n\n\t\tcoef = MAX_ACCEL_VALUE - abs(accel);\n\t\tif(coef < 0.1) coef = 0.1;\n\n\t\tcoef /= MAX_ACCEL_VALUE;\n\n\t\tif(accel >= MAX_ACCEL_VALUE)\tinc = false;\n\t\tif(accel <= -MAX_ACCEL_VALUE)\tinc = true;\n\t\t\n\n\t\tstd::this_thread::sleep_for(std::chrono::milliseconds(100));\n\n\t}\n\n\n\treturn 0;\n}\n\n\n"
  },
  {
    "path": "BinTest/FrameInject/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.5)\n\nproject(frameInject)\n\nset(CMAKE_BUILD_TYPE Debug)    #For debug purposes\n\nfind_package(J1939Framework REQUIRED)\n\nadd_definitions(-DDATABASE_PATH=\"${J1939_Database}\")\n\nset(CMAKE_CXX_STANDARD 11)\n\nadd_executable(frameInject \n    src/frame_inject.cpp\n)\n\n\ntarget_link_libraries(frameInject\n    PUBLIC\n        J1939 Can rt -rdynamic\n)\n\n\ninstall (TARGETS frameInject\n    DESTINATION bin)\n"
  },
  {
    "path": "BinTest/FrameInject/src/frame_inject.cpp",
    "content": "#ifndef DATABASE_PATH\n#define DATABASE_PATH\t\t\"/etc/j1939/frames.json\"\n#endif\n\n#include <getopt.h>\n\n#include <memory>\n#include <chrono>\n#include <thread>\n\n#include <CanEasy.h>\n\n#include <SPN/SPNNumeric.h>\n#include <J1939Frame.h>\n#include <GenericFrame.h>\n#include <J1939Factory.h>\n\n\n#include <TRCReader.h>\n#include <TRCWriter.h>\n\n\nusing namespace J1939;\nusing namespace Can;\nusing namespace Utils;\n\n\nint\nmain (int argc, char **argv)\n{\n\n\tTRCReader trcReader;\n\tTRCWriter writer;\n\n\t//Read database if available\n\tif(!J1939Factory::getInstance().registerDatabaseFrames(DATABASE_PATH)) {\n\t\tstd::cerr << \"Database not found in \" << DATABASE_PATH << std::endl;\n\t\texit(-2);\n\t}\n\n\tif(!trcReader.loadFile(\"input.trc\")) {\n\t\tstd::cerr << \"TRC file is corrupted or not readable by \" << argv[0] << std::endl;\n\t\treturn -2;\n\t}\n\n\tif(trcReader.getNumberOfFrames() == 0) {\n\t\tstd::cerr << \"TRC file is empty\" << std::endl;\n\t\treturn -3;\n\t}\n\n\n\tint progress = 0, oldProgress = 0;\n\n\tif(!writer.open(\"output.trc\")) {\n\t\tstd::cerr << \"File could not be opened for writing...\" << std::endl;\n\t\treturn 2;\n\t}\n\n\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(\"EEC1\");\n\n\tframe->setSrcAddr(0x15);\n\tframe->setPriority(4);\n\n\tGenericFrame *eec1Frame = static_cast<GenericFrame *>(frame.get());\n\n\tSPNNumeric *rpm = static_cast<SPNNumeric *>(eec1Frame->getSPN(190));\n\n\trpm->setFormattedValue(310);\t\t//310 rpm\n\n\n\tstd::pair<u64, CanFrame> pairTStampFrame;\n\n\tu64 eec1TimeStamp = 0;\n\n\tdo {\n\n\t\ttrcReader.readNextCanFrame();\n\n\t\tpairTStampFrame = trcReader.getLastCanFrame();\n\n\t\tu64 timeStamp = pairTStampFrame.first;\n\t\tconst CanFrame& frame = pairTStampFrame.second;\n\n\t\tif(eec1TimeStamp < timeStamp) {\n\n\t\t\tu32 id;\n\t\t\tsize_t length = eec1Frame->getDataLength();\n\t\t\tu8* buff = new u8[length];\n\n\t\t\teec1Frame->encode(id, buff, length);\n\n\t\t\t//Set data\n\n\t\t\tstd::string data;\n\t\t\tdata.append((char*)buff, length);\n\n\t\t\tdelete[] buff;\n\n\t\t\tCanFrame frame(true, id, data);\n\n\t\t\twriter.write(frame, TimeStamp(eec1TimeStamp/1000000, eec1TimeStamp % 1000000));\n\n\t\t\teec1TimeStamp += 100000;\t\t\t//100ms\n\t\t}\n\n\n\t\twriter.write(frame, TimeStamp(timeStamp/1000000, timeStamp % 1000000));\n\n\n\t\tprogress = 100 * trcReader.getCurrentPos() / trcReader.getNumberOfFrames();\n\n\t\tif(progress != oldProgress) {\n\t\t\tstd::cout << \"Progress: \" << progress << \" %\" << std::endl;\n\t\t}\n\n\t} while(trcReader.getCurrentPos() < trcReader.getNumberOfFrames() - 1);\n\n\twriter.close();\n\n\treturn 0;\n}\n\n\n"
  },
  {
    "path": "BinUtils/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.5)\n\nproject(BinUtils)\n\n#set(PROPERTIES EXCLUDE_FROM_ALL TRUE)\n\nadd_subdirectory(j1939Decoder)\nadd_subdirectory(j1939Sender)\nadd_subdirectory(j1939Sniffer)\nadd_subdirectory(TRCDumper)\nadd_subdirectory(TRCPlayer)\nadd_subdirectory(TRCToCap)\nadd_subdirectory(j1939AddrClaim)\nadd_subdirectory(j1939AddressMapper)\n"
  },
  {
    "path": "BinUtils/TRCDumper/.cproject",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<?fileVersion 4.0.0?><cproject storage_type_id=\"org.eclipse.cdt.core.XmlProjectDescriptionStorage\">\n\t<storageModule moduleId=\"org.eclipse.cdt.core.settings\">\n\t\t<cconfiguration id=\"cdt.managedbuild.config.gnu.exe.debug.1330864580\">\n\t\t\t<storageModule buildSystemId=\"org.eclipse.cdt.managedbuilder.core.configurationDataProvider\" id=\"cdt.managedbuild.config.gnu.exe.debug.1330864580\" moduleId=\"org.eclipse.cdt.core.settings\" name=\"Debug\">\n\t\t\t\t<externalSettings/>\n\t\t\t\t<extensions>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GNU_ELF\" point=\"org.eclipse.cdt.core.BinaryParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GASErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GmakeErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GLDErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.CWDLocator\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GCCErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t</extensions>\n\t\t\t</storageModule>\n\t\t\t<storageModule moduleId=\"cdtBuildSystem\" version=\"4.0.0\">\n\t\t\t\t<configuration artifactName=\"${ProjName}\" buildArtefactType=\"org.eclipse.cdt.build.core.buildArtefactType.exe\" buildProperties=\"org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug\" cleanCommand=\"rm -rf\" description=\"\" id=\"cdt.managedbuild.config.gnu.exe.debug.1330864580\" name=\"Debug\" parent=\"cdt.managedbuild.config.gnu.exe.debug\">\n\t\t\t\t\t<folderInfo id=\"cdt.managedbuild.config.gnu.exe.debug.1330864580.\" name=\"/\" resourcePath=\"\">\n\t\t\t\t\t\t<toolChain id=\"cdt.managedbuild.toolchain.gnu.exe.debug.1969173486\" name=\"Linux GCC\" superClass=\"cdt.managedbuild.toolchain.gnu.exe.debug\">\n\t\t\t\t\t\t\t<targetPlatform id=\"cdt.managedbuild.target.gnu.platform.exe.debug.213112325\" name=\"Debug Platform\" superClass=\"cdt.managedbuild.target.gnu.platform.exe.debug\"/>\n\t\t\t\t\t\t\t<builder buildPath=\"${workspace_loc:/TRCDumper}/Debug\" id=\"cdt.managedbuild.target.gnu.builder.exe.debug.1594714072\" keepEnvironmentInBuildfile=\"false\" managedBuildOn=\"true\" name=\"Gnu Make Builder\" superClass=\"cdt.managedbuild.target.gnu.builder.exe.debug\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.archiver.base.1162142427\" name=\"GCC Archiver\" superClass=\"cdt.managedbuild.tool.gnu.archiver.base\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.102738694\" name=\"GCC C++ Compiler\" superClass=\"cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug\">\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.exe.debug.option.optimization.level.434953571\" name=\"Optimization Level\" superClass=\"gnu.cpp.compiler.exe.debug.option.optimization.level\" useByScannerDiscovery=\"false\" value=\"gnu.cpp.compiler.optimization.level.none\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.exe.debug.option.debugging.level.1569851892\" name=\"Debug Level\" superClass=\"gnu.cpp.compiler.exe.debug.option.debugging.level\" useByScannerDiscovery=\"false\" value=\"gnu.cpp.compiler.debugging.level.max\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.option.dialect.std.852954257\" name=\"Language standard\" superClass=\"gnu.cpp.compiler.option.dialect.std\" useByScannerDiscovery=\"true\" value=\"gnu.cpp.compiler.dialect.c++11\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.option.include.paths.909966041\" name=\"Include paths (-I)\" superClass=\"gnu.cpp.compiler.option.include.paths\" useByScannerDiscovery=\"false\" valueType=\"includePath\">\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"&quot;${workspace_loc:/CAN}&quot;\"/>\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"&quot;${workspace_loc:/Common}&quot;\"/>\n\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.cpp.compiler.input.896935545\" superClass=\"cdt.managedbuild.tool.gnu.cpp.compiler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.c.compiler.exe.debug.1861911242\" name=\"GCC C Compiler\" superClass=\"cdt.managedbuild.tool.gnu.c.compiler.exe.debug\">\n\t\t\t\t\t\t\t\t<option defaultValue=\"gnu.c.optimization.level.none\" id=\"gnu.c.compiler.exe.debug.option.optimization.level.1095799029\" name=\"Optimization Level\" superClass=\"gnu.c.compiler.exe.debug.option.optimization.level\" useByScannerDiscovery=\"false\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.c.compiler.exe.debug.option.debugging.level.227924340\" name=\"Debug Level\" superClass=\"gnu.c.compiler.exe.debug.option.debugging.level\" useByScannerDiscovery=\"false\" value=\"gnu.c.debugging.level.max\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.c.compiler.input.1310179622\" superClass=\"cdt.managedbuild.tool.gnu.c.compiler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.c.linker.exe.debug.1292486260\" name=\"GCC C Linker\" superClass=\"cdt.managedbuild.tool.gnu.c.linker.exe.debug\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.cpp.linker.exe.debug.160984213\" name=\"GCC C++ Linker\" superClass=\"cdt.managedbuild.tool.gnu.cpp.linker.exe.debug\">\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.link.option.libs.1439875801\" name=\"Libraries (-l)\" superClass=\"gnu.cpp.link.option.libs\" useByScannerDiscovery=\"false\" valueType=\"libs\">\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"CAN\"/>\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"rt\"/>\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"dl\"/>\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"Common\"/>\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"pthread\"/>\n\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.link.option.paths.245495372\" name=\"Library search path (-L)\" superClass=\"gnu.cpp.link.option.paths\" useByScannerDiscovery=\"false\" valueType=\"libPaths\">\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"&quot;${workspace_loc:/CAN/Debug}&quot;\"/>\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"&quot;${workspace_loc:/Common/Debug}&quot;\"/>\n\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.cpp.linker.input.1355917260\" superClass=\"cdt.managedbuild.tool.gnu.cpp.linker.input\">\n\t\t\t\t\t\t\t\t\t<additionalInput kind=\"additionalinputdependency\" paths=\"$(USER_OBJS)\"/>\n\t\t\t\t\t\t\t\t\t<additionalInput kind=\"additionalinput\" paths=\"$(LIBS)\"/>\n\t\t\t\t\t\t\t\t</inputType>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.assembler.exe.debug.253399415\" name=\"GCC Assembler\" superClass=\"cdt.managedbuild.tool.gnu.assembler.exe.debug\">\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.assembler.input.21780481\" superClass=\"cdt.managedbuild.tool.gnu.assembler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t</toolChain>\n\t\t\t\t\t</folderInfo>\n\t\t\t\t\t<sourceEntries>\n\t\t\t\t\t\t<entry flags=\"VALUE_WORKSPACE_PATH|RESOLVED\" kind=\"sourcePath\" name=\"src\"/>\n\t\t\t\t\t</sourceEntries>\n\t\t\t\t</configuration>\n\t\t\t</storageModule>\n\t\t\t<storageModule moduleId=\"org.eclipse.cdt.core.externalSettings\"/>\n\t\t</cconfiguration>\n\t\t<cconfiguration id=\"cdt.managedbuild.config.gnu.exe.release.521378321\">\n\t\t\t<storageModule buildSystemId=\"org.eclipse.cdt.managedbuilder.core.configurationDataProvider\" id=\"cdt.managedbuild.config.gnu.exe.release.521378321\" moduleId=\"org.eclipse.cdt.core.settings\" name=\"Release\">\n\t\t\t\t<externalSettings/>\n\t\t\t\t<extensions>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GNU_ELF\" point=\"org.eclipse.cdt.core.BinaryParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GASErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GmakeErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GLDErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.CWDLocator\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GCCErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t</extensions>\n\t\t\t</storageModule>\n\t\t\t<storageModule moduleId=\"cdtBuildSystem\" version=\"4.0.0\">\n\t\t\t\t<configuration artifactName=\"${ProjName}\" buildArtefactType=\"org.eclipse.cdt.build.core.buildArtefactType.exe\" buildProperties=\"org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release\" cleanCommand=\"rm -rf\" description=\"\" id=\"cdt.managedbuild.config.gnu.exe.release.521378321\" name=\"Release\" parent=\"cdt.managedbuild.config.gnu.exe.release\">\n\t\t\t\t\t<folderInfo id=\"cdt.managedbuild.config.gnu.exe.release.521378321.\" name=\"/\" resourcePath=\"\">\n\t\t\t\t\t\t<toolChain id=\"cdt.managedbuild.toolchain.gnu.exe.release.33465770\" name=\"Linux GCC\" superClass=\"cdt.managedbuild.toolchain.gnu.exe.release\">\n\t\t\t\t\t\t\t<targetPlatform id=\"cdt.managedbuild.target.gnu.platform.exe.release.593486504\" name=\"Debug Platform\" superClass=\"cdt.managedbuild.target.gnu.platform.exe.release\"/>\n\t\t\t\t\t\t\t<builder buildPath=\"${workspace_loc:/TRCDumper}/Release\" id=\"cdt.managedbuild.target.gnu.builder.exe.release.858209272\" keepEnvironmentInBuildfile=\"false\" managedBuildOn=\"true\" name=\"Gnu Make Builder\" superClass=\"cdt.managedbuild.target.gnu.builder.exe.release\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.archiver.base.287758658\" name=\"GCC Archiver\" superClass=\"cdt.managedbuild.tool.gnu.archiver.base\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.1678206868\" name=\"GCC C++ Compiler\" superClass=\"cdt.managedbuild.tool.gnu.cpp.compiler.exe.release\">\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.exe.release.option.optimization.level.758901623\" name=\"Optimization Level\" superClass=\"gnu.cpp.compiler.exe.release.option.optimization.level\" useByScannerDiscovery=\"false\" value=\"gnu.cpp.compiler.optimization.level.most\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.exe.release.option.debugging.level.741989058\" name=\"Debug Level\" superClass=\"gnu.cpp.compiler.exe.release.option.debugging.level\" useByScannerDiscovery=\"false\" value=\"gnu.cpp.compiler.debugging.level.none\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.cpp.compiler.input.913889234\" superClass=\"cdt.managedbuild.tool.gnu.cpp.compiler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.c.compiler.exe.release.1073906800\" name=\"GCC C Compiler\" superClass=\"cdt.managedbuild.tool.gnu.c.compiler.exe.release\">\n\t\t\t\t\t\t\t\t<option defaultValue=\"gnu.c.optimization.level.most\" id=\"gnu.c.compiler.exe.release.option.optimization.level.405994449\" name=\"Optimization Level\" superClass=\"gnu.c.compiler.exe.release.option.optimization.level\" useByScannerDiscovery=\"false\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.c.compiler.exe.release.option.debugging.level.234492977\" name=\"Debug Level\" superClass=\"gnu.c.compiler.exe.release.option.debugging.level\" useByScannerDiscovery=\"false\" value=\"gnu.c.debugging.level.none\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.c.compiler.input.310719326\" superClass=\"cdt.managedbuild.tool.gnu.c.compiler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.c.linker.exe.release.327648754\" name=\"GCC C Linker\" superClass=\"cdt.managedbuild.tool.gnu.c.linker.exe.release\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.cpp.linker.exe.release.1662944550\" name=\"GCC C++ Linker\" superClass=\"cdt.managedbuild.tool.gnu.cpp.linker.exe.release\">\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.cpp.linker.input.483012504\" superClass=\"cdt.managedbuild.tool.gnu.cpp.linker.input\">\n\t\t\t\t\t\t\t\t\t<additionalInput kind=\"additionalinputdependency\" paths=\"$(USER_OBJS)\"/>\n\t\t\t\t\t\t\t\t\t<additionalInput kind=\"additionalinput\" paths=\"$(LIBS)\"/>\n\t\t\t\t\t\t\t\t</inputType>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.assembler.exe.release.1712517777\" name=\"GCC Assembler\" superClass=\"cdt.managedbuild.tool.gnu.assembler.exe.release\">\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.assembler.input.301397720\" superClass=\"cdt.managedbuild.tool.gnu.assembler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t</toolChain>\n\t\t\t\t\t</folderInfo>\n\t\t\t\t\t<sourceEntries>\n\t\t\t\t\t\t<entry flags=\"VALUE_WORKSPACE_PATH|RESOLVED\" kind=\"sourcePath\" name=\"src\"/>\n\t\t\t\t\t</sourceEntries>\n\t\t\t\t</configuration>\n\t\t\t</storageModule>\n\t\t\t<storageModule moduleId=\"org.eclipse.cdt.core.externalSettings\"/>\n\t\t</cconfiguration>\n\t</storageModule>\n\t<storageModule moduleId=\"cdtBuildSystem\" version=\"4.0.0\">\n\t\t<project id=\"TRCDumper.cdt.managedbuild.target.gnu.exe.489844440\" name=\"Executable\" projectType=\"cdt.managedbuild.target.gnu.exe\"/>\n\t</storageModule>\n\t<storageModule moduleId=\"scannerConfiguration\">\n\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.config.gnu.exe.debug.1330864580;cdt.managedbuild.config.gnu.exe.debug.1330864580.;cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.102738694;cdt.managedbuild.tool.gnu.cpp.compiler.input.896935545\">\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t</scannerConfigBuildInfo>\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.config.gnu.exe.debug.1330864580;cdt.managedbuild.config.gnu.exe.debug.1330864580.;cdt.managedbuild.tool.gnu.c.compiler.exe.debug.1861911242;cdt.managedbuild.tool.gnu.c.compiler.input.1310179622\">\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t</scannerConfigBuildInfo>\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.config.gnu.exe.release.521378321;cdt.managedbuild.config.gnu.exe.release.521378321.;cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.1678206868;cdt.managedbuild.tool.gnu.cpp.compiler.input.913889234\">\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t</scannerConfigBuildInfo>\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.config.gnu.exe.release.521378321;cdt.managedbuild.config.gnu.exe.release.521378321.;cdt.managedbuild.tool.gnu.c.compiler.exe.release.1073906800;cdt.managedbuild.tool.gnu.c.compiler.input.310719326\">\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t</scannerConfigBuildInfo>\n\t</storageModule>\n\t<storageModule moduleId=\"org.eclipse.cdt.core.LanguageSettingsProviders\"/>\n\t<storageModule moduleId=\"refreshScope\" versionNumber=\"2\">\n\t\t<configuration configurationName=\"Debug\">\n\t\t\t<resource resourceType=\"PROJECT\" workspacePath=\"/TRCDumper\"/>\n\t\t</configuration>\n\t\t<configuration configurationName=\"Release\">\n\t\t\t<resource resourceType=\"PROJECT\" workspacePath=\"/TRCDumper\"/>\n\t\t</configuration>\n\t</storageModule>\n\t<storageModule moduleId=\"org.eclipse.cdt.make.core.buildtargets\"/>\n</cproject>\n"
  },
  {
    "path": "BinUtils/TRCDumper/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.5)\n\nproject(TRCDumper)\n\nadd_executable(TRCDumper \n    src/TRCDumper.cpp\n)\n\ntarget_include_directories(TRCDumper\n    PUBLIC \n        include ${Can_SOURCE_DIR}/include ${Common_SOURCE_DIR}/include\n)\n\ntarget_link_libraries(TRCDumper\n    PUBLIC\n        Can dl rt\n)\n\n\ninstall (TARGETS TRCDumper\n    DESTINATION bin)\n"
  },
  {
    "path": "BinUtils/TRCDumper/src/TRCDumper.cpp",
    "content": "//============================================================================\n// Name        : TRCDumper.cpp\n// Author      : \n// Version     :\n// Copyright   : MIT License\n// Description : Application that reads frames from the can interface and writes them to a file in TRC format.\n//============================================================================\n\n#include <getopt.h>\n#include <signal.h>\n\n#include <iostream>\n\n\n//Can includes\n#include <TRCWriter.h>\n#include <CanEasy.h>\n\n\n//Bitrate for J1939 protocol\n#define BAUD_250K\t\t\t250000\n\n\nusing namespace Can;\nusing namespace Utils;\n\nTRCWriter writer;\nbool firstFrame;\nTimeStamp initialTimeStamp;\n\nvoid onRcv(const Can::CanFrame& frame, const TimeStamp&, const std::string& interface, void*);\nbool onTimeout();\nvoid onSignal(int);\n\n\nstd::string interface, file;\n\n\nint main(int argc, char **argv) {\n\n\tfirstFrame = true;\n\n\tstatic struct option long_options[] =\n\t\t{\n\t\t\t{\"interface\", required_argument, NULL, 'i'},\n\t\t\t{\"file\", required_argument, NULL, 'f'},\n\t\t\t{NULL, 0, NULL, 0}\n\t\t};\n\n\twhile (1)\n\t{\n\n\t\tint c = getopt_long (argc, argv, \"s:i:\",\n\t\t\t\t   long_options, NULL);\n\n\t\t/* Detect the end of the options. */\n\t\tif (c == -1)\n\t\t\tbreak;\n\n\t\tswitch (c)\n\t\t{\n\t\tcase 'f':\n\t\t\tfile = optarg;\n\t\t\tbreak;\n\t\tcase 'i':\n\t\t\tinterface = optarg;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tCanEasy::initialize(BAUD_250K, onRcv, onTimeout);\n\n\tCanSniffer& sniffer = CanEasy::getSniffer();\n\n\n\tif(sniffer.getNumberOfReceivers() == 0) {\n\t\tstd::cerr << \"No interface available from to sniffer\" << std::endl;\n\t\treturn 2;\n\t}\n\n\n\tif(!writer.open(file)) {\n\t\tstd::cerr << \"File could not be opened for writing...\" << std::endl;\n\t\treturn 2;\n\t}\n\n\tsignal(SIGINT, onSignal);\n\n\tsniffer.sniff(1000);\n\n}\n\n\nvoid onRcv(const Can::CanFrame& frame, const TimeStamp& timeStamp, const std::string& , void*) {\n\n\tif(firstFrame) {\n\t\tinitialTimeStamp = timeStamp;\n\t\tfirstFrame = false;\n\t}\n\n\twriter.write(frame, timeStamp - initialTimeStamp);\n\n}\n\n\nbool onTimeout() {\n\n\treturn true;\n\n}\n\nvoid onSignal(int) {\n\n\tstd::cout << \"Closing file...\" << std::endl;\n\n\twriter.close();\n\n\tstd::cout << \"Done\" << std::endl;\n\n\texit(0);\n\n}\n"
  },
  {
    "path": "BinUtils/TRCPlayer/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.5)\n\nproject(TRCPlayer)\n\nfind_package (Curses)\n\nif(CURSES_FOUND)\n\nmessage(\"-- NCURSES is available\")\n\nmessage(\"-- Project \" ${PROJECT_NAME} \" will be built\")\n\n\nadd_executable(TRCPlayer \n    src/TRCPlayer.cpp\n)\n\ntarget_include_directories(TRCPlayer\n    PUBLIC \n        include ${J1939_SOURCE_DIR}/include ${Can_SOURCE_DIR}/include ${Common_SOURCE_DIR}/include\n)\n\ntarget_link_libraries(TRCPlayer\n    PUBLIC\n        J1939 Can ncurses dl rt\n)\n\n\ninstall (TARGETS TRCPlayer\n    DESTINATION bin)\n\n\nendif(CURSES_FOUND)"
  },
  {
    "path": "BinUtils/TRCPlayer/README.md",
    "content": "\n## TRCPlayer\n\nLet's play trc files.\n\n```bash\nTRCPlayer -i vcan0 -f file.trc\n```\n\n![alt text](https://github.com/famez/J1939-Framework/blob/master/BinUtils/TRCPlayer/TRCPlayer.png)\n"
  },
  {
    "path": "BinUtils/TRCPlayer/src/TRCPlayer.cpp",
    "content": "//============================================================================\n// Name        : TRCDumper.cpp\n// Author      : \n// Version     :\n// Copyright   : MIT License\n// Description : Application that reads frames from the can interface and writes them to a file in TRC format.\n//============================================================================\n\n#include <getopt.h>\n#include <signal.h>\n\n#include <ncurses.h>\n\n#include <iostream>\n\n#include <thread>\n#include <chrono>\n\n\n#include <unordered_map>\n#include <vector>\n\n\n//Can includes\n#include <TRCReader.h>\n#include <CanEasy.h>\n\n//J1939 includes\n#include <J1939Frame.h>\n#include <J1939Factory.h>\n#include <Transport/BAM/BamReassembler.h>\n\n\n//Bitrate for J1939 protocol\n#define BAUD_250K\t\t\t250000\n\n#define SELECT_COLOR\t\t1\n\n\nusing namespace Can;\nusing namespace Utils;\nusing namespace J1939;\n\nTRCReader reader;\nTimeStamp start;\n\n\nstd::string interface, file;\n\n\n//Vector to show the parsed frames from trc file\nstd::vector< std::pair<bool/*show_details*/, J1939Frame*> > vectorFrames;\n\n//Same as the vector but useful for fast access by id (To check if frame exeist or copy frame in case that it exists)\nstd::unordered_map<u32/*id*/, J1939Frame*> mapFrames;\n\n//To reassemble frames fragmented by means of Broadcast Announce Message protocol\nBamReassembler reassembler;\n\n//Selected frame\nsize_t currentSel = 0;\n\n//KEY\nint key;\n\nu32 progress = 0;\n\nvoid printFrames();\n\n\nint main(int argc, char **argv) {\n\n\tstatic struct option long_options[] =\n\t\t{\n\t\t\t{\"interface\", required_argument, NULL, 'i'},\n\t\t\t{\"file\", required_argument, NULL, 'f'},\n\t\t\t{NULL, 0, NULL, 0}\n\t\t};\n\n\twhile (1)\n\t{\n\n\t\tint c = getopt_long (argc, argv, \"f:i:\",\n\t\t\t\t   long_options, NULL);\n\n\t\t/* Detect the end of the options. */\n\t\tif (c == -1)\n\t\t\tbreak;\n\n\t\tswitch (c)\n\t\t{\n\t\tcase 'f':\n\t\t\tfile = optarg;\n\t\t\tbreak;\n\t\tcase 'i':\n\t\t\tinterface = optarg;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tCanEasy::initialize(BAUD_250K);\n\n\tstd::shared_ptr<ICanSender> sender = CanEasy::getSender(interface);\n\n\tif(!sender) {\n\t\tstd::cerr << \"Cannot send through the interface\" << std::endl;\n\t\treturn 1;\n\t}\n\n\tstd::cout << \"Loading file...\" << std::endl;\n\n\tif(!reader.loadFile(file)) {\n\t\tstd::cerr << \"File could not be opened for reading...\" << std::endl;\n\t\treturn 2;\n\t}\n\n\tif(reader.getNumberOfFrames() == 0) {\n\t\tstd::cerr << \"TRC file is empty\" << std::endl;\n\t\treturn 3;\n\t}\n\n\tstd::pair<u64, CanFrame> pairTStampFrame;\n\n\tif(!J1939Factory::getInstance().registerDatabaseFrames(DATABASE_PATH)) {\n\t\tstd::cerr << \"Database not found in \" << DATABASE_PATH << std::endl;\n\t\treturn 4;\n\t}\n\n\t//Initialize ncurses\n\tinitscr();\n\tcbreak();\n\ttimeout(1);\n\tkeypad(stdscr, true);\n\tstart_color();\n\tinit_pair(SELECT_COLOR, COLOR_BLACK, COLOR_WHITE);\n\n\tint width = getmaxx(stdscr);\n\n\t//End of initialization\n\n\tstart = TimeStamp::now();\n\n\tTimeStamp lastPrintTime = TimeStamp::now();\n\n\tdo {\n\n\t\treader.readNextCanFrame();\n\n\t\tpairTStampFrame = reader.getLastCanFrame();\n\n\t\tconst CanFrame& frame = pairTStampFrame.second;\n\n\t\tTimeStamp aux(pairTStampFrame.first / 1000000, pairTStampFrame.first % 1000000);\n\n\t\tTimeStamp lastTs(start + aux);\n\n\n\t\t//While waiting, we try to read arrow keys\n\t\twhile(TimeStamp::now() < lastTs) {\n\n\t\t\t//Blocks during one millisecond\n\t\t\tkey = getch();\n\t\t\tswitch(key) {\n\t\t\tcase KEY_UP:\n\t\t\t\tif(currentSel > 0)\t\t\t\t\t\t\t--currentSel;\n\t\t\t\tbreak;\n\t\t\tcase KEY_DOWN:\n\t\t\t\tif(currentSel + 1 < vectorFrames.size())\t\t++currentSel;\n\t\t\t\tbreak;\n\t\t\tcase '\\n':\t\t\t//Key Enter. Show details of frame when it is selected (or hide them)\n\n\t\t\t\tif(!vectorFrames.empty()) {\n\t\t\t\t\tvectorFrames[currentSel].first = !vectorFrames[currentSel].first;\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\tdefault:\t\t//To skip printFrames if key not detected\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t//If one of the valid keys was pressed, repaint\n\t\t\tprintFrames();\n\n\t\t}\n\n\t\tsender->sendFrameOnce(frame);\n\n\t\tprogress = width * reader.getCurrentPos() / reader.getNumberOfFrames();\n\n\t\ttry {\n\n\t\t\t//Try to print frames\n\t\t\tstd::unique_ptr<J1939Frame> j1939Frame = J1939Factory::getInstance().\n\t\t\t\t\t\tgetJ1939Frame(frame.getId(), (const u8*)(frame.getData().c_str()), frame.getData().size());\n\n\t\t\tif(j1939Frame) {\t\t\t\t\t\t\t//Frame registered in the factory?\n\n\t\t\t\tif(reassembler.toBeHandled(*j1939Frame)) {\t\t\t\t//Check if the frame is part of a fragmented frame (BAM protocol)\n\t\t\t\t\t//Actually it is, reassembler will handle it.\n\t\t\t\t\treassembler.handleFrame(*j1939Frame);\n\n\t\t\t\t\tif(reassembler.reassembledFramesPending()) {\n\n\t\t\t\t\t\tj1939Frame = reassembler.dequeueReassembledFrame();\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcontinue;\t\t\t\t//Frame handled by reassembler but the original frame to be reassembled is not complete.\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t//Check if it is already added.\n\t\t\t\tauto iter = mapFrames.find(j1939Frame->getIdentifier());\n\n\t\t\t\tif(iter != mapFrames.end()) {\n\n\t\t\t\t\titer->second->copy(*j1939Frame);\t\t//Update frame\n\n\t\t\t\t} else {\n\t\t\t\t\t//Add frame to the list\n\t\t\t\t\tmapFrames[j1939Frame->getIdentifier()] = j1939Frame.get();\n\t\t\t\t\tvectorFrames.push_back(std::make_pair(false, j1939Frame.release()));\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} catch (J1939DecodeException &) {\n\t\t\t//Decode exception, skip frame. Add handler so that the program keeps running.\n\t\t}\n\n\n\t\tTimeStamp elapsed = TimeStamp::now() - lastPrintTime;\n\n\t\t//Every 100 ms print frames\n\t\tif(elapsed.getMicroSec() > 100000 || elapsed.getSeconds() > 0) {\n\t\t\tprintFrames();\n\t\t\tlastPrintTime = TimeStamp::now();\n\t\t}\n\n\t} while(reader.getCurrentPos() < reader.getNumberOfFrames() - 1);\n\n\t//Finalize ncurses\n\tendwin();\n\n\t//Free frames\n\tfor(auto iter = vectorFrames.begin(); iter != vectorFrames.end(); ++iter) {\n\t\tdelete iter->second;\n\t}\n\n\n\t//Finalize CanEasy\n\tCanEasy::finalize();\n\n}\n\n\nvoid printFrames() {\n\n\tclear();\n\n\t//Print progress\n\tstd::string progressBar = std::string(progress, '#') + \"\\n\";\n\tprintw(progressBar.c_str());\n\n\tfor(size_t i = 0; i < vectorFrames.size(); ++i) {\n\n\t\t//If currentSel then print black over white\n\t\tif(currentSel == i) {\n\t\t\tattron(COLOR_PAIR(SELECT_COLOR));\n\t\t}\n\n\t\tif(vectorFrames[i].first) {\t\t//Show details of frame when it is selected\n\t\t\tprintw(vectorFrames[i].second->toString().c_str());\n\t\t} else {\n\t\t\tprintw(vectorFrames[i].second->getHeader().c_str());\n\t\t}\n\n\t\tif(currentSel == i) {\n\t\t\tattroff(COLOR_PAIR(SELECT_COLOR));\n\t\t}\n\t}\n\n\trefresh();\n\n}\n"
  },
  {
    "path": "BinUtils/TRCToCap/.cproject",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<?fileVersion 4.0.0?><cproject storage_type_id=\"org.eclipse.cdt.core.XmlProjectDescriptionStorage\">\n\t<storageModule moduleId=\"org.eclipse.cdt.core.settings\">\n\t\t<cconfiguration id=\"cdt.managedbuild.config.gnu.exe.debug.2041120065\">\n\t\t\t<storageModule buildSystemId=\"org.eclipse.cdt.managedbuilder.core.configurationDataProvider\" id=\"cdt.managedbuild.config.gnu.exe.debug.2041120065\" moduleId=\"org.eclipse.cdt.core.settings\" name=\"Debug\">\n\t\t\t\t<externalSettings/>\n\t\t\t\t<extensions>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GNU_ELF\" point=\"org.eclipse.cdt.core.BinaryParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GASErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GmakeErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GLDErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.CWDLocator\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GCCErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t</extensions>\n\t\t\t</storageModule>\n\t\t\t<storageModule moduleId=\"cdtBuildSystem\" version=\"4.0.0\">\n\t\t\t\t<configuration artifactName=\"${ProjName}\" buildArtefactType=\"org.eclipse.cdt.build.core.buildArtefactType.exe\" buildProperties=\"org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug\" cleanCommand=\"rm -rf\" description=\"\" errorParsers=\"org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.CWDLocator;org.eclipse.cdt.core.GCCErrorParser\" id=\"cdt.managedbuild.config.gnu.exe.debug.2041120065\" name=\"Debug\" parent=\"cdt.managedbuild.config.gnu.exe.debug\" postannouncebuildStep=\"\" postbuildStep=\"\" preannouncebuildStep=\"\" prebuildStep=\"\">\n\t\t\t\t\t<folderInfo id=\"cdt.managedbuild.config.gnu.exe.debug.2041120065.\" name=\"/\" resourcePath=\"\">\n\t\t\t\t\t\t<toolChain errorParsers=\"\" id=\"cdt.managedbuild.toolchain.gnu.exe.debug.375070960\" name=\"Linux GCC\" superClass=\"cdt.managedbuild.toolchain.gnu.exe.debug\">\n\t\t\t\t\t\t\t<targetPlatform binaryParser=\"org.eclipse.cdt.core.GNU_ELF\" id=\"cdt.managedbuild.target.gnu.platform.exe.debug.1544984790\" name=\"Debug Platform\" superClass=\"cdt.managedbuild.target.gnu.platform.exe.debug\"/>\n\t\t\t\t\t\t\t<builder buildPath=\"${workspace_loc:/TRCToCap}/Debug\" errorParsers=\"org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.CWDLocator\" id=\"cdt.managedbuild.target.gnu.builder.exe.debug.1039576123\" keepEnvironmentInBuildfile=\"false\" managedBuildOn=\"true\" name=\"Gnu Make Builder\" superClass=\"cdt.managedbuild.target.gnu.builder.exe.debug\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.archiver.base.463441508\" name=\"GCC Archiver\" superClass=\"cdt.managedbuild.tool.gnu.archiver.base\"/>\n\t\t\t\t\t\t\t<tool command=\"g++\" commandLinePattern=\"${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}\" errorParsers=\"org.eclipse.cdt.core.GCCErrorParser\" id=\"cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.652316822\" name=\"GCC C++ Compiler\" superClass=\"cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug\">\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.exe.debug.option.optimization.level.1231659337\" name=\"Optimization Level\" superClass=\"gnu.cpp.compiler.exe.debug.option.optimization.level\" useByScannerDiscovery=\"false\" value=\"gnu.cpp.compiler.optimization.level.none\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.exe.debug.option.debugging.level.451115225\" name=\"Debug Level\" superClass=\"gnu.cpp.compiler.exe.debug.option.debugging.level\" useByScannerDiscovery=\"false\" value=\"gnu.cpp.compiler.debugging.level.max\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.option.include.paths.2021315473\" name=\"Include paths (-I)\" superClass=\"gnu.cpp.compiler.option.include.paths\" useByScannerDiscovery=\"false\" valueType=\"includePath\">\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"/home/fernado/wireshark-2.6.1/writecap\"/>\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"/usr/lib/x86_64-linux-gnu/glib-2.0/include\"/>\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"/usr/include/glib-2.0\"/>\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"&quot;${workspace_loc:/CAN}&quot;\"/>\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"&quot;${workspace_loc:/Common}&quot;\"/>\n\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.option.include.files.1641527207\" name=\"Include files (-include)\" superClass=\"gnu.cpp.compiler.option.include.files\" useByScannerDiscovery=\"false\"/>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.cpp.compiler.input.406755612\" superClass=\"cdt.managedbuild.tool.gnu.cpp.compiler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool command=\"gcc\" commandLinePattern=\"${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}\" errorParsers=\"org.eclipse.cdt.core.GCCErrorParser\" id=\"cdt.managedbuild.tool.gnu.c.compiler.exe.debug.197837162\" name=\"GCC C Compiler\" superClass=\"cdt.managedbuild.tool.gnu.c.compiler.exe.debug\">\n\t\t\t\t\t\t\t\t<option defaultValue=\"gnu.c.optimization.level.none\" id=\"gnu.c.compiler.exe.debug.option.optimization.level.1809481422\" name=\"Optimization Level\" superClass=\"gnu.c.compiler.exe.debug.option.optimization.level\" useByScannerDiscovery=\"false\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.c.compiler.exe.debug.option.debugging.level.2019851804\" name=\"Debug Level\" superClass=\"gnu.c.compiler.exe.debug.option.debugging.level\" useByScannerDiscovery=\"false\" value=\"gnu.c.debugging.level.max\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.c.compiler.input.1009854519\" superClass=\"cdt.managedbuild.tool.gnu.c.compiler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.c.linker.exe.debug.483796641\" name=\"GCC C Linker\" superClass=\"cdt.managedbuild.tool.gnu.c.linker.exe.debug\"/>\n\t\t\t\t\t\t\t<tool command=\"g++\" commandLinePattern=\"${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}\" errorParsers=\"org.eclipse.cdt.core.GLDErrorParser\" id=\"cdt.managedbuild.tool.gnu.cpp.linker.exe.debug.511293932\" name=\"GCC C++ Linker\" superClass=\"cdt.managedbuild.tool.gnu.cpp.linker.exe.debug\">\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.link.option.libs.252791330\" name=\"Libraries (-l)\" superClass=\"gnu.cpp.link.option.libs\" useByScannerDiscovery=\"false\" valueType=\"libs\">\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"writecap\"/>\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"CAN\"/>\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"Common\"/>\n\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.link.option.paths.539167547\" name=\"Library search path (-L)\" superClass=\"gnu.cpp.link.option.paths\" useByScannerDiscovery=\"false\" valueType=\"libPaths\">\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"/home/fernado/wireshark-2.6.1/run/\"/>\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"&quot;${workspace_loc:/CAN/Debug}&quot;\"/>\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"&quot;${workspace_loc:/Common/Debug}&quot;\"/>\n\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.cpp.linker.input.1378090319\" superClass=\"cdt.managedbuild.tool.gnu.cpp.linker.input\">\n\t\t\t\t\t\t\t\t\t<additionalInput kind=\"additionalinputdependency\" paths=\"$(USER_OBJS)\"/>\n\t\t\t\t\t\t\t\t\t<additionalInput kind=\"additionalinput\" paths=\"$(LIBS)\"/>\n\t\t\t\t\t\t\t\t</inputType>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool command=\"as\" commandLinePattern=\"${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}\" errorParsers=\"org.eclipse.cdt.core.GASErrorParser\" id=\"cdt.managedbuild.tool.gnu.assembler.exe.debug.1463918392\" name=\"GCC Assembler\" superClass=\"cdt.managedbuild.tool.gnu.assembler.exe.debug\">\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.assembler.input.1583152031\" superClass=\"cdt.managedbuild.tool.gnu.assembler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t</toolChain>\n\t\t\t\t\t</folderInfo>\n\t\t\t\t\t<sourceEntries>\n\t\t\t\t\t\t<entry flags=\"VALUE_WORKSPACE_PATH|RESOLVED\" kind=\"sourcePath\" name=\"src\"/>\n\t\t\t\t\t</sourceEntries>\n\t\t\t\t</configuration>\n\t\t\t</storageModule>\n\t\t\t<storageModule moduleId=\"org.eclipse.cdt.core.externalSettings\"/>\n\t\t</cconfiguration>\n\t\t<cconfiguration id=\"cdt.managedbuild.config.gnu.exe.release.573803866\">\n\t\t\t<storageModule buildSystemId=\"org.eclipse.cdt.managedbuilder.core.configurationDataProvider\" id=\"cdt.managedbuild.config.gnu.exe.release.573803866\" moduleId=\"org.eclipse.cdt.core.settings\" name=\"Release\">\n\t\t\t\t<externalSettings/>\n\t\t\t\t<extensions>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GNU_ELF\" point=\"org.eclipse.cdt.core.BinaryParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GASErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GmakeErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GLDErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.CWDLocator\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GCCErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t</extensions>\n\t\t\t</storageModule>\n\t\t\t<storageModule moduleId=\"cdtBuildSystem\" version=\"4.0.0\">\n\t\t\t\t<configuration artifactName=\"${ProjName}\" buildArtefactType=\"org.eclipse.cdt.build.core.buildArtefactType.exe\" buildProperties=\"org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release\" cleanCommand=\"rm -rf\" description=\"\" id=\"cdt.managedbuild.config.gnu.exe.release.573803866\" name=\"Release\" parent=\"cdt.managedbuild.config.gnu.exe.release\">\n\t\t\t\t\t<folderInfo id=\"cdt.managedbuild.config.gnu.exe.release.573803866.\" name=\"/\" resourcePath=\"\">\n\t\t\t\t\t\t<toolChain id=\"cdt.managedbuild.toolchain.gnu.exe.release.1541028182\" name=\"Linux GCC\" superClass=\"cdt.managedbuild.toolchain.gnu.exe.release\">\n\t\t\t\t\t\t\t<targetPlatform id=\"cdt.managedbuild.target.gnu.platform.exe.release.1405444378\" name=\"Debug Platform\" superClass=\"cdt.managedbuild.target.gnu.platform.exe.release\"/>\n\t\t\t\t\t\t\t<builder buildPath=\"${workspace_loc:/TRCToCap}/Release\" id=\"cdt.managedbuild.target.gnu.builder.exe.release.314812515\" keepEnvironmentInBuildfile=\"false\" managedBuildOn=\"true\" name=\"Gnu Make Builder\" superClass=\"cdt.managedbuild.target.gnu.builder.exe.release\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.archiver.base.1734797118\" name=\"GCC Archiver\" superClass=\"cdt.managedbuild.tool.gnu.archiver.base\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.2119085636\" name=\"GCC C++ Compiler\" superClass=\"cdt.managedbuild.tool.gnu.cpp.compiler.exe.release\">\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.exe.release.option.optimization.level.701219793\" name=\"Optimization Level\" superClass=\"gnu.cpp.compiler.exe.release.option.optimization.level\" useByScannerDiscovery=\"false\" value=\"gnu.cpp.compiler.optimization.level.most\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.exe.release.option.debugging.level.75043303\" name=\"Debug Level\" superClass=\"gnu.cpp.compiler.exe.release.option.debugging.level\" useByScannerDiscovery=\"false\" value=\"gnu.cpp.compiler.debugging.level.none\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.cpp.compiler.input.1167837724\" superClass=\"cdt.managedbuild.tool.gnu.cpp.compiler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.c.compiler.exe.release.617041756\" name=\"GCC C Compiler\" superClass=\"cdt.managedbuild.tool.gnu.c.compiler.exe.release\">\n\t\t\t\t\t\t\t\t<option defaultValue=\"gnu.c.optimization.level.most\" id=\"gnu.c.compiler.exe.release.option.optimization.level.1869811454\" name=\"Optimization Level\" superClass=\"gnu.c.compiler.exe.release.option.optimization.level\" useByScannerDiscovery=\"false\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.c.compiler.exe.release.option.debugging.level.307832572\" name=\"Debug Level\" superClass=\"gnu.c.compiler.exe.release.option.debugging.level\" useByScannerDiscovery=\"false\" value=\"gnu.c.debugging.level.none\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.c.compiler.input.1056140120\" superClass=\"cdt.managedbuild.tool.gnu.c.compiler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.c.linker.exe.release.1924034509\" name=\"GCC C Linker\" superClass=\"cdt.managedbuild.tool.gnu.c.linker.exe.release\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.cpp.linker.exe.release.1506807661\" name=\"GCC C++ Linker\" superClass=\"cdt.managedbuild.tool.gnu.cpp.linker.exe.release\">\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.cpp.linker.input.402950265\" superClass=\"cdt.managedbuild.tool.gnu.cpp.linker.input\">\n\t\t\t\t\t\t\t\t\t<additionalInput kind=\"additionalinputdependency\" paths=\"$(USER_OBJS)\"/>\n\t\t\t\t\t\t\t\t\t<additionalInput kind=\"additionalinput\" paths=\"$(LIBS)\"/>\n\t\t\t\t\t\t\t\t</inputType>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.assembler.exe.release.1667769140\" name=\"GCC Assembler\" superClass=\"cdt.managedbuild.tool.gnu.assembler.exe.release\">\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.assembler.input.1558534570\" superClass=\"cdt.managedbuild.tool.gnu.assembler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t</toolChain>\n\t\t\t\t\t</folderInfo>\n\t\t\t\t\t<sourceEntries>\n\t\t\t\t\t\t<entry flags=\"VALUE_WORKSPACE_PATH|RESOLVED\" kind=\"sourcePath\" name=\"src\"/>\n\t\t\t\t\t</sourceEntries>\n\t\t\t\t</configuration>\n\t\t\t</storageModule>\n\t\t\t<storageModule moduleId=\"org.eclipse.cdt.core.externalSettings\"/>\n\t\t</cconfiguration>\n\t</storageModule>\n\t<storageModule moduleId=\"cdtBuildSystem\" version=\"4.0.0\">\n\t\t<project id=\"TRCToCap.cdt.managedbuild.target.gnu.exe.1109455932\" name=\"Executable\" projectType=\"cdt.managedbuild.target.gnu.exe\"/>\n\t</storageModule>\n\t<storageModule moduleId=\"scannerConfiguration\">\n\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.config.gnu.exe.release.573803866;cdt.managedbuild.config.gnu.exe.release.573803866.;cdt.managedbuild.tool.gnu.c.compiler.exe.release.617041756;cdt.managedbuild.tool.gnu.c.compiler.input.1056140120\">\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t</scannerConfigBuildInfo>\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.config.gnu.exe.release.573803866;cdt.managedbuild.config.gnu.exe.release.573803866.;cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.2119085636;cdt.managedbuild.tool.gnu.cpp.compiler.input.1167837724\">\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t</scannerConfigBuildInfo>\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.config.gnu.exe.debug.2041120065;cdt.managedbuild.config.gnu.exe.debug.2041120065.;cdt.managedbuild.tool.gnu.c.compiler.exe.debug.197837162;cdt.managedbuild.tool.gnu.c.compiler.input.1009854519\">\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t</scannerConfigBuildInfo>\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.config.gnu.exe.debug.2041120065;cdt.managedbuild.config.gnu.exe.debug.2041120065.;cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.652316822;cdt.managedbuild.tool.gnu.cpp.compiler.input.406755612\">\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t</scannerConfigBuildInfo>\n\t</storageModule>\n\t<storageModule moduleId=\"org.eclipse.cdt.core.LanguageSettingsProviders\"/>\n\t<storageModule moduleId=\"refreshScope\" versionNumber=\"2\">\n\t\t<configuration configurationName=\"Debug\">\n\t\t\t<resource resourceType=\"PROJECT\" workspacePath=\"/TRCToCap\"/>\n\t\t</configuration>\n\t\t<configuration configurationName=\"Release\">\n\t\t\t<resource resourceType=\"PROJECT\" workspacePath=\"/TRCToCap\"/>\n\t\t</configuration>\n\t</storageModule>\n\t<storageModule moduleId=\"org.eclipse.cdt.make.core.buildtargets\"/>\n</cproject>\n"
  },
  {
    "path": "BinUtils/TRCToCap/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.5)\n\nproject(TRCToCap)\n\nfind_package (PkgConfig)\n\nif(PKGCONFIG_FOUND)\n\npkg_check_modules (GLIB2 glib-2.0)\n\nif(GLIB2_FOUND)\n\nmessage(\"-- GLIB2 is available\")\nmessage(\"-- Project \" ${PROJECT_NAME} \" will be built\")\n\nadd_executable(TRCToCap \n    src/TRCToCap.cpp\n    src/pcapio.c\n)\n\ntarget_include_directories(TRCToCap\n    PUBLIC \n        include ${Can_SOURCE_DIR}/include ${Common_SOURCE_DIR}/include ${GLIB2_INCLUDE_DIRS}\n)\n\ntarget_link_libraries(TRCToCap\n    PUBLIC\n        Can\n)\n\n\ninstall (TARGETS TRCToCap\n    DESTINATION bin)\n\nelse(GLIB2_FOUND)\n\nmessage(WARNING \"-- GLIB2 is not available\")\nmessage(WARNING \"-- Project \" ${PROJECT_NAME} \" is skipped...\")\nmessage(WARNING \"-- Try to install GLIB2 and run cmake again...\")\n\nendif(GLIB2_FOUND)\nendif(PKGCONFIG_FOUND)\n"
  },
  {
    "path": "BinUtils/TRCToCap/include/config.h",
    "content": "/* cmakeconfig.h.in */\n\n#ifndef __CONFIG_H__\n#define __CONFIG_H__\n\n/* Note: You cannot use earlier #defines in later #cmakedefines (cmake 2.6.2). */\n\n/* Name of package */\n#define PACKAGE \"wireshark\"\n\n#define VERSION_EXTRA \"\"\n\n/* Version number of package */\n#define VERSION \"2.6.1\"\n#define VERSION_MAJOR 2\n#define VERSION_MINOR 6\n#define VERSION_MICRO 1\n\n#define VERSION_RELEASE \"2.6\"\n#define VERSION_FLAVOR \"\"\n\n/* FIXME: Move the path stuff to the CMakeInstallDirs.cmake file */\n/* Directory for data */\n#define DATAFILE_DIR \"/usr/local/share/wireshark\"\n\n/* Build wsutil with SIMD optimization */\n#define HAVE_SSE4_2 1\n\n/* Directory where extcap hooks reside */\n#define EXTCAP_DIR \"/usr/local/lib/wireshark/extcap\"\n\n/* Define to 1 if we want to enable plugins */\n#define HAVE_PLUGINS 1\n\n/*  Define to 1 if we check hf conflict */\n/* #undef ENABLE_CHECK_FILTER */\n\n/* Link Wireshark libraries statically */\n/* #undef ENABLE_STATIC */\n\n/* Enable AirPcap */\n/* #undef HAVE_AIRPCAP */\n\n/* Define to 1 if you have the <alloca.h> header file. */\n/* #undef HAVE_ALLOCA_H */\n\n/* Define to 1 if you have the <arpa/inet.h> header file. */\n#define HAVE_ARPA_INET_H 1\n\n/* Define to 1 if you have the `bpf_image' function. */\n#define HAVE_BPF_IMAGE 1\n\n/* Define to use c-ares library */\n/* #undef HAVE_C_ARES */\n\n/* Define to 1 if you have the `dladdr' function. */\n/* #undef HAVE_DLADDR */\n\n/* Define to 1 if you have the <fcntl.h> header file. */\n#define HAVE_FCNTL_H 1\n\n/* Define to use the MaxMind DB library */\n/* #undef HAVE_MAXMINDDB */\n\n/* Define to 1 if you have the <ifaddrs.h> header file. */\n#define HAVE_IFADDRS_H 1\n\n/* Define to 1 if you have the `getexecname' function. */\n/* #undef HAVE_GETEXECNAME */\n\n/* Define to 1 if you have the `getifaddrs' function. */\n#define HAVE_GETIFADDRS 1\n\n/* Define if LIBSSH support is enabled */\n/* #undef HAVE_LIBSSH */\n\n/* Define if LIBSSH has ssh_userauth_agent() function */\n/* #undef HAVE_SSH_USERAUTH_AGENT */\n\n/* Define if you have the 'floorl' function. */\n#define HAVE_FLOORL 1\n\n/* Define if you have the 'lrint' function. */\n#define HAVE_LRINT 1\n\n/* Define to 1 if you have the getopt_long function. */\n#define HAVE_GETOPT_LONG 1\n\n/* Define to 1 if you have the <getopt.h> header file. */\n#define HAVE_GETOPT_H 1\n\n/* Define to 1 if you have the <grp.h> header file. */\n#define HAVE_GRP_H 1\n\n/* Define to use heimdal kerberos */\n/* #undef HAVE_HEIMDAL_KERBEROS */\n\n/* Define to 1 if you have the `inflatePrime' function. */\n#define HAVE_INFLATEPRIME 1\n\n/* Define to 1 if you have the `issetugid' function. */\n/* #undef HAVE_ISSETUGID */\n\n/* Define to use kerberos */\n/* #undef HAVE_KERBEROS */\n\n/* Define to use nghttp2 */\n/* #undef HAVE_NGHTTP2 */\n\n/* Define to use the libcap library */\n/* #undef HAVE_LIBCAP */\n\n/* Define to use GnuTLS library */\n/* #undef HAVE_LIBGNUTLS */\n\n/* Enable libnl support */\n/* #undef HAVE_LIBNL */\n\n/* libnl version 1 */\n/* #undef HAVE_LIBNL1 */\n\n/* libnl version 2 */\n/* #undef HAVE_LIBNL2 */\n\n/* libnl version 3 */\n/* #undef HAVE_LIBNL3 */\n\n/* Define to use libpcap library */\n#define HAVE_LIBPCAP 1\n\n/* Define to 1 if you have the `smi' library (-lsmi). */\n/* #undef HAVE_LIBSMI */\n\n/* Define to use zlib library */\n#define HAVE_ZLIB 1\n\n/* Define to use lz4 library */\n/* #undef HAVE_LZ4 */\n\n/* Define to use snappy library */\n/* #undef HAVE_SNAPPY */\n\n/* Define to 1 if you have the <linux/sockios.h> header file. */\n#define HAVE_LINUX_SOCKIOS_H 1\n\n/* Define to 1 if you have the <linux/if_bonding.h> header file. */\n#define HAVE_LINUX_IF_BONDING_H 1\n\n/* Define to use Lua */\n/* #undef HAVE_LUA */\n\n/* Define to 1 if you have the <lua.h> header file. */\n/* #undef HAVE_LUA_H */\n\n/* Define to 1 if you have the <memory.h> header file. */\n/* #undef HAVE_MEMORY_H */\n\n/* Define to use MIT kerberos */\n/* #undef HAVE_MIT_KERBEROS */\n\n/* Define to 1 if you have the `mkstemps' function. */\n#define HAVE_MKSTEMPS 1\n\n/* Define to 1 if you have the `mmap' function. */\n/* #undef HAVE_MMAP */\n\n/* Define to 1 if you have the `mprotect' function. */\n/* #undef HAVE_MPROTECT */\n\n/* Define to 1 if you have the <netdb.h> header file. */\n#define HAVE_NETDB_H 1\n\n/* Define to 1 if you have the <netinet/in.h> header file. */\n#define HAVE_NETINET_IN_H 1\n\n/* nl80211.h is new enough */\n/* #undef HAVE_NL80211 */\n\n/* SET_CHANNEL is supported */\n/* #undef HAVE_NL80211_CMD_SET_CHANNEL */\n\n/* SPLIT_WIPHY_DUMP is supported */\n/* #undef HAVE_NL80211_SPLIT_WIPHY_DUMP */\n\n/* VHT_CAPABILITY is supported */\n/* #undef HAVE_NL80211_VHT_CAPABILITY */\n\n/* Define to 1 if you have macOS frameworks */\n/* #undef HAVE_MACOS_FRAMEWORKS */\n\n/* Define to 1 if you have the macOS CFPropertyListCreateWithStream function */\n/* #undef HAVE_CFPROPERTYLISTCREATEWITHSTREAM */\n\n/* Define if pcap_breakloop is known */\n#define HAVE_PCAP_BREAKLOOP 1\n\n/* Define to 1 if you have the `pcap_create' function. */\n#define HAVE_PCAP_CREATE 1\n\n/* Define to 1 if the capture buffer size can be set. */\n#define CAN_SET_CAPTURE_BUFFER_SIZE 1\n\n/* Define to 1 if you have the `pcap_datalink_name_to_val' function. */\n#define HAVE_PCAP_DATALINK_NAME_TO_VAL 1\n\n/* Define to 1 if you have the `pcap_datalink_val_to_description' function. */\n#define HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION 1\n\n/* Define to 1 if you have the `pcap_datalink_val_to_name' function. */\n#define HAVE_PCAP_DATALINK_VAL_TO_NAME 1\n\n/* Define to 1 if you have the `pcap_findalldevs' function and a pcap.h that\n   declares pcap_if_t. */\n#define HAVE_PCAP_FINDALLDEVS 1\n\n/* Define to 1 if you have the `pcap_freecode' function. */\n#define HAVE_PCAP_FREECODE 1\n\n/* Define to 1 if you have the `pcap_free_datalinks' function. */\n#define HAVE_PCAP_FREE_DATALINKS 1\n\n/* Define to 1 if you have the `pcap_get_selectable_fd' function. */\n#define HAVE_PCAP_GET_SELECTABLE_FD 1\n\n/* Define to 1 if you have the `pcap_lib_version' function. */\n#define HAVE_PCAP_LIB_VERSION 1\n\n/* Define to 1 if you have the `pcap_list_datalinks' function. */\n#define HAVE_PCAP_LIST_DATALINKS 1\n\n/* Define to 1 if you have the `pcap_open' function. */\n/* #undef HAVE_PCAP_OPEN */\n\n/* Define to 1 if you have the `pcap_open_dead' function. */\n#define HAVE_PCAP_OPEN_DEAD 1\n\n/* Define to 1 if you have libpcap/WinPcap remote capturing support. */\n/* #undef HAVE_PCAP_REMOTE */\n\n/* Define to 1 if you have the `pcap_set_datalink' function. */\n#define HAVE_PCAP_SET_DATALINK 1\n\n/* Define to 1 if you have the `pcap_setsampling' function. */\n/* #undef HAVE_PCAP_SETSAMPLING */\n\n/* Define to 1 if you have the `pcap_set_tstamp_precision' function. */\n#define HAVE_PCAP_SET_TSTAMP_PRECISION 1\n\n/* Define to 1 if you have the `pcap_set_tstamp_type' function. */\n#define HAVE_PCAP_SET_TSTAMP_TYPE 1\n\n/* Define to 1 if you have the <pwd.h> header file. */\n#define HAVE_PWD_H 1\n\n/* Define to 1 if you have the optreset variable */\n/* #undef HAVE_OPTRESET */\n\n/* Define if sa_len field exists in struct sockaddr */\n/* #undef HAVE_STRUCT_SOCKADDR_SA_LEN */\n\n/* Define to 1 if you want to playing SBC by standalone BlueZ SBC library */\n/* #undef HAVE_SBC */\n\n/* Define to 1 if you have the SpanDSP library. */\n/* #undef HAVE_SPANDSP */\n\n/* Define to 1 if you have the bcg729 library. */\n/* #undef HAVE_BCG729 */\n\n/* Define to 1 if you have the lixbml2 library. */\n/* #undef HAVE_LIBXML2 */\n\n/* Define to 1 if you have the `setresgid' function. */\n#define HAVE_SETRESGID 1\n\n/* Define to 1 if you have the `setresuid' function. */\n#define HAVE_SETRESUID 1\n\n/* Define to 1 if you have the WinSparkle library */\n/* #undef HAVE_SOFTWARE_UPDATE */\n\n/* Define if you have the 'strptime' function. */\n#define HAVE_STRPTIME 1\n\n/* Define to 1 if `st_birthtime' is a member of `struct stat'. */\n/* #undef HAVE_STRUCT_STAT_ST_BIRTHTIME */\n\n/* Define if st_flags field exists in struct stat */\n/* #undef HAVE_STRUCT_STAT_ST_FLAGS */\n\n/* Define to 1 if `__st_birthtime' is a member of `struct stat'. */\n/* #undef HAVE_STRUCT_STAT___ST_BIRTHTIME */\n\n/* Define to 1 if you have the <sys/ioctl.h> header file. */\n#define HAVE_SYS_IOCTL_H 1\n\n/* Define to 1 if you have the <sys/socket.h> header file. */\n#define HAVE_SYS_SOCKET_H 1\n\n/* Define to 1 if you have the <sys/sockio.h> header file. */\n/* #undef HAVE_SYS_SOCKIO_H */\n\n/* Define to 1 if you have the <sys/stat.h> header file. */\n#define HAVE_SYS_STAT_H 1\n\n/* Define to 1 if you have the <sys/time.h> header file. */\n#define HAVE_SYS_TIME_H 1\n\n/* Define to 1 if you have the <sys/types.h> header file. */\n#define HAVE_SYS_TYPES_H 1\n\n/* Define to 1 if you have the <sys/utsname.h> header file. */\n#define HAVE_SYS_UTSNAME_H 1\n\n/* Define to 1 if you have the <sys/wait.h> header file. */\n#define HAVE_SYS_WAIT_H 1\n\n/* Define if tm_zone field exists in struct tm */\n#define HAVE_STRUCT_TM_TM_ZONE 1\n\n/* Define if tzname array exists */\n#define HAVE_TZNAME 1\n\n/* Define to 1 if you have the <unistd.h> header file. */\n#define HAVE_UNISTD_H 1\n\n/* Name of package */\n/* #undef PACKAGE */\n\n/* Define to the address where bug reports for this package should be sent. */\n/* #undef PACKAGE_BUGREPORT */\n\n/* Define to the full name of this package. */\n/* #undef PACKAGE_NAME */\n\n/* Define to the full name and version of this package. */\n/* #undef PACKAGE_STRING */\n\n/* Define to the one symbol short name of this package. */\n/* #undef PACKAGE_TARNAME */\n\n/* Define to the version of this package. */\n/* #undef PACKAGE_VERSION */\n\n/* Support for pcapng */\n#define PCAP_NG_DEFAULT 1\n\n/* Define if we are using version of of the Portaudio library API */\n/* #undef PORTAUDIO_API_1 */\n\n/* Define if we have QtMultimedia */\n#define QT_MULTIMEDIA_LIB 1\n\n/* Define if we have QtMacExtras */\n/* #undef QT_MACEXTRAS_LIB */\n\n/* Define if we have QtWinExtras */\n/* #undef QT_WINEXTRAS_LIB */\n\n/* Build androiddump with libpcap instead of wireshark stuff */\n/* #undef ANDROIDDUMP_USE_LIBPCAP */\n\n/* Large file support */\n/* #undef _LARGEFILE_SOURCE */\n/* #undef _LARGEFILE64_SOURCE */\n/* #undef _LARGE_FILES */\n/* #undef _FILE_OFFSET_BITS */\n\n/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a\n   `char[]'. */\n/* Note: not use in the code */\n/* #undef YYTEXT_POINTER */\n\n#if defined(_WIN32)\n   /*\n    * Make sure everyone is using the same API and that it's sufficient\n    * for our needs.\n    * This should match the following:\n    * - The <compatibility><application> section in image\\wireshark.exe.manifest.in\n    * - The GetWindowsVersion parts of packaging\\nsis\\wireshark.nsi\n    * - The VersionNT parts of packaging\\wix\\Prerequisites.wxi\n    */\n#  if defined(NTDDI_VERSION)\n#    error NTDDI_VERSION already defined.\n#  endif\n#  define NTDDI_VERSION NTDDI_WIN7\n#  if defined(_WIN32_WINNT)\n#    error _WIN32_WINNT already defined.\n#  endif\n#  define _WIN32_WINNT _WIN32_WINNT_WIN7\n\n   /* WpdPack/INclude/pcap/pcap.h checks for \"#if defined(WIN32)\" */\n#  ifndef WIN32\n#    define WIN32\t1\n#  endif\n\n#  if !defined(QT_VERSION) || !defined(_SSIZE_T_DEFINED)\n   typedef int ssize_t;\n#  endif\n\n   /*\n    * Flex (v 2.5.35) uses this symbol to \"exclude\" unistd.h\n    */\n#  define YY_NO_UNISTD_H\n\n#  define strncasecmp strnicmp\n#  define popen       _popen\n#  define pclose      _pclose\n\n#  ifndef __STDC__\n#    define __STDC__ 0\n#  endif\n   /* Use Unicode in Windows runtime functions. */\n#  define UNICODE 1\n#  define _UNICODE 1\n\n#  define NEED_STRPTIME_H 1\n#endif\n\n#if defined(__APPLE__)\n   /* This is to trigger the integration of objective-c\n    * code builds for removing unnecessary menu entries\n    * in 10.12 > and Qt 5.3 >\n    */\n#  define CMAKE_BUILD 1\n#endif\n\n#endif /* __CONFIG_H__ */\n"
  },
  {
    "path": "BinUtils/TRCToCap/include/pcapio.h",
    "content": "/* pcapio.h\n * Declarations of our own routines for writing libpcap files.\n *\n * Wireshark - Network traffic analyzer\n * By Gerald Combs <gerald@wireshark.org>\n * Copyright 1998 Gerald Combs\n *\n * Derived from code in the Wiretap Library\n * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>\n *\n * SPDX-License-Identifier: GPL-2.0-or-later\n */\n\n/* Writing pcap files */\n\n/** Write the file header to a dump file.\n   Returns TRUE on success, FALSE on failure.\n   Sets \"*err\" to an error code, or 0 for a short write, on failure*/\nextern gboolean\nlibpcap_write_file_header(FILE* pfile, int linktype, int snaplen,\n                          gboolean ts_nsecs, guint64 *bytes_written, int *err);\n\n/** Write a record for a packet to a dump file.\n   Returns TRUE on success, FALSE on failure. */\nextern gboolean\nlibpcap_write_packet(FILE* pfile,\n                     time_t sec, guint32 usec,\n                     guint32 caplen, guint32 len,\n                     const guint8 *pd,\n                     guint64 *bytes_written, int *err);\n\n/* Writing pcapng files */\n\n/* Write a pre-formatted pcapng block */\nextern gboolean\npcapng_write_block(FILE* pfile,\n                  const guint8 *data,\n                  guint32 block_total_length,\n                  guint64 *bytes_written,\n                  int *err);\n\n/** Write a section header block (SHB)\n *\n */\nextern gboolean\npcapng_write_session_header_block(FILE* pfile,  /**< Write information */\n                                  const char *comment,  /**< Comment on the section, Optinon 1 opt_comment\n                                                         * A UTF-8 string containing a comment that is associated to the current block.\n                                                         */\n                                  const char *hw,       /**< HW, Optinon 2 shb_hardware\n                                                         * An UTF-8 string containing the description of the hardware  used to create this section.\n                                                         */\n                                  const char *os,       /**< Operating system name, Optinon 3 shb_os\n                                                         * An UTF-8 string containing the name of the operating system used to create this section.\n                                                         */\n                                  const char *appname,  /**< Application name, Optinon 4 shb_userappl\n                                                         * An UTF-8 string containing the name of the application  used to create this section.\n                                                         */\n                                  guint64 section_length, /**< Length of section */\n                                  guint64 *bytes_written, /**< Number of written bytes */\n                                  int *err /**< Error type */\n                                  );\n\nextern gboolean\npcapng_write_interface_description_block(FILE* pfile,\n                                         const char *comment,  /* OPT_COMMENT           1 */\n                                         const char *name,     /* IDB_NAME              2 */\n                                         const char *descr,    /* IDB_DESCRIPTION       3 */\n                                         const char *filter,   /* IDB_FILTER           11 */\n                                         const char *os,       /* IDB_OS               12 */\n                                         int link_type,\n                                         int snap_len,\n                                         guint64 *bytes_written,\n                                         guint64 if_speed,     /* IDB_IF_SPEED          8 */\n                                         guint8 tsresol,       /* IDB_TSRESOL           9 */\n                                         int *err);\n\nextern gboolean\npcapng_write_interface_statistics_block(FILE* pfile,\n                                        guint32 interface_id,\n                                        guint64 *bytes_written,\n                                        const char *comment,   /* OPT_COMMENT           1 */\n                                        guint64 isb_starttime, /* ISB_STARTTIME         2 */\n                                        guint64 isb_endtime,   /* ISB_ENDTIME           3 */\n                                        guint64 isb_ifrecv,    /* ISB_IFRECV            4 */\n                                        guint64 isb_ifdrop,    /* ISB_IFDROP            5 */\n                                        int *err);\n\nextern gboolean\npcapng_write_enhanced_packet_block(FILE* pfile,\n                                   const char *comment,\n                                   time_t sec, guint32 usec,\n                                   guint32 caplen, guint32 len,\n                                   guint32 interface_id,\n                                   guint ts_mul,\n                                   const guint8 *pd,\n                                   guint32 flags,\n                                   guint64 *bytes_written,\n                                   int *err);\n\n/*\n * Editor modelines  -  http://www.wireshark.org/tools/modelines.html\n *\n * Local variables:\n * c-basic-offset: 4\n * tab-width: 8\n * indent-tabs-mode: nil\n * End:\n *\n * vi: set shiftwidth=4 tabstop=8 expandtab:\n * :indentSize=4:tabSize=8:noTabs=true:\n */\n"
  },
  {
    "path": "BinUtils/TRCToCap/src/TRCToCap.cpp",
    "content": "//============================================================================\n// Name        : TRCToCap.cpp\n// Author      : Fernando Ámez García\n// Version     :\n// Copyright   : \n// Description : A tool to convert TRC files to CAP files so that it can be analyzed by wireshark\n//============================================================================\nextern \"C\" {\n\n#include <stdio.h>\n#include <getopt.h>\n#include <glib.h>\n#include <pcapio.h>\t\t//To write cap files\n\n}\n\n\n#include <iostream>\n#include <TRCReader.h>\t//To read TRC files\n\n#define CAN_LINKTYPE\t\t0xE3\n\n#define CAN_ID_LENGTH\t\t4\n#define LENGTH_LENGTH\t\t1\n#define RESERVED_LENGTH\t\t3\n\n\nusing namespace Can;\n\nint main(int argc, char **argv) {\n\n\t//Get options\n\tint c;\n\tstd::string input, output;\n\n\tstatic struct option long_options[] =\n\t{\n\t\t{\"input\", required_argument, NULL, 'i'},\n\t\t{\"output\", required_argument, NULL, 'o'},\n\t\t{NULL, 0, NULL, 0}\n\t};\n\n\twhile (1)\n\t{\n\n\t\tc = getopt_long (argc, argv, \"i:o:\",\n\t\t\t\t   long_options, NULL);\n\n\t\t/* Detect the end of the options. */\n\t\tif (c == -1)\n\t\t\tbreak;\n\n\t\tswitch (c)\n\t\t{\n\t\tcase 'i':\n\t\t\tinput = optarg;\n\t\t\tbreak;\n\t\tcase 'o':\n\t\t\toutput = optarg;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif(input.empty()) {\n\t\tstd::cerr << \"No input specified\" << std::endl;\n\t\treturn -1;\n\t}\n\n\tif(output.empty()) {\n\t\tstd::cerr << \"No output specified\" << std::endl;\n\t\treturn -1;\n\t}\n\n\tTRCReader trcReader;\n\n\tif(!trcReader.loadFile(input)) {\n\t\tstd::cerr << \"TRC file is corrupted or not readable by \" << argv[0] << std::endl;\n\t\treturn -2;\n\t}\n\n\tif(trcReader.getNumberOfFrames() == 0) {\n\t\tstd::cerr << \"TRC file is empty\" << std::endl;\n\t\treturn -3;\n\t}\n\n\tstd::cout << \"TRC file loaded\" << std::endl;\n\n\tFILE *fd = fopen(output.c_str(), \"wb\");\n\n\tif(!fd) {\n\t\tstd::cerr << \"Output file could not be open\" << std::endl;\n\t}\n\n\tstd::cout << \"Cap file open\" << std::endl;\n\n\tguint64 bytes_written;\n\tint err;\n\tstd::pair<u64, CanFrame> pairTStampFrame;\n\n\tlibpcap_write_file_header(fd, CAN_LINKTYPE, 0xFFFF, TRUE, &bytes_written, &err);\n\n\tstd::cout << \"Header written\" << std::endl;\n\n\tint progress = 0, oldProgress = 0;\n\n\t//Iterate over the frames\n\tdo {\n\n\t\ttrcReader.readNextCanFrame();\n\n\t\tpairTStampFrame = trcReader.getLastCanFrame();\n\n\t\tu64 timeStamp = pairTStampFrame.first;\n\n\t\tconst CanFrame& frame = pairTStampFrame.second;\n\n\t\tsize_t length = CAN_ID_LENGTH + LENGTH_LENGTH + RESERVED_LENGTH + frame.getData().size();\n\n\t\tstd::string data;\n\n\n\t\t//Add the ID\n\t\tdata += (((frame.getId() >> 24) & 0xFF) | (frame.isExtendedFormat() ? 0x80 : 0x00));\t\t//Extended flag present?\n\t\tdata += ((frame.getId() >> 16) & 0xFF);\n\t\tdata += ((frame.getId() >> 8) & 0xFF);\n\t\tdata += (frame.getId() & 0xFF);\n\n\t\t//Add the length\n\t\tdata += frame.getData().size();\n\n\t\t//Add the reserved characters\n\t\tdata += (char)0;\n\t\tdata += (char)0;\n\t\tdata += (char)0;\n\n\t\t//Append the DLC of the frame\n\t\tdata += frame.getData();\n\n\n\t\tlibpcap_write_packet(fd, timeStamp / 1000000, timeStamp % 1000000, length, length, (const guint8 *)(data.c_str()),\n\t\t\t\t&bytes_written, &err);\n\n\t\tprogress = 100 * trcReader.getCurrentPos() / trcReader.getNumberOfFrames();\n\n\t\tif(progress != oldProgress) {\n\t\t\tstd::cout << \"Progress: \" << progress << \" %\" << std::endl;\n\t\t}\n\n\t\toldProgress = progress;\n\n\t} while(trcReader.getCurrentPos() < trcReader.getNumberOfFrames() - 1);\n\n\tfclose(fd);\n\n\tstd::cout << \"Cap file correctly generated\" << std::endl;\n\n}\n"
  },
  {
    "path": "BinUtils/TRCToCap/src/pcapio.c",
    "content": "/* pcapio.c\n * Our own private code for writing libpcap files when capturing.\n *\n * We have these because we want a way to open a stream for output given\n * only a file descriptor.  libpcap 0.9[.x] has \"pcap_dump_fopen()\", which\n * provides that, but\n *\n *      1) earlier versions of libpcap doesn't have it\n *\n * and\n *\n *      2) WinPcap doesn't have it, because a file descriptor opened\n *         by code built for one version of the MSVC++ C library\n *         can't be used by library routines built for another version\n *         (e.g., threaded vs. unthreaded).\n *\n * Libpcap's pcap_dump() also doesn't return any error indications.\n *\n * Wireshark - Network traffic analyzer\n * By Gerald Combs <gerald@wireshark.org>\n * Copyright 1998 Gerald Combs\n *\n * Derived from code in the Wiretap Library\n * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>\n *\n * SPDX-License-Identifier: GPL-2.0-or-later\n */\n\n#include <config.h>\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <errno.h>\n#include <string.h>\n#ifdef HAVE_SYS_TIME_H\n#include <sys/time.h>\n#endif\n#ifdef _WIN32\n#include <Windows.h>\n#endif\n\n#include <glib.h>\n\n#include \"pcapio.h\"\n\n/* Magic numbers in \"libpcap\" files.\n\n   \"libpcap\" file records are written in the byte order of the host that\n   writes them, and the reader is expected to fix this up.\n\n   PCAP_MAGIC is the magic number, in host byte order; PCAP_SWAPPED_MAGIC\n   is a byte-swapped version of that.\n\n   PCAP_NSEC_MAGIC is for Ulf Lamping's modified \"libpcap\" format,\n   which uses the same common file format as PCAP_MAGIC, but the\n   timestamps are saved in nanosecond resolution instead of microseconds.\n   PCAP_SWAPPED_NSEC_MAGIC is a byte-swapped version of that. */\n#define PCAP_MAGIC                      0xa1b2c3d4\n#define PCAP_SWAPPED_MAGIC              0xd4c3b2a1\n#define PCAP_NSEC_MAGIC                 0xa1b23c4d\n#define PCAP_SWAPPED_NSEC_MAGIC         0x4d3cb2a1\n\n/* \"libpcap\" file header. */\nstruct pcap_hdr {\n        guint32 magic;          /* magic number */\n        guint16 version_major;  /* major version number */\n        guint16 version_minor;  /* minor version number */\n        gint32  thiszone;       /* GMT to local correction */\n        guint32 sigfigs;        /* accuracy of timestamps */\n        guint32 snaplen;        /* max length of captured packets, in octets */\n        guint32 network;        /* data link type */\n};\n\n/* \"libpcap\" record header. */\nstruct pcaprec_hdr {\n        guint32 ts_sec;         /* timestamp seconds */\n        guint32 ts_usec;        /* timestamp microseconds (nsecs for PCAP_NSEC_MAGIC) */\n        guint32 incl_len;       /* number of octets of packet saved in file */\n        guint32 orig_len;       /* actual length of packet */\n};\n\n/* Magic numbers in \".pcapng\" files.\n *\n * .pcapng file records are written in the byte order of the host that\n * writes them, and the reader is expected to fix this up.\n * PCAPNG_MAGIC is the magic number, in host byte order;\n * PCAPNG_SWAPPED_MAGIC is a byte-swapped version of that.\n */\n#define PCAPNG_MAGIC         0x1A2B3C4D\n#define PCAPNG_SWAPPED_MAGIC 0xD4C3B2A1\n\n/* Currently we are only supporting the initial version of\n   the file format. */\n#define PCAPNG_MAJOR_VERSION 1\n#define PCAPNG_MINOR_VERSION 0\n\n/* Section Header Block without options and trailing Block Total Length */\nstruct shb {\n        guint32 block_type;\n        guint32 block_total_length;\n        guint32 byte_order_magic;\n        guint16 major_version;\n        guint16 minor_version;\n        guint64 section_length;\n};\n#define SECTION_HEADER_BLOCK_TYPE 0x0A0D0D0A\n\n/* Interface Description Block without options and trailing Block Total Length */\nstruct idb {\n        guint32 block_type;\n        guint32 block_total_length;\n        guint16 link_type;\n        guint16 reserved;\n        guint32 snap_len;\n};\n#define INTERFACE_DESCRIPTION_BLOCK_TYPE 0x00000001\n\n/* Interface Statistics Block without actual packet, options, and trailing\n   Block Total Length */\nstruct isb {\n        guint32 block_type;\n        guint32 block_total_length;\n        guint32 interface_id;\n        guint32 timestamp_high;\n        guint32 timestamp_low;\n};\n#define INTERFACE_STATISTICS_BLOCK_TYPE 0x00000005\n\n/* Enhanced Packet Block without actual packet, options, and trailing\n   Block Total Length */\nstruct epb {\n        guint32 block_type;\n        guint32 block_total_length;\n        guint32 interface_id;\n        guint32 timestamp_high;\n        guint32 timestamp_low;\n        guint32 captured_len;\n        guint32 packet_len;\n};\n#define ENHANCED_PACKET_BLOCK_TYPE 0x00000006\n\nstruct option {\n        guint16 type;\n        guint16 value_length;\n};\n#define OPT_ENDOFOPT      0\n#define OPT_COMMENT       1\n#define EPB_FLAGS         2\n#define SHB_HARDWARE      2 /* currently not used */\n#define SHB_OS            3\n#define SHB_USERAPPL      4\n#define IDB_NAME          2\n#define IDB_DESCRIPTION   3\n#define IDB_IF_SPEED      8\n#define IDB_TSRESOL       9\n#define IDB_FILTER       11\n#define IDB_OS           12\n#define ISB_STARTTIME     2\n#define ISB_ENDTIME       3\n#define ISB_IFRECV        4\n#define ISB_IFDROP        5\n#define ISB_FILTERACCEPT  6\n#define ISB_OSDROP        7\n#define ISB_USRDELIV      8\n#define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)\n\n/* Write to capture file */\nstatic gboolean\nwrite_to_file(FILE* pfile, const guint8* data, size_t data_length,\n              guint64 *bytes_written, int *err)\n{\n        size_t nwritten;\n\n        nwritten = fwrite(data, data_length, 1, pfile);\n        if (nwritten != 1) {\n                if (ferror(pfile)) {\n                        *err = errno;\n                } else {\n                        *err = 0;\n                }\n                return FALSE;\n        }\n\n        (*bytes_written) += data_length;\n        return TRUE;\n}\n\n/* Writing pcap files */\n\n/* Write the file header to a dump file.\n   Returns TRUE on success, FALSE on failure.\n   Sets \"*err\" to an error code, or 0 for a short write, on failure*/\ngboolean\nlibpcap_write_file_header(FILE* pfile, int linktype, int snaplen, gboolean ts_nsecs, guint64 *bytes_written, int *err)\n{\n        struct pcap_hdr file_hdr;\n\n        file_hdr.magic = ts_nsecs ? PCAP_NSEC_MAGIC : PCAP_MAGIC;\n        /* current \"libpcap\" format is 2.4 */\n        file_hdr.version_major = 2;\n        file_hdr.version_minor = 4;\n        file_hdr.thiszone = 0;  /* XXX - current offset? */\n        file_hdr.sigfigs = 0;   /* unknown, but also apparently unused */\n        file_hdr.snaplen = snaplen;\n        file_hdr.network = linktype;\n\n        return write_to_file(pfile, (const guint8*)&file_hdr, sizeof(file_hdr), bytes_written, err);\n}\n\n/* Write a record for a packet to a dump file.\n   Returns TRUE on success, FALSE on failure. */\ngboolean\nlibpcap_write_packet(FILE* pfile,\n                     time_t sec, guint32 usec,\n                     guint32 caplen, guint32 len,\n                     const guint8 *pd,\n                     guint64 *bytes_written, int *err)\n{\n        struct pcaprec_hdr rec_hdr;\n\n        rec_hdr.ts_sec = (guint32)sec; /* Y2.038K issue in pcap format.... */\n        rec_hdr.ts_usec = usec;\n        rec_hdr.incl_len = caplen;\n        rec_hdr.orig_len = len;\n        if (!write_to_file(pfile, (const guint8*)&rec_hdr, sizeof(rec_hdr), bytes_written, err))\n                return FALSE;\n\n        return write_to_file(pfile, pd, caplen, bytes_written, err);\n}\n\n/* Writing pcapng files */\n\nstatic guint32\npcapng_count_string_option(const char *option_value)\n{\n        if ((option_value != NULL) && (strlen(option_value) > 0) && (strlen(option_value) < G_MAXUINT16)) {\n                /* There's a value to write; get its length */\n                return (guint32)(sizeof(struct option) +\n                                 (guint16)ADD_PADDING(strlen(option_value)));\n        }\n        return 0; /* nothing to write */\n}\n\nstatic gboolean\npcapng_write_string_option(FILE* pfile,\n                           guint16 option_type, const char *option_value,\n                           guint64 *bytes_written, int *err)\n{\n        size_t option_value_length;\n        struct option option;\n        const guint32 padding = 0;\n\n        if (option_value == NULL)\n                return TRUE; /* nothing to write */\n        option_value_length = strlen(option_value);\n        if ((option_value_length > 0) && (option_value_length < G_MAXUINT16)) {\n                /* something to write */\n                option.type = option_type;\n                option.value_length = (guint16)option_value_length;\n\n                if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))\n                        return FALSE;\n\n                if (!write_to_file(pfile, (const guint8*)option_value, (int) option_value_length, bytes_written, err))\n                        return FALSE;\n\n                if (option_value_length % 4) {\n                        if (!write_to_file(pfile, (const guint8*)&padding, 4 - option_value_length % 4, bytes_written, err))\n                                return FALSE;\n                }\n        }\n        return TRUE;\n}\n\n/* Write a pre-formatted pcapng block directly to the output file */\ngboolean\npcapng_write_block(FILE* pfile,\n                   const guint8 *data,\n                   guint32 length,\n                   guint64 *bytes_written,\n                   int *err)\n{\n    guint32 block_length, end_lenth;\n    /* Check\n     * - length and data are aligned to 4 bytes\n     * - block_total_length field is the same at the start and end of the block\n     *\n     * The block_total_length is not checked against the provided length but\n     * getting the trailing block_total_length from the length argument gives\n     * us an implicit check of correctness without needing to do an endian swap\n     */\n    if (((length & 3) != 0) || (((gintptr)data & 3) != 0)) {\n        return FALSE;\n    }\n    memcpy(&block_length, data+sizeof(guint32), sizeof(guint32));\n    memcpy(&end_lenth, data+length-sizeof(guint32), sizeof(guint32));\n    if (block_length != end_lenth) {\n        return FALSE;\n    }\n    return write_to_file(pfile, data, length, bytes_written, err);\n}\n\ngboolean\npcapng_write_session_header_block(FILE* pfile,\n                                  const char *comment,\n                                  const char *hw,\n                                  const char *os,\n                                  const char *appname,\n                                  guint64 section_length,\n                                  guint64 *bytes_written,\n                                  int *err)\n{\n        struct shb shb;\n        struct option option;\n        guint32 block_total_length;\n        guint32 options_length;\n\n        /* Size of base header */\n        block_total_length = sizeof(struct shb) +\n                             sizeof(guint32);\n        options_length = 0;\n        options_length += pcapng_count_string_option(comment);\n        options_length += pcapng_count_string_option(hw);\n        options_length += pcapng_count_string_option(os);\n        options_length += pcapng_count_string_option(appname);\n        /* If we have options add size of end-of-options */\n        if (options_length != 0) {\n                options_length += (guint32)sizeof(struct option);\n        }\n        block_total_length += options_length;\n\n        /* write shb header */\n        shb.block_type = SECTION_HEADER_BLOCK_TYPE;\n        shb.block_total_length = block_total_length;\n        shb.byte_order_magic = PCAPNG_MAGIC;\n        shb.major_version = PCAPNG_MAJOR_VERSION;\n        shb.minor_version = PCAPNG_MINOR_VERSION;\n        shb.section_length = section_length;\n\n        if (!write_to_file(pfile, (const guint8*)&shb, sizeof(struct shb), bytes_written, err))\n                return FALSE;\n\n        if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment,\n                                        bytes_written, err))\n                return FALSE;\n        if (!pcapng_write_string_option(pfile, SHB_HARDWARE, hw,\n                                        bytes_written, err))\n                return FALSE;\n        if (!pcapng_write_string_option(pfile, SHB_OS, os,\n                                        bytes_written, err))\n                return FALSE;\n        if (!pcapng_write_string_option(pfile, SHB_USERAPPL, appname,\n                                        bytes_written, err))\n                return FALSE;\n        if (options_length != 0) {\n                /* write end of options */\n                option.type = OPT_ENDOFOPT;\n                option.value_length = 0;\n                if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))\n                        return FALSE;\n        }\n\n        /* write the trailing block total length */\n        return write_to_file(pfile, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err);\n}\n\ngboolean\npcapng_write_interface_description_block(FILE* pfile,\n                                         const char *comment, /* OPT_COMMENT        1 */\n                                         const char *name,    /* IDB_NAME           2 */\n                                         const char *descr,   /* IDB_DESCRIPTION    3 */\n                                         const char *filter,  /* IDB_FILTER        11 */\n                                         const char *os,      /* IDB_OS            12 */\n                                         int link_type,\n                                         int snap_len,\n                                         guint64 *bytes_written,\n                                         guint64 if_speed,    /* IDB_IF_SPEED       8 */\n                                         guint8 tsresol,      /* IDB_TSRESOL        9 */\n                                         int *err)\n{\n        struct idb idb;\n        struct option option;\n        guint32 block_total_length;\n        guint32 options_length;\n        const guint32 padding = 0;\n\n        block_total_length = (guint32)(sizeof(struct idb) + sizeof(guint32));\n        options_length = 0;\n        /* 01 - OPT_COMMENT */\n        options_length += pcapng_count_string_option(comment);\n\n        /* 02 - IDB_NAME */\n        options_length += pcapng_count_string_option(name);\n\n        /* 03 - IDB_DESCRIPTION */\n        options_length += pcapng_count_string_option(descr);\n\n        /* 08 - IDB_IF_SPEED */\n        if (if_speed != 0) {\n                options_length += (guint32)(sizeof(struct option) +\n                                            sizeof(guint64));\n        }\n\n        /* 09 - IDB_TSRESOL */\n        if (tsresol != 0) {\n                options_length += (guint32)(sizeof(struct option) +\n                                            sizeof(struct option));\n        }\n\n        /* 11 - IDB_FILTER */\n        if ((filter != NULL) && (strlen(filter) > 0) && (strlen(filter) < G_MAXUINT16)) {\n                /* No, this isn't a string, it has an extra type byte */\n                options_length += (guint32)(sizeof(struct option) +\n                                            (guint16)(ADD_PADDING(strlen(filter)+ 1)));\n        }\n\n        /* 12 - IDB_OS */\n        options_length += pcapng_count_string_option(os);\n\n        /* If we have options add size of end-of-options */\n        if (options_length != 0) {\n                options_length += (guint32)sizeof(struct option);\n        }\n        block_total_length += options_length;\n\n        /* write block header */\n        idb.block_type = INTERFACE_DESCRIPTION_BLOCK_TYPE;\n        idb.block_total_length = block_total_length;\n        idb.link_type = link_type;\n        idb.reserved = 0;\n        idb.snap_len = snap_len;\n        if (!write_to_file(pfile, (const guint8*)&idb, sizeof(struct idb), bytes_written, err))\n                return FALSE;\n\n        /* 01 - OPT_COMMENT - write comment string if applicable */\n        if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment,\n                                        bytes_written, err))\n                return FALSE;\n\n        /* 02 - IDB_NAME - write interface name string if applicable */\n        if (!pcapng_write_string_option(pfile, IDB_NAME, name,\n                                        bytes_written, err))\n                return FALSE;\n\n        /* 03 - IDB_DESCRIPTION */\n        /* write interface description string if applicable */\n        if (!pcapng_write_string_option(pfile, IDB_DESCRIPTION, descr,\n                                        bytes_written, err))\n                return FALSE;\n\n        /* 08 - IDB_IF_SPEED */\n        if (if_speed != 0) {\n                option.type = IDB_IF_SPEED;\n                option.value_length = sizeof(guint64);\n\n                if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))\n                        return FALSE;\n\n                if (!write_to_file(pfile, (const guint8*)&if_speed, sizeof(guint64), bytes_written, err))\n                        return FALSE;\n        }\n\n        /* 09 - IDB_TSRESOL */\n        if (tsresol != 0) {\n                option.type = IDB_TSRESOL;\n                option.value_length = sizeof(guint8);\n\n                if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))\n                        return FALSE;\n\n                if (!write_to_file(pfile, (const guint8*)&tsresol, sizeof(guint8), bytes_written, err))\n                        return FALSE;\n\n                if (!write_to_file(pfile, (const guint8*)&padding, 3, bytes_written, err))\n                        return FALSE;\n        }\n\n        /* 11 - IDB_FILTER - write filter string if applicable\n         * We only write version 1 of the filter, pcapng string\n         */\n        if ((filter != NULL) && (strlen(filter) > 0) && (strlen(filter) < G_MAXUINT16 - 1)) {\n                option.type = IDB_FILTER;\n                option.value_length = (guint16)(strlen(filter) + 1 );\n                if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))\n                        return FALSE;\n\n                /* The first byte of the Option Data keeps a code of the filter used, 0 = lipbpcap filter string */\n                if (!write_to_file(pfile, (const guint8*)&padding, 1, bytes_written, err))\n                        return FALSE;\n                if (!write_to_file(pfile, (const guint8*)filter, (int) strlen(filter), bytes_written, err))\n                        return FALSE;\n                if ((strlen(filter) + 1) % 4) {\n                        if (!write_to_file(pfile, (const guint8*)&padding, 4 - (strlen(filter) + 1) % 4, bytes_written, err))\n                                return FALSE;\n                }\n        }\n\n        /* 12 - IDB_OS - write os string if applicable */\n        if (!pcapng_write_string_option(pfile, IDB_OS, os,\n                                        bytes_written, err))\n                return FALSE;\n\n        if (options_length != 0) {\n                /* write end of options */\n                option.type = OPT_ENDOFOPT;\n                option.value_length = 0;\n                if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))\n                        return FALSE;\n        }\n\n        /* write the trailing Block Total Length */\n        return write_to_file(pfile, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err);\n}\n\n/* Write a record for a packet to a dump file.\n   Returns TRUE on success, FALSE on failure. */\ngboolean\npcapng_write_enhanced_packet_block(FILE* pfile,\n                                   const char *comment,\n                                   time_t sec, guint32 usec,\n                                   guint32 caplen, guint32 len,\n                                   guint32 interface_id,\n                                   guint ts_mul,\n                                   const guint8 *pd,\n                                   guint32 flags,\n                                   guint64 *bytes_written,\n                                   int *err)\n{\n        struct epb epb;\n        struct option option;\n        guint32 block_total_length;\n        guint64 timestamp;\n        guint32 options_length;\n        const guint32 padding = 0;\n        guint8 buff[8];\n        guint8 i;\n        guint8 pad_len = 0;\n\n        block_total_length = (guint32)(sizeof(struct epb) +\n                                       ADD_PADDING(caplen) +\n                                       sizeof(guint32));\n        options_length = 0;\n        options_length += pcapng_count_string_option(comment);\n        if (flags != 0) {\n                options_length += (guint32)(sizeof(struct option) +\n                                            sizeof(guint32));\n        }\n        /* If we have options add size of end-of-options */\n        if (options_length != 0) {\n                options_length += (guint32)sizeof(struct option);\n        }\n        block_total_length += options_length;\n        timestamp = (guint64)sec * ts_mul + (guint64)usec;\n        epb.block_type = ENHANCED_PACKET_BLOCK_TYPE;\n        epb.block_total_length = block_total_length;\n        epb.interface_id = interface_id;\n        epb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff);\n        epb.timestamp_low = (guint32)(timestamp & 0xffffffff);\n        epb.captured_len = caplen;\n        epb.packet_len = len;\n        if (!write_to_file(pfile, (const guint8*)&epb, sizeof(struct epb), bytes_written, err))\n                return FALSE;\n        if (!write_to_file(pfile, pd, caplen, bytes_written, err))\n                return FALSE;\n        /* Use more efficient write in case of no \"extras\" */\n        if(caplen % 4) {\n            pad_len = 4 - (caplen % 4);\n        }\n        /*\n         * If we have no options to write, just write out the padding and\n         * the block total length with one fwrite() call.\n         */\n        if(!comment && flags == 0 && options_length==0){\n            /* Put padding in the buffer */\n            for (i = 0; i < pad_len; i++) {\n                buff[i] = 0;\n            }\n            /* Write the total length */\n            memcpy(&buff[i], &block_total_length, sizeof(guint32));\n            i += sizeof(guint32);\n            return write_to_file(pfile, (const guint8*)&buff, i, bytes_written, err);\n        }\n        if (pad_len) {\n                if (!write_to_file(pfile, (const guint8*)&padding, pad_len, bytes_written, err))\n                        return FALSE;\n        }\n        if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment,\n                                        bytes_written, err))\n                return FALSE;\n        if (flags != 0) {\n                option.type = EPB_FLAGS;\n                option.value_length = sizeof(guint32);\n                if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))\n                        return FALSE;\n                if (!write_to_file(pfile, (const guint8*)&flags, sizeof(guint32), bytes_written, err))\n                        return FALSE;\n        }\n        if (options_length != 0) {\n                /* write end of options */\n                option.type = OPT_ENDOFOPT;\n                option.value_length = 0;\n                if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))\n                        return FALSE;\n        }\n\n       return write_to_file(pfile, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err);\n}\n\ngboolean\npcapng_write_interface_statistics_block(FILE* pfile,\n                                        guint32 interface_id,\n                                        guint64 *bytes_written,\n                                        const char *comment,   /* OPT_COMMENT           1 */\n                                        guint64 isb_starttime, /* ISB_STARTTIME         2 */\n                                        guint64 isb_endtime,   /* ISB_ENDTIME           3 */\n                                        guint64 isb_ifrecv,    /* ISB_IFRECV            4 */\n                                        guint64 isb_ifdrop,    /* ISB_IFDROP            5 */\n                                        int *err)\n{\n        struct isb isb;\n#ifdef _WIN32\n        FILETIME now;\n#else\n        struct timeval now;\n#endif\n        struct option option;\n        guint32 block_total_length;\n        guint32 options_length;\n        guint64 timestamp;\n\n#ifdef _WIN32\n        /*\n         * Current time, represented as 100-nanosecond intervals since\n         * January 1, 1601, 00:00:00 UTC.\n         *\n         * I think DWORD might be signed, so cast both parts of \"now\"\n         * to guint32 so that the sign bit doesn't get treated specially.\n         *\n         * Windows 8 provides GetSystemTimePreciseAsFileTime which we\n         * might want to use instead.\n         */\n        GetSystemTimeAsFileTime(&now);\n        timestamp = (((guint64)(guint32)now.dwHighDateTime) << 32) +\n                    (guint32)now.dwLowDateTime;\n\n        /*\n         * Convert to same thing but as 1-microsecond, i.e. 1000-nanosecond,\n         * intervals.\n         */\n        timestamp /= 10;\n\n        /*\n         * Subtract difference, in microseconds, between January 1, 1601\n         * 00:00:00 UTC and January 1, 1970, 00:00:00 UTC.\n         */\n        timestamp -= G_GUINT64_CONSTANT(11644473600000000);\n#else\n        /*\n         * Current time, represented as seconds and microseconds since\n         * January 1, 1970, 00:00:00 UTC.\n         */\n        gettimeofday(&now, NULL);\n\n        /*\n         * Convert to delta in microseconds.\n         */\n        timestamp = (guint64)(now.tv_sec) * 1000000 +\n                    (guint64)(now.tv_usec);\n#endif\n        block_total_length = (guint32)(sizeof(struct isb) + sizeof(guint32));\n        options_length = 0;\n        if (isb_ifrecv != G_MAXUINT64) {\n                options_length += (guint32)(sizeof(struct option) +\n                                            sizeof(guint64));\n        }\n        if (isb_ifdrop != G_MAXUINT64) {\n                options_length += (guint32)(sizeof(struct option) +\n                                            sizeof(guint64));\n        }\n        /* OPT_COMMENT */\n        options_length += pcapng_count_string_option(comment);\n        if (isb_starttime !=0) {\n                options_length += (guint32)(sizeof(struct option) +\n                                            sizeof(guint64)); /* ISB_STARTTIME */\n        }\n        if (isb_endtime !=0) {\n                options_length += (guint32)(sizeof(struct option) +\n                                            sizeof(guint64)); /* ISB_ENDTIME */\n        }\n        /* If we have options add size of end-of-options */\n        if (options_length != 0) {\n                options_length += (guint32)sizeof(struct option);\n        }\n        block_total_length += options_length;\n\n        isb.block_type = INTERFACE_STATISTICS_BLOCK_TYPE;\n        isb.block_total_length = block_total_length;\n        isb.interface_id = interface_id;\n        isb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff);\n        isb.timestamp_low = (guint32)(timestamp & 0xffffffff);\n        if (!write_to_file(pfile, (const guint8*)&isb, sizeof(struct isb), bytes_written, err))\n                return FALSE;\n\n        /* write comment string if applicable */\n        if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment,\n                                        bytes_written, err))\n                return FALSE;\n\n        if (isb_starttime !=0) {\n                guint32 high, low;\n\n                option.type = ISB_STARTTIME;\n                option.value_length = sizeof(guint64);\n                high = (guint32)((isb_starttime>>32) & 0xffffffff);\n                low = (guint32)(isb_starttime & 0xffffffff);\n                if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))\n                        return FALSE;\n\n                if (!write_to_file(pfile, (const guint8*)&high, sizeof(guint32), bytes_written, err))\n                        return FALSE;\n\n                if (!write_to_file(pfile, (const guint8*)&low, sizeof(guint32), bytes_written, err))\n                        return FALSE;\n        }\n        if (isb_endtime !=0) {\n                guint32 high, low;\n\n                option.type = ISB_ENDTIME;\n                option.value_length = sizeof(guint64);\n                high = (guint32)((isb_endtime>>32) & 0xffffffff);\n                low = (guint32)(isb_endtime & 0xffffffff);\n                if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))\n                        return FALSE;\n\n                if (!write_to_file(pfile, (const guint8*)&high, sizeof(guint32), bytes_written, err))\n                        return FALSE;\n\n                if (!write_to_file(pfile, (const guint8*)&low, sizeof(guint32), bytes_written, err))\n                        return FALSE;\n        }\n        if (isb_ifrecv != G_MAXUINT64) {\n                option.type = ISB_IFRECV;\n                option.value_length = sizeof(guint64);\n                if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))\n                        return FALSE;\n\n                if (!write_to_file(pfile, (const guint8*)&isb_ifrecv, sizeof(guint64), bytes_written, err))\n                        return FALSE;\n        }\n        if (isb_ifdrop != G_MAXUINT64) {\n                option.type = ISB_IFDROP;\n                option.value_length = sizeof(guint64);\n                if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))\n                        return FALSE;\n\n                if (!write_to_file(pfile, (const guint8*)&isb_ifdrop, sizeof(guint64), bytes_written, err))\n                        return FALSE;\n        }\n        if (options_length != 0) {\n                /* write end of options */\n                option.type = OPT_ENDOFOPT;\n                option.value_length = 0;\n                if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))\n                        return FALSE;\n        }\n\n        return write_to_file(pfile, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err);\n}\n\n/*\n * Editor modelines  -  http://www.wireshark.org/tools/modelines.html\n *\n * Local variables:\n * c-basic-offset: 8\n * tab-width: 8\n * indent-tabs-mode: nil\n * End:\n *\n * vi: set shiftwidth=8 tabstop=8 expandtab:\n * :indentSize=8:tabSize=8:noTabs=true:\n */\n"
  },
  {
    "path": "BinUtils/j1939AddrClaim/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.5)\n\nproject(j1939AddrClaim)\n\nadd_executable(j1939AddrClaim \n    j1939AddrClaim.cpp\n)\n\ntarget_include_directories(j1939AddrClaim\n    PUBLIC \n        include ${J1939_SOURCE_DIR}/include ${Can_SOURCE_DIR}/include ${Common_SOURCE_DIR}/include ${J1939AddressClaimer_SOURCE_DIR}/include\n)\n\ntarget_link_libraries(j1939AddrClaim\n    PUBLIC\n        J1939 Can J1939AddressClaimer rt jsoncpp -rdynamic\n)\n\ninstall (TARGETS j1939AddrClaim\n    DESTINATION bin)\n"
  },
  {
    "path": "BinUtils/j1939AddrClaim/Readme.md",
    "content": "Used to simulate the Address Claiming Process\n\nUsage:\n\n```bash\n    ./j1939AddrClaim -n <identity_number> -i <interface> -p \"[<preferred_addr1>,<preferred_addr2>,<preferred_addr3>,...]\" \n```\n"
  },
  {
    "path": "BinUtils/j1939AddrClaim/j1939AddrClaim.cpp",
    "content": "/*\n * AddressClaim.cpp\n *\n *  Created on: Jan 13, 2019\n *      Author: famez\n */\n\n\n\n#ifndef DATABASE_PATH\n#define DATABASE_PATH\t\t\"/etc/j1939/frames.json\"\n#endif\n\n#include <getopt.h>\n\n#include <memory>\n#include <chrono>\n#include <thread>\n\n#include <json/json.h>\n\n#include <CanEasy.h>\n\n#include <J1939Factory.h>\n#include <AddressClaimer.h>\n\n\n#define BAUD_250K\t\t\t250000\n\nnamespace J1939 {\n\nclass MyAddressClaimer : public AddressClaimer {\nprivate:\n\tstd::shared_ptr<Can::ICanSender> mSender;\n\nprotected:\n\tvoid onSrcAddrChanged(u8 newAddr) {\n\n\t\tif(newAddr == J1939_INVALID_ADDRESS) {\n\t\t\tstd::cout << \"No address!!!\" << std::endl;\n\t\t} else {\n\t\t\tstd::cout << \"New address obtained \" << static_cast<u32>(newAddr) << std::endl;\n\t\t}\n\n\t}\n\tvoid sendFrame(const J1939Frame& frame) {\n\n\t\tsize_t length = frame.getDataLength();\n\n\t\tu32 id;\n\t\tu8 *buff = new u8[length];\n\n\t\tframe.encode(id, buff, length);\n\n\t\tCan::CanFrame canFrame;\n\n\t\t//J1939 data is always transmitted in extended format\n\t\tcanFrame.setExtendedFormat(true);\n\n\t\t//Set identifier\n\t\tcanFrame.setId(id);\n\n\t\t//Set data\n\t\tstd::string data;\n\t\tdata.append((char*)buff, length);\n\n\t\tcanFrame.setData(data);\n\n\t\tmSender->sendFrameOnce(canFrame);\n\n\t\tdelete[] buff;\n\n\t}\n\npublic:\n\tMyAddressClaimer(const EcuName& name, const std::queue<u8>& preferred, std::shared_ptr<Can::ICanSender> sender) : AddressClaimer(name, preferred), mSender(sender) {}\n\t~MyAddressClaimer() {}\n\n};\n\n}\n\n\nusing namespace J1939;\nusing namespace Can;\nusing namespace Utils;\n\nstd::unique_ptr<MyAddressClaimer> addresClaimer;\n\n\nvoid onRcv(const CanFrame& frame, const TimeStamp&, const std::string& interface, void*);\nbool onTimeout();\n\nint\nmain (int argc, char **argv)\n{\n\n\t//Get options\n\tint c;\n\tstd::string interface;\n\tstd::string preferredAddr;\n\tstd::string idNumberStr;\n\n\tstatic struct option long_options[] =\n\t{\n\t\t{\"interface\", required_argument, NULL, 'i'},\n\t\t{\"preferred\", required_argument, NULL, 'p'},\n\t\t{\"identity_number\", required_argument, NULL, 'n'},\n\t\t{NULL, 0, NULL, 0}\n\t};\n\n\n\twhile (1)\n\t{\n\n\t\tc = getopt_long (argc, argv, \"i:p:n:\",\n\t\t\t\t   long_options, NULL);\n\n\t\t/* Detect the end of the options. */\n\t\tif (c == -1)\n\t\t\tbreak;\n\n\t\tswitch (c)\n\t\t{\n\t\tcase 'i':\n\t\t\tinterface = optarg;\n\t\t\tbreak;\n\t\tcase 'p':\n\t\t\tpreferredAddr = optarg;\n\t\t\tbreak;\n\t\tcase 'n':\n\t\t\tidNumberStr = optarg;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tu32 idNumber;\n\n\ttry {\n\n\t\tidNumber = std::stoul(idNumberStr);\n\n\t} catch (std::invalid_argument& ) {\n\t\tstd::cerr << \"identity_number is not a number...\" << std::endl;\n\t\treturn -1;\n\t}\n\n\tCanEasy::initialize(BAUD_250K, onRcv, onTimeout);\n\n\tstd::set<std::string> interfaces = CanEasy::getCanIfaces();\n\n\tif(interfaces.find(interface) == interfaces.end()) {\n\t\tstd::cerr << \"Interface not available\" << std::endl;\n\t\tstd::cerr << \"Interfaces: \" << std::endl;\n\n\t\tfor(auto iter = interfaces.begin(); iter != interfaces.end(); ++iter) {\n\t\t\tstd::cerr << *iter << std::endl;\n\t\t}\n\t\treturn -2;\n\t}\n\n\tstd::shared_ptr<ICanSender> sender = CanEasy::getSender(interface);\n\n\tif(!sender) {\n\t\tstd::cerr << \"Cannot send through the interface\" << std::endl;\n\t\treturn -3;\n\t}\n\n\tEcuName name;\n\n\tname.setIdNumber(idNumber);\n\n\tJson::Value addresses;\n\n\tJson::CharReaderBuilder builder;\n\tJson::CharReader *jSonReader = builder.newCharReader();\n\tstd::string errs;\n\n\tif(!jSonReader->parse(preferredAddr.c_str(), preferredAddr.c_str() + preferredAddr.size(), &addresses, &errs)) {\n\t\tstd::cerr << \"No json format for preferred\" << std::endl;\n\t\treturn -4;\n\t}\n\n\tstd::queue<u8> preferred;\n\n\tif(!addresses.isArray()) {\n\t\tstd::cerr << \"preferred is not an array\" << std::endl;\n\t\treturn -5;\n\t}\n\n\tfor(unsigned int i = 0; i < addresses.size(); ++i) {\n\t\tif(addresses[i].isUInt() && (addresses[i].asUInt() == addresses[i].asUInt() & J1939_SRC_ADDR_MASK)) {\n\t\t\tpreferred.push(addresses[i].asUInt());\n\t\t}\n\t}\n\n\tif(addresses.empty()) {\n\t\tstd::cerr << \"No addresses passed to argument preferred\" << std::endl;\n\t\treturn -6;\n\t}\n\n\taddresClaimer = std::unique_ptr<MyAddressClaimer>(new MyAddressClaimer(name, preferred, sender));\n\n\tconst CanSniffer& canSniffer = CanEasy::getSniffer();\n\n\tcanSniffer.sniff(1000);\n\n\treturn 0;\n}\n\n\nvoid onRcv(const CanFrame& frame, const TimeStamp&, const std::string& interface, void*) {\n\n\tstd::unique_ptr<J1939Frame> j1939Frame = J1939Factory::getInstance().\n\t\t\t\tgetJ1939Frame(frame.getId(), (const u8*)(frame.getData().c_str()), frame.getData().size());\n\n\tif(j1939Frame) {\n\n\t\tif(addresClaimer->toBeHandled(*j1939Frame)) {\n\t\t\taddresClaimer->receive(*j1939Frame);\n\t\t}\n\n\t}\n\n}\n\n\nbool onTimeout() {\n\treturn true;\n}\n"
  },
  {
    "path": "BinUtils/j1939AddressMapper/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.5)\n\nproject(j1939AddressMapper)\n\nadd_executable(j1939AddressMapper \n    j1939AddressMapper.cpp\n)\n\ntarget_include_directories(j1939AddressMapper\n    PUBLIC \n        include ${J1939_SOURCE_DIR}/include ${Can_SOURCE_DIR}/include ${Common_SOURCE_DIR}/include\n)\n\ntarget_link_libraries(j1939AddressMapper\n    PUBLIC\n        J1939 Can rt jsoncpp -rdynamic\n)\n\ninstall (TARGETS j1939AddressMapper\n    DESTINATION bin)\n"
  },
  {
    "path": "BinUtils/j1939AddressMapper/Readme.md",
    "content": "To detect the ECUs in the Can Network, their Sources Address and Ecu Names\n\nUsage:\n\n```bash\n   j1939AddressMapper \n```\n"
  },
  {
    "path": "BinUtils/j1939AddressMapper/j1939AddressMapper.cpp",
    "content": "/*\n * j1939AddressMapper.cpp\n *\n *  Created on: Jan 25, 2019\n *      Author: famez\n */\n\n\n\n#ifndef DATABASE_PATH\n#define DATABASE_PATH\t\t\"/etc/j1939/frames.json\"\n#endif\n\n\n#include <memory>\n#include <chrono>\n#include <thread>\n\n#include <json/json.h>\n\n#include <CanEasy.h>\n\n#include <J1939Factory.h>\n\n#include <Frames/RequestFrame.h>\n#include <Addressing/AddressClaimFrame.h>\n\n\n#define BAUD_250K\t\t\t250000\n\nusing namespace J1939;\nusing namespace Can;\nusing namespace Utils;\n\nstd::set<EcuName> names;\n\n\nvoid onRcv(const CanFrame& frame, const TimeStamp&, const std::string& interface, void*);\nbool onTimeout();\n\nint\nmain (int argc, char **argv)\n{\n\n\t//Initialize can\n\tCanEasy::initialize(BAUD_250K, onRcv, onTimeout);\n\n\tconst std::set<std::string>& ifaces = CanEasy::getInitializedCanIfaces();\n\n\tif(ifaces.empty()) {\n\t\tstd::cerr << \"No interfaces initialized\" << std::endl;\n\t\treturn 1;\n\t}\n\n\t/*\n\t * Create request frame to request the PGN corresponding to the Address Claim\n\t */\n\n\tRequestFrame reqFrame(ADDRESS_CLAIM_PGN);\n\treqFrame.setSrcAddr(J1939_INVALID_ADDRESS);\n\treqFrame.setDstAddr(J1939_BROADCAST_ADDRESS);\n\n\tCanFrame canFrame;\n\n\tsize_t length = reqFrame.getDataLength();\n\n\tu32 id;\n\tu8 *buff = new u8[length];\n\n\treqFrame.encode(id, buff, length);\n\n\t//J1939 data is always transmitted in extended format\n\tcanFrame.setExtendedFormat(true);\n\n\t//Set identifier\n\tcanFrame.setId(id);\n\n\t//Set data\n\tstd::string data;\n\tdata.append((char*)buff, length);\n\n\tcanFrame.setData(data);\n\n\tdelete[] buff;\n\n\n\n\tfor(auto iface = ifaces.begin(); iface != ifaces.end(); ++iface) {\n\n\t\tstd::shared_ptr<ICanSender> sender = CanEasy::getSender(*iface);\n\n\t\tsender->sendFrame(canFrame, 1000);\t\t\t//Send the frame every second\n\n\t}\n\n\tCanSniffer& canSniffer = CanEasy::getSniffer();\n\n\tstd::set<CanFilter> filters;\n\n\t//Receive only frames with the ADDRESS_CLAIM_PGN\n\n\tCanFilter filter(ADDRESS_CLAIM_PGN << J1939_PGN_OFFSET\n\t\t\t, ((J1939_PDU_FMT_MASK << J1939_PDU_FMT_OFFSET) << J1939_PGN_OFFSET), true, false);\n\n\tfilters.insert(filter);\n\n\tcanSniffer.setFilters(filters);\n\n\tstd::cout << \"Interface\\tSource Address\\tIN\\tMC\\tEI\\tFI\"\n\t\t\t\"\\tF\\tVS\\tVSI\\tIG\\tAAC\" << std::endl << std::endl;\n\n\tcanSniffer.sniff(1000);\n\n\treturn 0;\n}\n\nvoid onRcv(const CanFrame& frame, const TimeStamp&, const std::string& interface, void*) {\n\n\tstd::unique_ptr<J1939Frame> j1939Frame = J1939Factory::getInstance().\n\t\t\t\tgetJ1939Frame(frame.getId(), (const u8*)(frame.getData().c_str()), frame.getData().size());\n\n\tif(j1939Frame && j1939Frame->getPGN() == ADDRESS_CLAIM_PGN) {\n\n\t\tAddressClaimFrame *addrClaimFrame = static_cast<AddressClaimFrame*>(j1939Frame.get());\n\n\t\tconst EcuName &name = addrClaimFrame->getEcuName();\n\n\t\tif(names.find(name) == names.end()) {\t\t//Check if we have already shown the frame\n\t\t\tstd::cout << interface << '\\t' << '\\t' << static_cast<u32>(j1939Frame->getSrcAddr()) << '\\t' << '\\t' << name.getIdNumber() << '\\t'\n\t\t\t\t\t<< static_cast<u32>(name.getManufacturerCode()) << '\\t' << static_cast<u32>(name.getEcuInstance()) << '\\t'\n\t\t\t\t\t<< static_cast<u32>(name.getFunctionInstance()) << '\\t'\n\t\t\t\t\t<< static_cast<u32>(name.getFunction()) << '\\t' << static_cast<u32>(name.getVehicleSystem()) << '\\t'\n\t\t\t\t\t<< static_cast<u32>(name.getVehicleSystemInstance()) << '\\t'\n\t\t\t\t\t<< static_cast<u32>(name.getIndustryGroup()) << '\\t' << (name.isArbitraryAddressCapable() ? \"Address Capable\" : \"No address capable\") << std::endl;\n\n\t\t\tnames.insert(name);\n\t\t}\n\n\t}\n\n}\n\n\nbool onTimeout() {\n\n\treturn true;\n\n}\n"
  },
  {
    "path": "BinUtils/j1939Decoder/.cproject",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<?fileVersion 4.0.0?><cproject storage_type_id=\"org.eclipse.cdt.core.XmlProjectDescriptionStorage\">\n\t<storageModule moduleId=\"org.eclipse.cdt.core.settings\">\n\t\t<cconfiguration id=\"cdt.managedbuild.config.gnu.exe.debug.1861074874\">\n\t\t\t<storageModule buildSystemId=\"org.eclipse.cdt.managedbuilder.core.configurationDataProvider\" id=\"cdt.managedbuild.config.gnu.exe.debug.1861074874\" moduleId=\"org.eclipse.cdt.core.settings\" name=\"Debug\">\n\t\t\t\t<externalSettings/>\n\t\t\t\t<extensions>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.ELF\" point=\"org.eclipse.cdt.core.BinaryParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GmakeErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.CWDLocator\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GCCErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GASErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GLDErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t</extensions>\n\t\t\t</storageModule>\n\t\t\t<storageModule moduleId=\"cdtBuildSystem\" version=\"4.0.0\">\n\t\t\t\t<configuration artifactName=\"${ProjName}\" buildArtefactType=\"org.eclipse.cdt.build.core.buildArtefactType.exe\" buildProperties=\"org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe\" cleanCommand=\"rm -rf\" description=\"\" id=\"cdt.managedbuild.config.gnu.exe.debug.1861074874\" name=\"Debug\" parent=\"cdt.managedbuild.config.gnu.exe.debug\">\n\t\t\t\t\t<folderInfo id=\"cdt.managedbuild.config.gnu.exe.debug.1861074874.\" name=\"/\" resourcePath=\"\">\n\t\t\t\t\t\t<toolChain id=\"cdt.managedbuild.toolchain.gnu.exe.debug.41297790\" name=\"Linux GCC\" superClass=\"cdt.managedbuild.toolchain.gnu.exe.debug\">\n\t\t\t\t\t\t\t<targetPlatform id=\"cdt.managedbuild.target.gnu.platform.exe.debug.13883019\" name=\"Debug Platform\" superClass=\"cdt.managedbuild.target.gnu.platform.exe.debug\"/>\n\t\t\t\t\t\t\t<builder buildPath=\"${workspace_loc:/j1939Encoder}/Debug\" id=\"cdt.managedbuild.target.gnu.builder.exe.debug.292210226\" keepEnvironmentInBuildfile=\"false\" managedBuildOn=\"true\" name=\"Gnu Make Builder\" superClass=\"cdt.managedbuild.target.gnu.builder.exe.debug\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.archiver.base.1889993658\" name=\"GCC Archiver\" superClass=\"cdt.managedbuild.tool.gnu.archiver.base\"/>\n\t\t\t\t\t\t\t<tool commandLinePattern=\"${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}\" id=\"cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.1543165477\" name=\"GCC C++ Compiler\" superClass=\"cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug\">\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.exe.debug.option.optimization.level.728948622\" name=\"Optimization Level\" superClass=\"gnu.cpp.compiler.exe.debug.option.optimization.level\" value=\"gnu.cpp.compiler.optimization.level.none\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.exe.debug.option.debugging.level.1882222916\" name=\"Debug Level\" superClass=\"gnu.cpp.compiler.exe.debug.option.debugging.level\" value=\"gnu.cpp.compiler.debugging.level.max\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.option.include.paths.472704876\" name=\"Include paths (-I)\" superClass=\"gnu.cpp.compiler.option.include.paths\" valueType=\"includePath\">\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"&quot;${workspace_loc:/J1939}&quot;\"/>\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"&quot;${workspace_loc:/Common}&quot;\"/>\n\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.option.dialect.std.497669387\" name=\"Language standard\" superClass=\"gnu.cpp.compiler.option.dialect.std\" value=\"gnu.cpp.compiler.dialect.c++11\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.cpp.compiler.input.269450500\" superClass=\"cdt.managedbuild.tool.gnu.cpp.compiler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.c.compiler.exe.debug.2037226843\" name=\"GCC C Compiler\" superClass=\"cdt.managedbuild.tool.gnu.c.compiler.exe.debug\">\n\t\t\t\t\t\t\t\t<option defaultValue=\"gnu.c.optimization.level.none\" id=\"gnu.c.compiler.exe.debug.option.optimization.level.542025320\" name=\"Optimization Level\" superClass=\"gnu.c.compiler.exe.debug.option.optimization.level\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.c.compiler.exe.debug.option.debugging.level.2029967667\" name=\"Debug Level\" superClass=\"gnu.c.compiler.exe.debug.option.debugging.level\" value=\"gnu.c.debugging.level.max\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.c.compiler.option.dialect.std.1946434284\" name=\"Language standard\" superClass=\"gnu.c.compiler.option.dialect.std\" value=\"gnu.c.compiler.dialect.default\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.c.compiler.input.590237086\" superClass=\"cdt.managedbuild.tool.gnu.c.compiler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.c.linker.exe.debug.415907468\" name=\"GCC C Linker\" superClass=\"cdt.managedbuild.tool.gnu.c.linker.exe.debug\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.cpp.linker.exe.debug.280908848\" name=\"GCC C++ Linker\" superClass=\"cdt.managedbuild.tool.gnu.cpp.linker.exe.debug\">\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.link.option.libs.114738467\" name=\"Libraries (-l)\" superClass=\"gnu.cpp.link.option.libs\" valueType=\"libs\">\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"J1939\"/>\n\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.link.option.paths.1184525820\" name=\"Library search path (-L)\" superClass=\"gnu.cpp.link.option.paths\" valueType=\"libPaths\">\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"&quot;${workspace_loc:/J1939/Debug}&quot;\"/>\n\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.link.option.flags.784585019\" name=\"Linker flags\" superClass=\"gnu.cpp.link.option.flags\" value=\"-rdynamic\" valueType=\"string\"/>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.cpp.linker.input.1601160676\" superClass=\"cdt.managedbuild.tool.gnu.cpp.linker.input\">\n\t\t\t\t\t\t\t\t\t<additionalInput kind=\"additionalinputdependency\" paths=\"$(USER_OBJS)\"/>\n\t\t\t\t\t\t\t\t\t<additionalInput kind=\"additionalinput\" paths=\"$(LIBS)\"/>\n\t\t\t\t\t\t\t\t</inputType>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.assembler.exe.debug.1117711655\" name=\"GCC Assembler\" superClass=\"cdt.managedbuild.tool.gnu.assembler.exe.debug\">\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.assembler.input.1493080121\" superClass=\"cdt.managedbuild.tool.gnu.assembler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t</toolChain>\n\t\t\t\t\t</folderInfo>\n\t\t\t\t\t<sourceEntries>\n\t\t\t\t\t\t<entry flags=\"VALUE_WORKSPACE_PATH|RESOLVED\" kind=\"sourcePath\" name=\"src\"/>\n\t\t\t\t\t</sourceEntries>\n\t\t\t\t</configuration>\n\t\t\t</storageModule>\n\t\t\t<storageModule moduleId=\"org.eclipse.cdt.core.externalSettings\"/>\n\t\t</cconfiguration>\n\t\t<cconfiguration id=\"cdt.managedbuild.config.gnu.exe.release.1740876316\">\n\t\t\t<storageModule buildSystemId=\"org.eclipse.cdt.managedbuilder.core.configurationDataProvider\" id=\"cdt.managedbuild.config.gnu.exe.release.1740876316\" moduleId=\"org.eclipse.cdt.core.settings\" name=\"Release\">\n\t\t\t\t<externalSettings/>\n\t\t\t\t<extensions>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.ELF\" point=\"org.eclipse.cdt.core.BinaryParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GmakeErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.CWDLocator\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GCCErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GASErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GLDErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t</extensions>\n\t\t\t</storageModule>\n\t\t\t<storageModule moduleId=\"cdtBuildSystem\" version=\"4.0.0\">\n\t\t\t\t<configuration artifactName=\"${ProjName}\" buildArtefactType=\"org.eclipse.cdt.build.core.buildArtefactType.exe\" buildProperties=\"org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe\" cleanCommand=\"rm -rf\" description=\"\" id=\"cdt.managedbuild.config.gnu.exe.release.1740876316\" name=\"Release\" parent=\"cdt.managedbuild.config.gnu.exe.release\">\n\t\t\t\t\t<folderInfo id=\"cdt.managedbuild.config.gnu.exe.release.1740876316.\" name=\"/\" resourcePath=\"\">\n\t\t\t\t\t\t<toolChain id=\"cdt.managedbuild.toolchain.gnu.exe.release.1331478304\" name=\"Linux GCC\" superClass=\"cdt.managedbuild.toolchain.gnu.exe.release\">\n\t\t\t\t\t\t\t<targetPlatform id=\"cdt.managedbuild.target.gnu.platform.exe.release.1241502955\" name=\"Debug Platform\" superClass=\"cdt.managedbuild.target.gnu.platform.exe.release\"/>\n\t\t\t\t\t\t\t<builder buildPath=\"${workspace_loc:/j1939Encoder}/Release\" id=\"cdt.managedbuild.target.gnu.builder.exe.release.1330907601\" keepEnvironmentInBuildfile=\"false\" managedBuildOn=\"true\" name=\"Gnu Make Builder\" superClass=\"cdt.managedbuild.target.gnu.builder.exe.release\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.archiver.base.1987214766\" name=\"GCC Archiver\" superClass=\"cdt.managedbuild.tool.gnu.archiver.base\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.488040747\" name=\"GCC C++ Compiler\" superClass=\"cdt.managedbuild.tool.gnu.cpp.compiler.exe.release\">\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.exe.release.option.optimization.level.1122889053\" name=\"Optimization Level\" superClass=\"gnu.cpp.compiler.exe.release.option.optimization.level\" value=\"gnu.cpp.compiler.optimization.level.most\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.exe.release.option.debugging.level.1443593314\" name=\"Debug Level\" superClass=\"gnu.cpp.compiler.exe.release.option.debugging.level\" value=\"gnu.cpp.compiler.debugging.level.none\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.cpp.compiler.input.971739607\" superClass=\"cdt.managedbuild.tool.gnu.cpp.compiler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.c.compiler.exe.release.1153223945\" name=\"GCC C Compiler\" superClass=\"cdt.managedbuild.tool.gnu.c.compiler.exe.release\">\n\t\t\t\t\t\t\t\t<option defaultValue=\"gnu.c.optimization.level.most\" id=\"gnu.c.compiler.exe.release.option.optimization.level.1534366200\" name=\"Optimization Level\" superClass=\"gnu.c.compiler.exe.release.option.optimization.level\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.c.compiler.exe.release.option.debugging.level.2082751618\" name=\"Debug Level\" superClass=\"gnu.c.compiler.exe.release.option.debugging.level\" value=\"gnu.c.debugging.level.none\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.c.compiler.input.821619422\" superClass=\"cdt.managedbuild.tool.gnu.c.compiler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.c.linker.exe.release.1830197936\" name=\"GCC C Linker\" superClass=\"cdt.managedbuild.tool.gnu.c.linker.exe.release\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.cpp.linker.exe.release.1189973488\" name=\"GCC C++ Linker\" superClass=\"cdt.managedbuild.tool.gnu.cpp.linker.exe.release\">\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.cpp.linker.input.1531319115\" superClass=\"cdt.managedbuild.tool.gnu.cpp.linker.input\">\n\t\t\t\t\t\t\t\t\t<additionalInput kind=\"additionalinputdependency\" paths=\"$(USER_OBJS)\"/>\n\t\t\t\t\t\t\t\t\t<additionalInput kind=\"additionalinput\" paths=\"$(LIBS)\"/>\n\t\t\t\t\t\t\t\t</inputType>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.assembler.exe.release.49455526\" name=\"GCC Assembler\" superClass=\"cdt.managedbuild.tool.gnu.assembler.exe.release\">\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.assembler.input.118685022\" superClass=\"cdt.managedbuild.tool.gnu.assembler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t</toolChain>\n\t\t\t\t\t</folderInfo>\n\t\t\t\t\t<sourceEntries>\n\t\t\t\t\t\t<entry flags=\"VALUE_WORKSPACE_PATH|RESOLVED\" kind=\"sourcePath\" name=\"src\"/>\n\t\t\t\t\t</sourceEntries>\n\t\t\t\t</configuration>\n\t\t\t</storageModule>\n\t\t\t<storageModule moduleId=\"org.eclipse.cdt.core.externalSettings\"/>\n\t\t</cconfiguration>\n\t</storageModule>\n\t<storageModule moduleId=\"cdtBuildSystem\" version=\"4.0.0\">\n\t\t<project id=\"j1939Encoder.cdt.managedbuild.target.gnu.exe.1404579584\" name=\"Executable\" projectType=\"cdt.managedbuild.target.gnu.exe\"/>\n\t</storageModule>\n\t<storageModule moduleId=\"scannerConfiguration\">\n\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.config.gnu.exe.release.1740876316;cdt.managedbuild.config.gnu.exe.release.1740876316.;cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.488040747;cdt.managedbuild.tool.gnu.cpp.compiler.input.971739607\">\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t</scannerConfigBuildInfo>\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.config.gnu.exe.release.1740876316;cdt.managedbuild.config.gnu.exe.release.1740876316.;cdt.managedbuild.tool.gnu.c.compiler.exe.release.1153223945;cdt.managedbuild.tool.gnu.c.compiler.input.821619422\">\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t</scannerConfigBuildInfo>\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.config.gnu.exe.debug.1861074874;cdt.managedbuild.config.gnu.exe.debug.1861074874.;cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.1543165477;cdt.managedbuild.tool.gnu.cpp.compiler.input.269450500\">\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t</scannerConfigBuildInfo>\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.config.gnu.exe.debug.1861074874;cdt.managedbuild.config.gnu.exe.debug.1861074874.;cdt.managedbuild.tool.gnu.c.compiler.exe.debug.2037226843;cdt.managedbuild.tool.gnu.c.compiler.input.590237086\">\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t</scannerConfigBuildInfo>\n\t</storageModule>\n\t<storageModule moduleId=\"org.eclipse.cdt.core.LanguageSettingsProviders\"/>\n\t<storageModule moduleId=\"refreshScope\" versionNumber=\"2\">\n\t\t<configuration configurationName=\"Release\">\n\t\t\t<resource resourceType=\"PROJECT\" workspacePath=\"/j1939Encoder\"/>\n\t\t</configuration>\n\t\t<configuration configurationName=\"Debug\">\n\t\t\t<resource resourceType=\"PROJECT\" workspacePath=\"/j1939Encoder\"/>\n\t\t</configuration>\n\t</storageModule>\n\t<storageModule moduleId=\"org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings\"/>\n</cproject>\n"
  },
  {
    "path": "BinUtils/j1939Decoder/.settings/org.eclipse.cdt.codan.core.prefs",
    "content": "eclipse.preferences.version=1\norg.eclipse.cdt.codan.checkers.errnoreturn=Warning\norg.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},implicit\\=>false}\norg.eclipse.cdt.codan.checkers.errreturnvalue=Error\norg.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.checkers.noreturn=Error\norg.eclipse.cdt.codan.checkers.noreturn.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},implicit\\=>false}\norg.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=-Error\norg.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error\norg.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},no_break_comment\\=>\"no break\",last_case_param\\=>false,empty_case_param\\=>false}\norg.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning\norg.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},unknown\\=>false,exceptions\\=>()}\norg.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning\norg.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},skip\\=>true}\norg.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.InvalidArguments=-Error\norg.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info\norg.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},pattern\\=>\"^[a-z]\",macro\\=>true,exceptions\\=>()}\norg.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.OverloadProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning\norg.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning\norg.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},macro\\=>true,exceptions\\=>()}\norg.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},paramNot\\=>false}\norg.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},else\\=>false,afterelse\\=>false}\norg.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},macro\\=>true}\norg.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},macro\\=>true}\norg.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},macro\\=>true,exceptions\\=>(\"@(\\#)\",\"$Id\")}\norg.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\nuseParentScope=false\n"
  },
  {
    "path": "BinUtils/j1939Decoder/.settings/org.eclipse.cdt.core.prefs",
    "content": "eclipse.preferences.version=1\nenvironment/project/cdt.managedbuild.config.gnu.exe.debug.1861074874/append=true\nenvironment/project/cdt.managedbuild.config.gnu.exe.debug.1861074874/appendContributed=true\n"
  },
  {
    "path": "BinUtils/j1939Decoder/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.5)\n\nproject(j1939Decoder)\n\nadd_executable(j1939Decoder \n    src/j1939Decoder.cpp\n)\n\ntarget_include_directories(j1939Decoder\n    PUBLIC \n        include ${J1939_SOURCE_DIR}/include ${Common_SOURCE_DIR}/include\n)\n\ntarget_link_libraries(j1939Decoder\n    PUBLIC\n        J1939\n)\n\ninstall (TARGETS j1939Decoder\n    DESTINATION bin)\n"
  },
  {
    "path": "BinUtils/j1939Decoder/README.md",
    "content": "To decode frames. For example:\n    \n```bash\n    ./j1939Decoder --id 00febffe --data \"00 c4 00 00 00 00 00 00\"\n    Name\tPGN\tSource Address\tPDU format\tPriority\t\n    EBC2\tFEBF\tFE\t\t2\t\t0\t\n    SPN 904: Front Axe Speed -> Value: 196 kph\n    SPN 905: Relative Speed; Front Axle, Left Wheel -> Value: -7 kph\n    SPN 906: Relative Speed; Front Axle, Right Wheel -> Value: -7 kph\n    SPN 907: Relative Speed; Rear Axle 1, Left Wheel -> Value: -7 kph\n    SPN 908: Relative Speed; Rear Axle 1, Right Wheel -> Value: -7 kph\n    SPN 909: Relative Speed; Rear Axle 2, Left Wheel -> Value: -7 kph\n    SPN 910: Relative Speed; Rear Axle 2, Right Wheel -> Value: -7 kph\n```\n"
  },
  {
    "path": "BinUtils/j1939Decoder/src/j1939Decoder.cpp",
    "content": "//============================================================================\n// Name        : j1939Encoder.cpp\n// Author      : \n// Version     :\n// Copyright   : Your copyright notice\n// Description : Hello World in C++, Ansi-style\n//============================================================================\n\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <getopt.h>\n\n#include <regex.h>\n#include <iterator>\n\n#include <iostream>\n#include <iomanip>\n\n#include <sstream>\n#include <string.h>\n\n#include <Types.h>\n\n#include <memory>\n\n//J1939 libraries\n#include <J1939DataBase.h>\n#include <J1939Factory.h>\n#include <GenericFrame.h>\n\n#include <Transport/BAM/BamReassembler.h>\n\n\n#ifndef DATABASE_PATH\n#define DATABASE_PATH\t\t\"/etc/j1939/frames.json\"\n#endif\n\n\nusing namespace J1939;\n\nstd::basic_string<u8> decodeData(const std::string &data) {\n\n\n\t//At this point we have the options, we build regular expressions to validate them\n\n\t//Data regex will match the format XXXXXXXXXXXXXXXX where X is an hexadecimal digit.\n\tstd::string dataRegex(\"^(\\\\s{0,1}([0-9a-fA-F][0-9a-fA-F]))+$\");\n\n\tregex_t regex;\n\tint retVal;\n\n\n\tretVal = regcomp(&regex, dataRegex.c_str(), REG_EXTENDED);\n\tif (retVal) {\n\t\tstd::cerr << \"Problem compiling reg expression for data\" << std::endl;\n\t\texit(2);\n\t}\n\n\tretVal = regexec(&regex, data.c_str(), 0, NULL, 0);\n\tif (retVal == REG_NOMATCH) {\n\t\tstd::cerr << \"The introduced data has wrong format...\" << std::endl;\n\t\texit(3);\n\t}\n\telse if(retVal){\n\t\tstd::cerr << \"Problem executing reg expression for ID\"<< std::endl;\n\t\texit(2);\n\t}\n\n\tregfree(&regex);\n\n\tstd::stringstream dataStream;\n\tdataStream << std::hex << data;\n\n\t//String where to store the data of the frame ready to be passed to the frame factory with the correct format.\n\tstd::basic_string<u8> formattedData;\n\tstd::string token;\n\n\tdo {\n\t\tdataStream >> std::ws >> std::setw(2) >> token;\n\t\tformattedData.push_back(static_cast<u8>(std::stoul(token, nullptr, 16)));\n\t} while(!(dataStream.rdstate() & std::ios_base::eofbit));\t\t//End of file\n\n\treturn formattedData;\n\n}\n\nu32 decodeID(const std::string& id) {\n\n\t//ID regex will match the format XXXXXXXX where X is an hexadecimal digit. The id in extended format in CAN has a length of 29 bits. It must be at least 8 digits.\n\tstd::string idRegex(\"^[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]\"\n\t\t\t\"[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]$\");\n\n\tregex_t regex;\n\tint retVal;\n\n\tretVal = regcomp(&regex, idRegex.c_str(), 0);\n\tif (retVal) {\n\t\tstd::cerr << \"Problem compiling reg expression for ID\"<< std::endl;\n\t\texit(2);\n\t}\n\n\tretVal = regexec(&regex, id.c_str(), 0, NULL, 0);\n\tif (retVal == REG_NOMATCH) {\n\t\tstd::cerr << \"The introduced ID has wrong format...\" << std::endl;\n\t\texit(3);\n\t}\n\telse if(retVal){\n\t\tstd::cerr << \"Problem executing reg expression for ID\" << std::endl;\n\t\texit(2);\n\t}\n\n\tregfree(&regex);\n\n\t//Convert the introduced string to a number to be interpreted by the frame factory when using it.\n\tu32 formattedId = std::stoul(id, nullptr, 16);\n\n\treturn formattedId;\n\n}\n\n\n\nint\nmain (int argc, char **argv)\n{\n\tint c;\n\n\n\t//In case of BAM decoding\n\tBamReassembler reassembler;\n\n\tstd::string id, data;\n\n\tstatic struct option long_options[] =\n\t\t{\n\t\t\t{\"id\", required_argument, NULL, 'i'},\n\t\t\t{\"data\", required_argument, NULL, 'd'},\n\t\t\t{NULL, 0, NULL, 0}\n\t\t};\n\n\n\twhile (1)\n\t{\n\n\t\tc = getopt_long (argc, argv, \"i:d:\",\n\t\t\t\t   long_options, NULL);\n\n\t\t/* Detect the end of the options. */\n\t\tif (c == -1)\n\t\t\tbreak;\n\n\t\tswitch (c)\n\t\t{\n\t\tcase 'i':\n\t\t\tid = optarg;\n\t\t\tbreak;\n\t\tcase 'd':\n\t\t\tdata = optarg;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif(id.empty() || data.empty()) {\n\t\tstd::cerr << \"Id or data of J1939 frame not specified\";\n\t\texit(1);\n\t}\n\n\n\t//At this point we have the options, we build regular expressions to validate them\n\n\tu32 formattedId = decodeID(id);\n\n\tstd::basic_string<u8> formattedData = decodeData(data);\n\n\tif(!J1939Factory::getInstance().registerDatabaseFrames(DATABASE_PATH)) {\n\t\tstd::cerr << \"Database not found in \" << DATABASE_PATH << std::endl;\n\t\texit(4);\n\t}\n\n\t//The rest is easy\n\tstd::unique_ptr<J1939Frame> frame;\n\n\ttry {\n\t\tframe = J1939Factory::getInstance().getJ1939Frame(formattedId,\n\t\t\t\tformattedData.c_str(), formattedData.size());\n\n\t} catch(J1939DecodeException& e) {\n\t\tstd::cerr << \"Error decoding frame: \" << e.getMessage() << std::endl;\n\t\t\t\texit(6);\n\t}\n\n\n\tif(!frame) {\n\n\t\tstd::cerr << \"Frame not identified\" << std::endl;\n\t\texit(5);\n\n\t}\n\n\t//Check if it is part of the BAM protocol\n\n\tif(reassembler.toBeHandled(*frame)) {\n\n\t\tstd::cout << \"Bam frame detected... Waiting for the rest of frames to be received...\" << std::endl;\n\n\t\t//First frame should be CM frame, otherwise, it is likely that we remain in the loop forever\n\t\treassembler.handleFrame(*frame);\n\n\t\twhile(!reassembler.reassembledFramesPending()) {\n\n\t\t\tstd::cout << \"Id: \" << std::endl;\n\t\t\tstd::getline(std::cin, id);\n\t\t\tformattedId = decodeID(id);\n\n\t\t\tstd::cout << \"Data: \" << std::endl;\n\t\t\tstd::getline(std::cin, data);\n\t\t\tformattedData = decodeData(data);\n\n\t\t\ttry {\n\t\t\t\tframe = J1939Factory::getInstance().getJ1939Frame(formattedId,\n\t\t\t\t\t\tformattedData.c_str(), formattedData.size());\n\n\t\t\t\tif(frame) {\n\t\t\t\t\treassembler.handleFrame(*frame);\n\t\t\t\t} else {\n\t\t\t\t\tstd::cerr << \"Frame not identified\" << std::endl;\n\t\t\t\t\texit(5);\n\t\t\t\t}\n\n\t\t\t} catch(J1939DecodeException& e) {\n\t\t\t\tstd::cerr << \"Error decoding frame: \" << e.getMessage() << std::endl;\n\t\t\t\texit(6);\n\t\t\t}\n\n\t\t}\n\n\t\tframe = reassembler.dequeueReassembledFrame();\n\n\t\t//Check again if the frame is well decoded\n\n\t\tif(!frame) {\n\t\t\tstd::cerr << \"Frame not identified\" << std::endl;\n\t\t\texit(5);\n\t\t}\n\n\t}\n\n\n\tstd::cout << frame->toString();\n\n\texit (0);\n}\n"
  },
  {
    "path": "BinUtils/j1939Sender/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.5)\n\nproject(j1939Sender)\n\nadd_executable(j1939Sender \n    src/j1939Sender.cpp\n)\n\ntarget_include_directories(j1939Sender\n    PUBLIC \n        include ${J1939_SOURCE_DIR}/include ${Can_SOURCE_DIR}/include ${Common_SOURCE_DIR}/include\n)\n\ntarget_link_libraries(j1939Sender\n    PUBLIC\n        J1939 Can rt -rdynamic\n)\n\n\ninstall (TARGETS j1939Sender\n    DESTINATION bin)\n"
  },
  {
    "path": "BinUtils/j1939Sender/README.md",
    "content": "A CLI utility to create frames, configure them and send them through the CAN bus.\n    \n```bash\n    j1939Sender\n    Version: 1.0\n    Interfaces: \n    can0 \n    Initialized: can0 \n    j1939Sender>\n    j1939Sender> create frame name: my_frame title: CCVS\n    Frame correctly created\n    j1939Sender> create frame name: my_frame1 pgn: FEF1\n    Frame correctly created\n    j1939Sender> list frames\n    my_frame: 00fef1fe ff ff ff ff ff ff ff ff \n    my_frame1: 00fef1fe ff ff ff ff ff ff ff ff \n    set frame my_frame period: 100\n    set frame my_frame source: 45\n    set frame my_frame spn: 84  value: 15\n    print frame my_frame\n    send frame my_frame interface: can0\n\n```\n\n# Commands\n\n## Create frame\n\n\n```bash\n\tcreate frame name: <name> title: <pgn_name>\n\tcreate frame name: <name> pgn: <pgn_number>\n```\n\nExample:\n\n```bash\n\tcreate frame name: my_frame title: CCVS\n\tcreate frame name: my_frame1 pgn: FEF1\n```\n\n## List frames\n\n\n```bash\n\tlist frames\n```\n\n## Set frame values\n\n```bash\n\tset frame <name> [period: <millis>] [source: <src_addr_hex>] [source: <src_addr_hex>] [priority: <prio>] [spn: <spn>  value: <value>] [spn: <spn>  value: <value>]...\n```\n\nExample:\n\n```bash\n\tset frame my_frame period: 100 source: 2C\n\tset frame my_frame spn: 84 value: 15 priority: 4\n```\n\n## Print frame\n\n```bash\n\tprint frame <name>\n```\n\nExample:\n\n```bash\n\tprint frame my_frame\n```\n\n## List interfaces\n\n```bash\n\tlist interfaces\n```\n\n## Send frame\n\n```bash\n\tsend frame <name> interface: <interface>\n```\n\nExample:\n\n```bash\n\tsend frame my_frame interface: can0\n```\n\n## Unsend frame\n\n```bash\n\tunsend frame <name> [interface: <interface>]\n```\n\nExample:\n\n```bash\n\tunsend frame my_frame\n\tunsend frame my_frame interface: can0\n```\n\n## List TTS\n\n```bash\n\tlist tts all\n\tlist tts number: <number>\n```\n\nExample:\n\n```bash\n\tlist tts number: 18\n```\n\n\n## Set TTS\n\n```bash\n\tset tts number: <number> status: <status>\n```\n\nExample:\n\n```bash\n\tset tts number: 3 status: 2\n```\n\n\n## Send TTS\n\n```bash\n\tsend tts interface: <interface> period: <millis>\n```\n\nExample:\n\n```bash\n\tsend tts interface: can0 period: 4000\n```\n\n\n## Add dtc\n\n```bash\n\tadd dtc <name> oc: <occurrence_code> fmi: <failure_mode_identidier> spn: <suspect_number_parameter>\n```\n\nExample:\n\n```bash\n\tcreate frame name: dm1 title: DM1\n\tadd dtc dm1 oc: 2 fmi: 6 spn: 84\n```\n\n## Set dtc\n\n```bash\n\tset dtc <name> <pos> oc: <occurrence_code> fmi: <failure_mode_identidier> spn: <suspect_number_parameter>\n```\n\nExample:\n\n```bash\n\tset dtc dm1 0 oc: 3 fmi: 5 spn: 84\n```\n\n## Delete dtc\n\n```bash\n\tdelete dtc <name> <pos>\n```\n\nExample:\n\n```bash\n\tdelete dtc dm1 0\n```\n\n\n## Quit\n\n```bash\n\tquit\n```\n"
  },
  {
    "path": "BinUtils/j1939Sender/src/j1939Sender.cpp",
    "content": "//============================================================================\n// Name        : j1939Sender.cpp\n// Author      : \n// Version     :\n// Copyright   : Your copyright notice\n// Description : Hello World in C++, Ansi-style\n//============================================================================\n\n\n#include <getopt.h>\n\n#include <iostream>\n#include <fstream>\n#include <string>\n#include <vector>\n#include <list>\n#include <sstream>\n#include <iomanip>\n#include <functional>\n\n#include <stdlib.h>\n#include <stdexcept>\n\n\n//J1939 includes\n#include <J1939Factory.h>\n#include <J1939DataBase.h>\n#include <GenericFrame.h>\n#include <SPN/SPNNumeric.h>\n#include <SPN/SPNStatus.h>\n#include <SPN/SPNString.h>\n#include <FMS/TellTale/FMS1Frame.h>\n#include <Transport/BAM/BamFragmenter.h>\n#include <Diagnosis/Frames/DM1.h>\n\n\n//CAN includes\n#include <CanEasy.h>\n\n\n\n#define VERSION_STR\t\t\t\"1.0\"\n\n//Bitrate for J1939 protocol\n#define BAUD_250K\t\t\t250000\n\n\n\n#define SENDER_PROMPT\t\t\"j1939Sender> \"\n#define CREATE_TOKEN\t\t\"create\"\n#define QUIT_TOKEN\t\t\t\"quit\"\n\n#define SEND_TOKEN\t\t\t\"send\"\n#define UNSEND_TOKEN\t\t\"unsend\"\n\n#define EXEC_TOKEN\t\t\t\"exec\"\n\n#define LIST_TOKEN\t\t\t\"list\"\n#define PRINT_TOKEN\t\t\t\"print\"\n#define SET_TOKEN\t\t\t\"set\"\n\n#define FRAME_TOKEN\t\t\t\"frame\"\n#define FRAMES_TOKEN\t\t\"frames\"\n\n#define COMMANDS_TOKEN\t\t\"commands\"\n\n#define INTERFACE_TOKEN\t\t\"interface\"\n#define INTERFACES_TOKEN\t\"interfaces\"\n\n#define ADD_TOKEN\t\t\t\"add\"\n#define CHANGE_TOKEN\t\t\"change\"\n#define DELETE_TOKEN\t\t\"delete\"\n#define DTC_TOKEN\t\t\t\"dtc\"\n\n#define OC_TOKEN\t\t\t\"oc\"\n#define FMI_TOKEN\t\t\t\"fmi\"\n\n\n#define NAME_TOKEN\t\t\t\"name\"\n#define PGN_TOKEN\t\t\t\"pgn\"\n#define TITLE_TOKEN\t\t\t\"title\"\n\n\n#define PRIORITY_TOKEN\t\t\"priority\"\n#define SOURCE_TOKEN\t\t\"source\"\n#define PERIOD_TOKEN\t\t\"period\"\n\n#define SPN_TOKEN\t\t\t\"spn\"\n#define VALUE_TOKEN\t\t\t\"value\"\n\n#define VIN_TOKEN\t\t\t\"vin\"\n#define TTS_TOKEN\t\t\t\"tts\"\n#define TTS_NUMBER\t\t\t\"number\"\n#define TTS_STATUS\t\t\t\"status\"\n#define TTS_ALL\t\t\t\t\"all\"\n\n\n#ifndef DATABASE_PATH\n#define DATABASE_PATH\t\t\"/etc/j1939/frames.json\"\n#endif\n\n\n\n\n\ntypedef std::function<void(const std::string&, const std::string&)> ParamParserFunc;\n\n\nusing namespace Can;\nusing namespace J1939;\n\n\nclass CommandHelper {\n\npublic:\n\ttypedef void (*CmdFunc)(void);\n\ttypedef void (*CmdFuncWithArgs)(std::list<std::string>);\n\nprivate:\n\tstd::string mCommand;\n\tCmdFunc mCmdFunc;\n\tCmdFuncWithArgs mCmdFuncWithArgs;\n\tstd::vector<CommandHelper> mSubCommands;\n\npublic:\n\n\tCommandHelper(const std::string& command = \"\") : mCommand(command), mCmdFunc(nullptr), mCmdFuncWithArgs(nullptr) {}\n\tCommandHelper(const std::string& command, CmdFunc func) : mCommand(command), mCmdFunc(func), mCmdFuncWithArgs(nullptr) {}\n\tCommandHelper(const std::string& command, CmdFuncWithArgs func) : mCommand(command), mCmdFunc(nullptr), mCmdFuncWithArgs(func) {}\n\n\tCmdFunc getCmdFunc() const { return mCmdFunc; }\n\tCmdFuncWithArgs getCmdFuncWithArgs() const { return mCmdFuncWithArgs; }\n\tconst std::string& getCommand() const { return mCommand; }\n\tCommandHelper& addSubCommand(const CommandHelper& command) { mSubCommands.push_back(command); return *this; }\n\n\tconst std::vector<CommandHelper>& getSubCommands() const { return mSubCommands; }\n\n};\n\n\n//Command that will hold the other commands\nCommandHelper baseCommand;\n\n//Map of the created frames to be sent to the CAN interface\nstd::map<std::string, J1939Frame*> framesToSend;\n\n//Map to specify the period for the different frames (in millis)\nstd::map<std::string, u32> framePeriods;\n\n//Take all the tokens from a line (separated by spaces) and introduces them in the list\nstd::list<std::string> splitTokens(std::string);\n\n//TTS\nstd::vector<FMS1Frame> fms1Frames;\nu32 ttsPeriod;\n\nbool silent;\n\n\nvoid registerCommands();\nconst CommandHelper& findSubCommand(const CommandHelper&, std::list<std::string>&);\nstd::list<std::string> getSubCommandNames(const CommandHelper&);\n\nvoid parseLine(const std::string& line);\n\n\n//Functions to interpret the different commands\nvoid parseSetFrameCommand(std::list<std::string> arguments);\nvoid parseSetTTSCommand(std::list<std::string> arguments);\nvoid parseListCommandsCommand();\nvoid parseListTTSCommand(std::list<std::string> arguments);\nvoid processCommandParameters(std::list<std::string> arguments, ParamParserFunc func);\nvoid parsePrintFrameCommand(std::list<std::string> arguments);\nvoid parseQuitCommand();\nvoid parseCreateFrameCommand(std::list<std::string> arguments);\nvoid parseListFramesCommand();\nvoid parseListInterfacesCommand();\nvoid parseSendFrameCommand(std::list<std::string> arguments);\nvoid parseSendTTSCommand(std::list<std::string> arguments);\nvoid parseUnsendTTSCommand();\nvoid parseExecCommand(std::list<std::string> arguments);\nvoid parseUnsendFrameCommand(std::list<std::string> arguments);\nvoid parseAddDtcCommand(std::list<std::string> arguments);\nvoid parseSetDtcCommand(std::list<std::string> arguments);\nvoid parseDeleteDtcCommand(std::list<std::string> arguments);\n\nbool parseDtcCommand(std::list<std::string> arguments, DTC& dtc);\n\nstd::vector<CanFrame> ttsFramesToCanFrames(const std::vector<FMS1Frame>& ttsFrames);\n\n\n\n\nvoid execScript(const std::string& file);\nvoid uninitializeVariables();\n\n\n\nbool parseSetGenericParams(const std::string& name, J1939Frame* frame, const std::string& key, const std::string& value);\n\nvoid sendFrameThroughInterface(const J1939Frame* frame, u32 period, const std::string& interface);\nvoid unsendFrameThroughInterface(const J1939Frame* frame, const std::string& interface);\nbool isFrameSent(const J1939Frame* frame, const std::string& interface);\n\n\n\n\nint main(int argc, char **argv) {\n\n\n\t//Get options\n\tint c;\n\tstd::string file;\n\tsilent = false;\n\n\n\tstatic struct option long_options[] =\n\t{\n\t\t{\"file\", required_argument, NULL, 'f'},\n\t\t{\"silent\", no_argument, NULL, 's'},\n\t\t{NULL, 0, NULL, 0}\n\t};\n\n\n\twhile (1)\n\t{\n\n\t\tc = getopt_long (argc, argv, \"f:s:\",\n\t\t\t\t   long_options, NULL);\n\n\t\t/* Detect the end of the options. */\n\t\tif (c == -1)\n\t\t\tbreak;\n\n\t\tswitch (c)\n\t\t{\n\t\tcase 'f':\n\t\t\tfile = optarg;\n\t\t\tbreak;\n\t\tcase 's':\n\t\t\tsilent = true;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\n\n\tstd::string line;\n\n\t//Print the version\n\tif(!silent) {\n\t\tstd::cout << \"Version: \" << VERSION_STR << std::endl;\n\t}\n\n\n\t//Register possible commands to execute by the user\n\tregisterCommands();\n\n\t//Load database\n\tJ1939DataBase ddbb;\n\tif(!ddbb.parseJsonFile(DATABASE_PATH)) {\n\n\t\tswitch (ddbb.getLastError()) {\n\t\t\tcase J1939DataBase::ERROR_FILE_NOT_FOUND:\n\t\t\t\tstd::cerr << \"Json database not found in \" DATABASE_PATH << std::endl;\n\t\t\t\tbreak;\n\t\t\tcase J1939DataBase::ERROR_JSON_SYNTAX:\n\t\t\t\tstd::cerr << \"Json file has syntax errors\" << std::endl;\n\t\t\t\tbreak;\n\t\t\tcase J1939DataBase::ERROR_UNEXPECTED_TOKENS:\n\t\t\t\tstd::cerr << \"Json file has tokens not identified by the application\" << std::endl;\n\t\t\t\tbreak;\n\t\t\tcase J1939DataBase::ERROR_OUT_OF_RANGE:\n\t\t\t\tstd::cerr << \"Json file has some values that exceed the permitted ranges\" << std::endl;\n\t\t\t\tbreak;\n\t\t\tcase J1939DataBase::ERROR_UNKNOWN_SPN_TYPE:\n\t\t\t\tstd::cerr << \"Json file has undefined type for SPN\" << std::endl;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tstd::cerr << \"Something in the database is not working\" << std::endl;\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn -1;\n\t}\n\n\t//Register frames in the factory\n\n\tconst std::vector<GenericFrame>& frames = ddbb.getParsedFrames();\n\n\tfor(auto iter = frames.begin(); iter != frames.end(); ++iter) {\n\t\tJ1939Factory::getInstance().registerFrame(*iter);\n\t}\n\n\t//Generate frames for the TTSs\n\tfms1Frames.push_back(FMS1Frame(0));\n\tfms1Frames.push_back(FMS1Frame(1));\n\tfms1Frames.push_back(FMS1Frame(2));\n\tfms1Frames.push_back(FMS1Frame(3));\n\n\n\t//Determine the possible backends\n\n\tstd::set<std::string> ifaces = CanEasy::getCanIfaces();\n\n\tif(!silent)\tstd::cout << \"Interfaces: \" << std::endl;\n\n\tfor(auto iter = ifaces.begin(); iter != ifaces.end(); ++iter) {\n\t\tif(!silent)\tstd::cout << *iter << \" \";\n\t}\n\n\tif(!silent)\tstd::cout << std::endl;\n\n\tCanEasy::initialize(BAUD_250K);\n\n\tifaces = CanEasy::getInitializedCanIfaces();\n\n\tif(!silent)\tstd::cout << \"Initialized: \";\n\n\tfor(auto iter = ifaces.begin(); iter != ifaces.end(); ++iter) {\n\t\tif(!silent)\tstd::cout << *iter << \" \";\n\t}\n\n\tif(!silent)\tstd::cout << std::endl;\n\n\t//If any file is defined, first execute commands from it\n\tif(!file.empty()) {\n\t\texecScript(file);\n\t}\n\n\n\t//Read from standard input\n\tif(!silent) std::cout << SENDER_PROMPT;\n\n\twhile (std::getline(std::cin, line)) {\n\t\tparseLine(line);\n\t\tif(!silent) std::cout << SENDER_PROMPT;\n\t}\n\n\n\treturn 0;\n}\n\n\nvoid registerCommands() {\n\n\tbaseCommand.addSubCommand(\n\t\t\tCommandHelper(CREATE_TOKEN).addSubCommand(CommandHelper(FRAME_TOKEN, parseCreateFrameCommand))\n\t).addSubCommand(\n\t\t\tCommandHelper(QUIT_TOKEN, parseQuitCommand)\n\t).addSubCommand(\n\t\t\tCommandHelper(LIST_TOKEN).addSubCommand(CommandHelper(FRAMES_TOKEN, parseListFramesCommand)).\n\t\t\t\t\taddSubCommand(CommandHelper(COMMANDS_TOKEN, parseListCommandsCommand)).\n\t\t\t\t\taddSubCommand(CommandHelper(INTERFACES_TOKEN, parseListInterfacesCommand)).\n\t\t\t\t\taddSubCommand(CommandHelper(TTS_TOKEN, parseListTTSCommand))\n\t).addSubCommand(\n\t\t\tCommandHelper(PRINT_TOKEN).addSubCommand(CommandHelper(FRAME_TOKEN, parsePrintFrameCommand))\n\t).addSubCommand(\n\t\t\tCommandHelper(SET_TOKEN).addSubCommand(CommandHelper(FRAME_TOKEN, parseSetFrameCommand)).\n\t\t\t\t\taddSubCommand(CommandHelper(TTS_TOKEN, parseSetTTSCommand)).\n\t\t\t\t\taddSubCommand(CommandHelper(DTC_TOKEN, parseSetDtcCommand))\n\t).addSubCommand(\n\t\t\tCommandHelper(SEND_TOKEN).addSubCommand(CommandHelper(FRAME_TOKEN, parseSendFrameCommand)).\n\t\t\t\t\taddSubCommand(CommandHelper(TTS_TOKEN, parseSendTTSCommand))\n\t).addSubCommand(\n\t\t\tCommandHelper(EXEC_TOKEN, parseExecCommand)\n\t).addSubCommand(\n\t\t\tCommandHelper(UNSEND_TOKEN).addSubCommand(CommandHelper(FRAME_TOKEN, parseUnsendFrameCommand)).\n\t\t\t\t\taddSubCommand(CommandHelper(TTS_TOKEN, parseUnsendTTSCommand))\n\t).addSubCommand(\n\t\t\tCommandHelper(ADD_TOKEN).addSubCommand(CommandHelper(DTC_TOKEN, parseAddDtcCommand))\n\t).addSubCommand(\n\t\t\tCommandHelper(DELETE_TOKEN).addSubCommand(CommandHelper(DTC_TOKEN, parseDeleteDtcCommand))\n\t);\n\n}\n\n\n\n\nvoid parseLine(const std::string& line) {\n\n\tstd::string command;\n\tstd::list<std::string> arguments;\n\n\tif(line.empty()) {\n\t\treturn;\t\t//Nothing to do\n\t}\n\n\t//If there is the character #, omit every character until the end of line (including the # character)\n\tsize_t found = line.find_first_of('#');\n\n\tif(found == 0) {\n\t\treturn;\n\t}\n\n\tstd::list<std::string> tokens = splitTokens(line.substr(0, found));\n\n\tconst CommandHelper& cmd = findSubCommand(baseCommand, tokens);\n\n\tif(cmd.getCmdFuncWithArgs() == nullptr && cmd.getCmdFunc() == nullptr) {\n\t\tstd::cerr << \"This command does not exist\" << std::endl;\n\t\treturn;\n\t}\n\n\tif(!tokens.empty() && cmd.getCmdFuncWithArgs()) {\n\n\t\t(cmd.getCmdFuncWithArgs())(tokens);\n\n\t} else if(tokens.empty() && cmd.getCmdFunc()) {\n\n\t\t(cmd.getCmdFunc())();\n\n\t} else {\n\t\tstd::cerr << \"This command does \" << (arguments.empty() ? \"\" : \"not \") << \"need arguments\" << std::endl;\n\t}\n\n\n}\n\n\nstd::list<std::string> splitTokens(std::string arguments) {\n\n\tstd::list<std::string> retVal;\n\n\tsize_t startArgPos = 0, endArgPos = 0;\n\n\twhile(startArgPos != std::string::npos) {\n\n\n\t\tendArgPos = arguments.find_first_of(' ', startArgPos);\n\n\t\tif(endArgPos == std::string::npos) {\n\t\t\tendArgPos = arguments.size();\n\t\t}\n\n\t\tretVal.push_back(arguments.substr(startArgPos, endArgPos - startArgPos));\n\n\t\tstartArgPos = arguments.find_first_not_of(' ', endArgPos);\n\n\t}\n\n\treturn retVal;\n\n}\n\n\n\n//To have some introspection...\nvoid parseListCommandsCommand() {\n\n\tstd::list<std::string> commands = getSubCommandNames(baseCommand);\n\n\tfor(auto iter = commands.begin(); iter != commands.end(); ++iter) {\n\t\tstd::cout << *iter << std::endl;\n\t}\n\n}\n\n\nvoid parseCreateFrameCommand(std::list<std::string> arguments) {\n\n\tstd::string name;\n\tstd::string pgn;\n\tstd::string title;\n\n\n\tauto func = [&name, &pgn, &title](const std::string& key, const std::string& value) {\n\n\t\tif(key == NAME_TOKEN) {\n\n\t\t\tname = value;\n\n\t\t} else if(key == PGN_TOKEN) {\n\t\t\tpgn = value;\n\t\t} else if(key == TITLE_TOKEN) {\n\t\t\ttitle = value;\n\t\t}\n\t};\n\n\n\tprocessCommandParameters(arguments, func);\n\n\tif(name.empty()) {\n\t\tstd::cerr << \"No name defined for this frame\" << std::endl;\n\t\treturn;\n\t}\n\n\tif(pgn.empty() == title.empty()) {\n\t\tstd::cerr << \"Define either pgn or title of frame\" << std::endl;\n\t\treturn;\n\t}\n\n\tif(framesToSend.find(name) != framesToSend.end()) {\n\t\tstd::cerr << \"Name already in use...\" << std::endl;\n\t\treturn;\n\t}\n\n\n\tstd::unique_ptr<J1939Frame> frameToAdd(nullptr);\n\n\tif(!title.empty()) {\t\t//Title was specified\n\n\t\tframeToAdd = J1939Factory::getInstance().getJ1939Frame(title);\n\n\t}\n\n\tif(!pgn.empty()) {\t\t\t//PGN was defined\n\n\t\ttry {\n\n\t\t\tu32 pgnNumber = std::stoul(pgn, nullptr, 16);\n\n\t\t\tframeToAdd = J1939Factory::getInstance().getJ1939Frame(pgnNumber);\n\n\n\t\t} catch (std::invalid_argument& e) {\n\t\t\tstd::cerr << \"PGN is not a number...\" << std::endl;\n\t\t}\n\n\t}\n\n\tif(frameToAdd.get()) {\n\t\tframesToSend[name] = frameToAdd.release();\n\n\t\tstd::cout << \"Frame correctly created\" << std::endl;\n\t} else {\n\t\tstd::cerr << \"Frame not recognized...\" << std::endl;\n\t}\n\n}\n\nvoid parseListFramesCommand() {\n\n\tstd::stringstream str;\n\n\n\tfor(auto iter = framesToSend.begin(); iter != framesToSend.end(); ++iter) {\n\n\t\tJ1939Frame* frame = iter->second;\n\t\tsize_t size = frame->getDataLength();\n\t\tstd::vector<std::string> txInterfaces;\n\n\t\t//Add the given name when the frame was created\n\t\tstr << iter->first << \": \";\n\n\n\t\t//Encode the frame to raw data\n\t\tu32 id;\n\t\tu8* buff = new u8[size];\n\n\t\ttry {\n\n\t\t\tframe->encode(id, buff, size);\n\n\t\t\t//Add identifier to the stream\n\t\t\tstr << std::setfill('0') << std::setw(8) << std::hex << static_cast<u32>(id) << \" \";\n\n\n\t\t\t//Add the raw data, but before, we format it\n\n\t\t\tfor(unsigned int i = 0; i < size; ++i) {\n\t\t\t\tstr << std::setfill('0') << std::setw(2) << std::hex << static_cast<u32>(buff[i]) << \" \";\n\t\t\t}\n\n\n\t\t\t//Check if the frame is being sent through an interface\n\t\t\tconst std::set<std::string>& ifaces = CanEasy::getInitializedCanIfaces();\n\n\t\t\tfor(auto iter = ifaces.begin(); iter != ifaces.end(); ++iter) {\n\n\t\t\t\tif(isFrameSent(frame, *iter)) {\n\t\t\t\t\ttxInterfaces.push_back(*iter);\n\t\t\t\t}\n\n\t\t\t}\n\n\n\t\t} catch (J1939EncodeException& e) {\n\n\t\t\tstd::cerr << e.getMessage() << std::endl;\n\n\t\t}\n\n\n\t\t//Print period if defined\n\t\tauto periodIter = framePeriods.find(iter->first);\n\n\t\tif(periodIter != framePeriods.end()) {\n\t\t\tstr << \" Period: \" << std::dec << periodIter->second << \" ms\";\n\t\t}\n\n\t\t//Print if the frame is being sent\n\t\tif(!txInterfaces.empty()) {\n\n\t\t\tstr << \" Sent from: \";\n\t\t\tfor(auto iter = txInterfaces.begin(); iter != txInterfaces.end(); ++iter) {\n\t\t\t\tstr << *iter << \" \";\n\t\t\t}\n\t\t}\n\n\t\tstr << std::endl;\n\n\t\tdelete[] buff;\n\n\t}\n\n\tstd::cout << str.str();\n\n}\n\nvoid parseListTTSCommand(std::list<std::string> arguments) {\n\n\n\tstd::vector<u32> ids;\n\tu8 number = 0;\n\n\tauto paramParser = [&number](const std::string& key, const std::string& value) {\n\n\t\tif(key == TTS_NUMBER) {\n\n\t\t\ttry {\n\n\t\t\t\tu32 ttsNumber = std::stoul(value);\n\n\t\t\t\tif(ttsNumber == (ttsNumber & 0xFF)) {\n\t\t\t\t\tnumber = static_cast<u8>(ttsNumber);\n\t\t\t\t} else {\n\t\t\t\t\tstd::cerr << \"number out of range...\" << std::endl;\n\t\t\t\t}\n\n\t\t\t} catch (std::invalid_argument&) {\n\t\t\t\tstd::cerr << \"number is not a number...\" << std::endl;\n\t\t\t}\n\n\t\t}\n\n\t};\n\n\tif(arguments.front() != TTS_ALL) {\n\t\tprocessCommandParameters(arguments, paramParser);\n\t}\n\n\n\tbool somePrinted = false;\n\n\tfor(auto iter = fms1Frames.begin(); iter != fms1Frames.end(); ++iter) {\n\n\t\tif(number == 0) {\n\t\t\tsomePrinted = true;\n\n\t\t\tstd::cout << iter->toString();\n\n\n\t\t} else {\n\n\t\t\tif(iter->hasTTS(number)) {\n\t\t\t\tstd::cout << iter->getTTS(number).toString();\n\t\t\t\tsomePrinted = true;\n\t\t\t}\n\n\t\t}\n\n\t\tids.push_back(iter->getIdentifier());\n\t}\n\n\tif(somePrinted) {\n\n\t\tconst std::set<std::string>& ifaces = CanEasy::getInitializedCanIfaces();\n\n\t\tfor(auto iter = ifaces.begin(); iter != ifaces.end(); ++iter) {\n\t\t\t//Print the interface from which tts are sent\n\t\t\tstd::shared_ptr<ICanSender> sender = CanEasy::getSender(*iter);\n\n\t\t\tif(sender->isSent(ids)) {\n\t\t\t\tstd::cout << \"Sent from interface \" << *iter << std::endl;\n\t\t\t}\n\n\t\t}\n\n\t}\n\n}\n\n\nvoid parseUnsendTTSCommand() {\n\n\tstd::vector<u32> ids;\n\n\tfor(auto iter = fms1Frames.begin(); iter != fms1Frames.end(); ++iter) {\n\n\t\tids.push_back(iter->getIdentifier());\n\n\t}\n\n\tconst std::set<std::string>& ifaces = CanEasy::getInitializedCanIfaces();\n\n\tfor(auto iter = ifaces.begin(); iter != ifaces.end(); ++iter) {\n\n\t\tstd::shared_ptr<ICanSender> sender = CanEasy::getSender(*iter);\n\n\t\tsender->unSendFrames(ids);\n\n\t}\n\n}\n\nvoid parseSendTTSCommand(std::list<std::string> arguments) {\n\n\n\tstd::string interface;\n\n\tbool periodValid = false;\n\n\tauto paramParser = [&interface, &periodValid](const std::string& key, const std::string& value) {\n\n\t\tif(key == INTERFACE_TOKEN) {\n\n\t\t\tconst std::set<std::string>& ifaces = CanEasy::getInitializedCanIfaces();\n\n\t\t\tfor(auto iter = ifaces.begin(); iter != ifaces.end(); ++iter) {\n\n\t\t\t\tif(*iter == value) {\n\t\t\t\t\tinterface = value;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if(key == PERIOD_TOKEN) {\n\n\t\t\ttry {\n\n\t\t\t\tttsPeriod = std::stoul(value);\n\t\t\t\tperiodValid = true;\n\n\t\t\t} catch (std::invalid_argument& e) {\n\t\t\t\tstd::cerr << \"Period is not a number...\" << std::endl;\n\n\t\t\t}\n\n\t\t}\n\n\t};\n\n\tprocessCommandParameters(arguments, paramParser);\n\n\tif(!periodValid) {\n\t\tstd::cerr << \"Period not defined...\" << std::endl;\n\t\treturn;\n\t}\n\n\tif(interface.empty()) {\n\t\tstd::cerr << \"Interface not defined or not initialized...\" << std::endl;\n\t\treturn;\n\t}\n\n\tstd::vector<CanFrame> frames = ttsFramesToCanFrames(fms1Frames);\n\n\tstd::shared_ptr<ICanSender> sender = CanEasy::getSender(interface);\n\n\tsender->sendFrames(frames, ttsPeriod);\n\n}\n\n\n\nvoid parseSetTTSCommand(std::list<std::string> arguments) {\n\n\tu8 number = 0xFF, status = 0xFF;\n\n\tauto paramParser = [&number, &status](const std::string& key, const std::string& value) {\n\n\t\tif(key == TTS_NUMBER) {\n\n\t\t\ttry {\n\n\t\t\t\tu32 ttsNumber = std::stoul(value);\n\n\t\t\t\tif(ttsNumber == (ttsNumber & 0xFF)) {\n\t\t\t\t\tnumber = static_cast<u8>(ttsNumber);\n\t\t\t\t} else {\n\t\t\t\t\tstd::cerr << \"Number out of range...\" << std::endl;\n\t\t\t\t\tnumber = 0xFF;\n\t\t\t\t}\n\n\n\t\t\t} catch (std::invalid_argument&) {\n\t\t\t\tstd::cerr << \"Number is not a number...\" << std::endl;\n\t\t\t\tnumber = 0xFF;\n\t\t\t}\n\n\t\t} else if(key == TTS_STATUS) {\n\n\t\t\ttry {\n\n\t\t\t\tu32 ttsStatus = std::stoul(value);\n\n\t\t\t\tif(ttsStatus == (ttsStatus & 0xFF)) {\n\t\t\t\t\tstatus = static_cast<u8>(ttsStatus);\n\t\t\t\t} else {\n\t\t\t\t\tstd::cerr << \"Status out of range...\" << std::endl;\n\t\t\t\t\tstatus = 0xFF;\n\t\t\t\t}\n\n\t\t\t} catch (std::invalid_argument&) {\n\t\t\t\tstd::cerr << \"Status is not a number...\" << std::endl;\n\t\t\t\tstatus = 0xFF;\n\t\t\t}\n\n\t\t}\n\n\t};\n\n\tprocessCommandParameters(arguments, paramParser);\n\n\n\tif(number != 0xFF && status != 0xFF) {\n\n\t\tbool ttsSet = false;\n\n\t\tfor(auto iter = fms1Frames.begin(); iter != fms1Frames.end(); ++iter) {\n\n\t\t\tif(iter->hasTTS(number)) {\n\n\t\t\t\titer->setTTS(number, status);\n\t\t\t\tif(!silent) \tstd::cout << \"TTS \" << static_cast<u32>(number) << \" set to \" << TellTale::getSatusname(status) << std::endl;\n\t\t\t\tttsSet = true;\n\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif(!ttsSet) {\n\t\t\tstd::cerr << \"TTS not found\";\n\t\t} else {\n\n\t\t\tstd::vector<u32> ids;\n\n\t\t\tfor(auto iter = fms1Frames.begin(); iter != fms1Frames.end(); ++iter) {\n\n\n\t\t\t\tids.push_back(iter->getIdentifier());\n\t\t\t}\n\n\n\t\t\tconst std::set<std::string>& ifaces = CanEasy::getInitializedCanIfaces();\n\n\t\t\tfor(auto iter = ifaces.begin(); iter != ifaces.end(); ++iter) {\n\t\t\t\tstd::shared_ptr<ICanSender> sender = CanEasy::getSender(*iter);\n\n\t\t\t\tif(sender->isSent(ids)) {\n\t\t\t\t\tstd::vector<CanFrame> frames = ttsFramesToCanFrames(fms1Frames);\n\t\t\t\t\tsender->sendFrames(frames, ttsPeriod);\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n}\n\n\nvoid parsePrintFrameCommand(std::list<std::string> arguments) {\n\n\tstd::string name = arguments.back();\n\n\tauto frameIter = framesToSend.find(name);\n\n\tif(frameIter != framesToSend.end()) {\n\t\tstd::cout << frameIter->second->toString() << std::endl;\n\t} else {\n\t\tstd::cerr << \"Frame not defined...\" << std::endl;\n\t}\n\n}\n\nvoid parseSetFrameCommand(std::list<std::string> arguments) {\n\n\tstd::string name = arguments.front();\n\targuments.pop_front();\n\tauto frameIter = framesToSend.find(name);\n\n\n\tif(frameIter == framesToSend.end()) {\n\t\tstd::cerr << \"Frame not defined...\" << std::endl;\n\t\treturn;\n\t}\n\n\tJ1939Frame* frame = frameIter->second;\n\n\tSPN* spn = nullptr;\n\n\tauto paramParser = [name, &frame, &spn](const std::string& key, const std::string& value) {\n\n\t\tif(key == SPN_TOKEN) {\t\t//Setting a SPN\n\n\t\t\tif(!frame->isGenericFrame()) {\n\t\t\t\tstd::cerr << \"This frame does not have standard SPNs...\" << std::endl;\n\t\t\t}\n\t\t\tGenericFrame* genFrame = static_cast<GenericFrame*>(frame);\n\n\t\t\ttry {\n\n\t\t\t\tu32 spnNumber = std::stoul(value);\n\t\t\t\tif(!genFrame->hasSPN(spnNumber)) {\n\t\t\t\t\tstd::cerr << \"This spn does not belong to the given frame...\" << std::endl;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tspn = genFrame->getSPN(spnNumber);\n\n\t\t\t} catch (std::invalid_argument& e) {\n\t\t\t\tstd::cerr << \"spn is not a number...\" << std::endl;\n\t\t\t}\n\n\t\t} else if(key == VALUE_TOKEN) {\t\t//The value used to set the SPN\n\n\t\t\tif(!spn) {\n\t\t\t\tstd::cerr << \"Not spn to which assign this value...\" << std::endl;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\ttry {\n\n\n\n\n\t\t\t\tswitch(spn->getType()) {\n\t\t\t\tcase SPN::SPN_NUMERIC:\n\t\t\t\t{\n\t\t\t\t\tdouble valueNumber = std::stod(value);\n\t\t\t\t\tSPNNumeric* spnNum = static_cast<SPNNumeric*>(spn);\n\t\t\t\t\tif(spnNum->setFormattedValue(valueNumber)) {\n\t\t\t\t\t\tstd::cout << \"Spn \" << spn->getSpnNumber() << \" from frame \" << frame->getName() << \" set to value \" << spnNum->getFormattedValue() << std::endl;\n\t\t\t\t\t}\n\t\t\t\t}\tbreak;\n\t\t\t\tcase SPN::SPN_STATUS:\n\t\t\t\t{\n\t\t\t\t\tu32 valueNumber = std::stoul(value);\n\t\t\t\t\tu8 status = static_cast<u8>(valueNumber);\n\t\t\t\t\tif((status & 0xFF) == valueNumber) {\n\t\t\t\t\t\tSPNStatus* spnStat = static_cast<SPNStatus*>(spn);\n\t\t\t\t\t\tif(!spnStat->setValue(status)) {\n\t\t\t\t\t\t\tstd::cerr << \"Value out of range\" << std::endl;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tstd::cout << \"SPN \" << spn->getSpnNumber() << \" set to (\" << valueNumber << \") \" << spnStat->getValueDescription(status) << std::endl;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstd::cerr << \"Value out of range\" << std::endl;\n\t\t\t\t\t}\n\n\t\t\t\t}\tbreak;\n\t\t\t\tcase SPN::SPN_STRING:\n\t\t\t\t{\n\t\t\t\t\tSPNString* spnStr = static_cast<SPNString*>(spn);\n\t\t\t\t\tspnStr->setValue(value);\n\n\t\t\t\t}\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t} catch (std::invalid_argument& e) {\n\t\t\t\tstd::cerr << \"value is not a number...\" << std::endl;\n\t\t\t}\n\n\n\t\t\tspn = nullptr;\n\n\t\t} else {\t\t//If we are not setting a SPN, maybe we are setting generic parameters of a frame...\n\n\t\t\t//Parse generic parameters as the period to send the frames, the priority, the source address, dst address and so on\n\t\t\tif(!parseSetGenericParams(name, frame, key, value)) {\n\t\t\t\t//If this function returns false, it means that the given key is not a generic parameter, but it is particular of certain frame\n\n\t\t\t\tstd::cerr << \"Unknown parameter...\" << std::endl;\n\n\t\t\t}\n\t\t}\n\n\t};\n\n\tprocessCommandParameters(arguments, paramParser);\n\n\n\n\tauto period = framePeriods.find(name);\n\n\tif(period == framePeriods.end()) {\n\t\treturn;\n\t}\n\n\tu32 id;\n\tsize_t length = frame->getDataLength();\n\tu8* buff = new u8[length];\n\n\tframe->encode(id, buff, length);\n\n\tCanFrame canFrame;\n\n\t//J1939 data is always transmitted in extended format\n\tcanFrame.setExtendedFormat(true);\n\n\t//Set identifier\n\tcanFrame.setId(id);\n\n\t//Set data\n\tstd::string data;\n\tdata.append((char*)buff, length);\n\n\tcanFrame.setData(data);\n\n\tdelete[] buff;\n\n\t//If the frame is being sent, refresh the information to the sender\n\n\tconst std::set<std::string>& ifaces = CanEasy::getInitializedCanIfaces();\n\n\tfor(auto iter = ifaces.begin(); iter != ifaces.end(); ++iter) {\n\t\tstd::shared_ptr<ICanSender> sender = CanEasy::getSender(*iter);\n\n\t\tif(isFrameSent(frame, *iter)) {\n\t\t\tsendFrameThroughInterface(frame, period->second, *iter);\n\t\t}\n\n\t}\n\n}\n\nvoid processCommandParameters(std::list<std::string> arguments, ParamParserFunc parserFunc) {\n\n\twhile(!arguments.empty()) {\n\n\t\tstd::string key = arguments.front();\n\t\targuments.pop_front();\n\n\t\tif(key.find(':') == key.size() - 1) {\n\t\t\tkey = key.substr(0, key.size() - 1);\n\t\t} else {\n\t\t\tstd::cerr << \"Necessary to add a colon at the end\" << std::endl;\n\t\t\treturn;\n\t\t}\n\n\t\tif(arguments.empty()) {\n\t\t\tstd::cerr << \"Incomplete arguments for this command\" << std::endl;\n\t\t\treturn;\n\t\t}\n\n\t\tstd::string value = arguments.front();\n\t\targuments.pop_front();\n\n\t\tparserFunc(key, value);\n\n\t}\n\n}\n\n\nvoid parseQuitCommand() {\n\tuninitializeVariables();\n\tstd::cout << \"Exiting...\" << std::endl;\n\texit(0);\n}\n\nconst CommandHelper& findSubCommand(const CommandHelper& cmd, std::list<std::string>& args) {\n\n\tif(args.empty()) {\t\t//No more tokens, return the cmd itself\n\t\treturn cmd;\n\t}\n\n\tstd::string arg = args.front();\n\n\tfor(auto iter = cmd.getSubCommands().begin(); iter != cmd.getSubCommands().end(); ++iter) {\n\t\tif(iter->getCommand() == arg) {\n\t\t\targs.pop_front();\n\t\t\treturn findSubCommand(*iter, args);\n\t\t}\n\t}\n\n\treturn cmd;\n\n}\n\nstd::list<std::string> getSubCommandNames(const CommandHelper& command) {\n\n\tstd::list<std::string> retVal;\n\n\tfor(auto iter = command.getSubCommands().begin(); iter != command.getSubCommands().end(); ++iter) {\n\n\t\tstd::list<std::string> aux = getSubCommandNames(*iter);\n\n\t\tfor(auto name = aux.begin(); name != aux.end(); ++name) {\n\t\t\tretVal.push_back(command.getCommand() + (command.getCommand().empty() ? \"\" : \" \") + *name);\n\t\t}\n\n\t}\n\n\tif(retVal.empty()) {\n\t\tretVal.push_back(command.getCommand());\n\t}\n\n\treturn retVal;\n\n}\n\n\nvoid parseListInterfacesCommand() {\n\n\tconst std::set<std::string>& ifaces = CanEasy::getInitializedCanIfaces();\n\n\tfor(auto iter = ifaces.begin(); iter != ifaces.end(); ++iter) {\n\t\tstd::cout << *iter << std::endl;\n\t}\n\n}\n\nvoid parseSendFrameCommand(std::list<std::string> arguments) {\n\n\tstd::string interface;\n\tstd::string name = arguments.front();\n\targuments.pop_front();\n\tauto frameIter = framesToSend.find(name);\n\n\n\tif(frameIter == framesToSend.end()) {\n\t\tstd::cerr << \"Frame not defined...\" << std::endl;\n\t\treturn;\n\t}\n\n\tconst J1939Frame* j1939Frame = frameIter->second;\n\n\tauto func = [&interface](const std::string& key, const std::string& value) {\n\n\t\tif(key == INTERFACE_TOKEN) {\n\n\t\t\tconst std::set<std::string>& ifaces = CanEasy::getInitializedCanIfaces();\n\n\t\t\tfor(auto iface = ifaces.begin(); iface != ifaces.end(); ++iface) {\n\n\t\t\t\t//Check that the corresponding interface really exists\n\t\t\t\tif(*iface == value) {\n\t\t\t\t\tinterface = value;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t};\n\n\tprocessCommandParameters(arguments, func);\n\n\tif(interface.empty()) {\n\t\tstd::cerr << \"Interface not defined or not initialized...\" << std::endl;\n\t\treturn;\n\t}\n\n\t//The frame has a periodicity associated?\n\n\tauto period = framePeriods.find(name);\n\n\tif(period == framePeriods.end()) {\n\t\tstd::cerr << \"Period not defined...\" << std::endl;\n\t\treturn;\n\t}\n\n\tsendFrameThroughInterface(j1939Frame, period->second, interface);\n\n}\n\nvoid sendFrameThroughInterface(const J1939Frame* j1939Frame, u32 period, const std::string& interface) {\n\n\n\t//Send the frame with the configured period\n\tstd::shared_ptr<ICanSender> sender = CanEasy::getSender(interface);\n\n\n\tsize_t length = j1939Frame->getDataLength();\n\tCanFrame canFrame;\n\tu32 id;\n\tu8* buff;\n\tstd::string data;\n\n\t//J1939 data is always transmitted in extended format\n\tcanFrame.setExtendedFormat(true);\n\n\t//If the frame is bigger than 8 bytes, we use BAM\n\tif(length > MAX_CAN_DATA_SIZE) {\n\n\t\tstd::vector<CanFrame> canFrames;\n\t\tBamFragmenter fragmenter;\n\t\tfragmenter.fragment(*j1939Frame);\n\n\t\tconst TPCMFrame& connFrame = fragmenter.getConnFrame();\n\t\tlength = connFrame.getDataLength();\n\n\t\tbuff = new u8[length];\n\n\t\tconnFrame.encode(id, buff, length);\n\n\t\t//Set identifier\n\t\tcanFrame.setId(id);\n\n\t\t//Set data\n\t\tstd::string data;\n\t\tdata.append((char*)buff, length);\n\n\t\tcanFrame.setData(data);\n\n\t\tdelete[] buff;\n\n\t\tcanFrames.push_back(canFrame);\n\n\t\tstd::vector<TPDTFrame> dataFrames = fragmenter.getDataFrames();\n\n\t\tfor(auto iter = dataFrames.begin(); iter != dataFrames.end(); ++iter) {\n\n\t\t\tlength = iter->getDataLength();\n\t\t\tbuff = new u8[length];\n\t\t\titer->encode(id, buff, length);\n\n\t\t\t//Set identifier\n\t\t\tcanFrame.setId(id);\n\n\t\t\t//Set data\n\t\t\tstd::string data;\n\t\t\tdata.append((char*)buff, length);\n\n\t\t\tcanFrame.setData(data);\n\n\t\t\tdelete[] buff;\n\n\t\t\tcanFrames.push_back(canFrame);\n\n\t\t}\n\n\t\tsender->sendFrames(canFrames, period);\n\n\n\t} else {\t\t\t//Can be sent in one frame\n\n\t\tbuff = new u8[length];\n\n\t\tj1939Frame->encode(id, buff, length);\n\n\t\t//Set identifier\n\t\tcanFrame.setId(id);\n\n\t\t//Set data\n\t\tstd::string data;\n\t\tdata.append((char*)buff, length);\n\n\t\tcanFrame.setData(data);\n\n\t\tdelete[] buff;\n\n\t\tsender->sendFrame(canFrame, period);\n\n\t}\n\n\n}\n\n\nvoid unsendFrameThroughInterface(const J1939Frame* j1939Frame, const std::string& interface) {\n\n\n\tstd::vector<u32> ids;\n\tbool found = false;\n\n\n\t//If the frame is bigger than 8 bytes, we use BAM\n\tif(j1939Frame->getDataLength() > MAX_CAN_DATA_SIZE) {\n\n\t\tBamFragmenter fragmenter;\n\t\tfragmenter.fragment(*j1939Frame);\n\n\t\tconst TPCMFrame& connFrame = fragmenter.getConnFrame();\n\n\t\tids.push_back(connFrame.getIdentifier());\n\n\t\tstd::vector<TPDTFrame> dataFrames = fragmenter.getDataFrames();\n\n\t\tfor(auto iter = dataFrames.begin(); iter != dataFrames.end(); ++iter) {\n\n\t\t\tids.push_back(iter->getIdentifier());\n\n\t\t}\n\n\n\t} else {\t\t\t//Can be sent in one frame\n\n\t\tids.push_back(j1939Frame->getIdentifier());\n\t}\n\n\tconst std::set<std::string>& ifaces = CanEasy::getInitializedCanIfaces();\n\n\tfor(auto iter = ifaces.begin(); iter != ifaces.end(); ++iter) {\n\t\tstd::shared_ptr<ICanSender> sender = CanEasy::getSender(*iter);\n\n\t\tif(interface.empty() || interface == *iter) {\n\n\t\t\tsender->unSendFrames(ids);\n\t\t\tfound = true;\n\t\t}\n\n\t}\n\n\tif(!found) {\n\t\tstd::cerr << \"Frame not sent through the given interface...\" << std::endl;\n\t}\n\n}\n\nbool isFrameSent(const J1939Frame* frame, const std::string& interface) {\n\n\tstd::vector<u32> ids;\n\tstd::shared_ptr<ICanSender> sender = CanEasy::getSender(interface);\n\n\t//If the frame is bigger than 8 bytes, we use BAM\n\tif(frame->getDataLength() > MAX_CAN_DATA_SIZE) {\n\n\t\tBamFragmenter fragmenter;\n\t\tfragmenter.fragment(*frame);\n\n\t\tconst TPCMFrame& connFrame = fragmenter.getConnFrame();\n\n\t\tids.push_back(connFrame.getIdentifier());\n\n\t\tstd::vector<TPDTFrame> dataFrames = fragmenter.getDataFrames();\n\n\t\tfor(auto iter = dataFrames.begin(); iter != dataFrames.end(); ++iter) {\n\n\t\t\tids.push_back(iter->getIdentifier());\n\n\t\t}\n\n\t} else {\t\t\t//Can be sent in one frame\n\n\t\tids.push_back(frame->getIdentifier());\n\t}\n\n\treturn sender->isSent(ids);\n\n}\n\nvoid execScript(const std::string& file) {\n\n\tstd::string line;\n\n\n\tstd::ifstream fileScript;\n\tfileScript.open(file);\n\n\tif(fileScript.is_open()) {\n\n\t\tif(!silent) std::cout << \"Executing commands...\" << std::endl;\n\n\t\twhile (std::getline(fileScript, line)) {\n\n\t\t\tstd::cout << (!silent ? SENDER_PROMPT : \"\") << line << std::endl;\t\t//Feedback of read command in the file\n\n\t\t\tparseLine(line);\n\t\t}\n\t} else {\n\t\tstd::cerr << \"Could not open the script file...\" << std::endl;\n\t}\n\n}\n\nvoid parseUnsendFrameCommand(std::list<std::string> arguments) {\n\n\tstd::string name = arguments.front();\n\targuments.pop_front();\n\tauto frameIter = framesToSend.find(name);\n\n\n\tif(frameIter == framesToSend.end()) {\n\t\tstd::cerr << \"Frame not defined...\" << std::endl;\n\t\treturn;\n\t}\n\n\tJ1939Frame* frame = frameIter->second;\n\tstd::string interface;\n\n\tauto func = [&interface](const std::string& key, const std::string& value) {\n\n\t\tif(key == INTERFACE_TOKEN) {\n\n\t\t\tinterface = value;\n\t\t}\n\n\t};\n\n\tprocessCommandParameters(arguments, func);\n\n\tunsendFrameThroughInterface(frame, interface);\n\n}\n\nvoid parseExecCommand(std::list<std::string> arguments) {\n\n\tstd::string file = arguments.front();\n\targuments.pop_front();\n\n\tif(arguments.empty()) {\n\t\texecScript(file);\n\t} else {\n\t\tstd::cerr << \"Too many arguments...\" << std::endl;\n\t}\n\n}\n\nvoid uninitializeVariables() {\n\n\n\t//Dealloc allocated frames\n\tfor(auto iter = framesToSend.begin(); iter != framesToSend.end(); ++iter) {\n\t\tdelete iter->second;\n\t}\n\n\n\t//Finalize Can Backends...\n\tCanEasy::finalize();\n\n\t//Deallocate frames\n\tJ1939Factory::getInstance().releaseInstance();\n\n}\n\n\nbool parseSetGenericParams(const std::string& name, J1939Frame* frame, const std::string& key, const std::string& value) {\n\n\n\tbool retVal = true;\n\n\tif(key == PRIORITY_TOKEN) {\n\n\t\ttry {\n\n\t\t\tu32 priority = std::stoul(value);\n\n\n\t\t\tif(priority == (priority & J1939_PRIORITY_MASK)) {\n\t\t\t\tframe->setPriority(static_cast<u8>(priority));\n\t\t\t} else {\n\t\t\t\tstd::cerr << \"Priority out of range\" << std::endl;\n\t\t\t}\n\n\n\t\t} catch (std::invalid_argument& e) {\n\t\t\tstd::cerr << \"Priority is not a number...\" << std::endl;\n\t\t}\n\n\t} else if(key == PERIOD_TOKEN) {\n\t\ttry {\n\n\t\t\tu32 period = std::stoul(value);\n\n\t\t\tframePeriods[name] = period;\n\n\n\t\t} catch (std::invalid_argument& e) {\n\t\t\tstd::cerr << \"Period is not a number...\" << std::endl;\n\t\t}\n\t} else if(key == SOURCE_TOKEN) {\n\n\t\ttry {\n\n\t\t\tu32 src = std::stoul(value, nullptr, 16);\n\n\t\t\tif(src == (src & J1939_SRC_ADDR_MASK)) {\n\t\t\t\tframe->setSrcAddr(static_cast<u8>(src));\n\t\t\t} else {\n\t\t\t\tstd::cerr << \"Source address out of range\" << std::endl;\n\t\t\t}\n\n\t\t} catch (std::invalid_argument& e) {\n\t\t\tstd::cerr << \"Source address is not a number...\" << std::endl;\n\t\t}\n\n\t} else {\n\t\tretVal = false;\n\t}\n\n\treturn retVal;\n}\n\n\nstd::vector<CanFrame> ttsFramesToCanFrames(const std::vector<FMS1Frame>& ttsFrames) {\n\n\tstd::vector<CanFrame> frames;\n\n\tsize_t length;\n\tCanFrame canFrame;\n\tu32 id;\n\tu8* buff;\n\tstd::string data;\n\n\tfor(auto frame = fms1Frames.begin(); frame != fms1Frames.end(); ++frame) {\n\n\t\tlength = frame->getDataLength();\n\n\t\tbuff = new u8[length];\n\n\t\tframe->encode(id, buff, length);\n\n\t\tcanFrame.setId(id);\n\t\tcanFrame.setExtendedFormat(true);\n\n\t\tstd::string data;\n\t\tdata.append((char*)buff, length);\n\n\t\tcanFrame.setData(data);\n\n\t\tdelete[] buff;\n\n\t\tframes.push_back(canFrame);\n\n\t}\n\n\treturn frames;\n}\n\nbool parseDtcCommand(std::list<std::string> arguments, DTC& dtc) {\n\n\tu32 spn = 0;\n\tu8 oc = 0xFF;\n\tu8 fmi = 0xFF;\n\n\tauto func = [&spn, &oc, &fmi](const std::string& key, const std::string& value) {\n\n\t\tif(key == SPN_TOKEN) {\n\n\t\t\ttry {\n\n\t\t\t\tspn = std::stoul(value);\n\n\t\t\t} catch (std::invalid_argument& e) {\n\t\t\t\tstd::cerr << \"Spn is not a number...\" << std::endl;\n\t\t\t}\n\n\t\t} else if(key == OC_TOKEN) {\n\n\t\t\ttry {\n\n\t\t\t\tu32 ocNumber = std::stoul(value);\n\n\t\t\t\tif(ocNumber == (ocNumber & DTC_OC_MASK)) {\n\t\t\t\t\toc = static_cast<u8>(ocNumber);\n\t\t\t\t} else {\n\n\t\t\t\t\tstd::cerr << \"Occurrence Count is out of range...\" << std::endl;\n\t\t\t\t}\n\n\t\t\t} catch (std::invalid_argument& e) {\n\t\t\t\tstd::cerr << \"Occurrence Count is not a number...\" << std::endl;\n\t\t\t}\n\t\t} else if(key == FMI_TOKEN) {\n\n\t\t\ttry {\n\n\t\t\t\tu32 fmiNumber = std::stoul(value);\n\n\t\t\t\tif(fmiNumber == (fmiNumber & DTC_FMI_MASK)) {\n\t\t\t\t\tfmi = static_cast<u8>(fmiNumber);\n\t\t\t\t} else {\n\n\t\t\t\t\tstd::cerr << \"Failure Mode Identifier is out of range...\" << std::endl;\n\t\t\t\t}\n\n\t\t\t} catch (std::invalid_argument& e) {\n\t\t\t\tstd::cerr << \"Failure Mode Identifier is not a number...\" << std::endl;\n\t\t\t}\n\t\t}\n\n\t};\n\n\tprocessCommandParameters(arguments, func);\n\n\tif(spn == 0) {\n\t\tstd::cerr << \"SPN not set...\" << std::endl;\n\t\treturn false;\n\t}\n\n\tif(oc == 0xFF) {\n\t\tstd::cerr << \"Occurrence Count not set...\" << std::endl;\n\t\treturn false;\n\t}\n\n\tif(fmi == 0xFF) {\n\t\tstd::cerr << \"Failure Mode Identifier not set...\" << std::endl;\n\t\treturn false;\n\t}\n\n\tdtc = DTC(spn, fmi, oc);\n\n\treturn true;\n\n}\n\n\n//Example: add dtc abb spn: 87 oc: 3 fmi: 8 (To add a dtc to frame aaa to the tail).\nvoid parseAddDtcCommand(std::list<std::string> arguments) {\n\n\tstd::string name = arguments.front();\n\targuments.pop_front();\n\tauto frameIter = framesToSend.find(name);\n\n\tif(frameIter == framesToSend.end()) {\n\t\tstd::cerr << \"Frame not defined...\" << std::endl;\n\t\treturn;\n\t}\n\n\tJ1939Frame* frame = frameIter->second;\n\n\tif(frame->getPGN() != DM1_PGN) {\n\t\tstd::cerr << \"Not a DM1 frame...\" << std::endl;\n\t\treturn;\n\t}\n\n\tDTC dtc;\n\n\tif(parseDtcCommand(arguments, dtc)) {\n\t\tDM1* dm1Frame = static_cast<DM1*>(frame);\n\t\tdm1Frame->addDTC(std::move(dtc));\n\t}\n\n}\n\n//Example: set dtc aaa 1 spn: 14 oc: 2 fmi: 5 (To set second dtc for frame aaa).\nvoid parseSetDtcCommand(std::list<std::string> arguments) {\n\n\t//Take frame name from arguments\n\tstd::string name = arguments.front();\n\targuments.pop_front();\n\tauto frameIter = framesToSend.find(name);\n\n\tif(frameIter == framesToSend.end()) {\n\t\tstd::cerr << \"Frame not defined...\" << std::endl;\n\t\treturn;\n\t}\n\n\tJ1939Frame* frame = frameIter->second;\n\n\tif(frame->getPGN() != DM1_PGN) {\n\t\tstd::cerr << \"Not a DM1 frame...\" << std::endl;\n\t\treturn;\n\t}\n\n\n\t//Take dtc postion from arguments\n\tstd::string posStr = arguments.front();\n\targuments.pop_front();\n\n\tsize_t pos;\n\n\ttry {\n\n\t\tpos = std::stoul(posStr);\n\n\t} catch (std::invalid_argument& e) {\n\t\tstd::cerr << \"Position is not a number...\" << std::endl;\n\t}\n\n\tDTC dtc;\n\n\tif(parseDtcCommand(arguments, dtc)) {\n\t\tDM1* dm1Frame = static_cast<DM1*>(frame);\n\t\tdm1Frame->setDTC(pos, std::move(dtc));\n\t}\n\n}\n\n//Example: delete dtc abb 0 (To delete first dtc from frame abb).\n\nvoid parseDeleteDtcCommand(std::list<std::string> arguments) {\n\n\t//Take frame name from arguments\n\tstd::string name = arguments.front();\n\targuments.pop_front();\n\tauto frameIter = framesToSend.find(name);\n\n\tif(frameIter == framesToSend.end()) {\n\t\tstd::cerr << \"Frame not defined...\" << std::endl;\n\t\treturn;\n\t}\n\n\tJ1939Frame* frame = frameIter->second;\n\n\tif(frame->getPGN() != DM1_PGN) {\n\t\tstd::cerr << \"Not a DM1 frame...\" << std::endl;\n\t\treturn;\n\t}\n\n\n\t//Take dtc postion from arguments\n\tstd::string posStr = arguments.front();\n\targuments.pop_front();\n\n\tsize_t pos;\n\n\ttry {\n\n\t\tpos = std::stoul(posStr);\n\n\t} catch (std::invalid_argument& e) {\n\t\tstd::cerr << \"Position is not a number...\" << std::endl;\n\t}\n\n\n\tDM1* dm1Frame = static_cast<DM1*>(frame);\n\n\tdm1Frame->deleteDTC(pos);\n\n}\n"
  },
  {
    "path": "BinUtils/j1939Sniffer/.cproject",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<?fileVersion 4.0.0?><cproject storage_type_id=\"org.eclipse.cdt.core.XmlProjectDescriptionStorage\">\n\t<storageModule moduleId=\"org.eclipse.cdt.core.settings\">\n\t\t<cconfiguration id=\"cdt.managedbuild.config.gnu.exe.debug.1823270490\">\n\t\t\t<storageModule buildSystemId=\"org.eclipse.cdt.managedbuilder.core.configurationDataProvider\" id=\"cdt.managedbuild.config.gnu.exe.debug.1823270490\" moduleId=\"org.eclipse.cdt.core.settings\" name=\"Debug\">\n\t\t\t\t<externalSettings/>\n\t\t\t\t<extensions>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GNU_ELF\" point=\"org.eclipse.cdt.core.BinaryParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GASErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GmakeErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GLDErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.CWDLocator\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GCCErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t</extensions>\n\t\t\t</storageModule>\n\t\t\t<storageModule moduleId=\"cdtBuildSystem\" version=\"4.0.0\">\n\t\t\t\t<configuration artifactName=\"${ProjName}\" buildArtefactType=\"org.eclipse.cdt.build.core.buildArtefactType.exe\" buildProperties=\"org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug\" cleanCommand=\"rm -rf\" description=\"\" id=\"cdt.managedbuild.config.gnu.exe.debug.1823270490\" name=\"Debug\" parent=\"cdt.managedbuild.config.gnu.exe.debug\">\n\t\t\t\t\t<folderInfo id=\"cdt.managedbuild.config.gnu.exe.debug.1823270490.\" name=\"/\" resourcePath=\"\">\n\t\t\t\t\t\t<toolChain id=\"cdt.managedbuild.toolchain.gnu.exe.debug.1897798032\" name=\"Linux GCC\" superClass=\"cdt.managedbuild.toolchain.gnu.exe.debug\">\n\t\t\t\t\t\t\t<targetPlatform id=\"cdt.managedbuild.target.gnu.platform.exe.debug.1415164888\" name=\"Debug Platform\" superClass=\"cdt.managedbuild.target.gnu.platform.exe.debug\"/>\n\t\t\t\t\t\t\t<builder buildPath=\"${workspace_loc:/j1939Sniffer}/Debug\" id=\"cdt.managedbuild.target.gnu.builder.exe.debug.1480028597\" keepEnvironmentInBuildfile=\"false\" managedBuildOn=\"true\" name=\"Gnu Make Builder\" superClass=\"cdt.managedbuild.target.gnu.builder.exe.debug\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.archiver.base.140688525\" name=\"GCC Archiver\" superClass=\"cdt.managedbuild.tool.gnu.archiver.base\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.944164048\" name=\"GCC C++ Compiler\" superClass=\"cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug\">\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.exe.debug.option.optimization.level.1474975970\" name=\"Optimization Level\" superClass=\"gnu.cpp.compiler.exe.debug.option.optimization.level\" useByScannerDiscovery=\"false\" value=\"gnu.cpp.compiler.optimization.level.none\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.exe.debug.option.debugging.level.942411302\" name=\"Debug Level\" superClass=\"gnu.cpp.compiler.exe.debug.option.debugging.level\" useByScannerDiscovery=\"false\" value=\"gnu.cpp.compiler.debugging.level.max\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.option.include.paths.1434142944\" name=\"Include paths (-I)\" superClass=\"gnu.cpp.compiler.option.include.paths\" useByScannerDiscovery=\"false\" valueType=\"includePath\">\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"&quot;${workspace_loc:/CAN}&quot;\"/>\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"&quot;${workspace_loc:/Common}&quot;\"/>\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"&quot;${workspace_loc:/J1939}&quot;\"/>\n\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.option.dialect.std.518867606\" name=\"Language standard\" superClass=\"gnu.cpp.compiler.option.dialect.std\" useByScannerDiscovery=\"true\" value=\"gnu.cpp.compiler.dialect.c++11\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.cpp.compiler.input.1305411185\" superClass=\"cdt.managedbuild.tool.gnu.cpp.compiler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.c.compiler.exe.debug.1019824305\" name=\"GCC C Compiler\" superClass=\"cdt.managedbuild.tool.gnu.c.compiler.exe.debug\">\n\t\t\t\t\t\t\t\t<option defaultValue=\"gnu.c.optimization.level.none\" id=\"gnu.c.compiler.exe.debug.option.optimization.level.571359833\" name=\"Optimization Level\" superClass=\"gnu.c.compiler.exe.debug.option.optimization.level\" useByScannerDiscovery=\"false\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.c.compiler.exe.debug.option.debugging.level.1569476303\" name=\"Debug Level\" superClass=\"gnu.c.compiler.exe.debug.option.debugging.level\" useByScannerDiscovery=\"false\" value=\"gnu.c.debugging.level.max\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.c.compiler.input.1639232821\" superClass=\"cdt.managedbuild.tool.gnu.c.compiler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.c.linker.exe.debug.1852645664\" name=\"GCC C Linker\" superClass=\"cdt.managedbuild.tool.gnu.c.linker.exe.debug\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.cpp.linker.exe.debug.274171196\" name=\"GCC C++ Linker\" superClass=\"cdt.managedbuild.tool.gnu.cpp.linker.exe.debug\">\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.link.option.paths.985479177\" name=\"Library search path (-L)\" superClass=\"gnu.cpp.link.option.paths\" useByScannerDiscovery=\"false\" valueType=\"libPaths\">\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"&quot;${workspace_loc:/CAN/Debug}&quot;\"/>\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"&quot;${workspace_loc:/Common/Debug}&quot;\"/>\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"&quot;${workspace_loc:/J1939/Debug}&quot;\"/>\n\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.link.option.libs.393837245\" name=\"Libraries (-l)\" superClass=\"gnu.cpp.link.option.libs\" useByScannerDiscovery=\"false\" valueType=\"libs\">\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"CAN\"/>\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"ncurses\"/>\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"dl\"/>\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"Common\"/>\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"J1939\"/>\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"pthread\"/>\n\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.link.option.flags.79458475\" name=\"Linker flags\" superClass=\"gnu.cpp.link.option.flags\" useByScannerDiscovery=\"false\" value=\"-rdynamic\" valueType=\"string\"/>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.cpp.linker.input.113497849\" superClass=\"cdt.managedbuild.tool.gnu.cpp.linker.input\">\n\t\t\t\t\t\t\t\t\t<additionalInput kind=\"additionalinputdependency\" paths=\"$(USER_OBJS)\"/>\n\t\t\t\t\t\t\t\t\t<additionalInput kind=\"additionalinput\" paths=\"$(LIBS)\"/>\n\t\t\t\t\t\t\t\t</inputType>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.assembler.exe.debug.1780139637\" name=\"GCC Assembler\" superClass=\"cdt.managedbuild.tool.gnu.assembler.exe.debug\">\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.assembler.input.284107585\" superClass=\"cdt.managedbuild.tool.gnu.assembler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t</toolChain>\n\t\t\t\t\t</folderInfo>\n\t\t\t\t</configuration>\n\t\t\t</storageModule>\n\t\t\t<storageModule moduleId=\"org.eclipse.cdt.core.externalSettings\"/>\n\t\t</cconfiguration>\n\t\t<cconfiguration id=\"cdt.managedbuild.config.gnu.exe.release.1257976290\">\n\t\t\t<storageModule buildSystemId=\"org.eclipse.cdt.managedbuilder.core.configurationDataProvider\" id=\"cdt.managedbuild.config.gnu.exe.release.1257976290\" moduleId=\"org.eclipse.cdt.core.settings\" name=\"Release\">\n\t\t\t\t<externalSettings/>\n\t\t\t\t<extensions>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GNU_ELF\" point=\"org.eclipse.cdt.core.BinaryParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GASErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GmakeErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GLDErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.CWDLocator\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GCCErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t</extensions>\n\t\t\t</storageModule>\n\t\t\t<storageModule moduleId=\"cdtBuildSystem\" version=\"4.0.0\">\n\t\t\t\t<configuration artifactName=\"${ProjName}\" buildArtefactType=\"org.eclipse.cdt.build.core.buildArtefactType.exe\" buildProperties=\"org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release\" cleanCommand=\"rm -rf\" description=\"\" id=\"cdt.managedbuild.config.gnu.exe.release.1257976290\" name=\"Release\" parent=\"cdt.managedbuild.config.gnu.exe.release\">\n\t\t\t\t\t<folderInfo id=\"cdt.managedbuild.config.gnu.exe.release.1257976290.\" name=\"/\" resourcePath=\"\">\n\t\t\t\t\t\t<toolChain id=\"cdt.managedbuild.toolchain.gnu.exe.release.589196453\" name=\"Linux GCC\" superClass=\"cdt.managedbuild.toolchain.gnu.exe.release\">\n\t\t\t\t\t\t\t<targetPlatform id=\"cdt.managedbuild.target.gnu.platform.exe.release.1018521427\" name=\"Debug Platform\" superClass=\"cdt.managedbuild.target.gnu.platform.exe.release\"/>\n\t\t\t\t\t\t\t<builder buildPath=\"${workspace_loc:/j1939Sniffer}/Release\" id=\"cdt.managedbuild.target.gnu.builder.exe.release.1798508598\" keepEnvironmentInBuildfile=\"false\" managedBuildOn=\"true\" name=\"Gnu Make Builder\" superClass=\"cdt.managedbuild.target.gnu.builder.exe.release\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.archiver.base.1094973440\" name=\"GCC Archiver\" superClass=\"cdt.managedbuild.tool.gnu.archiver.base\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.1059403163\" name=\"GCC C++ Compiler\" superClass=\"cdt.managedbuild.tool.gnu.cpp.compiler.exe.release\">\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.exe.release.option.optimization.level.1483235521\" name=\"Optimization Level\" superClass=\"gnu.cpp.compiler.exe.release.option.optimization.level\" useByScannerDiscovery=\"false\" value=\"gnu.cpp.compiler.optimization.level.most\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.exe.release.option.debugging.level.2038881296\" name=\"Debug Level\" superClass=\"gnu.cpp.compiler.exe.release.option.debugging.level\" useByScannerDiscovery=\"false\" value=\"gnu.cpp.compiler.debugging.level.none\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.cpp.compiler.input.1304422705\" superClass=\"cdt.managedbuild.tool.gnu.cpp.compiler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.c.compiler.exe.release.1689728863\" name=\"GCC C Compiler\" superClass=\"cdt.managedbuild.tool.gnu.c.compiler.exe.release\">\n\t\t\t\t\t\t\t\t<option defaultValue=\"gnu.c.optimization.level.most\" id=\"gnu.c.compiler.exe.release.option.optimization.level.548713967\" name=\"Optimization Level\" superClass=\"gnu.c.compiler.exe.release.option.optimization.level\" useByScannerDiscovery=\"false\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.c.compiler.exe.release.option.debugging.level.1662928989\" name=\"Debug Level\" superClass=\"gnu.c.compiler.exe.release.option.debugging.level\" useByScannerDiscovery=\"false\" value=\"gnu.c.debugging.level.none\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.c.compiler.input.819103258\" superClass=\"cdt.managedbuild.tool.gnu.c.compiler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.c.linker.exe.release.1880607432\" name=\"GCC C Linker\" superClass=\"cdt.managedbuild.tool.gnu.c.linker.exe.release\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.cpp.linker.exe.release.1328092022\" name=\"GCC C++ Linker\" superClass=\"cdt.managedbuild.tool.gnu.cpp.linker.exe.release\">\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.cpp.linker.input.1518738130\" superClass=\"cdt.managedbuild.tool.gnu.cpp.linker.input\">\n\t\t\t\t\t\t\t\t\t<additionalInput kind=\"additionalinputdependency\" paths=\"$(USER_OBJS)\"/>\n\t\t\t\t\t\t\t\t\t<additionalInput kind=\"additionalinput\" paths=\"$(LIBS)\"/>\n\t\t\t\t\t\t\t\t</inputType>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.assembler.exe.release.703854502\" name=\"GCC Assembler\" superClass=\"cdt.managedbuild.tool.gnu.assembler.exe.release\">\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.assembler.input.1111746818\" superClass=\"cdt.managedbuild.tool.gnu.assembler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t</toolChain>\n\t\t\t\t\t</folderInfo>\n\t\t\t\t</configuration>\n\t\t\t</storageModule>\n\t\t\t<storageModule moduleId=\"org.eclipse.cdt.core.externalSettings\"/>\n\t\t</cconfiguration>\n\t</storageModule>\n\t<storageModule moduleId=\"cdtBuildSystem\" version=\"4.0.0\">\n\t\t<project id=\"j1939Sniffer.cdt.managedbuild.target.gnu.exe.197305081\" name=\"Executable\" projectType=\"cdt.managedbuild.target.gnu.exe\"/>\n\t</storageModule>\n\t<storageModule moduleId=\"scannerConfiguration\">\n\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.config.gnu.exe.release.1257976290;cdt.managedbuild.config.gnu.exe.release.1257976290.;cdt.managedbuild.tool.gnu.c.compiler.exe.release.1689728863;cdt.managedbuild.tool.gnu.c.compiler.input.819103258\">\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t</scannerConfigBuildInfo>\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.config.gnu.exe.debug.1823270490;cdt.managedbuild.config.gnu.exe.debug.1823270490.;cdt.managedbuild.tool.gnu.c.compiler.exe.debug.1019824305;cdt.managedbuild.tool.gnu.c.compiler.input.1639232821\">\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t</scannerConfigBuildInfo>\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.config.gnu.exe.release.1257976290;cdt.managedbuild.config.gnu.exe.release.1257976290.;cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.1059403163;cdt.managedbuild.tool.gnu.cpp.compiler.input.1304422705\">\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t</scannerConfigBuildInfo>\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.config.gnu.exe.debug.1823270490;cdt.managedbuild.config.gnu.exe.debug.1823270490.;cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.944164048;cdt.managedbuild.tool.gnu.cpp.compiler.input.1305411185\">\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t</scannerConfigBuildInfo>\n\t</storageModule>\n\t<storageModule moduleId=\"org.eclipse.cdt.core.LanguageSettingsProviders\"/>\n\t<storageModule moduleId=\"refreshScope\" versionNumber=\"2\">\n\t\t<configuration configurationName=\"Debug\">\n\t\t\t<resource resourceType=\"PROJECT\" workspacePath=\"/j1939Sniffer\"/>\n\t\t</configuration>\n\t\t<configuration configurationName=\"Release\">\n\t\t\t<resource resourceType=\"PROJECT\" workspacePath=\"/j1939Sniffer\"/>\n\t\t</configuration>\n\t</storageModule>\n\t<storageModule moduleId=\"org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings\"/>\n\t<storageModule moduleId=\"org.eclipse.cdt.make.core.buildtargets\"/>\n</cproject>\n"
  },
  {
    "path": "BinUtils/j1939Sniffer/.gitignore",
    "content": "/Debug/\n"
  },
  {
    "path": "BinUtils/j1939Sniffer/.settings/org.eclipse.cdt.codan.core.prefs",
    "content": "eclipse.preferences.version=1\norg.eclipse.cdt.codan.checkers.errnoreturn=Warning\norg.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"No return\\\\\")\",implicit\\=>false}\norg.eclipse.cdt.codan.checkers.errreturnvalue=Error\norg.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Unused return value\\\\\")\"}\norg.eclipse.cdt.codan.checkers.nocommentinside=-Error\norg.eclipse.cdt.codan.checkers.nocommentinside.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Nesting comments\\\\\")\"}\norg.eclipse.cdt.codan.checkers.nolinecomment=-Error\norg.eclipse.cdt.codan.checkers.nolinecomment.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Line comments\\\\\")\"}\norg.eclipse.cdt.codan.checkers.noreturn=Error\norg.eclipse.cdt.codan.checkers.noreturn.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"No return value\\\\\")\",implicit\\=>false}\norg.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=-Error\norg.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Abstract class cannot be instantiated\\\\\")\"}\norg.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Ambiguous problem\\\\\")\"}\norg.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Assignment in condition\\\\\")\"}\norg.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error\norg.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Assignment to itself\\\\\")\"}\norg.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"No break at end of case\\\\\")\",no_break_comment\\=>\"no break\",last_case_param\\=>false,empty_case_param\\=>false}\norg.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning\norg.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Catching by reference is recommended\\\\\")\",unknown\\=>false,exceptions\\=>()}\norg.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Circular inheritance\\\\\")\"}\norg.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning\norg.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Class members should be properly initialized\\\\\")\",skip\\=>true}\norg.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Field cannot be resolved\\\\\")\"}\norg.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Function cannot be resolved\\\\\")\"}\norg.eclipse.cdt.codan.internal.checkers.InvalidArguments=-Error\norg.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Invalid arguments\\\\\")\"}\norg.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Invalid template argument\\\\\")\"}\norg.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Label statement not found\\\\\")\"}\norg.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Member declaration not found\\\\\")\"}\norg.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Method cannot be resolved\\\\\")\"}\norg.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info\norg.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Name convention for function\\\\\")\",pattern\\=>\"^[a-z]\",macro\\=>true,exceptions\\=>()}\norg.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Class has a virtual method and non-virtual destructor\\\\\")\"}\norg.eclipse.cdt.codan.internal.checkers.OverloadProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Invalid overload\\\\\")\"}\norg.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Invalid redeclaration\\\\\")\"}\norg.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Invalid redefinition\\\\\")\"}\norg.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning\norg.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Return with parenthesis\\\\\")\"}\norg.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning\norg.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Format String Vulnerability\\\\\")\"}\norg.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Statement has no effect\\\\\")\",macro\\=>true,exceptions\\=>()}\norg.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Suggested parenthesis around expression\\\\\")\",paramNot\\=>false}\norg.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Suspicious semicolon\\\\\")\",else\\=>false,afterelse\\=>false}\norg.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Type cannot be resolved\\\\\")\"}\norg.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Unused function declaration\\\\\")\",macro\\=>true}\norg.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Unused static function\\\\\")\",macro\\=>true}\norg.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Unused variable declaration in file scope\\\\\")\",macro\\=>true,exceptions\\=>(\"@(\\#)\",\"$Id\")}\norg.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},suppression_comment\\=>\"@suppress(\\\\\"Symbol is not resolved\\\\\")\"}\nuseParentScope=false\n"
  },
  {
    "path": "BinUtils/j1939Sniffer/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.5)\n\nproject(j1939Sniffer)\n\nfind_package (Curses)\n\nif(CURSES_FOUND)\n\nmessage(\"-- NCURSES is available\")\n\nmessage(\"-- Project \" ${PROJECT_NAME} \" will be built\")\n\nadd_executable(j1939Sniffer \n    src/j1939Sniffer.cpp\n)\n\ntarget_include_directories(j1939Sniffer\n    PUBLIC \n        include ${J1939_SOURCE_DIR}/include ${Can_SOURCE_DIR}/include ${Common_SOURCE_DIR}/include\n)\n\ntarget_link_libraries(j1939Sniffer\n    PUBLIC\n        J1939 Can ncurses -rdynamic\n)\n\n\ninstall (TARGETS j1939Sniffer\n    DESTINATION bin)\n\nelse(CURSES_FOUND)\n\nmessage(WARNING \"-- NCURSES is not available\")\nmessage(WARNING \"-- Project \" ${PROJECT_NAME} \" is skipped...\")\nmessage(WARNING \"-- Try to install ncurses and run cmake again...\")\n\nendif(CURSES_FOUND)\n"
  },
  {
    "path": "BinUtils/j1939Sniffer/src/j1939Sniffer.cpp",
    "content": "/*\n * j1939Sniffer.cpp\n *\n *  Created on: May 7, 2018\n *      Author: fernado\n */\n\n\n#include <ncurses.h>\n\n#include <getopt.h>\n\n#include <iostream>\n\n#include <Utils.h>\n#include <Transport/BAM/BamReassembler.h>\n#include <J1939Factory.h>\n#include <J1939DataBase.h>\n#include <GenericFrame.h>\n#include <Transport/TPCMFrame.h>\n#include <Transport/TPDTFrame.h>\n\n\n#include <CanEasy.h>\n\n\n\n//Bitrate for J1939 protocol\n#define BAUD_250K\t\t\t250000\n\n#ifndef DATABASE_PATH\n#define DATABASE_PATH\t\t\"/etc/j1939/frames.json\"\n#endif\n\nusing namespace Can;\nusing namespace Utils;\nusing namespace J1939;\n\n\n//To reassemble frames fragmented by means of Broadcast Announce Message protocol\nBamReassembler reassembler;\n\nvoid onRcv(const Can::CanFrame& frame, const TimeStamp&, const std::string& interface, void*);\nbool onTimeout();\n\nu32 pgn;\nu32 spn;\nstd::string interface, title;\nu8 source;\n\n\nint main (int argc, char **argv)\n{\n\n\tint c;\n\n\tpgn = 0;\n\tspn = 0;\n\tsource = J1939_INVALID_ADDRESS;\n\tstd::string pgnStr, spnStr, sourceStr;\n\n\tstatic struct option long_options[] =\n\t\t{\n\t\t\t{\"pgn\", required_argument, NULL, 'p'},\n\t\t\t{\"spn\", required_argument, NULL, 's'},\n\t\t\t{\"interface\", required_argument, NULL, 'i'},\n\t\t\t{\"title\", required_argument, NULL, 't'},\n\t\t\t{\"source\", required_argument, NULL, 'o'},\n\t\t\t{NULL, 0, NULL, 0}\n\t\t};\n\n\n\twhile (1)\n\t{\n\n\t\tc = getopt_long (argc, argv, \"p:s:i:t:\",\n\t\t\t\t   long_options, NULL);\n\n\t\t/* Detect the end of the options. */\n\t\tif (c == -1)\n\t\t\tbreak;\n\n\t\tswitch (c)\n\t\t{\n\t\tcase 'p':\n\t\t\tpgnStr = optarg;\n\t\t\tbreak;\n\t\tcase 's':\n\t\t\tspnStr = optarg;\n\t\t\tbreak;\n\t\tcase 'i':\n\t\t\tinterface = optarg;\n\t\t\tbreak;\n\t\tcase 't':\n\t\t\ttitle = optarg;\n\t\t\tbreak;\n\t\tcase 'o':\n\t\t\tsourceStr = optarg;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif(!sourceStr.empty()) {\n\t\ttry {\n\n\t\t\tu32 src = std::stoul(sourceStr, nullptr, 16);\n\n\t\t\tif((src & J1939_SRC_ADDR_MASK) != src) {\n\t\t\t\tstd::cerr << \"The parameter source is too big...\" << std::endl;\n\t\t\t\treturn 2;\n\t\t\t}\n\n\t\t\tsource = static_cast<u8>(src);\n\n\t\t} catch (std::invalid_argument& ) {\n\n\t\t\tstd::cerr << \"The parameter source is not a number...\" << std::endl;\n\t\t\treturn 2;\n\t\t}\n\t}\n\n\tif(pgnStr.empty() && title.empty()) {\n\n\t\tstd::cerr << \"The parameter pgn or title are not specified...\" << std::endl;\n\t\treturn 1;\n\n\t}\n\n\tif(!pgnStr.empty() && !title.empty()) {\n\n\t\tstd::cerr << \"Only pgn or title can be specified...\" << std::endl;\n\t\treturn 1;\n\n\t}\n\n\tif(!pgnStr.empty()) {\n\n\t\ttry {\n\n\t\t\tpgn = std::stoul(pgnStr, nullptr, 16);\n\n\t\t\tif((pgn & J1939_PGN_MASK) != pgn) {\n\t\t\t\tstd::cerr << \"The parameter pgn is too big...\" << std::endl;\n\t\t\t\treturn 2;\n\t\t\t}\n\n\t\t} catch (std::invalid_argument& ) {\n\n\t\t\tstd::cerr << \"The parameter pgn is not a number...\" << std::endl;\n\t\t\treturn 2;\n\t\t}\n\n\t}\n\n\tif(!spnStr.empty()) {\n\n\n\t\ttry {\n\n\t\t\tspn = std::stoul(spnStr);\n\n\t\t} catch (std::invalid_argument& ) {\n\n\t\t\tstd::cerr << \"The parameter spn is not a number...\" << std::endl;\n\t\t\treturn 3;\n\t\t}\n\n\t}\n\n\n\t//Load database\n\tJ1939DataBase ddbb;\n\tif(!ddbb.parseJsonFile(DATABASE_PATH)) {\n\n\t\tswitch (ddbb.getLastError()) {\n\t\t\tcase J1939DataBase::ERROR_FILE_NOT_FOUND:\n\t\t\t\tstd::cerr << \"Json database not found in\" DATABASE_PATH << std::endl;\n\t\t\t\tbreak;\n\t\t\tcase J1939DataBase::ERROR_JSON_SYNTAX:\n\t\t\t\tstd::cerr << \"Json file has syntax errors\" << std::endl;\n\t\t\t\tbreak;\n\t\t\tcase J1939DataBase::ERROR_UNEXPECTED_TOKENS:\n\t\t\t\tstd::cerr << \"Json file has tokens not identified by the application\" << std::endl;\n\t\t\t\tbreak;\n\t\t\tcase J1939DataBase::ERROR_OUT_OF_RANGE:\n\t\t\t\tstd::cerr << \"Json file has some values that exceed the permitted ranges\" << std::endl;\n\t\t\t\tbreak;\n\t\t\tcase J1939DataBase::ERROR_UNKNOWN_SPN_TYPE:\n\t\t\t\tstd::cerr << \"Json file has undefined type for SPN\" << std::endl;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tstd::cerr << \"Something in the database is not working\" << std::endl;\n\t\t\t\tbreak;\n\t\t}\n\t\treturn 4;\n\t}\n\n\t//Register frames in the factory\n\n\tconst std::vector<GenericFrame>& frames = ddbb.getParsedFrames();\n\n\tfor(auto iter = frames.begin(); iter != frames.end(); ++iter) {\n\t\tJ1939Factory::getInstance().registerFrame(*iter);\n\t}\n\n\n\t//Search the frame in the database by the given pgn\n\tstd::unique_ptr<J1939Frame> frame;\n\n\tif(pgn != 0) {\n\n\t\tframe = J1939Factory::getInstance().getJ1939Frame(pgn);\n\n\t} else if(!title.empty()) {\n\n\t\tframe = J1939Factory::getInstance().getJ1939Frame(title);\n\n\t}\n\n\n\tif(!frame) {\n\t\tstd::cerr << \"The frame given by the pgn or title is not defined...\" << std::endl;\n\t\treturn 5;\n\t}\n\n\n\tif(spn != 0) {\t\t//Spn has been defined\n\n\t\tif(!frame->isGenericFrame()) {\n\t\t\tstd::cerr << \"The frame given by the pgn does not have SPNs associated...\" << std::endl;\n\t\t\treturn 6;\n\t\t}\n\n\t\tGenericFrame* genFrame = static_cast<GenericFrame*>(frame.get());\n\n\t\tif(!genFrame->hasSPN(spn)) {\n\t\t\tstd::cerr << \"The frame given by the pgn does not have the given SPN...\" << std::endl;\n\t\t\treturn 7;\n\t\t}\n\n\t}\n\n\tCanEasy::initialize(BAUD_250K, onRcv, onTimeout);\n\n\tCanSniffer& sniffer = CanEasy::getSniffer();\n\n\tif(sniffer.getNumberOfReceivers() == 0) {\n\t\tstd::cerr << \"No interface available from to sniffer\" << std::endl;\n\t\treturn 8;\n\t}\n\n\tstd::set<CanFilter> filters;\n\n\t//Install filter to get only the frame whose pgn is equals to the specified as argument.\n\n\tCanFilter dataFilter((frame->getPGN() << J1939_PGN_OFFSET) | (source != J1939_INVALID_ADDRESS ? (source << J1939_SRC_ADDR_OFFSET) : 0)\n\t\t\t, (J1939_PGN_MASK << J1939_PGN_OFFSET) | (source != J1939_INVALID_ADDRESS ? (J1939_SRC_ADDR_MASK << J1939_SRC_ADDR_OFFSET) : 0), true, false);\n\n\n\t//Also install filters to receive frames which are part of BAM transport protocol\n\n\tCanFilter tpcmFilter((TP_CM_PGN  << J1939_PGN_OFFSET) | (source != J1939_INVALID_ADDRESS ? (source << J1939_SRC_ADDR_OFFSET) : 0),\n\t\t\t((J1939_PDU_FMT_MASK << J1939_PDU_FMT_OFFSET) << J1939_PGN_OFFSET) | (source != J1939_INVALID_ADDRESS ? (J1939_SRC_ADDR_MASK << J1939_SRC_ADDR_OFFSET) : 0), true, false);\n\n\n\tCanFilter tpdtFilter((TP_DT_PGN  << J1939_PGN_OFFSET) | (source != J1939_INVALID_ADDRESS ? (source << J1939_SRC_ADDR_OFFSET) : 0),\n\t\t\t((J1939_PDU_FMT_MASK << J1939_PDU_FMT_OFFSET) << J1939_PGN_OFFSET) | (source != J1939_INVALID_ADDRESS ? (J1939_SRC_ADDR_MASK << J1939_SRC_ADDR_OFFSET) : 0), true, false);\n\n\tfilters.insert(dataFilter);\n\n\tfilters.insert(tpcmFilter);\n\n\tfilters.insert(tpdtFilter);\n\n\n\tsniffer.setFilters(filters);\n\n\n\t//Initialize ncurses\n\tinitscr();\n\n\tsniffer.sniff(1000);\n\n\tendwin();\n\n\treturn 0;\n}\n\n\n\nvoid onRcv(const Can::CanFrame& frame, const TimeStamp&, const std::string& interface, void*) {\n\n\tstd::unique_ptr<J1939Frame> j1939Frame = J1939Factory::getInstance().\n\t\t\tgetJ1939Frame(frame.getId(), (const u8*)(frame.getData().c_str()), frame.getData().size());\n\n\tif(!j1939Frame)\t\treturn;\t\t\t\t\t\t//Frame not registered in the factory. Should never happen\n\n\tif(reassembler.toBeHandled(*j1939Frame)) {\t\t\t\t//Check if the frame is part of a fragmented frame (BAM protocol)\n\t\t//Actually it is, reassembler will handle it.\n\t\treassembler.handleFrame(*j1939Frame);\n\n\t\tif(reassembler.reassembledFramesPending()) {\n\n\t\t\tj1939Frame = reassembler.dequeueReassembledFrame();\n\n\t\t} else {\n\t\t\treturn;\t\t\t\t//Frame handled by reassembler but the original frame to be reassembled is not complete.\n\t\t}\n\n\t}\n\n\n\t//At this point we have either a simple frame or a reassembled frame.\n\n\t//Necesary to check again if pgn is the same even if the filters are supposed to do the work, because maybe,\n\t//we have reassembled another frame than the expected one. Check the title also.\n\n\tif(pgn == j1939Frame->getPGN() || title == j1939Frame->getName()) {\n\n\t\tstd::string toPrint;\n\n\t\tif(spn != 0) { \t\t//Defined\n\n\t\t\tif(j1939Frame->isGenericFrame()) {\n\t\t\t\tGenericFrame* genFrame = static_cast<GenericFrame*>(j1939Frame.get());\n\n\t\t\t\tif(genFrame->hasSPN(spn)) {\n\t\t\t\t\tSPN* spnToPrint = genFrame->getSPN(spn);\n\t\t\t\t\ttoPrint = spnToPrint->toString();\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} else {\t\t//Spn not defined\n\n\t\t\ttoPrint = j1939Frame->toString();\n\n\t\t}\n\n\n\t\tclear();\n\t\tprintw(toPrint.c_str());\n\t\trefresh();\n\n\t}\n\n}\n\n\nbool onTimeout() {\n\n\treturn true;\n\n}\n"
  },
  {
    "path": "CAN/.gitignore",
    "content": "/Debug/\n"
  },
  {
    "path": "CAN/.settings/org.eclipse.cdt.codan.core.prefs",
    "content": "eclipse.preferences.version=1\norg.eclipse.cdt.codan.checkers.errnoreturn=Warning\norg.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},implicit\\=>false}\norg.eclipse.cdt.codan.checkers.errreturnvalue=Error\norg.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.checkers.noreturn=Error\norg.eclipse.cdt.codan.checkers.noreturn.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},implicit\\=>false}\norg.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=-Error\norg.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error\norg.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},no_break_comment\\=>\"no break\",last_case_param\\=>false,empty_case_param\\=>false}\norg.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning\norg.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},unknown\\=>false,exceptions\\=>()}\norg.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning\norg.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},skip\\=>true}\norg.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.InvalidArguments=-Error\norg.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info\norg.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},pattern\\=>\"^[a-z]\",macro\\=>true,exceptions\\=>()}\norg.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.OverloadProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning\norg.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning\norg.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},macro\\=>true,exceptions\\=>()}\norg.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},paramNot\\=>false}\norg.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},else\\=>false,afterelse\\=>false}\norg.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},macro\\=>true}\norg.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},macro\\=>true}\norg.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},macro\\=>true,exceptions\\=>(\"@(\\#)\",\"$Id\")}\norg.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\nuseParentScope=false\n"
  },
  {
    "path": "CAN/Backends/PeakCan/PeakCanChannels.cpp",
    "content": "/*\n * PeakCanChannels.cpp\n *\n *  Created on: Apr 4, 2018\n *      Author: famez\n */\n\n#include <Backends/PeakCan/PeakCanChannels.h>\n\nnamespace Can {\nnamespace PeakCan {\n\nPeakCanChannels::PeakCanChannels() {\n\n\t//USB channels\n\tREGISTER_CHANNEL(\"usb0\",  PCAN_USBBUS1);\n\tREGISTER_CHANNEL(\"usb1\",  PCAN_USBBUS2);\n\tREGISTER_CHANNEL(\"usb2\",  PCAN_USBBUS3);\n\tREGISTER_CHANNEL(\"usb3\",  PCAN_USBBUS4);\n\tREGISTER_CHANNEL(\"usb4\",  PCAN_USBBUS5);\n\tREGISTER_CHANNEL(\"usb5\",  PCAN_USBBUS6);\n\tREGISTER_CHANNEL(\"usb6\",  PCAN_USBBUS7);\n\tREGISTER_CHANNEL(\"usb7\",  PCAN_USBBUS8);\n\tREGISTER_CHANNEL(\"usb8\",  PCAN_USBBUS9);\n\tREGISTER_CHANNEL(\"usb9\",  PCAN_USBBUS10);\n\tREGISTER_CHANNEL(\"usb10\",  PCAN_USBBUS11);\n\tREGISTER_CHANNEL(\"usb11\",  PCAN_USBBUS12);\n\tREGISTER_CHANNEL(\"usb12\",  PCAN_USBBUS13);\n\tREGISTER_CHANNEL(\"usb13\",  PCAN_USBBUS14);\n\tREGISTER_CHANNEL(\"usb14\",  PCAN_USBBUS15);\n\tREGISTER_CHANNEL(\"usb15\",  PCAN_USBBUS16);\n\n}\n\nPeakCanChannels::~PeakCanChannels() {\n}\n\nChannel PeakCanChannels::getChannel(const std::string& name) const {\n\n\tauto iter = mChannels.find(name);\n\n\tif(iter != mChannels.end()) {\n\t\treturn iter->second;\n\t}\n\n\n\treturn Channel();\n\n}\n\n} /* namespace PeakCan */\n} /* namespace Can */\n"
  },
  {
    "path": "CAN/Backends/PeakCan/PeakCanHelper.cpp",
    "content": "/*\n * CanHelper.cpp\n *\n *  Created on: Sep 28, 2017\n *      Author: famez\n */\n\n#include <Backends/PeakCan/PeakCanHelper.h>\n#include <Backends/PeakCan/PeakCanSymbols.h>\n#include <Backends/PeakCan/PeakCanChannels.h>\n#include <Backends/PeakCan/PeakCanSender.h>\n#include <Backends/PeakCan/PeakCanReceiver.h>\n\n\n\nstruct BitrateItem\n{\n\tu32 bitrate;\n\tTPCANBaudrate code;\n};\n\nstatic const BitrateItem bitratetable[] = {\n\t{ 5000, PCAN_BAUD_5K },\n\t{ 10000, PCAN_BAUD_10K },\n\t{ 20000, PCAN_BAUD_20K },\n\t{ 33000, PCAN_BAUD_33K },\n\t{ 47000, PCAN_BAUD_47K },\n\t{ 50000, PCAN_BAUD_50K },\n\t{ 83000, PCAN_BAUD_83K },\n\t{ 95000, PCAN_BAUD_95K },\n\t{ 100000, PCAN_BAUD_100K },\n\t{ 125000, PCAN_BAUD_125K },\n\t{ 250000, PCAN_BAUD_250K },\n\t{ 500000, PCAN_BAUD_500K },\n\t{ 800000, PCAN_BAUD_800K },\n\t{ 1000000, PCAN_BAUD_1M }\n};\n\nnamespace Can {\nnamespace PeakCan {\n\nPeakCanHelper::PeakCanHelper() {\n\tif(!PeakCanSymbols::getInstance().areSymbolsLoaded()) {\n\t\tPeakCanSymbols::getInstance().tryLoadSymbols();\n\t}\n}\n\nPeakCanHelper::~PeakCanHelper() {\n}\n\n\nstd::set<std::string> PeakCanHelper::getCanIfaces() {\n\n\tstd::set<std::string> retVal;\n\n\n\tif(PeakCanSymbols::getInstance().getLoadingError() ||\n\t\t\t(!PeakCanSymbols::getInstance().areSymbolsLoaded() && !PeakCanSymbols::getInstance().tryLoadSymbols())) {\n\t\treturn retVal;\t\t//Symbols not available. Cannot keep going...\n\t}\n\n\n\t//Get registered channels\n\n\tstd::map<std::string, Channel> channels = PeakCanChannels::getInstance().getChannels();\n\n\n\tfor(auto channel = channels.begin(); channel != channels.end(); ++channel) {\n\n\t\tint value = 0;\n\n\t\t//Callback to PeakCan library to get the condition of channel\n\t\tTPCANStatus status = PeakCanSymbols::getInstance().CAN_GetValue(channel->second.getIndex(), PCAN_CHANNEL_CONDITION,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t&value, sizeof(value));\n\n\t\tif((status == PCAN_ERROR_OK) && (value & PCAN_CHANNEL_PCANVIEW)) {\t\t//The channel is available or occupied, we add to the set\n\n\t\t\tretVal.insert(channel->second.getName());\n\n\t\t}\n\n\t}\n\n\treturn retVal;\n\n}\n\n\nbool PeakCanHelper::initialize(std::string interface, u32 bitrate) {\n\n\n\tTPCANBaudrate baudrate = 0;\n\tTPCANStatus status;\n\n\n\t//Are symbols already loaded?\n\tif(!PeakCanSymbols::getInstance().areSymbolsLoaded()) {\n\t\treturn false;\n\t}\n\n\t//Have there been any errors?\n\tif(PeakCanSymbols::getInstance().getLoadingError()) {\n\t\treturn false;\n\t}\n\n\n\tfor(unsigned int i = 0; i < (sizeof(bitratetable) / sizeof(BitrateItem)); ++i) {\n\t\tif(bitratetable[i].bitrate == bitrate) {\n\t\t\tbaudrate = bitratetable[i].code;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif(!baudrate) {\t\t//No available baudrate for this number\n\t\treturn false;\n\t}\n\n\n\t//Get the interface\n\tChannel channel = PeakCanChannels::getInstance().getChannel(interface);\n\n\n\tif(channel.getName() != interface) {\t\t//The interface does not exist\n\t\treturn false;\n\t}\n\n\t//Try to initialize the channel\n\tstatus = PeakCanSymbols::getInstance().CAN_Initialize(channel.getIndex(), baudrate, 0, 0, 0);\n\n\tif(status != PCAN_ERROR_OK) {\n\n\t\treturn false;\n\t}\n\n\tmCurrentHandle = channel.getIndex();\n\n\treturn true;\n\n}\n\n\nvoid PeakCanHelper::finalize() {\n\n\t//uninitialize PCAN device...\n\tPeakCanSymbols::getInstance().CAN_Uninitialize(mCurrentHandle);\n\n}\n\nbool PeakCanHelper::initialized() {\n\n\tint value = 0;\n\n\t//Callback to PeakCan library to get the condition of channel\n\tTPCANStatus status = PeakCanSymbols::getInstance().CAN_GetValue(mCurrentHandle, PCAN_CHANNEL_CONDITION,\n\t\t\t\t\t\t\t\t\t\t\t\t\t&value, sizeof(value));\n\n\treturn ((status == PCAN_ERROR_OK) && (value & PCAN_CHANNEL_OCCUPIED));\t//Channel already initialized?\n\n}\n\n\nICanSender* PeakCanHelper::allocateCanSender() {\n\treturn new PeakCanSender(mCurrentHandle);\n}\n\nCommonCanReceiver* PeakCanHelper::allocateCanReceiver() {\n\treturn new PeakCanReceiver(mCurrentHandle);\n}\n\n\n} /* namespace Can */\n} /* namespace Sockets */\n"
  },
  {
    "path": "CAN/Backends/PeakCan/PeakCanReceiver.cpp",
    "content": "/*\n * PeakCanReceiver.cpp\n *\n *  Created on: May 10, 2018\n *      Author: fernado\n */\n\n#include <Backends/PeakCan/PeakCanReceiver.h>\n#include <Backends/PeakCan/PeakCanChannels.h>\n\nusing namespace Utils;\n\n\nnamespace Can {\nnamespace PeakCan {\n\nPeakCanReceiver::PeakCanReceiver(TPCANHandle handle) : mCurrentHandle(handle), mReadFd(-1) {\n\n\tPeakCanSymbols::getInstance().CAN_GetValue(handle, PCAN_RECEIVE_EVENT,\t\t//To obtain the file descriptor to watch for events\n\t\t\t\t\t&mReadFd, sizeof(mReadFd));\n}\n\nPeakCanReceiver::~PeakCanReceiver() {\n}\n\n\nbool PeakCanReceiver::receive(CanFrame& frame, TimeStamp& timestamp) {\n\n\tTPCANMsg message;\n\tTPCANTimestamp tmStamp;\n\n\tTPCANStatus status = PeakCanSymbols::getInstance().CAN_Read(mCurrentHandle, &message, &tmStamp);\n\n\tif (status != PCAN_ERROR_OK || message.LEN > MAX_CAN_DATA_SIZE || (message.MSGTYPE != PCAN_MESSAGE_STANDARD &&\n\t\t\tmessage.MSGTYPE != PCAN_MESSAGE_EXTENDED)) {\n\t\treturn false;\n\t}\n\n\t//Set data\n\tstd::string data;\n\tdata.append((char*)message.DATA, message.LEN);\n\n\tframe = CanFrame(message.MSGTYPE == PCAN_MESSAGE_EXTENDED, message.ID, data);\n\n\ttimestamp = TimeStamp(tmStamp.millis / 1000, (tmStamp.millis % 1000) * 1000 + tmStamp.micros);\n\n\treturn true;\n\n}\n\n\nint PeakCanReceiver::getFD() {\n\n\treturn mReadFd;\n\n}\n\n} /* namespace PeakCan */\n} /* namespace Can */\n"
  },
  {
    "path": "CAN/Backends/PeakCan/PeakCanSender.cpp",
    "content": "/*\n * CanSender.cpp\n *\n *  Created on: Apr 1, 2018\n *      Author: famez\n */\n\n\n#include <unistd.h>\n#include <string.h>\n\n#include <Types.h>\n#include <Utils.h>\n\n#include <Backends/PeakCan/PeakCanSender.h>\n#include <Backends/PeakCan/PeakCanChannels.h>\n\n\n\nnamespace Can {\nnamespace PeakCan {\n\nPeakCanSender::PeakCanSender(TPCANHandle handle) : mCurrentHandle(handle) {\n\n}\n\nPeakCanSender::~PeakCanSender() {\n}\n\nvoid PeakCanSender::_sendFrame(const CanFrame& frame) const {\n\n\tTPCANStatus status;\n\n\tTPCANMsg frameToSend;\n\n\n\t//Copy the frame\n\tframeToSend.MSGTYPE = (frame.isExtendedFormat() ? PCAN_MESSAGE_EXTENDED : PCAN_MESSAGE_STANDARD);\n\tframeToSend.ID = frame.getId();\n\tframeToSend.LEN = frame.getData().size();\n\n\tmemcpy(frameToSend.DATA, frame.getData().c_str(), frameToSend.LEN);\n\n\tstatus = PeakCanSymbols::getInstance().CAN_Write(mCurrentHandle, &frameToSend);\n\n\tif(status == PCAN_ERROR_OK) {\n\t\t//OK\n\t} else {\n\t\t//ERROR\n\t}\n\n}\n\n} /* namespace Sockets */\n} /* namespace Can */\n"
  },
  {
    "path": "CAN/Backends/PeakCan/PeakCanSymbols.cpp",
    "content": "/*\n * PeakCanSymbols.cpp\n *\n *  Created on: Apr 3, 2018\n *      Author: famez\n */\n\n#include <dlfcn.h>\n\n\n#include <Backends/PeakCan/PeakCanSymbols.h>\n\nnamespace Can {\nnamespace PeakCan {\n\nbool PeakCanSymbols::tryLoadSymbols() {\n\n\tvoid* handle = dlopen(PEAKCAN_LIB, RTLD_LAZY);\n\n\tif (!handle) {\n\t\tmLoadingError = true;\n\t\tmSymbolsLoaded = false;\n\t\treturn false;\n\t}\n\n\t//Reset errors\n\tdlerror();\n\n\tCAN_Initialize = (CAN_InitializePtr)(dlsym(handle, \"CAN_Initialize\"));\n\tif (dlerror()) goto dll_error;\n\n\tCAN_Uninitialize = (CAN_UninitializePtr)(dlsym(handle, \"CAN_Uninitialize\"));\n\tif (dlerror()) goto dll_error;\n\n\tCAN_Reset = (CAN_ResetPtr)(dlsym(handle, \"CAN_Reset\"));\n\tif (dlerror()) goto dll_error;\n\n\tCAN_Read = (CAN_ReadPtr)(dlsym(handle, \"CAN_Read\"));\n\tif (dlerror()) goto dll_error;\n\n\tCAN_Write = (CAN_WritePtr)(dlsym(handle, \"CAN_Write\"));\n\tif (dlerror()) goto dll_error;\n\n\tCAN_FilterMessages = (CAN_FilterMessagesPtr)(dlsym(handle, \"CAN_FilterMessages\"));\n\tif (dlerror()) goto dll_error;\n\n\tCAN_GetValue = (CAN_GetValuePtr)(dlsym(handle, \"CAN_GetValue\"));\n\tif (dlerror()) goto dll_error;\n\n\tCAN_SetValue = (CAN_SetValuePtr)(dlsym(handle, \"CAN_SetValue\"));\n\tif (dlerror()) goto dll_error;\n\n\tCAN_GetErrorText = (CAN_GetErrorTextPtr)(dlsym(handle, \"CAN_GetErrorText\"));\n\tif (dlerror()) goto dll_error;\n\n\n\n\n\t//Success reading all the symbols\n\tmSymbolsLoaded = true;\n\tmLoadingError = false;\n\n\treturn true;\n\n\n\tdll_error:\n\n\tdlclose(handle);\n\n\tmSymbolsLoaded = false;\n\tmLoadingError = true;\n\n\treturn false;\n\n}\n\n\n} /* namespace PeakCan */\n} /* namespace Can */\n"
  },
  {
    "path": "CAN/Backends/Sockets/SocketCanHelper.cpp",
    "content": "/*\n * CanHelper.cpp\n *\n *  Created on: Sep 28, 2017\n *      Author: famez\n */\n\n#include <unistd.h>\n#include <stdio.h>\n#include <limits.h>\n#include <stdlib.h>\n\n\n#include <net/if.h>\n#include <ifaddrs.h>\n#include <sys/socket.h>\n#include <sys/ioctl.h>\n#include <linux/can.h>\n#include <linux/can/raw.h>\n#include <linux/net_tstamp.h>\n\n#include <string.h>\n\n#include <Backends/Sockets/SocketCanHelper.h>\n#include <Backends/Sockets/SocketCanSender.h>\n#include <Backends/Sockets/SocketCanReceiver.h>\n\n\n#define SYS_CLASS_NET_PATH\t\t\"/sys/class/net/\"\n\n/**\n * System commands to get/configure the interfaces. Much better than handling netlink sockets...\n */\n#define GET_IFACE_STAT_CMD\t\t\"ip link show %s up\"\n#define SET_IFACE_UP_CMD\t\t\"ip link set %s up\"\n#define SET_IFACE_DOWN_CMD\t\t\"ip link set %s down\"\n#define SET_IFACE_BITRATE_CMD\t\"ip link set %s type can bitrate %d\"\n\n\nnamespace Can {\nnamespace Sockets {\n\nSocketCanHelper::SocketCanHelper() {\n\n}\n\nSocketCanHelper::~SocketCanHelper() {\n}\n\nbool SocketCanHelper::isVirtual() const {\n\t\n\tchar resolvedPath[PATH_MAX];\n\t\n\tstd::string path = SYS_CLASS_NET_PATH + mInterface;\n\t\n\trealpath(path.c_str(), resolvedPath);\n\tstd::string realPath = resolvedPath;\n\t\n\treturn realPath.find(\"virtual\") != std::string::npos;\n\t\n}\n\n\nstd::set<std::string> SocketCanHelper::getCanIfaces() {\n\n\tstruct ifaddrs *addrs,*tmp;\n\tint sock;\n\tstruct sockaddr_can addr;\n\n\tmemset(&addr, 0, sizeof(sockaddr_can));\n\n\tstd::set<std::string> retVal;\n\n\tif((sock = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {\n\t\treturn retVal;\n\t}\n\n\tgetifaddrs(&addrs);\n\ttmp = addrs;\n\n\n\t//Iterate over all network interfaces\n\twhile (tmp)\n\t{\n\t\tstruct ifreq ifr;\n\n\t\tstrcpy(ifr.ifr_name, tmp->ifa_name);\n\t\tioctl(sock, SIOCGIFINDEX, &ifr);\n\n\t\taddr.can_family  = AF_CAN;\n\t\taddr.can_ifindex = ifr.ifr_ifindex;\n\n\t\t//Only Can Interfaces will succeed to do a proper bind of an address family of type CAN\n\t\tif(bind(sock, (sockaddr *)&addr, sizeof(addr)) >= 0) {\n\t\t\tretVal.insert(tmp->ifa_name);\n\t\t}\n\n\n\t\ttmp = tmp->ifa_next;\n\t}\n\n\tfreeifaddrs(addrs);\n\n\tclose(sock);\n\n\treturn retVal;\n\n}\n\n\n\nbool SocketCanHelper::isUp() const {\n\t\n\tchar aux[1024];\n\t\n\tsnprintf(aux, 1024, GET_IFACE_STAT_CMD, mInterface.c_str());\n\t\n\tFILE *fp = popen(aux, \"r\");\n\t\n\tif(fp == NULL) {\n\t\treturn false;\n\t}\n\t\n\tif(fgets(aux, sizeof(aux), fp) != NULL) {\t\t//if there is some output, interface up, otherwise, interface down.\n\t\treturn true;\n\t}\n\t\n\treturn false;\n\t\n}\n\n\nbool SocketCanHelper::bringUp() const {\n\t\n\tchar aux[1024];\n\t\t\n\tsnprintf(aux, 1024, SET_IFACE_UP_CMD, mInterface.c_str());\n\t\t\n\tint ret = system(aux);\n\t\t\n\treturn ret == 0;\n\t\n}\n\n\nbool SocketCanHelper::bringDown() const {\n\t\n\tchar aux[1024];\n\t\t\t\n\tsnprintf(aux, 1024, SET_IFACE_DOWN_CMD, mInterface.c_str());\n\t\t\n\tint ret = system(aux);\n\t\t\n\treturn ret == 0;\n\t\n}\n\nbool SocketCanHelper::setBitrate(u32 bitrate) const {\n\tchar aux[1024];\n\t\t\t\n\tsnprintf(aux, 1024, SET_IFACE_BITRATE_CMD, mInterface.c_str(), bitrate);\n\t\t\n\tint ret = system(aux);\n\t\t\n\treturn ret == 0;\n}\n\n\nbool SocketCanHelper::initialize(std::string interface, u32 bitrate) {\n\n\tmInterface = interface;\n\n\tif(!isUp()) {\t\t//Interface is down?\n\t\t\n\t\tif(!isVirtual()) {\t\t//Avoid setting bitrate for virtual interfaces...\n\t\t\tif(!setBitrate(bitrate)) {\n\t\t\t\treturn false;\t//Something went wrong\n\t\t\t}\n\t\t}\n\n\t\t//Bring the interface up\n\t\tif(!bringUp()) {\n\t\t\treturn false;\t//Something went wrong\n\t\t}\n\t}\n\n\n\t//Initialize socket\n\n\tifreq ifr;\n\tsockaddr_can addr;\n\n\tmemset(&ifr, 0, sizeof(ifreq));\n\tmemset(&addr, 0, sizeof(sockaddr_can));\n\n\n\t/* open socket */\n\tmSock = socket(PF_CAN, SOCK_RAW, CAN_RAW);\n\n\tif(mSock < 0)\n\t{\n\t\treturn false;\n\t}\n\n\tconst int timestamp_flags = (SOF_TIMESTAMPING_SOFTWARE | \\\n\t\t\t\t\t\t\t\t\t\tSOF_TIMESTAMPING_RX_SOFTWARE | \\\n\t\t\t\t\t\t\t\t\t\tSOF_TIMESTAMPING_RAW_HARDWARE);\n\n\t//Activate timestamp\n\tif (setsockopt(mSock, SOL_SOCKET, SO_TIMESTAMPING,\n\t\t\t&timestamp_flags, sizeof(timestamp_flags)) < 0) {\n\t\tmTimeStamp = false;\t\t\t//Option not supported by kernel. Timestamp cannot be obtained.\n\t}\n\n\t//Bind to socket to start receiving frames from the specified interface\n\taddr.can_family = AF_CAN;\n\tstrncpy(ifr.ifr_name, interface.c_str(), IFNAMSIZ - 1);\n\n\tif (ioctl(mSock, SIOCGIFINDEX, &ifr) < 0)\n\t{\n\t\tclose(mSock);\n\t\tmSock = -1;\n\t\treturn false;\n\t}\n\n\taddr.can_ifindex = ifr.ifr_ifindex;\n\n\tif (bind(mSock, (struct sockaddr *)&addr, sizeof(addr)) < 0)\n\t{\n\t\tclose(mSock);\n\t\tmSock = -1;\n\t\treturn false;\n\t}\n\n\n\t//Avoid receiving the same frame which is sent in the reception buffer\n\n\tint recvOwnMsg = 0;\n\n\tif(setsockopt(mSock, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &recvOwnMsg, sizeof(recvOwnMsg)) < 0) {\n\t\tclose(mSock);\n\t\tmSock = -1;\n\t\treturn false;\n\t}\n\n\tmInterface = interface;\n\n\treturn true;\n\n}\n\nvoid SocketCanHelper::finalize() {\n\t\n\tif(mSock != -1) {\n\t\tclose(mSock);\n\t\tmSock = -1;\n\t}\n\n\t//Down interface\n\tbringDown();\n\n}\n\nbool SocketCanHelper::initialized() {\n\n\treturn isUp();\t\t\t\t\t\t//If the interface is already up, that means that it has been already initialized by\n\t\t\t\t\t\t\t\t\t\t\t\t//another application or by ourselves\n}\n\n\nICanSender* SocketCanHelper::allocateCanSender() {\n\treturn new SocketCanSender(mSock);\n}\n\nCommonCanReceiver* SocketCanHelper::allocateCanReceiver() {\n\treturn new SocketCanReceiver(mSock, mTimeStamp);\n}\n\n} /* namespace Can */\n} /* namespace Sockets */\n"
  },
  {
    "path": "CAN/Backends/Sockets/SocketCanReceiver.cpp",
    "content": "/*\n * SocketCanReceiver.cpp\n *\n *  Created on: May 10, 2018\n *      Author: fernado\n */\n\n\n#include <stdio.h>\n#include <string.h>\n#include <fcntl.h>\n#include <unistd.h>\n#include <sys/ioctl.h>\n#include <net/if.h>\n#include <linux/can.h>\n#include <linux/can/raw.h>\n#include <linux/net_tstamp.h>\n\n\n#include <Backends/Sockets/SocketCanReceiver.h>\n\nusing namespace Utils;\n\n\nnamespace Can {\nnamespace Sockets {\n\nSocketCanReceiver::SocketCanReceiver(int sock, bool timeStamp) : mSock(sock), mTimeStamp(timeStamp) {\n\n\n\tiov.iov_base = &frame;\n\tmsg.msg_name = &addr;\n\tmsg.msg_iov = &iov;\n\tmsg.msg_iovlen = 1;\n\tmsg.msg_control = &ctrlmsg;\n\n}\n\nSocketCanReceiver::~SocketCanReceiver() {\n}\n\n\nbool SocketCanReceiver::setFilters(std::set<CanFilter> filters) {\n\n\tbool retVal;\n\n\tcan_filter *rfilters, *filterPtr;\n\n\tif(mSock == -1)\t\t\treturn false;\t\t\t\t\t\t\t\t//Socket is not open... nothing todo\n\n\tif(filters.empty())\t\treturn false;\t\t\t\t\t\t\t\t//No filters specified\n\n\tfilterPtr = rfilters = new can_filter[filters.size()]; \t\t\t\t//Allocate filters according to the number of them\n\n\tfor(auto iter = filters.begin(); iter != filters.end(); ++iter) {\n\n\t\tfilterPtr->can_id = iter->getId() & CAN_EFF_MASK;\n\t\tfilterPtr->can_mask = iter->getMask() & CAN_EFF_MASK;\n\n\t\tif(iter->filterStdFrame() == iter->filterExtFrame()) {\t\t\t//If none of them are filtered or both are filtered, remove the extended frame flag from the mask\n\n\t\t\tfilterPtr->can_mask &= ~CAN_EFF_FLAG;\n\n\t\t} else {\n\n\t\t\tfilterPtr->can_mask |= CAN_EFF_FLAG;\t\t\t\t\t\t//Set the flag in the mask to check if it is a standard frame or extended frame\n\n\t\t\tif(iter->filterExtFrame()) {\n\n\t\t\t\tfilterPtr->can_id |= CAN_EFF_FLAG;\t\t\t\t\t\t//If it is extended, we set the EFF flag\n\t\t\t} else {\n\t\t\t\tfilterPtr->can_mask &= CAN_SFF_MASK;\t\t\t\t\t//If it is standard, we set to 0 the unnecessary bits from the id (only 11 bits)\n\t\t\t}\n\n\t\t}\n\n\t\t++filterPtr;\n\n\t}\n\n\tretVal = (setsockopt(mSock, SOL_CAN_RAW, CAN_RAW_FILTER,\n\t\t\trfilters, filters.size() * sizeof(can_filter)) == 0);\n\n\tdelete[] rfilters;\t\t//Deallocate filters\n\n\treturn retVal;\n\n}\n\nbool SocketCanReceiver::receive(CanFrame& canFrame, TimeStamp& timestamp) {\n\n\tcmsghdr *cmsg;\n\tint nbytes;\n\n\tiov.iov_len = sizeof(frame);\n\tmsg.msg_namelen = sizeof(addr);\n\tmsg.msg_controllen = sizeof(ctrlmsg);\n\tmsg.msg_flags = 0;\n\n\n\tnbytes = recvmsg(mSock, &msg, 0);\n\n\tif(nbytes >= 0) {\n\n\t\tif(mTimeStamp) {\t\t\t//Timestamp option is enabled\n\n\t\t\t//Extract timestamp\n\t\t\tfor (cmsg = CMSG_FIRSTHDR(&msg);\n\t\t\t\t cmsg && (cmsg->cmsg_level == SOL_SOCKET);\n\t\t\t\t cmsg = CMSG_NXTHDR(&msg,cmsg)) {\n\t\t\t\tif (cmsg->cmsg_type == SO_TIMESTAMP) {\n\n\t\t\t\t\ttimeval *stamp = (timeval*)(CMSG_DATA(cmsg));\n\n\t\t\t\t\ttimestamp.setMicroSec(stamp->tv_usec);\n\t\t\t\t\ttimestamp.setSeconds(stamp->tv_sec);\n\n\t\t\t\t} else if (cmsg->cmsg_type == SO_TIMESTAMPING) {\n\n\t\t\t\t\ttimespec *stamp = (struct timespec *)CMSG_DATA(cmsg);\n\n\t\t\t\t\t//Take timestamp from software\n\n\t\t\t\t\ttimestamp.setSeconds(stamp[0].tv_sec);\n\t\t\t\t\ttimestamp.setMicroSec(stamp[0].tv_nsec/1000);\n\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\n\n\t\t//Copy Frame\n\t\tcanFrame.setExtendedFormat(frame.can_id & CAN_EFF_FLAG);\n\t\tcanFrame.setId(frame.can_id & ~CAN_EFF_FLAG);\n\n\t\tstd::string data;\n\t\tdata.append((char*)(frame.data), frame.len);\n\n\n\t\tcanFrame.setData(data);\n\n\n\t}\n\n\treturn true;\n\n}\n\n\nint SocketCanReceiver::getFD() {\n\n\treturn mSock;\n\n}\n\n} /* namespace Sockets */\n} /* namespace Can */\n"
  },
  {
    "path": "CAN/Backends/Sockets/SocketCanSender.cpp",
    "content": "/*\n * CanSender.cpp\n *\n *  Created on: Apr 1, 2018\n *      Author: famez\n */\n\n\n\n#include <stdio.h>\n#include <string.h>\n#include <fcntl.h>\n#include <unistd.h>\n#include <sys/ioctl.h>\n#include <net/if.h>\n#include <linux/can.h>\n#include <linux/can/raw.h>\n\n#include <Utils.h>\n\n#include <Backends/Sockets/SocketCanSender.h>\n\nnamespace Can {\nnamespace Sockets {\n\nSocketCanSender::SocketCanSender(int sock) : mSock(sock) {\n\n}\n\nSocketCanSender::~SocketCanSender() {\n\tfinalize();\n}\n\nvoid SocketCanSender::_sendFrame(const CanFrame& frame) const {\n\n\tint retval;\n\n\tcan_frame frameToSend;\n\tmemset(&frameToSend, 0, sizeof(can_frame));\n\n\tframeToSend.can_id = frame.getId();\n\tframeToSend.can_id |= (frame.isExtendedFormat() ? CAN_EFF_FLAG : 0);\n\tframeToSend.can_dlc = frame.getData().size();\n\n\tmemcpy(frameToSend.data, frame.getData().c_str(), frameToSend.can_dlc);\n\n\tretval = write(mSock, &frameToSend, sizeof(struct can_frame));\n\tif (retval != sizeof(struct can_frame))\n\t{\n\t\tprintf(\"[SocketCanSender::_sendFrame] retval: %d, error: %s\\n\", retval, strerror(errno));\n\t}\n\n}\n\n} /* namespace Sockets */\n} /* namespace Can */\n"
  },
  {
    "path": "CAN/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.5)\n\nproject(Can)\n\nadd_library(Can SHARED \n    \t./CanFrame.cpp\n\t./TRCWriter.cpp\n\t./CanSniffer.cpp\n\t./Backends/Sockets/SocketCanReceiver.cpp\n\t./Backends/Sockets/SocketCanHelper.cpp\n\t./Backends/Sockets/SocketCanSender.cpp\n\t./Backends/PeakCan/PeakCanChannels.cpp\n\t./Backends/PeakCan/PeakCanReceiver.cpp\n\t./Backends/PeakCan/PeakCanSender.cpp\n\t./Backends/PeakCan/PeakCanHelper.cpp\n\t./Backends/PeakCan/PeakCanSymbols.cpp\n\t./TRCReader.cpp\n\t./CommonCanSender.cpp\n\t./ICanHelper.cpp\n\t./CommonCanReceiver.cpp\n\t./CanEasy.cpp\n)\n\ntarget_include_directories(Can\n    PUBLIC \n        include ${Common_SOURCE_DIR}/include\n)\n\ntarget_link_libraries(Can\n    PUBLIC\n        Common pthread dl\n)\n\n\ninstall (TARGETS Can\n    LIBRARY DESTINATION lib)\n\ninstall(DIRECTORY include/ \n    DESTINATION include)\n"
  },
  {
    "path": "CAN/CanEasy.cpp",
    "content": "/*\n * CanEasy.cpp\n *\n *  Created on: Jan 13, 2019\n *      Author: famez\n */\n\n#include <CanEasy.h>\n\nnamespace Can {\n\nstd::map<std::string, std::shared_ptr<ICanSender> > CanEasy::mSenders;\nCanSniffer CanEasy::mSniffer;\nstd::set<std::string> CanEasy::mInitializedIfaces;\n\n\nvoid CanEasy::initialize(u32 bitrate, OnReceiveFramePtr recvCB, OnTimeoutPtr timeoutCB) {\n\n\t//Initialize can\n\tconst std::map<std::string/*Interface*/, ICanHelper*>& canHelpers = ICanHelper::createCanHelpers(bitrate);\n\n\tmSniffer.setOnRecv(recvCB);\n\tmSniffer.setOnTimeout(timeoutCB);\n\n\tfor(auto iter = canHelpers.begin(); iter != canHelpers.end(); ++iter) {\n\n\t\tICanSender* sender = iter->second->allocateCanSender();\n\t\tmSenders[iter->first] = std::shared_ptr<ICanSender>(sender);\n\n\t\tCommonCanReceiver* receiver = iter->second->allocateCanReceiver();\n\t\treceiver->setInterface(iter->first);\n\t\tmSniffer.addReceiver(receiver);\n\n\t\tmInitializedIfaces.insert(iter->first);\n\n\t}\n\n}\n\nvoid CanEasy::initialize(u32 bitrate) {\n\n\tstd::set<std::string> initializedIfaces;\n\t//Initialize can\n\tconst std::map<std::string/*Interface*/, ICanHelper*>& canHelpers = ICanHelper::createCanHelpers(bitrate);\n\n\tfor(auto iter = canHelpers.begin(); iter != canHelpers.end(); ++iter) {\n\n\t\tICanSender* sender = iter->second->allocateCanSender();\n\t\tmSenders[iter->first] = std::shared_ptr<ICanSender>(sender);\n\n\t\tmInitializedIfaces.insert(iter->first);\n\n\t}\n\n\n}\n\nstd::set<std::string> CanEasy::getCanIfaces() {\n\n\treturn ICanHelper::getInterfaces();\n\n}\n\nstd::shared_ptr<ICanSender> CanEasy::getSender(const std::string& interface) {\n\n\tauto iter = mSenders.find(interface);\n\n\tif(iter != mSenders.end()) {\n\t\treturn iter->second;\n\t}\n\n\treturn nullptr;\n\n}\n\nvoid CanEasy::finalize() {\n\n\t//Auto pointers will free the senders\n\tmSenders.clear();\n\n\t//Free the helpers\n\tICanHelper::deallocateCanHelpers();\n\n}\n\n\n} /* namespace Can */\n"
  },
  {
    "path": "CAN/CanFrame.cpp",
    "content": "/*\n * CanFrame.cpp\n *\n *  Created on: Oct 15, 2017\n *      Author: famez\n */\n\n#include <sstream>\n#include <iomanip>\n\n#include \"CanFrame.h\"\n\nnamespace Can {\n\nCanFrame::CanFrame() : mId (0) {\n\n}\n\nCanFrame::~CanFrame() {\n}\n\nstd::string CanFrame::hexDump() const {\n\t\n\tstd::stringstream sstr;\n\n\tfor(auto c = mData.begin(); c != mData.end(); ++c) {\n\t\tsstr << std::setfill('0') << std::setw(2) << std::hex << (static_cast<u32>(*c) & 0xFF) << \" \";\n\t}\n\t\n\treturn sstr.str();\n\t\n}\n\n\n} /* namespace Can */\n"
  },
  {
    "path": "CAN/CanSniffer.cpp",
    "content": "/*\n * CanSniffer.cpp\n *\n *  Created on: Jun 5, 2018\n *      Author: fernado\n */\n\n#include <CanSniffer.h>\n#include <Assert.h>\n\nusing namespace Utils;\n\nnamespace Can {\n\nCanSniffer::CanSniffer(OnReceiveFramePtr recvCB, OnTimeoutPtr timeoutCB, void* data) : mRcvCB(recvCB), mTimeoutCB(timeoutCB), mData(data) {\n\n}\n\nCanSniffer::~CanSniffer() {\n\n\tfor(auto receiver = mReceivers.begin(); receiver != mReceivers.end(); ++receiver) {\n\t\tdelete *receiver;\n\t}\n\n}\n\nvoid CanSniffer::setFilters(std::set<CanFilter> filters) {\n\n\tfor(auto receiver = mReceivers.begin(); receiver != mReceivers.end(); ++receiver) {\n\t\t(*receiver)->setFilters(filters);\n\t}\n\n}\n\n\nvoid CanSniffer::sniff(u32 timeout) const {\n\n\tint result;\n\tfd_set rdfs;\n\ttimeval tv;\n\n\tCanFrame canFrame;\n\tTimeStamp timestamp;\n\n\tASSERT(!mReceivers.empty());\n\tASSERT(mRcvCB != nullptr);\n\tASSERT(mTimeoutCB != nullptr);\n\n\tdo {\n\n\t\ttv.tv_sec = timeout / 1000;\n\t\ttv.tv_usec = (timeout % 1000) / 1000000;\n\n\t\tdo {\n\n\t\t\tint maxFd = -1;\n\t\t\tFD_ZERO(&rdfs);\n\t\t\tfor(auto receiver = mReceivers.begin(); receiver != mReceivers.end(); ++receiver) {\n\n\t\t\t\tif((*receiver)->getFD() > maxFd){\n\t\t\t\t\tmaxFd = (*receiver)->getFD();\n\t\t\t\t}\n\n\t\t\t\tFD_SET((*receiver)->getFD(), &rdfs);\n\t\t\t}\n\n\t\t\tif(maxFd == -1)\t\treturn;\n\n\t\t\tresult = select(maxFd + 1, &rdfs, NULL, NULL, &tv);\n\n\t\t} while (result == -1 && errno == EINTR);\n\n\t\tif (result > 0) {\n\n\t\t\tfor(auto receiver = mReceivers.begin(); receiver != mReceivers.end(); ++receiver) {\n\t\t\t\tif (FD_ISSET((*receiver)->getFD(), &rdfs)) {\t\t//Frame available from interface\n\n\n\t\t\t\t\tif((*receiver)->receive(canFrame, timestamp) && (*receiver)->filter(canFrame.getId())) {\n\n\t\t\t\t\t\t(mRcvCB)(canFrame, timestamp, (*receiver)->getInterface(), mData);\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else if (result == 0) {\t\t//Timeout expired\n\t\t\t(mTimeoutCB)();\n\t\t}\n\n\t} while (mRunning);\n\n\n\n}\n\n\n} /* namespace Can */\n"
  },
  {
    "path": "CAN/CommonCanReceiver.cpp",
    "content": "#include <CommonCanReceiver.h>\n\n\nnamespace Can {\n\nbool CommonCanReceiver::setInterface(const std::string& interface) {\n\n\tmInterface = interface;\n\n\treturn true;\n\n}\n\nbool CommonCanReceiver::setFilters(std::set<CanFilter> filters) {\n\n\tmFilters = filters;\n\n\treturn true;\n\n}\n\n\nbool CommonCanReceiver::filter(u32 id) {\n\n\tbool filtered = false;\n\n\tif(mFilters.empty())\treturn true;\t\t//If no filters set, send everything\n\n\tfor(auto filter = mFilters.begin(); filter != mFilters.end(); ++filter) {\n\t\tif((filter->getId() & filter->getMask()) == (id & filter->getMask())) {\n\t\t\tfiltered = true;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn filtered;\n\n}\n\n}\n"
  },
  {
    "path": "CAN/CommonCanSender.cpp",
    "content": "/*\n * CommonCanSender.cpp\n *\n *  Created on: Apr 1, 2018\n *      Author: famez\n */\n\n#include <unistd.h>\n\n#include <Utils.h>\n\n#include \"CommonCanSender.h\"\n\nnamespace Can {\n\nvoid CommonCanSender::CanFrameRing::setFrames(const std::vector<CanFrame>& frames) {\n\n\tmFrames = frames;\n\n\tmCurrentpos = 0;\n\n}\n\nvoid CommonCanSender::CanFrameRing::pushFrame(const CanFrame& frame) {\n\n\tmFrames.push_back(frame);\n\tmCurrentpos = 0;\n\n}\n\nvoid CommonCanSender::CanFrameRing::shift() {\n\n\tif(mCurrentpos == mFrames.size())\t\treturn;\n\n\tif(++mCurrentpos == mFrames.size())\t\tmCurrentpos = 0;\n\n}\n\nu32 CommonCanSender::CanFrameRing::getCurrentPeriod() const {\n\n\tif(mFrames.empty())\t\t\t\treturn 0;\n\n\tu32 period;\n\n\t//Little algorithm to compensate the loss of accuracy when dividing the period by the number of frames\n\tif(mCurrentpos + 1 == mFrames.size()) {\t\t\t//Last frame. The period is slightly different to compensate the loss of the decimal part for the other frames which is accumulated\n\t\tperiod = mPeriod - (mPeriod  / mFrames.size()) * (mFrames.size() - 1);\n\t} else {\t\t\t\t\t\t\t\t\t\t//Any other frame.\n\t\tperiod = mPeriod / mFrames.size();\n\t}\n\n\treturn period;\n}\n\nCommonCanSender::CommonCanSender() : mFinished(false) {\n\tinitialize();\n}\n\nCommonCanSender::~CommonCanSender() {\n\tfinalize();\n}\n\nbool CommonCanSender::initialize() {\n\n\tmThread = std::unique_ptr<std::thread>(new std::thread(&CommonCanSender::run, this));\t\t\t//Initialize the thread in charge of sending the frames\n\n\treturn true;\n\n}\n\nbool CommonCanSender::finalize() {\n\n\tif(mFinished) return false;\t\t//Already finalized\n\n\tmFinished = true;\t\t//This makes the thread finish\n\n\tmThread->join();\t\t\t\t\t//Wait for thread to finish doing proper cleaning and claim resources\n\n\treturn true;\n}\n\nbool CommonCanSender::sendFrame(CanFrame frame, u32 period, OnSendCallback callback) {\n\n\tstd::vector<CanFrame> frames;\n\tframes.push_back(frame);\n\n\tsendFrames(frames, period, callback);\n\n\treturn true;\n\n}\n\nbool CommonCanSender::sendFrames(std::vector<CanFrame> frames, u32 period, OnSendCallback callback) {\n\n\n\tif(frames.empty())\treturn false;\n\n\tCanFrameRing ring(period, callback);\n\n\tring.setFrames(frames);\n\n\t//Check if a frame with the same id is being sent\n\tauto found = mFrameRings.end();\n\n\t//The access is concurrent but only for reading, not necessary to lock the mutex.\n\tfor(auto iter = mFrameRings.begin(); iter != mFrameRings.end(); ++iter) {\n\t\tif(iter->getFrames().size() != ring.getFrames().size())\t\tcontinue;\n\n\t\tfound = iter;\n\n\t\tfor(auto iter2 = iter->getFrames().begin(); iter2 != iter->getFrames().end(); ++iter2) {\n\t\t\tif(iter2->getId() != (ring.getFrames())[iter2 - iter->getFrames().begin()].getId()) {\n\t\t\t\tfound = mFrameRings.end();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif(found != mFrameRings.end()) \tbreak;\n\n\t}\n\n\t//To modify, lock the mutex\n\tmFramesLock.lock();\n\n\tif(found != mFrameRings.end()) {\n\t\tmFrameRings.erase(found);\n\t}\n\n\tmFrameRings.push_back(ring);\n\n\tmFramesLock.unlock();\n\n\treturn true;\n\n}\n\n\nvoid CommonCanSender::unSendFrame(u32 id) {\n\n\tstd::vector<u32> ids;\n\tids.push_back(id);\n\n\tunSendFrames(ids);\n\n\n}\n\nvoid CommonCanSender::run() {\n\n\ttimespec now, current;\n\tu32 elapsed;\n\n\twhile(!mFinished) {\n\n\t\tclock_gettime(CLOCK_MONOTONIC, &now);\n\n\t\tmFramesLock.lock();\n\n\t\tfor(auto ring = mFrameRings.begin(); ring != mFrameRings.end(); ++ring) {\n\n\t\t\ttimespec start = ring->getTxTimestamp();\n\n\t\t\telapsed = abs(Utils::getElapsedMillis(&start, &now));\n\n\t\t\tif((start.tv_nsec == 0 && start.tv_sec == 0) || (elapsed >= ring->getCurrentPeriod())) {\n\n\t\t\t\tCanFrame& toSend = ring->getCurrentFrame();\n\t\t\t\tif(ring->getCallback()) {\n\t\t\t\t\tstd::string data;\n\t\t\t\t\tring->getCallback()(toSend.getId(), data);\n\t\t\t\t\ttoSend.setData(data);\n\t\t\t\t}\n\n\t\t\t\t_sendFrame(toSend);\t\t//Backend in charge of sending the frame\n\t\t\t\tring->shift();\t\t//Move to the next frame\n\n\t\t\t\tcurrent = Utils::addMillis(&start, ring->getCurrentPeriod());\t\t//Calculate the time in which the frame should have been sent\n\n\t\t\t\telapsed = abs(Utils::getElapsedMillis(&current, &now));\t\n\n\t\t\t\t//Does the calculated time (current) differ from the current one (now) more than the period?\n\n\t\t\t\tif(elapsed < ring->getCurrentPeriod()) {\t\t\n\t\t\t\t\tring->setTxTimestamp(current);\t\t//If not, the calculated time will be the timestamp\n\t\t\t\t} else {\n\t\t\t\t\tring->setTxTimestamp(now);\t\t//If so, the current time will be the timestamp\n\t\t\t\t}\n\n\t\t\t}\n\t\t}\n\n\t\tmFramesLock.unlock();\n\n\t\tusleep(1000);\n\t}\n\n\n}\n\nvoid CommonCanSender::unSendFrames(const std::vector<u32>& ids) {\n\n\t//Check if a frame with the same id is being sent\n\tauto found = mFrameRings.end();\n\n\t//The access is concurrent but only for reading, not necessary to lock the mutex.\n\tfor(auto iter = mFrameRings.begin(); iter != mFrameRings.end(); ++iter) {\n\t\tif(iter->getFrames().size() != ids.size())\t\tcontinue;\n\n\t\t\tfound = iter;\n\n\t\t\tfor(auto iter2 = iter->getFrames().begin(); iter2 != iter->getFrames().end(); ++iter2) {\n\t\t\t\tif(iter2->getId() != ids[iter2 - iter->getFrames().begin()]) {\n\t\t\t\t\tfound = mFrameRings.end();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(found != mFrameRings.end()) \tbreak;\n\t}\n\n\t//To modify, lock the mutex\n\tmFramesLock.lock();\n\n\tif(found != mFrameRings.end()) {\n\t\tmFrameRings.erase(found);\n\t}\n\n\tmFramesLock.unlock();\n\n}\n\nbool CommonCanSender::isSent(const std::vector<u32>& ids) {\n\n\tbool found = false;\n\n\tfor(auto iter = mFrameRings.begin(); iter != mFrameRings.end(); ++iter) {\n\t\tif(iter->getFrames().size() != ids.size())\t\tcontinue;\n\n\t\tfound = true;\n\n\t\tfor(auto iter2 = iter->getFrames().begin(); iter2 != iter->getFrames().end(); ++iter2) {\n\t\t\tif(iter2->getId() != ids[iter2 - iter->getFrames().begin()]) {\n\t\t\t\tfound = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif(found)\t\treturn true;\n\t}\n\n\treturn false;\n\n}\n\nbool CommonCanSender::isSent(u32 id) {\n\n\tstd::vector<u32> ids;\n\tids.push_back(id);\n\n\treturn isSent(ids);\n\n}\n\n} /* namespace Can */\n"
  },
  {
    "path": "CAN/ICanHelper.cpp",
    "content": "/*\n * ICanHelper.cpp\n *\n *  Created on: Apr 19, 2018\n *      Author: famez\n */\n\n#include <ICanHelper.h>\n\n#include <Backends/PeakCan/PeakCanHelper.h>\n#include <Backends/Sockets/SocketCanHelper.h>\n\nnamespace Can {\n\nstd::map<std::string/*Interface*/, ICanHelper*> ICanHelper::mHelpers;\n\nconst std::map<std::string/*Interface*/, ICanHelper*>& ICanHelper::createCanHelpers(u32 bitrate) {\n\n\tif(mHelpers.empty()) {\n\n\t\tstd::set<std::string> socketCanIfaces = Sockets::SocketCanHelper::getCanIfaces();\n\n\t\tfor(auto iter = socketCanIfaces.begin(); iter != socketCanIfaces.end(); ++iter) {\n\n\t\t\tICanHelper* canHelper = new Sockets::SocketCanHelper;\n\n\t\t\tif(canHelper->initialize(*iter, bitrate)) {\n\t\t\t\tmHelpers[*iter] = canHelper;\n\t\t\t} else {\n\t\t\t\tdelete canHelper;\n\t\t\t}\n\n\n\t\t}\n\n\t\tstd::set<std::string> peakCanIfaces = PeakCan::PeakCanHelper::getCanIfaces();\n\n\t\tfor(auto iter = peakCanIfaces.begin(); iter != peakCanIfaces.end(); ++iter) {\n\n\t\t\tICanHelper* canHelper = new PeakCan::PeakCanHelper;\n\n\t\t\tif(canHelper->initialize(*iter, bitrate)) {\n\t\t\t\tmHelpers[*iter] = canHelper;\n\t\t\t} else {\n\t\t\t\tdelete canHelper;\n\t\t\t}\n\t\t}\n\n\t}\n\n\treturn mHelpers;\n\n}\n\nvoid ICanHelper::deallocateCanHelpers() {\n\n\tfor(auto iter = mHelpers.begin(); iter != mHelpers.end(); ++iter) {\n\t\titer->second->finalize();\n\t\tdelete iter->second;\n\t}\n\n\tmHelpers.clear();\n\n}\n\nstd::set<std::string> ICanHelper::getInterfaces() {\n\n\tstd::set<std::string> retVal;\n\n\tstd::set<std::string> socketCanIfaces = Sockets::SocketCanHelper::getCanIfaces();\n\n\tretVal.insert(socketCanIfaces.begin(), socketCanIfaces.end());\n\n\tstd::set<std::string> peakCanIfaces = PeakCan::PeakCanHelper::getCanIfaces();\n\n\tretVal.insert(peakCanIfaces.begin(), peakCanIfaces.end());\n\n\treturn retVal;\n\n}\n\n\n}\n"
  },
  {
    "path": "CAN/README.md",
    "content": "# Developing with libCAN\n\n## Sending frames\n\n```c++\n\n#include <CanEasy.h>\nusing namespace Can;\n\nvoid main() {\n\n\t//Initialize Can\n\tCanEasy::initialize(250000/*J1939 Baudrate*/);\n\n\t//Get available interfaces\n\tstd::set<std::string> interfaces = CanEasy::getCanIfaces();\n\n\t//Check whether the interface \"can0\" exists\n\tif(interfaces.find(\"can0\") == interfaces.end())\t\texit(1);\t\t//No can0 interface\n\n\t//Get sender from the interface we are insterested in.\n\tstd::shared_ptr<ICanSender> sender = CanEasy::getSender(\"can0\");\t\t\n\n\tif(!sender)\t\texit(2);\t\t//If can0 not available or it does not exist, sender is equals to nullPtr.\n\n\n\t//Create frame.\n\n\tchar raw[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};\n\n\tstd::string data;\n\n\tdata.append(raw, sizeof(raw));\n\n\tu32 id = 0xAD45FD2A;\n\n\tCanFrame frame(true/*Extended format*/, id, data);\n\n\n\t////Send frames\n\n\t//First method. Send frame once.\n\n\tsender->sendFrameOnce(canFrame);\n\n\t//Second method. Send frame periodically (period: 500 ms)\n\n\tsender->sendFrame(canFrame, 500/*Period*/);\n\n\t//Stop sending frames \n\n\tsender->unSendFrame(id);\n\n\t//Third method. Send frame periodically (period: 200 ms), with dynamic modifications (callback called every time the frame is about to be sent).\n\n\tsender->sendFrame(canFrame, 200/*Period*/, [](u32 id, std::string& data) {\t\n\n\t\tchar raw[] = {0x01, 0x23, 0x45};\n\t\t\n\t\t//Set data\n\t\tdata.append(raw, sizeof(raw));\n\n\t});\n\n}\n\n```\n\n\n## Sniffing frames\n\n```c++\n\n#include <CanEasy.h>\nusing namespace Can;\n\n//Callbacks.\n\n//Called when frames are received \nvoid onRcv(const Can::CanFrame& frame, const TimeStamp&, const std::string& interface, void*);\n\n//Called when nothing is received within a given timeout\nbool onTimeout();\n\nvoid main() {\n\n\t//Initialize Can. Pass the callbacks as arguments.\n\tCanEasy::initialize(250000/*J1939 Baudrate*/, onRcv/*Called when frame received*/, onTimeout);\n\n\n\t//Sniffer class\n\tCanSniffer& sniffer = CanEasy::getSniffer();\n\n\tif(sniffer.getNumberOfReceivers() == 0) {\n\n\t\t//No interfaces from where to sniff.\n\t\tstd::cerr << \"No interface available from to sniffer\" << std::endl;\n\t\treturn 8;\n\t}\n\n\t//Blocking call. Loop. Waiting for frames to be received.\n\tsniffer.sniff(1000 /*Timeout in millis*/);\n\t\n}\n\n\n//Implement our callback to handle the received frames.\nvoid onRcv(const Can::CanFrame& frame, const TimeStamp&, const std::string& interface, void*) {\n\n\t//Get id\n\tu32 id = frame.getId();\n\t\n\n\t//Get data\n\tstd::string data = frame.getData();\n\t\n\t//Get format\n\tbool ext = frame.isExtendedFormat();\n\t\n\t...\n\t\n}\n\n```\n\n\n## Adding filters\n\nFilters can be added to out Sniffer object to receive only the frames we are interested in.\n\n```c++\n\n#include <CanEasy.h>\nusing namespace Can;\n\nvoid main() {\n\n\t....\n\n\n\t//Sniffer class\n\tCanSniffer& sniffer = CanEasy::getSniffer();\n\n\tstd::set<CanFilter> filters;\n\t\n\t\n\t//Install filters.\n\tCanFilter filter1(0x12ABCD34, 0x00FFFF00/*Only filter 2nd and 3rd byte from the ID*/, true/*Extended format frames are received*/, false/*Base format frames are filtered*/);\n\tCanFilter filter2(0x148, 0x7FF/*Only filter 1st 11 bits from the ID*/, false/*Extended format frames are filtered*/, true/*Base format frames are received*/);\n\n\tfilters.insert(filter1);\n\n\tfilters.insert(filter2);\n\t\n\tsniffer.setFilters(filters);\n\n\tsniffer.sniff(1000 /*Timeout in millis*/);\n\t\n\t....\n\t\n}\n\n```\n\n### CAN/\nThis static library is in charge of the transmission and reception of CAN frames and provides an abstraction layer to manage the communication through the CAN bus. It provides:\n\n- #### CanFrame\nClass that represents a frame to be sent / received through the CAN interface.\n\n-Two interfaces ICanHelper and ICanSender to be implemented by a lower level layer and provide access to the CAN interfaces and the capability of transmitting frames through a CAN interface.\n\n- #### CAN/Backends/\nProvides the low level implementation of the modules in charge of communicating with the bus CAN. This modules implement ICanHelper and ICanSender.\n- ##### CAN/Backends/SocketCan/\nIs the low level implementation of [SocketCan](https://www.kernel.org/doc/Documentation/networking/can.txt) Stack. It is necessary that linux kernel is compiled with SocketCan networking stack. \n- ##### CAN/Backends/PeakCan/\nIs the low level implementation of Peak Can propietary stack. It is necessary to install the [Peak Can Linux driver](https://www.peak-system.com/fileadmin/media/linux/files/peak-linux-driver-8.5.1.tar.gz) and the [PCAN basic api](http://www.peak-system.com/produktcd/Develop/PC%20interfaces/Linux/PCAN-Basic_API_for_Linux/PCAN_Basic_Linux-4.2.0.tar.gz).\n    \n- #### TRCReader\nClass to read TRC files (only version 1.1). This format is used by the Peak Can programs. See [PEAK CAN TRC File Format ](https://www.peak-system.com/produktcd/Pdf/English/PEAK_CAN_TRC_File_Format.pdf) for detailed infomarion.\n"
  },
  {
    "path": "CAN/TRCReader.cpp",
    "content": "/*\n * TRCReader.cpp\n *\n *  Created on: Oct 24, 2017\n *      Author: root\n */\n\n#include <limits>\n#include <vector>\n\n#include \"TRCReader.h\"\n\n\n#define TABULATION_CHAR\t\t'\\t'\n#define WHITE_SPACE_CHAR\t' '\n#define END_OF_LINE_CHAR\t'\\n'\n#define SEMI_COLON_CHAR\t\t';'\n#define PARENTHESIS_CHAR\t')'\n#define RETURN_CHAR\t\t\t'\\r'\n\n\n#define \tPARSE_STATE_GET_POSITION\t0\n#define\t\tPARSE_STATE_GET_TIME\t\t1\n#define\t\tPARSE_STATE_GET_TYPE\t\t2\n#define\t\tPARSE_STATE_GET_ID\t\t\t3\n#define\t\tPARSE_STATE_GET_LENGTH\t\t4\n#define\t\tPARSE_STATE_GET_DATA\t\t5\n#define\t\tPARSE_STATE_GET_END\t\t\t6\n#define\t\tPARSE_STATE_GET_ERROR\t\t7\n\nnamespace Can {\n\n\nTRCReader::TRCReader() : mCurrentPos (0), mTotalFrames(0) {\n\n}\n\nTRCReader::TRCReader(const std::string& path) : mCurrentPos (0), mTotalFrames(0) {\n\tloadFile(path);\n}\n\n\nTRCReader::~TRCReader() {\n}\n\n\nbool TRCReader::loadFile(const std::string& path) {\n\n\tunloadFile();\n\n\tmFileName = path;\n\n    //It is important to open the file in binary mode, as in text mode,\n    //for gcc compiler in windows, the method tellg() returns incorrect size\n    mFileStream.open(path.c_str(), std::ifstream::in | std::ifstream::binary);\n\n\n\tif(mFileStream.rdstate() & std::ios_base::failbit) {\n\t\tunloadFile();\n\t\treturn false;\n\t}\n\n\tif(!checkIntegrity()) {\n\t\tunloadFile();\n\t\treturn false;\n\t}\n\n\treset();\n\n\treturn true;\n\n}\n\nvoid TRCReader::unloadFile() {\n\n\tif(mFileStream.is_open()) {\n\t\tmFileStream.close();\n\t}\n\n\tmFileName.clear();\n\tmCurrentPos = 0;\n\tmTotalFrames = 0;\n}\n\nvoid TRCReader::reset() {\n\n\tmFileStream.clear();\n\tmFileStream.seekg(0, mFileStream.beg);\n\n\tmCurrentPos = 0;\n\n}\n\nbool TRCReader::seekPosition(size_t pos) {\n\n\tif(!isFileLoaded() || pos >= mTotalFrames ) {\n\t\treturn false;\n\t}\n\n\tif(mCurrentPos == pos) {\n\t\treturn true;\n\t}\n\n\tmFileStream.clear();\n\tmFileStream.seekg(0, mFileStream.beg);\n\n\tmCurrentPos = 0;\n\n\n\tbool error, empty;\n\n\twhile(!mFileStream.eof()) {\n\t\treadNextLine(error, empty);\n\t\tif(error) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif(mCurrentPos == pos) {\n\t\t\treturn true;\n\t\t}\n\n\t}\n\n\treturn false;\n\n}\n\nstd::pair<u64, CanFrame> TRCReader::getLastCanFrame() {\n\n\treturn mLastReadFrameTimePair;\n}\n\n\nvoid TRCReader::readNextLine(bool& error, bool& empty) {\n\n\n\tchar c;\n\t\n\tdouble timeAux;\n\n    u32 position, id, length;\n    u64 time;\n\n\tstd::string type;\n\n\tu32 dataAux;\n\n\tstd::string data;\n\n\n\terror = false;\n\tempty = false;\n\n\tu8 state = PARSE_STATE_GET_POSITION;\n\n\tmLastReadFrameTimePair.first = 0;\n\tmLastReadFrameTimePair.second.clear();\n\n\n\twhile (mFileStream.get(c)) {\n\n\t\tif(c == WHITE_SPACE_CHAR || c == TABULATION_CHAR)\n\t\t\tcontinue;\n\n\t\tif(c == SEMI_COLON_CHAR) {\t\t//Skip until end of line\n\t\t\tmFileStream.ignore(std::numeric_limits<std::streamsize>::max(), END_OF_LINE_CHAR);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif(c == END_OF_LINE_CHAR)\n\t\t\tbreak;\n\n\t\tif(c == RETURN_CHAR) {\n\t\t\tmFileStream.get(c);\n\t\t\tif(c == END_OF_LINE_CHAR) {\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\tstate = PARSE_STATE_GET_ERROR;\n\t\t\t}\n\t\t}\n\n        int pos = mFileStream.tellg();\n\n        pos -= 1;\n\n\t\tmFileStream.seekg(pos);\n\n\n\t\tswitch(state) {\n\t\tcase PARSE_STATE_GET_POSITION:\n\t\t\tmFileStream >> std::dec >> position;\n\t\t\tmFileStream.get(c);\n\n\t\t\tif(c != PARENTHESIS_CHAR)\n\t\t\t\tstate = PARSE_STATE_GET_ERROR;\n\t\t\tbreak;\n\n\t\tcase PARSE_STATE_GET_TIME:\n\n\t\t\tmFileStream >> std::dec >> timeAux;\n\t\t\ttimeAux *= 1000;\n            time = (u64)timeAux;\n\n\t\t\tbreak;\n\n\t\tcase PARSE_STATE_GET_TYPE:\n\t\t\tmFileStream.get(c);\n\t\t\ttype.append(1, c);\n\t\t\tmFileStream.get(c);\n\t\t\ttype.append(1, c);\n\t\t\tbreak;\n\n\t\tcase PARSE_STATE_GET_ID:\n\t\t\tmFileStream >> std::hex >> id;\n\t\t\tbreak;\n\t\tcase PARSE_STATE_GET_LENGTH:\n\t\t\tmFileStream >> length;\n\t\t\tbreak;\n\t\tcase PARSE_STATE_GET_DATA:\n\t\t\tmFileStream >> std::hex >> dataAux;\n\n\t\t\tif(dataAux <= 0xFF) {\n\t\t\t\tdata.push_back((char)dataAux);\n\t\t\t} else {\n\t\t\t\tstate = PARSE_STATE_GET_ERROR;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif(data.size() < length) {\n\t\t\t\t--state;\n\t\t\t}\n\n\t\t\tbreak;\n\t\tcase PARSE_STATE_GET_END:\n\t\tdefault:\n\t\t\tbreak;\n\n\t\t}\n\n\n\t\tif(mFileStream.rdstate() == std::ios_base::failbit || mFileStream.rdstate() == std::ios_base::badbit) {\t\t//If error parsing stream...\n\t\t\tmFileStream.clear();\t//Clear bit state\n\t\t\tmFileStream.ignore(std::numeric_limits<std::streamsize>::max(), END_OF_LINE_CHAR);\t//Just go until end of line\n\t\t\tmFileStream.get(c);\t\t//Get end of line\n\n\t\t\tstate = PARSE_STATE_GET_ERROR;\n\n\t\t}\n\n\t\tif(state == PARSE_STATE_GET_ERROR)\n\t\t{\n\t\t\tbreak;\n\n\t\t}\n\n\n\t\t++state;\n\n\n\t}\n\n\tif(state != PARSE_STATE_GET_END && state != PARSE_STATE_GET_POSITION) {\n\t\terror = true;\n\t\treturn;\n\t}\n\n\tif(state == PARSE_STATE_GET_POSITION) {\n\t\tempty = true;\n\t\treturn;\n\t}\n\n\n\tif(data.size() != length) {\n\t\terror = true;\n\t\treturn;\n\t}\n\n\tmCurrentPos = position - 1;\n\n\n\tCanFrame frame(true, id, data);\n\n\tmLastReadFrameTimePair.first = time;\n\tmLastReadFrameTimePair.second = frame;\n\n\n}\n\nbool TRCReader::checkIntegrity() {\n\n\tbool error, empty;\n\n\twhile(!mFileStream.eof()) {\n\t\treadNextLine(error, empty);\n\t\tif(error) {\n\t\t\treturn false;\n\t\t}\n\n\t}\n\n\tmTotalFrames = mCurrentPos + 1;\n\n\treturn true;\n\n}\n\nvoid TRCReader::readNextCanFrame() {\n\tbool error, empty;\n\tif(!mFileStream.eof()) {\n\t\treadNextLine(error, empty);\n\t}\n}\n\n} /* namespace Can */\n"
  },
  {
    "path": "CAN/TRCWriter.cpp",
    "content": "/*\n * TRCWriter.cpp\n *\n *  Created on: Jun 8, 2018\n *      Author: fernado\n */\n\n#include <iomanip>\n#include <sstream>\n\n#include \"TRCWriter.h\"\n\n#define TRC_FILE_HEADER\t\t\t\";$FILEVERSION=1.1\\n;\\n\"\n\n\nnamespace Can {\n\nTRCWriter::TRCWriter() : mCounter(0) {\n\n}\n\nTRCWriter::TRCWriter(const std::string& file) : mCounter(0) {\n\n\topen(file);\n\n}\n\nTRCWriter::~TRCWriter() {\n\n\n}\n\nvoid TRCWriter::write(const CanFrame& frame, const Utils::TimeStamp& timeStamp) {\n\n\tif(!mFileStream.is_open()) {\t\t//File not open\n\t\tthrow TRCWriteException();\n\t}\n\n\tstd::stringstream sstr;\n\tdouble ts = timeStamp.getSeconds() * 1000 + (double)(timeStamp.getMicroSec()) /1000;\n\n\tsize_t size = frame.getData().length();\n\n\tsstr << ++mCounter << \")\";\n\n\tmFileStream << std::right << std::setw(8) << sstr.str();\n\n\tsstr.str(\"\");\n\tsstr.clear(); // Clear state flags.\n\n\tsstr << std::fixed << std::setprecision(1) << ts;\n\n\tmFileStream << std::right << std::setw(12) << sstr.str();\n\n\tsstr.str(\"\");\n\tsstr.clear(); // Clear state flags.\n\n\tmFileStream << std::right << std::setw(4) << \"Rx\";\n\n\tsstr << std::setfill('0') << std::setw(8) << std::hex << std::uppercase << frame.getId();\n\n\tmFileStream << std::right << std::setw(13) << sstr.str();\n\n\tsstr.str(\"\");\n\tsstr.clear(); // Clear state flags.\n\n\tmFileStream << std::right << std::setw(3) << size;\n\n\tsstr << \"  \";\n\n\tfor(unsigned int i = 0; i < size; ++i) {\n\n\t\tu8 octet = frame.getData()[i];\n\n\t\tsstr << std::setfill('0') << std::setw(2) << std::hex << static_cast<u32>(octet) << \" \";\n\t}\n\n\tmFileStream << sstr.str() << std::endl;\n\n}\n\n\nbool TRCWriter::open(const std::string& file) {\n\n\tclose();\n\n\tmFileStream.open(file.c_str(), std::ifstream::out | std::ifstream::trunc);\n\n\tif(mFileStream.is_open()) {\n\t\tmFileStream << TRC_FILE_HEADER;\n\t}\n\n\treturn mFileStream.is_open();\n}\n\nvoid TRCWriter::close() {\n\n\tmCounter = 0;\n\n\tif(mFileStream.is_open())\n\t\tmFileStream.close();\n\n}\n\n} /* namespace Can */\n"
  },
  {
    "path": "CAN/include/Backends/PeakCan/PeakCanChannels.h",
    "content": "/*\n * PeakCanChannels.h\n *\n *  Created on: Apr 4, 2018\n *      Author: famez\n */\n\n#ifndef BACKENDS_PEAKCAN_PEAKCANCHANNELS_H_\n#define BACKENDS_PEAKCAN_PEAKCANCHANNELS_H_\n\n#include <string>\n#include <map>\n\n#include <Singleton.h>\n\n#include \"PeakCanSymbols.h\"\n\n\n#define REGISTER_CHANNEL(x, y)\t\tmChannels[x] = Channel(x, y)\n\nnamespace Can {\nnamespace PeakCan {\n\n//Class to represent available channels in PeakCan\n\tclass Channel{\n\tprivate:\n\t\tstd::string mName;\n\t    TPCANHandle mIndex;\n\tpublic:\n\t    Channel() : mIndex(0) {}\n\t    Channel(const std::string name, TPCANHandle index) : mName(name), mIndex(index) {}\n\t    ~Channel() {}\n\n\t    const std::string& getName() const { return mName; }\n\t    TPCANHandle getIndex() const { return mIndex; }\n\t};\n\nclass PeakCanChannels : public ISingleton<PeakCanChannels>{\n\tSINGLETON_ACCESS;\nprivate:\n\tPeakCanChannels();\n\tstd::map<std::string, Channel> mChannels;\npublic:\n\tvirtual ~PeakCanChannels();\n\n\tconst std::map<std::string, Channel>& getChannels() const { return mChannels; }\n\n\tChannel getChannel(const std::string& name) const;\n\n\n};\n\n} /* namespace PeakCan */\n} /* namespace Can */\n\n#endif /* BACKENDS_PEAKCAN_PEAKCANCHANNELS_H_ */\n"
  },
  {
    "path": "CAN/include/Backends/PeakCan/PeakCanHelper.h",
    "content": "/*\n * CanHelper.h\n *\n *  Created on: Sep 28, 2017\n *      Author: famez\n */\n\n#ifndef PEAKCANHELPER_H_\n#define PEAKCANHELPER_H_\n\n#include <set>\n#include <string>\n\n#include <ICanHelper.h>\n\n#include <Backends/PeakCan/PeakCanSymbols.h>\n\n\nnamespace Can {\nnamespace PeakCan {\n\nclass PeakCanHelper : public Can::ICanHelper {\nprivate:\n\tTPCANHandle mCurrentHandle;\npublic:\n\tPeakCanHelper();\n\tvirtual ~PeakCanHelper();\n\n\tstatic std::set<std::string> getCanIfaces();\n\n\tstd::string getBackend() override { return \"PeakCan\"; }\n\n\tICanSender* allocateCanSender() override;\n\tCommonCanReceiver* allocateCanReceiver() override;\n\n\tbool initialize(std::string interface, u32 bitrate) override;\n\n\tvoid finalize() override;\n\n\tbool initialized();\n\n};\n\n}\n} /* namespace Can */\n\n\n#endif /* CANHELPER_H_ */\n"
  },
  {
    "path": "CAN/include/Backends/PeakCan/PeakCanReceiver.h",
    "content": "/*\n * PeakCanReceiver.h\n *\n *  Created on: May 10, 2018\n *      Author: fernado\n */\n\n#ifndef BACKENDS_PEAKCAN_PEAKCANRECEIVER_H_\n#define BACKENDS_PEAKCAN_PEAKCANRECEIVER_H_\n\n#include <CommonCanReceiver.h>\n\n#include <Backends/PeakCan/PeakCanSymbols.h>\n\nnamespace Can {\nnamespace PeakCan {\n\nclass PeakCanReceiver : public CommonCanReceiver {\n\nprivate:\n\tTPCANHandle mCurrentHandle;\n\tint mReadFd;\n\npublic:\n\tPeakCanReceiver(TPCANHandle handle);\n\tvirtual ~PeakCanReceiver();\n\n\tint getFD() override;\n\n\tbool receive(CanFrame&, Utils::TimeStamp&) override;\n};\n\n} /* namespace PeakCan */\n} /* namespace Can */\n\n#endif /* BACKENDS_PEAKCAN_PEAKCANRECEIVER_H_ */\n"
  },
  {
    "path": "CAN/include/Backends/PeakCan/PeakCanSender.h",
    "content": "/*\n * CanSender.h\n *\n *  Created on: Apr 1, 2018\n *      Author: famez\n *      Implementation of can sender for the linux sockets layer\n */\n\n#ifndef BACKENDS_SOCKETS_PEAKCANSENDER_H_\n#define BACKENDS_SOCKETS_PEAKCANSENDER_H_\n\n#include <CommonCanSender.h>\n\n#include <Backends/PeakCan/PeakCanSymbols.h>\n\nnamespace Can {\nnamespace PeakCan {\n\n\n\nclass PeakCanSender : public CommonCanSender {\nprivate:\n\tTPCANHandle mCurrentHandle;\nprotected:\n\tvoid _sendFrame(const CanFrame& frame) const override;\npublic:\n\tPeakCanSender(TPCANHandle handle);\n\tvirtual ~PeakCanSender();\n\n};\n\n} /* namespace Sockets */\n} /* namespace Can */\n\n#endif /* BACKENDS_SOCKETS_CANSENDER_H_ */\n"
  },
  {
    "path": "CAN/include/Backends/PeakCan/PeakCanSymbols.h",
    "content": "/*\n * PeakCanSymbols.h\n *\n *  Created on: Apr 3, 2018\n *      Author: famez\n */\n\n#ifndef BACKENDS_PEAKCAN_PEAKCANSYMBOLS_H_\n#define BACKENDS_PEAKCAN_PEAKCANSYMBOLS_H_\n\n#include <Singleton.h>\n#include <Types.h>\n\n\n// Currently defined and supported PCAN channels\n//\n#define PCAN_NONEBUS                 0x00U  // Undefined/default value for a PCAN bus\n\n#define PCAN_ISABUS1                 0x21U  // PCAN-ISA interface, channel 1\n#define PCAN_ISABUS2                 0x22U  // PCAN-ISA interface, channel 2\n#define PCAN_ISABUS3                 0x23U  // PCAN-ISA interface, channel 3\n#define PCAN_ISABUS4                 0x24U  // PCAN-ISA interface, channel 4\n#define PCAN_ISABUS5                 0x25U  // PCAN-ISA interface, channel 5\n#define PCAN_ISABUS6                 0x26U  // PCAN-ISA interface, channel 6\n#define PCAN_ISABUS7                 0x27U  // PCAN-ISA interface, channel 7\n#define PCAN_ISABUS8                 0x28U  // PCAN-ISA interface, channel 8\n\n#define PCAN_DNGBUS1                 0x31U  // PCAN-Dongle/LPT interface, channel 1\n\n#define PCAN_PCIBUS1                 0x41U  // PCAN-PCI interface, channel 1\n#define PCAN_PCIBUS2                 0x42U  // PCAN-PCI interface, channel 2\n#define PCAN_PCIBUS3                 0x43U  // PCAN-PCI interface, channel 3\n#define PCAN_PCIBUS4                 0x44U  // PCAN-PCI interface, channel 4\n#define PCAN_PCIBUS5                 0x45U  // PCAN-PCI interface, channel 5\n#define PCAN_PCIBUS6\t             0x46U  // PCAN-PCI interface, channel 6\n#define PCAN_PCIBUS7\t             0x47U  // PCAN-PCI interface, channel 7\n#define PCAN_PCIBUS8\t             0x48U  // PCAN-PCI interface, channel 8\n#define PCAN_PCIBUS9                 0x409U  // PCAN-PCI interface, channel 9\n#define PCAN_PCIBUS10                0x40AU  // PCAN-PCI interface, channel 10\n#define PCAN_PCIBUS11                0x40BU  // PCAN-PCI interface, channel 11\n#define PCAN_PCIBUS12                0x40CU  // PCAN-PCI interface, channel 12\n#define PCAN_PCIBUS13                0x40DU  // PCAN-PCI interface, channel 13\n#define PCAN_PCIBUS14\t             0x40EU  // PCAN-PCI interface, channel 14\n#define PCAN_PCIBUS15\t             0x40FU  // PCAN-PCI interface, channel 15\n#define PCAN_PCIBUS16\t             0x410U  // PCAN-PCI interface, channel 16\n\n#define PCAN_USBBUS1                 0x51U  // PCAN-USB interface, channel 1\n#define PCAN_USBBUS2                 0x52U  // PCAN-USB interface, channel 2\n#define PCAN_USBBUS3                 0x53U  // PCAN-USB interface, channel 3\n#define PCAN_USBBUS4                 0x54U  // PCAN-USB interface, channel 4\n#define PCAN_USBBUS5                 0x55U  // PCAN-USB interface, channel 5\n#define PCAN_USBBUS6                 0x56U  // PCAN-USB interface, channel 6\n#define PCAN_USBBUS7                 0x57U  // PCAN-USB interface, channel 7\n#define PCAN_USBBUS8                 0x58U  // PCAN-USB interface, channel 8\n#define PCAN_USBBUS9                 0x509U  // PCAN-USB interface, channel 9\n#define PCAN_USBBUS10                0x50AU  // PCAN-USB interface, channel 10\n#define PCAN_USBBUS11                0x50BU  // PCAN-USB interface, channel 11\n#define PCAN_USBBUS12                0x50CU  // PCAN-USB interface, channel 12\n#define PCAN_USBBUS13                0x50DU  // PCAN-USB interface, channel 13\n#define PCAN_USBBUS14                0x50EU  // PCAN-USB interface, channel 14\n#define PCAN_USBBUS15                0x50FU  // PCAN-USB interface, channel 15\n#define PCAN_USBBUS16                0x510U  // PCAN-USB interface, channel 16\n\n#define PCAN_PCCBUS1                 0x61U  // PCAN-PC Card interface, channel 1\n#define PCAN_PCCBUS2                 0x62U  // PCAN-PC Card interface, channel 2\n\n#define PCAN_LANBUS1                 0x801U  // PCAN-LAN interface, channel 1\n#define PCAN_LANBUS2                 0x802U  // PCAN-LAN interface, channel 2\n#define PCAN_LANBUS3                 0x803U  // PCAN-LAN interface, channel 3\n#define PCAN_LANBUS4                 0x804U  // PCAN-LAN interface, channel 4\n#define PCAN_LANBUS5                 0x805U  // PCAN-LAN interface, channel 5\n#define PCAN_LANBUS6                 0x806U  // PCAN-LAN interface, channel 6\n#define PCAN_LANBUS7                 0x807U  // PCAN-LAN interface, channel 7\n#define PCAN_LANBUS8                 0x808U  // PCAN-LAN interface, channel 8\n#define PCAN_LANBUS9                 0x809U  // PCAN-LAN interface, channel 9\n#define PCAN_LANBUS10                0x80AU  // PCAN-LAN interface, channel 10\n#define PCAN_LANBUS11                0x80BU  // PCAN-LAN interface, channel 11\n#define PCAN_LANBUS12                0x80CU  // PCAN-LAN interface, channel 12\n#define PCAN_LANBUS13                0x80DU  // PCAN-LAN interface, channel 13\n#define PCAN_LANBUS14                0x80EU  // PCAN-LAN interface, channel 14\n#define PCAN_LANBUS15                0x80FU  // PCAN-LAN interface, channel 15\n#define PCAN_LANBUS16                0x810U  // PCAN-LAN interface, channel 16\n\n// Represent the PCAN error and status codes\n//\n#define PCAN_ERROR_OK                0x00000U  // No error\n#define PCAN_ERROR_XMTFULL           0x00001U  // Transmit buffer in CAN controller is full\n#define PCAN_ERROR_OVERRUN           0x00002U  // CAN controller was read too late\n#define PCAN_ERROR_BUSLIGHT          0x00004U  // Bus error: an error counter reached the 'light' limit\n#define PCAN_ERROR_BUSHEAVY          0x00008U  // Bus error: an error counter reached the 'heavy' limit\n#define PCAN_ERROR_BUSWARNING        PCAN_ERROR_BUSHEAVY // Bus error: an error counter reached the 'warning' limit\n#define PCAN_ERROR_BUSPASSIVE        0x40000U  // Bus error: the CAN controller is error passive\n#define PCAN_ERROR_BUSOFF            0x00010U  // Bus error: the CAN controller is in bus-off state\n#define PCAN_ERROR_ANYBUSERR         (PCAN_ERROR_BUSWARNING | PCAN_ERROR_BUSLIGHT | PCAN_ERROR_BUSHEAVY | PCAN_ERROR_BUSOFF | PCAN_ERROR_BUSPASSIVE) // Mask for all bus errors\n#define PCAN_ERROR_QRCVEMPTY         0x00020U  // Receive queue is empty\n#define PCAN_ERROR_QOVERRUN          0x00040U  // Receive queue was read too late\n#define PCAN_ERROR_QXMTFULL          0x00080U  // Transmit queue is full\n#define PCAN_ERROR_REGTEST           0x00100U  // Test of the CAN controller hardware registers failed (no hardware found)\n#define PCAN_ERROR_NODRIVER          0x00200U  // Driver not loaded\n#define PCAN_ERROR_HWINUSE           0x00400U  // Hardware already in use by a Net\n#define PCAN_ERROR_NETINUSE          0x00800U  // A Client is already connected to the Net\n#define PCAN_ERROR_ILLHW             0x01400U  // Hardware handle is invalid\n#define PCAN_ERROR_ILLNET            0x01800U  // Net handle is invalid\n#define PCAN_ERROR_ILLCLIENT         0x01C00U  // Client handle is invalid\n#define PCAN_ERROR_ILLHANDLE         (PCAN_ERROR_ILLHW | PCAN_ERROR_ILLNET | PCAN_ERROR_ILLCLIENT)  // Mask for all handle errors\n#define PCAN_ERROR_RESOURCE          0x02000U  // Resource (FIFO, Client, timeout) cannot be created\n#define PCAN_ERROR_ILLPARAMTYPE      0x04000U  // Invalid parameter\n#define PCAN_ERROR_ILLPARAMVAL       0x08000U  // Invalid parameter value\n#define PCAN_ERROR_UNKNOWN           0x10000U  // Unknown error\n#define PCAN_ERROR_ILLDATA           0x20000U  // Invalid data, function, or action\n#define PCAN_ERROR_CAUTION           0x2000000U  // An operation was successfully carried out, however, irregularities were registered\n#define PCAN_ERROR_INITIALIZE        0x4000000U  // Channel is not initialized [Value was changed from 0x40000 to 0x4000000]\n#define PCAN_ERROR_ILLOPERATION      0x8000000U  // Invalid operation [Value was changed from 0x80000 to 0x8000000]\n\n// PCAN devices\n//\n#define PCAN_NONE                    0x00U  // Undefined, unknown or not selected PCAN device value\n#define PCAN_PEAKCAN                 0x01U  // PCAN Non-Plug&Play devices. NOT USED WITHIN PCAN-Basic API\n#define PCAN_ISA                     0x02U  // PCAN-ISA, PCAN-PC/104, and PCAN-PC/104-Plus\n#define PCAN_DNG                     0x03U  // PCAN-Dongle\n#define PCAN_PCI                     0x04U  // PCAN-PCI, PCAN-cPCI, PCAN-miniPCI, and PCAN-PCI Express\n#define PCAN_USB                     0x05U  // PCAN-USB and PCAN-USB Pro\n#define PCAN_PCC                     0x06U  // PCAN-PC Card\n#define PCAN_VIRTUAL                 0x07U  // PCAN Virtual hardware. NOT USED WITHIN PCAN-Basic API\n#define PCAN_LAN                     0x08U  // PCAN Gateway devices\n\n// PCAN parameters\n//\n#define PCAN_DEVICE_NUMBER           0x01U  // PCAN-USB device number parameter\n#define PCAN_5VOLTS_POWER            0x02U  // PCAN-PC Card 5-Volt power parameter\n#define PCAN_RECEIVE_EVENT           0x03U  // PCAN receive event handler parameter\n#define PCAN_MESSAGE_FILTER          0x04U  // PCAN message filter parameter\n#define PCAN_API_VERSION             0x05U  // PCAN-Basic API version parameter\n#define PCAN_CHANNEL_VERSION         0x06U  // PCAN device channel version parameter\n#define PCAN_BUSOFF_AUTORESET        0x07U  // PCAN Reset-On-Busoff parameter\n#define PCAN_LISTEN_ONLY             0x08U  // PCAN Listen-Only parameter\n#define PCAN_LOG_LOCATION            0x09U  // Directory path for log files\n#define PCAN_LOG_STATUS              0x0AU  // Debug-Log activation status\n#define PCAN_LOG_CONFIGURE           0x0BU  // Configuration of the debugged information (LOG_FUNCTION_***)\n#define PCAN_LOG_TEXT                0x0CU  // Custom insertion of text into the log file\n#define PCAN_CHANNEL_CONDITION       0x0DU  // Availability status of a PCAN-Channel\n#define PCAN_HARDWARE_NAME           0x0EU  // PCAN hardware name parameter\n#define PCAN_RECEIVE_STATUS          0x0FU  // Message reception status of a PCAN-Channel\n#define PCAN_CONTROLLER_NUMBER       0x10U  // CAN-Controller number of a PCAN-Channel\n#define PCAN_TRACE_LOCATION          0x11U  // Directory path for PCAN trace files\n#define PCAN_TRACE_STATUS            0x12U  // CAN tracing activation status\n#define PCAN_TRACE_SIZE              0x13U  // Configuration of the maximum file size of a CAN trace\n#define PCAN_TRACE_CONFIGURE         0x14U  // Configuration of the trace file storing mode (TRACE_FILE_***)\n#define PCAN_CHANNEL_IDENTIFYING     0x15U  // Physical identification of a USB based PCAN-Channel by blinking its associated LED\n#define PCAN_CHANNEL_FEATURES        0x16U  // Capabilities of a PCAN device (FEATURE_***)\n#define PCAN_BITRATE_ADAPTING        0x17U  // Using of an existing bit rate (PCAN-View connected to a channel)\n#define PCAN_BITRATE_INFO            0x18U  // Configured bit rate as Btr0Btr1 value\n#define PCAN_BITRATE_INFO_FD         0x19U  // Configured bit rate as TPCANBitrateFD string\n#define PCAN_BUSSPEED_NOMINAL        0x1AU  // Configured nominal CAN Bus speed as Bits per seconds\n#define PCAN_BUSSPEED_DATA           0x1BU  // Configured CAN data speed as Bits per seconds\n#define PCAN_IP_ADDRESS              0x1CU  // Remote address of a LAN channel as string in IPv4 format\n#define PCAN_LAN_SERVICE_STATUS      0x1DU  // Status of the Virtual PCAN-Gateway Service\n#define PCAN_ALLOW_STATUS_FRAMES     0x1EU  // Status messages reception status within a PCAN-Channel\n#define PCAN_ALLOW_RTR_FRAMES        0x1FU  // RTR messages reception status within a PCAN-Channel\n#define PCAN_ALLOW_ERROR_FRAMES      0x20U  // Error messages reception status within a PCAN-Channel\n#define PCAN_INTERFRAME_DELAY        0x21U  // Delay, in microseconds, between sending frames\n#define PCAN_ACCEPTANCE_FILTER_11BIT 0x22U  // Filter over code and mask patterns for 11-Bit messages\n#define PCAN_ACCEPTANCE_FILTER_29BIT 0x23U  // Filter over code and mask patterns for 29-Bit messages\n\n// PCAN parameter values\n//\n#define PCAN_PARAMETER_OFF           0x00U  // The PCAN parameter is not set (inactive)\n#define PCAN_PARAMETER_ON            0x01U  // The PCAN parameter is set (active)\n#define PCAN_FILTER_CLOSE            0x00U  // The PCAN filter is closed. No messages will be received\n#define PCAN_FILTER_OPEN             0x01U  // The PCAN filter is fully opened. All messages will be received\n#define PCAN_FILTER_CUSTOM           0x02U  // The PCAN filter is custom configured. Only registered messages will be received\n#define PCAN_CHANNEL_UNAVAILABLE     0x00U  // The PCAN-Channel handle is illegal, or its associated hardware is not available\n#define PCAN_CHANNEL_AVAILABLE       0x01U  // The PCAN-Channel handle is available to be connected (Plug&Play Hardware: it means furthermore that the hardware is plugged-in)\n#define PCAN_CHANNEL_OCCUPIED        0x02U  // The PCAN-Channel handle is valid, and is already being used\n#define PCAN_CHANNEL_PCANVIEW        (PCAN_CHANNEL_AVAILABLE |  PCAN_CHANNEL_OCCUPIED) // The PCAN-Channel handle is already being used by a PCAN-View application, but is available to connect\n\n#define LOG_FUNCTION_DEFAULT         0x00U    // Logs system exceptions / errors\n#define LOG_FUNCTION_ENTRY           0x01U    // Logs the entries to the PCAN-Basic API functions\n#define LOG_FUNCTION_PARAMETERS      0x02U    // Logs the parameters passed to the PCAN-Basic API functions\n#define LOG_FUNCTION_LEAVE           0x04U    // Logs the exits from the PCAN-Basic API functions\n#define LOG_FUNCTION_WRITE           0x08U    // Logs the CAN messages passed to the CAN_Write function\n#define LOG_FUNCTION_READ            0x10U    // Logs the CAN messages received within the CAN_Read function\n#define LOG_FUNCTION_ALL             0xFFFFU  // Logs all possible information within the PCAN-Basic API functions\n\n#define TRACE_FILE_SINGLE            0x00U  // A single file is written until it size reaches PAN_TRACE_SIZE\n#define TRACE_FILE_SEGMENTED         0x01U  // Traced data is distributed in several files with size PAN_TRACE_SIZE\n#define TRACE_FILE_DATE              0x02U  // Includes the date into the name of the trace file\n#define TRACE_FILE_TIME              0x04U  // Includes the start time into the name of the trace file\n#define TRACE_FILE_OVERWRITE         0x80U  // Causes the overwriting of available traces (same name)\n\n#define FEATURE_FD_CAPABLE           0x01U  // Device supports flexible data-rate (CAN-FD)\n#define FEATURE_DELAY_CAPABLE        0x02U  // Device supports a delay between sending frames (FPGA based USB devices)\n\n#define SERVICE_STATUS_STOPPED       0x01U  // The service is not running\n#define SERVICE_STATUS_RUNNING       0x04U  // The service is running\n\n// PCAN message types\n//\n#define PCAN_MESSAGE_STANDARD        0x00U  // The PCAN message is a CAN Standard Frame (11-bit identifier)\n#define PCAN_MESSAGE_RTR             0x01U  // The PCAN message is a CAN Remote-Transfer-Request Frame\n#define PCAN_MESSAGE_EXTENDED        0x02U  // The PCAN message is a CAN Extended Frame (29-bit identifier)\n#define PCAN_MESSAGE_FD              0x04U  // The PCAN message represents a FD frame in terms of CiA Specs\n#define PCAN_MESSAGE_BRS             0x08U  // The PCAN message represents a FD bit rate switch (CAN data at a higher bit rate)\n#define PCAN_MESSAGE_ESI             0x10U  // The PCAN message represents a FD error state indicator(CAN FD transmitter was error active)\n#define PCAN_MESSAGE_ERRFRAME        0x40U  // The PCAN message represents an error frame\n#define PCAN_MESSAGE_STATUS          0x80U  // The PCAN message represents a PCAN status message\n\n// Frame Type / Initialization Mode\n//\n#define PCAN_MODE_STANDARD           PCAN_MESSAGE_STANDARD\n#define PCAN_MODE_EXTENDED           PCAN_MESSAGE_EXTENDED\n\n// Baud rate codes = BTR0/BTR1 register values for the CAN controller.\n// You can define your own Baud rate with the BTROBTR1 register.\n// Take a look at www.peak-system.com for our free software \"BAUDTOOL\"\n// to calculate the BTROBTR1 register for every bit rate and sample point.\n//\n#define PCAN_BAUD_1M                 0x0014U  //   1 MBit/s\n#define PCAN_BAUD_800K               0x0016U  // 800 kBit/s\n#define PCAN_BAUD_500K               0x001CU  // 500 kBit/s\n#define PCAN_BAUD_250K               0x011CU  // 250 kBit/s\n#define PCAN_BAUD_125K               0x031CU  // 125 kBit/s\n#define PCAN_BAUD_100K               0x432FU  // 100 kBit/s\n#define PCAN_BAUD_95K                0xC34EU  //  95,238 kBit/s\n#define PCAN_BAUD_83K                0x852BU  //  83,333 kBit/s\n#define PCAN_BAUD_50K                0x472FU  //  50 kBit/s\n#define PCAN_BAUD_47K                0x1414U  //  47,619 kBit/s\n#define PCAN_BAUD_33K                0x8B2FU  //  33,333 kBit/s\n#define PCAN_BAUD_20K                0x532FU  //  20 kBit/s\n#define PCAN_BAUD_10K                0x672FU  //  10 kBit/s\n#define PCAN_BAUD_5K                 0x7F7FU  //   5 kBit/s\n\n// Represents the configuration for a CAN bit rate\n// Note:\n//    * Each parameter and its value must be separated with a '='.\n//    * Each pair of parameter/value must be separated using ','.\n//\n// Example:\n//    f_clock=80000000,nom_brp=10,nom_tseg1=5,nom_tseg2=2,nom_sjw=1,data_brp=4,data_tseg1=7,data_tseg2=2,data_sjw=1\n//\n#define PCAN_BR_CLOCK                __T(\"f_clock\")\n#define PCAN_BR_CLOCK_MHZ            __T(\"f_clock_mhz\")\n#define PCAN_BR_NOM_BRP              __T(\"nom_brp\")\n#define PCAN_BR_NOM_TSEG1            __T(\"nom_tseg1\")\n#define PCAN_BR_NOM_TSEG2            __T(\"nom_tseg2\")\n#define PCAN_BR_NOM_SJW              __T(\"nom_sjw\")\n#define PCAN_BR_NOM_SAMPLE           __T(\"nom_sam\")\n#define PCAN_BR_DATA_BRP             __T(\"data_brp\")\n#define PCAN_BR_DATA_TSEG1           __T(\"data_tseg1\")\n#define PCAN_BR_DATA_TSEG2           __T(\"data_tseg2\")\n#define PCAN_BR_DATA_SJW             __T(\"data_sjw\")\n#define PCAN_BR_DATA_SAMPLE          __T(\"data_ssp_offset\")\n\n// Type of PCAN (non plug&play) hardware\n//\n#define PCAN_TYPE_ISA                0x01U  // PCAN-ISA 82C200\n#define PCAN_TYPE_ISA_SJA            0x09U  // PCAN-ISA SJA1000\n#define PCAN_TYPE_ISA_PHYTEC         0x04U  // PHYTEC ISA\n#define PCAN_TYPE_DNG                0x02U  // PCAN-Dongle 82C200\n#define PCAN_TYPE_DNG_EPP            0x03U  // PCAN-Dongle EPP 82C200\n#define PCAN_TYPE_DNG_SJA            0x05U  // PCAN-Dongle SJA1000\n#define PCAN_TYPE_DNG_SJA_EPP        0x06U  // PCAN-Dongle EPP SJA1000\n\n#define PEAKCAN_LIB\t\t\t\t\t\"libpcanbasic.so\"\n\n\n////////////////////////////////////////////////////////////\n// Type definitions\n////////////////////////////////////////////////////////////\n\n\ntypedef u16 TPCANHandle;\ntypedef u32\tTPCANStatus;\ntypedef u8 TPCANParameter;\ntypedef u8 TPCANDevice;\ntypedef u8 TPCANMessageType;\ntypedef u8 TPCANType;\ntypedef u8 TPCANMode;\ntypedef u16 TPCANBaudrate;\n\n\n// Represents a PCAN message\ntypedef struct tagTPCANMsg\n{\n\tu32             \tID;      // 11/29-bit message identifier\n    TPCANMessageType    MSGTYPE; // Type of the message\n    u8              \tLEN;     // Data Length Code of the message (0..8)\n    u8              \tDATA[8]; // Data of the message (DATA[0]..DATA[7])\n} TPCANMsg;\n// Represents a timestamp of a received PCAN message\n// Total Microseconds = micros + 1000 * millis + 0xFFFFFFFF * 1000 * millis_overflow\ntypedef struct tagTPCANTimestamp\n{\n\tu32   millis;             // Base-value: milliseconds: 0.. 2^32-1\n\tu16   millis_overflow;    // Roll-arounds of millis\n\tu16   micros;             // Microseconds: 0..999\n} TPCANTimestamp;\n\ntypedef TPCANStatus (*CAN_InitializePtr)(TPCANHandle, TPCANBaudrate, TPCANType, u32, u16);\ntypedef TPCANStatus (*CAN_UninitializePtr) (TPCANHandle);\ntypedef TPCANStatus (*CAN_ResetPtr) (TPCANHandle);\ntypedef TPCANStatus (*CAN_ReadPtr) (TPCANHandle, TPCANMsg *, TPCANTimestamp *);\ntypedef TPCANStatus (*CAN_WritePtr) (TPCANHandle, TPCANMsg *);\ntypedef TPCANStatus (*CAN_FilterMessagesPtr) (TPCANHandle, u32, u32, TPCANMode);\ntypedef TPCANStatus (*CAN_GetValuePtr) (TPCANHandle, TPCANParameter, void *, u32);\ntypedef TPCANStatus (*CAN_SetValuePtr) (TPCANHandle, TPCANParameter, void *, u32);\ntypedef TPCANStatus (*CAN_GetErrorTextPtr) (TPCANStatus, u16, char *);\n\n\nnamespace Can {\nnamespace PeakCan {\n\n\nclass PeakCanSymbols : public ISingleton<PeakCanSymbols> {\n\tSINGLETON_ACCESS;\n\n\tfriend class PeakCanHelper;\n\tfriend class PeakCanSender;\n\tfriend class PeakCanReceiver;\n\t\nprivate:\n\tPeakCanSymbols() {}\n\t~PeakCanSymbols() {}\n\n\t//All functions to load as interface of PeakCan library\n\tCAN_InitializePtr CAN_Initialize = nullptr;\n\tCAN_UninitializePtr CAN_Uninitialize = nullptr;\n\tCAN_ResetPtr CAN_Reset = nullptr;\n\tCAN_ReadPtr CAN_Read = nullptr;\n\tCAN_WritePtr CAN_Write = nullptr;\n\tCAN_FilterMessagesPtr CAN_FilterMessages = nullptr;\n\tCAN_GetValuePtr CAN_GetValue = nullptr;\n\tCAN_SetValuePtr CAN_SetValue = nullptr;\n\tCAN_GetErrorTextPtr CAN_GetErrorText = nullptr;\n\n\t//Keep track of the status of the symbols\n\tbool mSymbolsLoaded = false;\n\tbool areSymbolsLoaded() const { return mSymbolsLoaded; }\n\n\tbool mLoadingError = false;\n\tbool getLoadingError() const { return mLoadingError; }\n\n\n\t//Method to load the symbols\n\tbool tryLoadSymbols();\n\n};\n\n} /* namespace PeakCan */\n} /* namespace Can */\n\n#endif /* BACKENDS_PEAKCAN_PEAKCANSYMBOLS_H_ */\n"
  },
  {
    "path": "CAN/include/Backends/Sockets/SocketCanHelper.h",
    "content": "/*\n * CanHelper.h\n *\n *  Created on: Sep 28, 2017\n *      Author: famez\n */\n\n#ifndef SOCKETCANHELPER_H_\n#define SOCKETCANHELPER_H_\n\n#include <set>\n#include <string>\n\n#include <ICanHelper.h>\n\nnamespace Can {\nnamespace Sockets {\n\nclass SocketCanHelper : public Can::ICanHelper {\nprivate:\n\n\tint mSock = -1;\n\tbool mTimeStamp = true;\n\tstd::string mInterface;\n\n\tbool isUp() const;\n\tbool bringUp() const;\n\tbool bringDown() const;\n\tbool setBitrate(u32 bitrate) const;\n\tbool isVirtual() const;\n\npublic:\n\tSocketCanHelper();\n\tvirtual ~SocketCanHelper();\n\n\tstatic std::set<std::string> getCanIfaces();\n\n\tstd::string getBackend() override { return \"SocketCan\"; }\n\n\tICanSender* allocateCanSender() override;\n\tCommonCanReceiver* allocateCanReceiver() override;\n\n\tbool initialize(std::string interface, u32 bitrate) override;\n\n\tvoid finalize() override;\n\n\tbool initialized() override;\n\n};\n\n} /* namespace Can */\n}\n\n#endif /* CANHELPER_H_ */\n"
  },
  {
    "path": "CAN/include/Backends/Sockets/SocketCanReceiver.h",
    "content": "/*\n * SocketCanReceiver.h\n *\n *  Created on: May 10, 2018\n *      Author: fernado\n */\n\n#ifndef BACKENDS_SOCKETS_SOCKETCANRECEIVER_H_\n#define BACKENDS_SOCKETS_SOCKETCANRECEIVER_H_\n\n#include <CommonCanReceiver.h>\n\nnamespace Can {\nnamespace Sockets {\n\nclass SocketCanReceiver : public CommonCanReceiver {\nprivate:\n\t/*\n\t * An already initialized socket where to send the frames\n\t */\n\tint mSock;\n\tbool mTimeStamp;\n\n\tiovec iov;\n\tmsghdr msg;\n\tcanfd_frame frame;\n\tsockaddr_can addr;\n\tchar ctrlmsg[CMSG_SPACE(sizeof(timeval) + 3*sizeof(timespec) + sizeof(u32))];\n\npublic:\n\tSocketCanReceiver(int sock, bool timeStamp);\n\tvirtual ~SocketCanReceiver();\n\n\t/*ICanReceiver implementation*/\n\n\tbool setFilters(std::set<CanFilter> filters) override;\n\n\tbool filter(u32 id) override { return true; }\t\t//Filtering is already done in kernel space\n\n\tbool receive(CanFrame&, Utils::TimeStamp&) override;\n\n\tint getFD() override;\n\n\n};\n\n} /* namespace Sockets */\n} /* namespace Can */\n\n#endif /* BACKENDS_SOCKETS_SOCKETCANRECEIVER_H_ */\n"
  },
  {
    "path": "CAN/include/Backends/Sockets/SocketCanSender.h",
    "content": "/*\n * CanSender.h\n *\n *  Created on: Apr 1, 2018\n *      Author: famez\n *      Implementation of can sender for the linux sockets layer\n */\n\n#ifndef BACKENDS_SOCKETS_SOCKETCANSENDER_H_\n#define BACKENDS_SOCKETS_SOCKETCANSENDER_H_\n\n#include \"../../CommonCanSender.h\"\n\nnamespace Can {\nnamespace Sockets {\n\n\n\nclass SocketCanSender : public CommonCanSender {\nprivate:\n\t/*\n\t * An already initialized socket where to send the frames\n\t */\n\tint mSock;\n\nprotected:\n\tvoid _sendFrame(const CanFrame& frame) const override;\npublic:\n\tSocketCanSender(int sock);\n\tvirtual ~SocketCanSender();\n\n};\n\n} /* namespace Sockets */\n} /* namespace Can */\n\n#endif /* BACKENDS_SOCKETS_SOCKETCANSENDER_H_ */\n"
  },
  {
    "path": "CAN/include/CanEasy.h",
    "content": "/*\n * CanEasy.h\n *\n *  Created on: Jan 13, 2019\n *      Author: famez\n */\n\n#ifndef CANEASY_H_\n#define CANEASY_H_\n\n#include <memory>\n\n#include <map>\n#include <string>\n\n#include <ICanHelper.h>\n#include <CanSniffer.h>\n\n\nnamespace Can {\n\nclass CanEasy {\nprivate:\n\n\t//Backends in charge of sending the corresponding frames\n\tstatic std::map<std::string, std::shared_ptr<ICanSender> > mSenders;\n\n\tstatic CanSniffer mSniffer;\n\n\tstatic std::set<std::string> mInitializedIfaces;\n\npublic:\n\n\t/*\n\t * To initialize for sending and receiving\n\t */\n\tstatic void initialize(u32 bitrate, OnReceiveFramePtr recvCB, OnTimeoutPtr timeoutCB);\n\n\t/*\n\t * To initialize only for sending frames\n\t */\n\tstatic void initialize(u32 bitrate);\n\n\tstatic std::set<std::string> getCanIfaces();\n\tstatic const std::set<std::string>& getInitializedCanIfaces() { return mInitializedIfaces; }\n\n\tstatic std::shared_ptr<ICanSender> getSender(const std::string& interface);\n\n\tstatic CanSniffer& getSniffer() { return mSniffer; }\n\n\tstatic void finalize();\n\n};\n\n} /* namespace Can */\n\n#endif /* CANEASY_H_ */\n"
  },
  {
    "path": "CAN/include/CanFilter.h",
    "content": "/*\n * CanFilter.h\n *\n *  Created on: Oct 15, 2017\n *      Author: famez\n */\n\n#ifndef CANFILTER_H_\n#define CANFILTER_H_\n\n#include <Types.h>\n\n\nnamespace Can {\n\nclass CanFilter {\n\nprivate:\n\n\tu32 mId;\n\tu32 mMask;\n\tbool mStdFrame;\n\tbool mExtFrame;\n\npublic:\n\tCanFilter() : mId(0), mMask(0), mStdFrame(false), mExtFrame(false) {}\n\tCanFilter(u32 id, u32 mask, bool filterExt, bool filterStd) : mId(id), mMask(mask), mStdFrame(filterStd), mExtFrame(filterExt) {}\n\n\tvirtual ~CanFilter() {}\n\n\tu32 getId() const {\n\t\treturn mId;\n\t}\n\n\tvoid setId(u32 id) {\n\t\tmId = id;\n\t}\n\n\tu32 getMask() const {\n\t\treturn mMask;\n\t}\n\n\tvoid setMask(u32 mask) {\n\t\tmMask = mask;\n\t}\n\n\tbool filterExtFrame() const {\n\t\treturn mExtFrame;\n\t}\n\n\tvoid setExtFrame(bool extFrame) {\n\t\tmExtFrame = extFrame;\n\t}\n\n\tbool filterStdFrame() const {\n\t\treturn mStdFrame;\n\t}\n\n\tvoid setStdFrame(bool stdFrame) {\n\t\tmStdFrame = stdFrame;\n\t}\n\n\n\tbool operator<(const CanFilter& other) const {\n\t\tif(mId < other.mId)\n\t\t\treturn true;\n\n\t\tif(mId > other.mId)\n\t\t\treturn false;\n\n\t\tif(mMask < other.mMask)\n\t\t\treturn true;\n\n\t\tif(mMask > other.mMask)\n\t\t\treturn false;\n\n\n\t\tif(!mStdFrame && other.mStdFrame)\n\t\t\treturn true;\n\n\t\tif(mStdFrame && !other.mStdFrame)\n\t\t\treturn false;\n\n\n\t\tif(!mExtFrame && other.mExtFrame)\n\t\t\treturn true;\n\n\t\treturn false;\n\n\n\t}\n};\n\n} /* namespace Can */\n\n#endif /* CANFILTER_H_ */\n"
  },
  {
    "path": "CAN/include/CanFrame.h",
    "content": "/*\n * CanFrame.h\n *\n *  Created on: Oct 15, 2017\n *      Author: famez\n */\n\n#ifndef CANFRAME_H_\n#define CANFRAME_H_\n\n#include <string>\n#include <Types.h>\n\n#define MAX_CAN_DATA_SIZE\t\t8\n\nnamespace Can {\n\nclass CanFrame {\nprivate:\n\n\tbool mExtendedFormat;\n\tu32 mId;\n\tstd::string mData;\n\npublic:\n\tCanFrame();\n\tCanFrame(bool extFormat, u32 id) : mExtendedFormat(extFormat), mId(id) {}\n\tCanFrame(bool extFormat, u32 id, const std::string& data) : mExtendedFormat(extFormat), mId(id) { setData(data); }\n\tvirtual ~CanFrame();\n\n\tconst std::string& getData() const {\n\t\treturn mData;\n\t}\n\n\tbool setData(const std::string& data) {\n\n\t\tif(data.size() > MAX_CAN_DATA_SIZE)\n\t\t\treturn false;\n\t\tmData = data;\n\t\treturn true;\n\t}\n\n\tu32 getId() const {\n\t\treturn mId;\n\t}\n\n\tvoid setId(u32 id) {\n\t\tmId = id;\n\t}\n\n\tvoid clear() { mId = 0; mData.clear(); }\n\n\tbool isExtendedFormat() const {\n\t\treturn mExtendedFormat;\n\t}\n\n\tvoid setExtendedFormat(bool extendedFormat) {\n\t\tmExtendedFormat = extendedFormat;\n\t}\n\t\n\t//To show human readable data\n\t\n\tstd::string hexDump() const;\n\t\n\t\n};\n\n} /* namespace Can */\n\n#endif /* CANFRAME_H_ */\n"
  },
  {
    "path": "CAN/include/CanSniffer.h",
    "content": "/*\n * CanSniffer.h\n *\n *  Created on: Jun 5, 2018\n *      Author: fernado\n */\n\n#ifndef CANSNIFFER_H_\n#define CANSNIFFER_H_\n\n#include <vector>\n\n#include \"CommonCanReceiver.h\"\n\n\ntypedef void (*OnReceiveFramePtr)(const Can::CanFrame& frame, const Utils::TimeStamp& tStamp, const std::string& interface, void* data);\ntypedef bool (*OnTimeoutPtr)();\n\nnamespace Can {\n\nclass CanSniffer {\nprivate:\n\tOnReceiveFramePtr mRcvCB = nullptr;\n\tOnTimeoutPtr mTimeoutCB = nullptr;\n\tvoid* mData = nullptr;\t\t//Data to be passed to the OnReceiveFramePtr callback\n\tstd::vector<CommonCanReceiver*> mReceivers;\n\tbool mRunning = true;\n\npublic:\n\tCanSniffer() {}\n\tCanSniffer(OnReceiveFramePtr recvCB, OnTimeoutPtr timeoutCB, void* data = nullptr);\n\tCanSniffer(const CanFilter &other) = delete;\n\tCanSniffer(CanFilter &&other) = delete;\n\tvirtual ~CanSniffer();\n\n\tCanSniffer& operator=(const CanFilter &other) = delete;\n\tCanSniffer& operator=(CanFilter &&other) = delete;\n\n\t/*\n\t * Add a receiver from where to receive the frames. CanSniffer becomes the owner and will deallocate the receiver.\n\t */\n\tvoid addReceiver(CommonCanReceiver *receiver) { mReceivers.push_back(receiver); }\n\tvoid sniff(u32 timeout) const;\n\tvoid setFilters(std::set<CanFilter> filters);\n\tint getNumberOfReceivers() const { return mReceivers.size(); }\n\tvoid reset() { mRunning = true; }\n\tvoid finish() { mRunning = false; }\n\tvoid setOnRecv(OnReceiveFramePtr recvCB) { mRcvCB = recvCB; }\n\tvoid setOnTimeout(OnTimeoutPtr timeoutCB) { mTimeoutCB = timeoutCB; }\n\tvoid setData(void* data) { mData = data; }\n\n};\n\n} /* namespace Can */\n\n#endif /* CANSNIFFER_H_ */\n"
  },
  {
    "path": "CAN/include/CommonCanReceiver.h",
    "content": "/*\n * ICanReceiver.h\n *\n *  Created on: May 7, 2018\n *      Author: fernado\n */\n\n#ifndef COMMONCANRECEIVER_H_\n#define COMMONCANRECEIVER_H_\n\n#include <set>\n\n#include <Utils.h>\n\n#include <CanFilter.h>\n#include <CanFrame.h>\n\nnamespace Can {\n\nclass CommonCanReceiver {\nprivate:\n\tstd::set<CanFilter> mFilters;\n\tstd::string mInterface;\npublic:\n\tCommonCanReceiver() {}\n\tvirtual ~CommonCanReceiver() {}\n\n\t/*\n\t * Initializes the receiver to be used with the specified interface\n\t */\n\tbool setInterface(const std::string& interface);\n\n\t/*\n\t * There is the default implementation which is based in a check in user space, but there are specific implementations that let delegate the work to kernel space\n\t */\n\tvirtual bool setFilters(std::set<CanFilter> filters);\n\n\n\tvirtual int getFD() = 0;\n\n\tvirtual bool receive(CanFrame&, Utils::TimeStamp&) = 0;\n\n\tvirtual bool filter(u32 id);\n\n\tconst std::string& getInterface() const { return mInterface; }\n\n};\n\n} /* namespace Can */\n\n#endif /* COMMONCANRECEIVER_H_ */\n"
  },
  {
    "path": "CAN/include/CommonCanSender.h",
    "content": "/*\n * CommonCanSender.h\n *\n *  Created on: Apr 1, 2018\n *      Author: famez\n *      Implementation of can sender for the linux sockets layer\n */\n\n#ifndef BACKENDS_SOCKETS_COMMONCANSENDER_H_\n#define BACKENDS_SOCKETS_COMMONCANSENDER_H_\n\n\n#include <vector>\n#include <memory>\n\n#include <thread>\n#include <mutex>\n\n#include <time.h>\n\n\n#include <ICanSender.h>\n\n\nnamespace Can {\n\n\nclass CommonCanSender : public ICanSender {\nprivate:\n\n\tclass CanFrameRing {\n\tprivate:\n\t\tstd::vector<CanFrame> mFrames;\n\t\ttimespec mTxTimestamp;\n\t\tu32 mPeriod;\n\t\tsize_t mCurrentpos;\n\t\tOnSendCallback mCallback;\n\tpublic:\n\t\tCanFrameRing(u32 period, OnSendCallback callback = OnSendCallback()) : mPeriod(period), mCurrentpos(0), mCallback(callback) { mTxTimestamp = {0, 0}; }\n\t\t~CanFrameRing() {}\n\t\tCanFrameRing(const CanFrameRing& other) \t\t\t\t= default;\n\t\tCanFrameRing& operator=(const CanFrameRing& other) \t\t= delete;\n\t\tCanFrameRing(CanFrameRing&& other)                 \t\t= default;\n\t\tCanFrameRing& operator=(CanFrameRing&& other)         \t\t= default;\n\n\n\t\tvoid setTxTimestamp(timespec timeStamp) { mTxTimestamp = timeStamp; }\n\t\ttimespec getTxTimestamp() const { return mTxTimestamp; }\n\n\t\tvoid pushFrame(const CanFrame& frame);\n\t\tvoid setFrames(const std::vector<CanFrame>&);\n\t\tvoid shift();\n\t\tCanFrame& getCurrentFrame() { return mFrames[mCurrentpos]; }\n\t\tu32 getCurrentPeriod() const;\n\t\tconst std::vector<CanFrame>& getFrames() const { return mFrames; }\n\n\t\tconst OnSendCallback& getCallback() { return mCallback; }\n\n\t};\n\n\tmutable std::mutex mFramesLock;\n\tstd::vector<CanFrameRing> mFrameRings;\n\tbool mFinished;\n\tstd::unique_ptr<std::thread> mThread = nullptr;\n\nprotected:\n\tvirtual void _sendFrame(const CanFrame& frame) const = 0;\n\npublic:\n\tCommonCanSender();\n\tvirtual ~CommonCanSender();\n\n\t//ICanSender implementation\n\tbool initialize();\n\tbool finalize();\n\tbool sendFrame(CanFrame frame, u32 period, OnSendCallback callback = OnSendCallback());\n\tbool sendFrames(std::vector<CanFrame> frames, u32 period, OnSendCallback callback = OnSendCallback());\n\n\t/*\n\t * Sends the frame given as argument to the CAN network only once.\n\t */\n\tvoid sendFrameOnce(const CanFrame& frame) override { _sendFrame(frame); }\n\tvoid unSendFrame(u32 id);\n\tvoid unSendFrames(const std::vector<u32>& ids);\n\tbool isSent(const std::vector<u32>& ids);\n\tbool isSent(u32 id);\n\n\tvoid run();\n\n};\n\n} /* namespace Can */\n\n#endif /* BACKENDS_SOCKETS_CANSENDER_H_ */\n"
  },
  {
    "path": "CAN/include/ICanHelper.h",
    "content": "/*\n * CanHelper.h\n *\n *  Created on: Sep 28, 2017\n *      Author: famez\n */\n\n#ifndef ICANHELPER_H_\n#define ICANHELPER_H_\n\n#include <map>\n#include <string>\n\n#include <ICanSender.h>\n#include <CommonCanReceiver.h>\n\nnamespace Can {\n\nclass ICanHelper {\n\nprivate:\n\tstatic std::map<std::string/*Interface*/, ICanHelper*> mHelpers;\npublic:\n\n\tICanHelper() {}\n\tvirtual ~ICanHelper() {}\n\n\tstatic std::set<std::string> getInterfaces();\n\tvirtual std::string getBackend() = 0;\n\n\tvirtual bool initialize(std::string interface, u32 bitrate) = 0;\n\tvirtual void finalize() = 0;\n\n\t/*\n\t * Determines if the corresponding interface is correctly initialized\n\t */\n\tvirtual bool initialized() = 0;\n\n\t/*\n\t * Allocates a CanSender, the caller is in charge of the deallocation\n\t */\n\tvirtual ICanSender* allocateCanSender() = 0;\n\n\t/*\n\t * Allocates a CanReceiver, the caller is in charge of the deallocation\n\t */\n\tvirtual CommonCanReceiver* allocateCanReceiver() = 0;\n\n\t/*\n\t * Returns a set with all the available helpers. To free the helpers, call deallocateCanHelpers().\n\t */\n\tstatic const std::map<std::string/*Interface*/, ICanHelper*>& createCanHelpers(u32 bitrate);\n\n\tstatic void deallocateCanHelpers();\n\n};\n\n} /* namespace Can */\n\n#endif /* ICANHELPER_H_ */\n"
  },
  {
    "path": "CAN/include/ICanSender.h",
    "content": "/*\n * ICanSender.h\n *\n *  Created on: Apr 1, 2018\n *      Author: famez\n */\n\n#ifndef ICANSENDER_H_\n#define ICANSENDER_H_\n\n#include <string>\n#include <vector>\n\n#include <Types.h>\n\n#include <CanFrame.h>\n\n#include <functional>\n\n\nnamespace Can {\n\ntypedef std::function<void(u32, std::string&)> OnSendCallback;\n\nclass ICanSender {\npublic:\n\tICanSender() {}\n\tvirtual ~ICanSender() {}\n\n\t/**\n\t * Sends a frame through the can interface with the specified period\n\t */\n\tvirtual bool sendFrame(CanFrame frame, u32 period, OnSendCallback callback = OnSendCallback()) = 0;\n\t\n\t/**\n\t * Stops sending the frame whose id matches the given argument\n\t */\n\tvirtual void unSendFrame(u32 id) = 0;\n\n\n\t/*\n\t * Sends periodically a set of frames within the given period in the order defined in the vector. \n\t */\n\tvirtual bool sendFrames(std::vector<CanFrame> frames, u32 period, OnSendCallback callback = OnSendCallback()) = 0;\n\t\n\tvirtual void sendFrameOnce(const CanFrame& frame) = 0;\n\n\t/*\n\t * Stop sending the set of frames whose ids match the ones given as arguments\n\t */\n\tvirtual void unSendFrames(const std::vector<u32>& ids) = 0;\n\t\n\t/*\n\t * Returns true if the set of frames given by their corresponding ids are sent \n\t * (All the ids must match in the same order as specified in the method (sendFrames))\n\t */\n\tvirtual bool isSent(const std::vector<u32>& ids) = 0;\n\n\t/**\n\t * To check if a frame with the current id is being sent through the interface\n\t */\n\tvirtual bool isSent(u32 id) = 0;\n\n};\n\n} /* namespace Can */\n\n#endif /* ICANSENDER_H_ */\n"
  },
  {
    "path": "CAN/include/TRCReader.h",
    "content": "/*\n * TRCReader.h\n *\n *  Created on: Oct 24, 2017\n *      Author: root\n */\n\n#ifndef TRCREADER_H_\n#define TRCREADER_H_\n\n\n#include <deque>\n#include <utility>\n#include <string>\n#include <iostream>\n#include <fstream>\n#include <exception>\n\n#include <Types.h>\n\n#include \"CanFrame.h\"\n\n\n#define MAX_LOADED_FRAMES\t\t1000000\n\nnamespace Can {\n\nclass TRCReadException : public std::exception {\n\n};\n\nclass TRCReader {\n\n\nprivate:\n\n\tstd::string mFileName;\n\tsize_t mCurrentPos;\n\tsize_t mTotalFrames;\n\tstd::ifstream mFileStream;\n    std::pair<u64, CanFrame> mLastReadFrameTimePair;\n\n\tvoid readNextLine(bool& error, bool& empty);\n\n\tbool checkIntegrity();\n\n\n\npublic:\n\tTRCReader();\n\tTRCReader(const std::string& path);\n\tvirtual ~TRCReader();\n\n\tbool loadFile(const std::string& path);\n\tvoid unloadFile();\n\tbool isFileLoaded() const { return !mFileName.empty(); }\n\tsize_t getNumberOfFrames() const { return mTotalFrames; }\n\tsize_t getCurrentPos() const { return mCurrentPos; }\n\tbool seekPosition(size_t pos);\n\tvoid seekTime(u32 millis);\n    std::pair<u64, CanFrame> getLastCanFrame();\n\tvoid readNextCanFrame();\n\n\t/*\n\t * Resets the reader to the beginning\n\t */\n\tvoid reset();\n\n\n};\n\n} /* namespace Can */\n\n#endif /* TRCREADER_H_ */\n"
  },
  {
    "path": "CAN/include/TRCWriter.h",
    "content": "/*\n * TRCWriter.h\n *\n *  Created on: Jun 8, 2018\n *      Author: fernado\n */\n\n#ifndef TRCWRITER_H_\n#define TRCWRITER_H_\n\n#include <iostream>\n#include <fstream>\n\n#include \"CanFrame.h\"\n#include \"Utils.h\"\n\n\nnamespace Can {\n\n\n\nclass TRCWriter {\nprivate:\n\tstd::ofstream mFileStream;\n\tunsigned int mCounter;\npublic:\n\tTRCWriter();\n\tTRCWriter(const std::string& file);\n\tvirtual ~TRCWriter();\n\n\tvoid write(const CanFrame& frame, const Utils::TimeStamp& timeStamp);\n\n\tbool open(const std::string& file);\n\tvoid close();\n\n\tclass TRCWriteException : public std::exception {\n\n\t};\n\n};\n\n} /* namespace Can */\n\n#endif /* TRCWRITER_H_ */\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.5)\n\nproject(J1939Framework)\n\nset(CMAKE_BUILD_TYPE Debug)    #For debug purposes\n\nset(J1939Framework_VERSION 1.0.0)\n\nset(CMAKE_MODULE_PATH \"./cmake/;${CMAKE_MODULE_PATH}\")\n\n\nfind_package (Threads REQUIRED)\nfind_package (jsoncpp REQUIRED)\n\n\nset (CMAKE_CXX_STANDARD 11)\nset(CMAKE_POSITION_INDEPENDENT_CODE ON)\n\nadd_definitions(-DDATABASE_PATH=\"${CMAKE_INSTALL_PREFIX}/etc/j1939/frames.json\")\n\nadd_subdirectory(Common)\nadd_subdirectory(CAN)\nadd_subdirectory(J1939)\nadd_subdirectory(Database)\nadd_subdirectory(BinUtils)\nadd_subdirectory(j1939AddressClaimer)\nadd_subdirectory(Tests)\n\nfind_package (LibWebSockets)\nfind_package(Protobuf)\n\nif(LIBWEBSOCKETS_FOUND AND PROTOBUF_FOUND)\n\nmessage(\"-- LibWebSockets and protobuf are available\")\nmessage(\"-- Protobuf version ${Protobuf_VERSION}\")\n\nif(\"${Protobuf_VERSION}\" VERSION_GREATER_EQUAL \"3.0.0\")\n\nmessage(\"-- Project j1939GUI will be built\")\nadd_subdirectory(GUI_WEB/backend)\n\nelse()\n\nmessage(\"-- Protobuf version must be equals to or greater than 3.0.0\")\n\nendif()\n\n\n\nelse(LIBWEBSOCKETS_FOUND AND PROTOBUF_FOUND)\n\nmessage(\"-- Project \" ${PROJECT_NAME} \" will not be built\")\n\nendif(LIBWEBSOCKETS_FOUND AND PROTOBUF_FOUND)\n\n\ninclude(GenerateExportHeader)\n\ngenerate_export_header(J1939)\nset_property(TARGET J1939 PROPERTY VERSION ${J1939Framework_VERSION})\nset_property(TARGET J1939 PROPERTY SOVERSION 1)\nset_property(TARGET J1939 PROPERTY INTERFACE_J1939_MAJOR_VERSION 1)\nset_property(TARGET J1939 APPEND PROPERTY\n  COMPATIBLE_INTERFACE_STRING J1939MAJOR_VERSION\n)\n\n\ninclude(CMakePackageConfigHelpers)\nwrite_basic_package_version_file(\n  \"${CMAKE_CURRENT_BINARY_DIR}/J1939FrameworkConfigVersion.cmake\"\n  VERSION ${J1939Framework_VERSION}\n\tCOMPATIBILITY AnyNewerVersion\n)\n\nexport(EXPORT J1939FrameworkTargets\n  FILE \"${CMAKE_CURRENT_BINARY_DIR}/J1939FrameworkTargets.cmake\"\n  NAMESPACE J1939::\n)\n\n\nconfigure_file(cmake/J1939FrameworkConfig.cmake\n  \"${CMAKE_CURRENT_BINARY_DIR}/J1939FrameworkConfig.cmake\"\nCOPYONLY\n  \n)\n\nset(ConfigPackageLocation lib/cmake/J1939Framework)\ninstall(EXPORT J1939FrameworkTargets\n  FILE\n   J1939FrameworkTargets.cmake\n  NAMESPACE\n    J1939::\n  DESTINATION\n    ${ConfigPackageLocation}\n)\n\ninstall(\n  FILES\n    cmake/J1939FrameworkConfig.cmake\n    \"${CMAKE_CURRENT_BINARY_DIR}/J1939FrameworkConfigVersion.cmake\"\n  DESTINATION\n    ${ConfigPackageLocation}\n  COMPONENT\n    Devel\n)\n"
  },
  {
    "path": "Common/.cproject",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<?fileVersion 4.0.0?><cproject storage_type_id=\"org.eclipse.cdt.core.XmlProjectDescriptionStorage\">\n\t<storageModule moduleId=\"org.eclipse.cdt.core.settings\">\n\t\t<cconfiguration id=\"cdt.managedbuild.config.gnu.lib.debug.109544253\">\n\t\t\t<storageModule buildSystemId=\"org.eclipse.cdt.managedbuilder.core.configurationDataProvider\" id=\"cdt.managedbuild.config.gnu.lib.debug.109544253\" moduleId=\"org.eclipse.cdt.core.settings\" name=\"Debug\">\n\t\t\t\t<externalSettings>\n\t\t\t\t\t<externalSetting>\n\t\t\t\t\t\t<entry flags=\"VALUE_WORKSPACE_PATH\" kind=\"includePath\" name=\"/Common\"/>\n\t\t\t\t\t\t<entry flags=\"VALUE_WORKSPACE_PATH\" kind=\"libraryPath\" name=\"/Common/Debug\"/>\n\t\t\t\t\t\t<entry flags=\"RESOLVED\" kind=\"libraryFile\" name=\"Common\" srcPrefixMapping=\"\" srcRootPath=\"\"/>\n\t\t\t\t\t</externalSetting>\n\t\t\t\t</externalSettings>\n\t\t\t\t<extensions>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.ELF\" point=\"org.eclipse.cdt.core.BinaryParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GmakeErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.CWDLocator\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GCCErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GASErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t</extensions>\n\t\t\t</storageModule>\n\t\t\t<storageModule moduleId=\"cdtBuildSystem\" version=\"4.0.0\">\n\t\t\t\t<configuration artifactExtension=\"a\" artifactName=\"${ProjName}\" buildArtefactType=\"org.eclipse.cdt.build.core.buildArtefactType.staticLib\" buildProperties=\"org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.staticLib\" cleanCommand=\"rm -rf\" description=\"\" id=\"cdt.managedbuild.config.gnu.lib.debug.109544253\" name=\"Debug\" parent=\"cdt.managedbuild.config.gnu.lib.debug\">\n\t\t\t\t\t<folderInfo id=\"cdt.managedbuild.config.gnu.lib.debug.109544253.\" name=\"/\" resourcePath=\"\">\n\t\t\t\t\t\t<toolChain id=\"cdt.managedbuild.toolchain.gnu.lib.debug.800227795\" name=\"Linux GCC\" superClass=\"cdt.managedbuild.toolchain.gnu.lib.debug\">\n\t\t\t\t\t\t\t<targetPlatform id=\"cdt.managedbuild.target.gnu.platform.lib.debug.667837724\" name=\"Debug Platform\" superClass=\"cdt.managedbuild.target.gnu.platform.lib.debug\"/>\n\t\t\t\t\t\t\t<builder buildPath=\"${workspace_loc:/Common}/Debug\" id=\"cdt.managedbuild.target.gnu.builder.lib.debug.740364718\" managedBuildOn=\"true\" name=\"Gnu Make Builder.Debug\" superClass=\"cdt.managedbuild.target.gnu.builder.lib.debug\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.archiver.lib.debug.923223552\" name=\"GCC Archiver\" superClass=\"cdt.managedbuild.tool.gnu.archiver.lib.debug\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.cpp.compiler.lib.debug.1929034594\" name=\"GCC C++ Compiler\" superClass=\"cdt.managedbuild.tool.gnu.cpp.compiler.lib.debug\">\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.lib.debug.option.optimization.level.1398968462\" superClass=\"gnu.cpp.compiler.lib.debug.option.optimization.level\" value=\"gnu.cpp.compiler.optimization.level.none\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.lib.debug.option.debugging.level.2104653069\" superClass=\"gnu.cpp.compiler.lib.debug.option.debugging.level\" value=\"gnu.cpp.compiler.debugging.level.max\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.cpp.compiler.input.69737359\" superClass=\"cdt.managedbuild.tool.gnu.cpp.compiler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.c.compiler.lib.debug.190459794\" name=\"GCC C Compiler\" superClass=\"cdt.managedbuild.tool.gnu.c.compiler.lib.debug\">\n\t\t\t\t\t\t\t\t<option defaultValue=\"gnu.c.optimization.level.none\" id=\"gnu.c.compiler.lib.debug.option.optimization.level.1301906033\" superClass=\"gnu.c.compiler.lib.debug.option.optimization.level\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.c.compiler.lib.debug.option.debugging.level.1233297231\" superClass=\"gnu.c.compiler.lib.debug.option.debugging.level\" value=\"gnu.c.debugging.level.max\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.c.compiler.input.885591078\" superClass=\"cdt.managedbuild.tool.gnu.c.compiler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.c.linker.base.1040140587\" name=\"GCC C Linker\" superClass=\"cdt.managedbuild.tool.gnu.c.linker.base\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.cpp.linker.base.230832002\" name=\"GCC C++ Linker\" superClass=\"cdt.managedbuild.tool.gnu.cpp.linker.base\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.assembler.lib.debug.1994571073\" name=\"GCC Assembler\" superClass=\"cdt.managedbuild.tool.gnu.assembler.lib.debug\">\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.assembler.input.861719962\" superClass=\"cdt.managedbuild.tool.gnu.assembler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t</toolChain>\n\t\t\t\t\t</folderInfo>\n\t\t\t\t</configuration>\n\t\t\t</storageModule>\n\t\t\t<storageModule moduleId=\"org.eclipse.cdt.core.externalSettings\"/>\n\t\t</cconfiguration>\n\t\t<cconfiguration id=\"cdt.managedbuild.config.gnu.lib.release.930918412\">\n\t\t\t<storageModule buildSystemId=\"org.eclipse.cdt.managedbuilder.core.configurationDataProvider\" id=\"cdt.managedbuild.config.gnu.lib.release.930918412\" moduleId=\"org.eclipse.cdt.core.settings\" name=\"Release\">\n\t\t\t\t<externalSettings>\n\t\t\t\t\t<externalSetting>\n\t\t\t\t\t\t<entry flags=\"VALUE_WORKSPACE_PATH\" kind=\"includePath\" name=\"/Common\"/>\n\t\t\t\t\t\t<entry flags=\"VALUE_WORKSPACE_PATH\" kind=\"libraryPath\" name=\"/Common/Release\"/>\n\t\t\t\t\t\t<entry flags=\"RESOLVED\" kind=\"libraryFile\" name=\"Common\" srcPrefixMapping=\"\" srcRootPath=\"\"/>\n\t\t\t\t\t</externalSetting>\n\t\t\t\t</externalSettings>\n\t\t\t\t<extensions>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.ELF\" point=\"org.eclipse.cdt.core.BinaryParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GmakeErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.CWDLocator\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GCCErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GASErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t</extensions>\n\t\t\t</storageModule>\n\t\t\t<storageModule moduleId=\"cdtBuildSystem\" version=\"4.0.0\">\n\t\t\t\t<configuration artifactExtension=\"a\" artifactName=\"${ProjName}\" buildArtefactType=\"org.eclipse.cdt.build.core.buildArtefactType.staticLib\" buildProperties=\"org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.staticLib\" cleanCommand=\"rm -rf\" description=\"\" id=\"cdt.managedbuild.config.gnu.lib.release.930918412\" name=\"Release\" parent=\"cdt.managedbuild.config.gnu.lib.release\">\n\t\t\t\t\t<folderInfo id=\"cdt.managedbuild.config.gnu.lib.release.930918412.\" name=\"/\" resourcePath=\"\">\n\t\t\t\t\t\t<toolChain id=\"cdt.managedbuild.toolchain.gnu.lib.release.1725854355\" name=\"Linux GCC\" superClass=\"cdt.managedbuild.toolchain.gnu.lib.release\">\n\t\t\t\t\t\t\t<targetPlatform id=\"cdt.managedbuild.target.gnu.platform.lib.release.1806268408\" name=\"Debug Platform\" superClass=\"cdt.managedbuild.target.gnu.platform.lib.release\"/>\n\t\t\t\t\t\t\t<builder buildPath=\"${workspace_loc:/Common}/Release\" id=\"cdt.managedbuild.target.gnu.builder.lib.release.835212119\" managedBuildOn=\"true\" name=\"Gnu Make Builder.Release\" superClass=\"cdt.managedbuild.target.gnu.builder.lib.release\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.archiver.lib.release.1118505577\" name=\"GCC Archiver\" superClass=\"cdt.managedbuild.tool.gnu.archiver.lib.release\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.cpp.compiler.lib.release.962888988\" name=\"GCC C++ Compiler\" superClass=\"cdt.managedbuild.tool.gnu.cpp.compiler.lib.release\">\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.lib.release.option.optimization.level.393319152\" superClass=\"gnu.cpp.compiler.lib.release.option.optimization.level\" value=\"gnu.cpp.compiler.optimization.level.most\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.lib.release.option.debugging.level.648456860\" superClass=\"gnu.cpp.compiler.lib.release.option.debugging.level\" value=\"gnu.cpp.compiler.debugging.level.none\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.cpp.compiler.input.778017070\" superClass=\"cdt.managedbuild.tool.gnu.cpp.compiler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.c.compiler.lib.release.198387541\" name=\"GCC C Compiler\" superClass=\"cdt.managedbuild.tool.gnu.c.compiler.lib.release\">\n\t\t\t\t\t\t\t\t<option defaultValue=\"gnu.c.optimization.level.most\" id=\"gnu.c.compiler.lib.release.option.optimization.level.1185083362\" superClass=\"gnu.c.compiler.lib.release.option.optimization.level\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.c.compiler.lib.release.option.debugging.level.1604821932\" superClass=\"gnu.c.compiler.lib.release.option.debugging.level\" value=\"gnu.c.debugging.level.none\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.c.compiler.input.2133695809\" superClass=\"cdt.managedbuild.tool.gnu.c.compiler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.c.linker.base.778437666\" name=\"GCC C Linker\" superClass=\"cdt.managedbuild.tool.gnu.c.linker.base\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.cpp.linker.base.673482589\" name=\"GCC C++ Linker\" superClass=\"cdt.managedbuild.tool.gnu.cpp.linker.base\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.assembler.lib.release.1990446606\" name=\"GCC Assembler\" superClass=\"cdt.managedbuild.tool.gnu.assembler.lib.release\">\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.assembler.input.18554064\" superClass=\"cdt.managedbuild.tool.gnu.assembler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t</toolChain>\n\t\t\t\t\t</folderInfo>\n\t\t\t\t</configuration>\n\t\t\t</storageModule>\n\t\t</cconfiguration>\n\t</storageModule>\n\t<storageModule moduleId=\"cdtBuildSystem\" version=\"4.0.0\">\n\t\t<project id=\"Common.cdt.managedbuild.target.gnu.lib.213660032\" name=\"Static Library\" projectType=\"cdt.managedbuild.target.gnu.lib\"/>\n\t</storageModule>\n\t<storageModule moduleId=\"scannerConfiguration\">\n\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.config.gnu.lib.release.930918412;cdt.managedbuild.config.gnu.lib.release.930918412.;cdt.managedbuild.tool.gnu.c.compiler.lib.release.198387541;cdt.managedbuild.tool.gnu.c.compiler.input.2133695809\">\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t</scannerConfigBuildInfo>\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.config.gnu.lib.debug.109544253;cdt.managedbuild.config.gnu.lib.debug.109544253.;cdt.managedbuild.tool.gnu.c.compiler.lib.debug.190459794;cdt.managedbuild.tool.gnu.c.compiler.input.885591078\">\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t</scannerConfigBuildInfo>\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.config.gnu.lib.release.930918412;cdt.managedbuild.config.gnu.lib.release.930918412.;cdt.managedbuild.tool.gnu.cpp.compiler.lib.release.962888988;cdt.managedbuild.tool.gnu.cpp.compiler.input.778017070\">\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t</scannerConfigBuildInfo>\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.config.gnu.lib.debug.109544253;cdt.managedbuild.config.gnu.lib.debug.109544253.;cdt.managedbuild.tool.gnu.cpp.compiler.lib.debug.1929034594;cdt.managedbuild.tool.gnu.cpp.compiler.input.69737359\">\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t</scannerConfigBuildInfo>\n\t</storageModule>\n\t<storageModule moduleId=\"org.eclipse.cdt.core.LanguageSettingsProviders\"/>\n</cproject>\n"
  },
  {
    "path": "Common/.gitignore",
    "content": "/Debug/\n"
  },
  {
    "path": "Common/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.5)\n\nproject(Common)\n\nadd_library(Common STATIC \n    Utils.cpp\n)\n\ntarget_include_directories(Common\n    PRIVATE \n        include\n)\n\n\ninstall (TARGETS Common EXPORT J1939FrameworkTargets\n    DESTINATION lib)\n\n\ninstall(DIRECTORY include/ \n    DESTINATION include)\n"
  },
  {
    "path": "Common/Utils.cpp",
    "content": "/*\n * Utils.cpp\n *\n *  Created on: Apr 5, 2018\n *      Author: famez\n */\n\n#include <chrono>\n\n#include \"Utils.h\"\n\n\nnamespace Utils {\n\nu32 getElapsedMillis(timespec* start, timespec* end)\n{\n    return (end->tv_sec - start->tv_sec) * 1000 + (end->tv_nsec - start->tv_nsec) / 1000000;\n}\n\ntimespec addMillis(timespec* time, u32 millis) {\n\n\ttimespec retVal;\n\n\tretVal.tv_nsec = time->tv_nsec + (millis % 1000) * 1000000;\n\tretVal.tv_sec = time->tv_sec + millis / 1000;\n\n\treturn retVal;\n\n}\n\nTimeStamp TimeStamp::operator-(const TimeStamp& other) const {\n\n\tTimeStamp retVal(*this);\n\n\tif(other.mMicroSec > mMicroSec) {\n\t\tif(other.mSeconds >= mSeconds) {\n\t\t\treturn TimeStamp();\n\t\t} else {\n\t\t\tretVal.mMicroSec = mMicroSec + 1000000;\n\t\t\tretVal.mSeconds = mSeconds - 1;\n\t\t}\n\t}\n\n\tif(other.mSeconds > retVal.mSeconds) {\n\t\treturn TimeStamp();\n\t}\n\n\n\tretVal.mSeconds = retVal.mSeconds - other.mSeconds;\n\tretVal.mMicroSec = retVal.mMicroSec - other.mMicroSec;\n\n\treturn retVal;\n\n}\n\nTimeStamp TimeStamp::operator+(const TimeStamp& other) const {\n\n\tTimeStamp retVal(*this);\n\n\tretVal.mSeconds = retVal.mSeconds + other.mSeconds;\n\tretVal.mMicroSec = retVal.mMicroSec + other.mMicroSec;\n\n\tif(retVal.mMicroSec > 1000000) {\n\t\tretVal.mMicroSec -= 1000000;\n\t\t++retVal.mSeconds;\n\t}\n\n\treturn retVal;\n\n}\n\nbool TimeStamp::operator>(const TimeStamp& other) const {\n\n\tif(mSeconds > other.mSeconds)\t\treturn true;\n\n\tif(mSeconds == other.mSeconds && mMicroSec > other.mMicroSec)\t\treturn true;\n\n\treturn false;\n}\n\nbool TimeStamp::operator<(const TimeStamp& other) const {\n\n\tif(mSeconds < other.mSeconds)\t\treturn true;\n\n\tif(mSeconds == other.mSeconds && mMicroSec < other.mMicroSec)\t\treturn true;\n\n\treturn false;\n\n}\n\nbool TimeStamp::operator<=(const TimeStamp& other) const {\n\treturn !(*this > other);\n}\n\nbool TimeStamp::operator>=(const TimeStamp& other) const {\n\treturn !(*this < other);\n}\n\nTimeStamp TimeStamp::operator-(u32 millis) const {\n\n\tTimeStamp aux(millis/1000, (millis%1000)*1000);\n\n\treturn (*this - aux);\n}\n\n\nTimeStamp TimeStamp::operator+(u32 millis) const {\n\n\tTimeStamp aux(millis/1000, (millis%1000)*1000);\n\n\treturn (*this + aux);\n\n}\n\nTimeStamp TimeStamp::now() {\n\n\tauto now = std::chrono::steady_clock::now();\n\tauto duration = now.time_since_epoch();\n\tauto micro = std::chrono::duration_cast<std::chrono::microseconds>(duration);\n\n\treturn TimeStamp(micro.count() / 1000000, micro.count() % 1000000);\n\n}\n\n}\n"
  },
  {
    "path": "Common/include/Assert.h",
    "content": "/*\n * Assert.h\n *\n *  Created on: Apr 14, 2018\n *      Author: famez\n */\n\n#ifndef ASSERT_H_\n#define ASSERT_H_\n\n#define ASSERT(condition)\t\tif(!(condition)) { fprintf(stderr, \"Assertion failed in condition \" #condition \", file %s, line %d\\n\", __FILE__, __LINE__); exit(-1); }\n\n#endif /* ASSERT_H_ */\n"
  },
  {
    "path": "Common/include/ICloneable.h",
    "content": "/*\n * ICloneable.h\n *\n *  Created on: Oct 10, 2017\n *      Author: famez\n */\n\n#ifndef ICLONEABLE_H_\n#define ICLONEABLE_H_\n\n\n#define IMPLEMENT_CLONEABLE(CLASS, SUBCLASS)\t\t\\\n\tvirtual CLASS* clone() const {\t\t\t\t\t\t\t\t\\\n\t\treturn new SUBCLASS(*this);\t\t\t\t\\\n\t}\n\ntemplate<class T>\nclass ICloneable {\npublic:\n\tICloneable() {}\n\tvirtual ~ICloneable() {}\n\n\tvirtual T* clone() const = 0;\n\n};\n\n#endif /* ICLONEABLE_H_ */\n"
  },
  {
    "path": "Common/include/Singleton.h",
    "content": "/*\n * Singleton.h\n *\n *  Created on: Mar 15, 2016\n *      Author: famez\n *      Interfaz para crear una clase singleton.\n *      Incluir siempre al inicio de la definición de la clase la macro SINGLETON_ACCESS\n */\n\n#ifndef SINGLETON_H_\n#define SINGLETON_H_\n\n#include <stdio.h>\n#include <exception>\n#include <typeinfo>\n\n\n//#define SINGLETON_DEBUG\n\n#define SINGLETON_ACCESS\t\tfriend class ISingleton;\n\n\ntemplate<class T>\nclass ISingleton {\n\nprotected:\n\tISingleton() {}\n\tstatic T* mInstance;\n\npublic:\n\tvirtual ~ISingleton(){}\n\tinline static T& getInstance()\n\t{\n\t\tif(!mInstance)\n\t\t{\n\t\t\ttry{\n\t\t\t\tmInstance = new T();\n\n\t\t\t}catch (std::exception& e) {\n#ifdef SINGLETON_DEBUG\n\t\t\t\tprintf(\"[ISingleton] Could not allocate instance for class %s. Constructor not defined\\n\", typeid(T).name());\n#endif\n\t\t\t}\n#ifdef SINGLETON_DEBUG\n\t\t\tif(mInstance)\tprintf(\"[ISingleton] Instance created for class %s\\n\", typeid(T).name());\n#endif\n\t\t}\n\t\treturn *mInstance;\n\t}\n\n\tinline static T* getInstancePtr()\n\t{\n\t\tif(!mInstance)\n\t\t{\n\t\t\ttry{\n\t\t\t\tmInstance = new T();\n\n\t\t\t}catch (std::exception& e) {\n#ifdef SINGLETON_DEBUG\n\t\t\t\tprintf(\"[ISingleton] Could not allocate instance for class %s. Constructor not defined\\n\", typeid(T).name());\n#endif\n\n\t\t\t}\n#ifdef SINGLETON_DEBUG\n\t\t\tif(mInstance)\tprintf(\"[ISingleton] Instance created for class %s\\n\", typeid(T).name());\n#endif\n\t\t}\n\t\treturn mInstance;\n\t}\n\n\n\tinline static void releaseInstance()\n\t{\n\t\tif(mInstance)\n\t\t{\n\t\t\tdelete mInstance;\n\t\t\tmInstance = NULL;\n#ifdef SINGLETON_DEBUG\n\t\t\tprintf(\"[ISingleton] Instance released for class %s\\n\", typeid(T).name());\n#endif\n\t\t}\n\t}\n};\n\n\ntemplate<class T>\nT* ISingleton<T>::mInstance = NULL;\n\n\n#endif /* SINGLETON_H_ */\n"
  },
  {
    "path": "Common/include/Types.h",
    "content": "/*\n * Types.h\n *\n *  Created on: Sep 23, 2017\n *      Author: famez\n */\n\n#ifndef TYPES_H_\n#define TYPES_H_\n\n#include <stddef.h>\n#include <stdint.h>\n\n\ntypedef unsigned char \tu8;\ntypedef uint16_t     \tu16;\ntypedef uint32_t     \tu32;\ntypedef uint64_t        u64;\n\ntypedef int32_t         s32;\n\n\n#endif /* TYPES_H_ */\n"
  },
  {
    "path": "Common/include/Utils.h",
    "content": "/*\n * Utils.h\n *\n *  Created on: Mar 11, 2018\n *      Author: famez\n */\n\n#ifndef UTILS_H_\n#define UTILS_H_\n\n#include <iostream>\n#include <time.h>\n\n#include \"Types.h\"\n\n#define J1939_MIN(a,b) ((a)<(b)?(a):(b))\n#define J1939_MAX(a,b) ((a)>(b)?(a):(b))\n\nnamespace Utils {\n\nu32 getElapsedMillis(timespec* start, timespec* end);\n\n\ntimespec addMillis(timespec* time, u32 millis);\n\n\n\nclass TimeStamp {\nprivate:\n\tu32 mSeconds;\n\tu32 mMicroSec;\n\npublic:\n\tTimeStamp(): mSeconds(0), mMicroSec(0) {}\n\tTimeStamp(u32 seconds, u32 microSec) : mSeconds(seconds), mMicroSec(microSec) {}\n\t~TimeStamp() {}\n\tu32 getMicroSec() const { return mMicroSec; }\n\tvoid setMicroSec(u32 microSec) { mMicroSec = microSec; }\n\tu32 getSeconds() const { return mSeconds; }\n\tvoid setSeconds(u32 seconds) { mSeconds = seconds; }\n\n\n\tTimeStamp operator-(const TimeStamp& other) const;\n\tTimeStamp operator+(const TimeStamp& other) const;\n\tTimeStamp operator-(u32 millis) const;\n\tTimeStamp operator+(u32 millis) const;\n\tbool operator==(const TimeStamp& other) const { return (mSeconds == other.mSeconds && mMicroSec == other.mMicroSec); };\n\tbool operator>(const TimeStamp& other) const;\n\tbool operator<(const TimeStamp& other) const;\n\tbool operator<=(const TimeStamp& other) const;\n\tbool operator>=(const TimeStamp& other) const;\n\n\tstatic TimeStamp now();\n\n};\n\n}\n\n\n\n\n\n#endif /* UTILS_H_ */\n"
  },
  {
    "path": "Database/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.5)\n\nproject(Database)\n\ninstall (FILES frames.json\n    DESTINATION etc/j1939/)\n"
  },
  {
    "path": "Database/README.md",
    "content": "Contains a database with some frames defined in FMS standard. This database is used by the utilities.\n"
  },
  {
    "path": "Database/frames.json",
    "content": "[\n\t{\n\t\t\"name\" : \"VI\",\n\t\t\"pgn\" : 65260,\n\t\t\"length\" : 0,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"name\" : \"Vehicle Number Identifier\",\n\t\t\t\t\"number\" : 237,\n\t\t\t\t\"type\" : 2\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"DI\",\n\t\t\"pgn\" : 65131,\n\t\t\"length\" : 0,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"name\" : \"Driver 1 Identification\",\n\t\t\t\t\"number\" : 1625,\n\t\t\t\t\"type\" : 2\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"name\" : \"Driver 2 Identification\",\n\t\t\t\t\"number\" : 1626,\n\t\t\t\t\"type\" : 2\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"DD\",\n\t\t\"pgn\" : 65276,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 0.40000000000000002,\n\t\t\t\t\"formatOffset\" : 0,\n\t\t\t\t\"name\" : \"Fuel Level\",\n\t\t\t\t\"number\" : 96,\n\t\t\t\t\"offset\" : 1,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"%\"\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"ETC1\",\n\t\t\"pgn\" : 61442,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 0.4,\n\t\t\t\t\"formatOffset\" : 0,\n\t\t\t\t\"name\" : \"Percent Clutch Slip\",\n\t\t\t\t\"number\" : 522,\n\t\t\t\t\"offset\" : 3,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"%\"\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"ETC2\",\n\t\t\"pgn\" : 61445,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 1,\n\t\t\t\t\"formatOffset\" : -125,\n\t\t\t\t\"name\" : \"Transmission Selected Gear\",\n\t\t\t\t\"number\" : 524,\n\t\t\t\t\"offset\" : 0,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 1,\n\t\t\t\t\"formatOffset\" : -125,\n\t\t\t\t\"name\" : \"Transmission Current Gear\",\n\t\t\t\t\"number\" : 523,\n\t\t\t\t\"offset\" : 3,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"\"\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"HOURS\",\n\t\t\"pgn\" : 65253,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"byteSize\" : 4,\n\t\t\t\t\"formatGain\" : 0.05,\n\t\t\t\t\"formatOffset\" : 0,\n\t\t\t\t\"name\" : \"Engine Total Hours of Operation\",\n\t\t\t\t\"number\" : 247,\n\t\t\t\t\"offset\" : 0,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"hours\"\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"TRF1\",\n\t\t\"pgn\" : 65272,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"byteSize\" : 2,\n\t\t\t\t\"formatGain\" : 0.03125,\n\t\t\t\t\"formatOffset\" : -273,\n\t\t\t\t\"name\" : \"Transmission Oil Temperature 1\",\n\t\t\t\t\"number\" : 177,\n\t\t\t\t\"offset\" : 4,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"°C\"\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"ERC1\",\n\t\t\"pgn\" : 61440,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 4,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"Retarder - brake assist disabled\",\n\t\t\t\t\t\"Retarder - brake assist enabled\",\n\t\t\t\t\t\"Error\",\n\t\t\t\t\t\"Not available\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"Retarder Enable - Brake Assist Switch\",\n\t\t\t\t\"number\" : 571,\n\t\t\t\t\"offset\" : 0,\n\t\t\t\t\"type\" : 1\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"EBC1\",\n\t\t\"pgn\" : 61441,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 0,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"Not Fully Operational\",\n\t\t\t\t\t\"Fully Operational\",\n\t\t\t\t\t\"Error\",\n\t\t\t\t\t\"Not available\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"ABS Fully Operational\",\n\t\t\t\t\"number\" : 1243,\n\t\t\t\t\"offset\" : 5,\n\t\t\t\t\"type\" : 1\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"IC1\",\n\t\t\"pgn\" : 65270,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 2,\n\t\t\t\t\"formatOffset\" : 0,\n\t\t\t\t\"name\" : \"Engine Intake Manifold #1 Pressure\",\n\t\t\t\t\"number\" : 102,\n\t\t\t\t\"offset\" : 1,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"kPa\"\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"RF\",\n\t\t\"pgn\" : 65275,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 16,\n\t\t\t\t\"formatOffset\" : 0,\n\t\t\t\t\"name\" : \"Hydraulic Retarder Pressure\",\n\t\t\t\t\"number\" : 119,\n\t\t\t\t\"offset\" : 0,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"kPa\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 1,\n\t\t\t\t\"formatOffset\" : -40,\n\t\t\t\t\"name\" : \"Hydraulic Retarder Oil Temperature\",\n\t\t\t\t\"number\" : 120,\n\t\t\t\t\"offset\" : 1,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"°C\"\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"VDHR\",\n\t\t\"pgn\" : 65217,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"byteSize\" : 4,\n\t\t\t\t\"formatGain\" : 5,\n\t\t\t\t\"formatOffset\" : 0,\n\t\t\t\t\"name\" : \"High resolution total vehicle distance\",\n\t\t\t\t\"number\" : 917,\n\t\t\t\t\"offset\" : 0,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"m\"\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"AT1T1I\",\n\t\t\"pgn\" : 65110,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 0.4,\n\t\t\t\t\"formatOffset\" : 0,\n\t\t\t\t\"name\" : \"Aftertreatment 1 Diesel Exhaust Fluid Tank 1 Level\",\n\t\t\t\t\"number\" : 1761,\n\t\t\t\t\"offset\" : 0,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"%\"\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"EFL\",\n\t\t\"pgn\" : 65263,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 4,\n\t\t\t\t\"formatOffset\" : 0,\n\t\t\t\t\"name\" : \"Engine Fuel Delivery Pressure\",\n\t\t\t\t\"number\" : 94,\n\t\t\t\t\"offset\" : 0,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"KPa\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 0.05,\n\t\t\t\t\"formatOffset\" : 0,\n\t\t\t\t\"name\" : \"Engine Extended Crankcase Blow-by Pressure\",\n\t\t\t\t\"number\" : 22,\n\t\t\t\t\"offset\" : 1,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"KPa\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 0.4,\n\t\t\t\t\"formatOffset\" : 0,\n\t\t\t\t\"name\" : \"Engine Oil Level\",\n\t\t\t\t\"number\" : 98,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"%\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 4,\n\t\t\t\t\"formatOffset\" : 0,\n\t\t\t\t\"name\" : \"Engine Oil Pressure\",\n\t\t\t\t\"number\" : 100,\n\t\t\t\t\"offset\" : 3,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"KPa\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"byteSize\" : 2,\n\t\t\t\t\"formatGain\" : 0.0078125,\n\t\t\t\t\"formatOffset\" : -250,\n\t\t\t\t\"name\" : \"Engine Crankcase Pressure\",\n\t\t\t\t\"number\" : 101,\n\t\t\t\t\"offset\" : 4,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"KPa\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 2,\n\t\t\t\t\"formatOffset\" : 0,\n\t\t\t\t\"name\" : \"Engine Coolant Pressure\",\n\t\t\t\t\"number\" : 109,\n\t\t\t\t\"offset\" : 6,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"KPa\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 0.4,\n\t\t\t\t\"formatOffset\" : 0,\n\t\t\t\t\"name\" : \"Engine Coolant Level\",\n\t\t\t\t\"number\" : 111,\n\t\t\t\t\"offset\" : 7,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"%\"\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"LFC\",\n\t\t\"pgn\" : 65257,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"byteSize\" : 4,\n\t\t\t\t\"formatGain\" : 0.5,\n\t\t\t\t\"formatOffset\" : 0,\n\t\t\t\t\"name\" : \"Engine total fuel used\",\n\t\t\t\t\"number\" : 250,\n\t\t\t\t\"offset\" : 4,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"L\"\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"ET1\",\n\t\t\"pgn\" : 65262,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 1,\n\t\t\t\t\"formatOffset\" : -40,\n\t\t\t\t\"name\" : \"Engine Coolant Temperature\",\n\t\t\t\t\"number\" : 110,\n\t\t\t\t\"offset\" : 0,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"°C\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"byteSize\" : 2,\n\t\t\t\t\"formatGain\" : 0.03125,\n\t\t\t\t\"formatOffset\" : -273,\n\t\t\t\t\"name\" : \"Engine Oil Temperature 1\",\n\t\t\t\t\"number\" : 175,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"°C\"\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"TRF1\",\n\t\t\"pgn\" : 65272,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 16,\n\t\t\t\t\"formatOffset\" : 0,\n\t\t\t\t\"name\" : \"Clutch Pressure\",\n\t\t\t\t\"number\" : 123,\n\t\t\t\t\"offset\" : 0,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"kPa\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 0.4,\n\t\t\t\t\"formatOffset\" : 0,\n\t\t\t\t\"name\" : \"Transmission Oil Level\",\n\t\t\t\t\"number\" : 124,\n\t\t\t\t\"offset\" : 1,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"%\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 2,\n\t\t\t\t\"formatOffset\" : 0,\n\t\t\t\t\"name\" : \"Transmission Filter Differential Pressure\",\n\t\t\t\t\"number\" : 126,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"kPa\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 16,\n\t\t\t\t\"formatOffset\" : 0,\n\t\t\t\t\"name\" : \"Transmission Oil Pressure\",\n\t\t\t\t\"number\" : 127,\n\t\t\t\t\"offset\" : 3,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"kPa\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"byteSize\" : 2,\n\t\t\t\t\"formatGain\" : 0.03125,\n\t\t\t\t\"formatOffset\" : -273,\n\t\t\t\t\"name\" : \"Transmission Oil Temperature\",\n\t\t\t\t\"number\" : 177,\n\t\t\t\t\"offset\" : 4,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"kPa\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 0.5,\n\t\t\t\t\"formatOffset\" : -62.5,\n\t\t\t\t\"name\" : \"Transmission Oil Level High / Low\",\n\t\t\t\t\"number\" : 3027,\n\t\t\t\t\"offset\" : 6,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"L\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 0.5,\n\t\t\t\t\"formatOffset\" : -62.5,\n\t\t\t\t\"name\" : \"Transmission Oil Level Countdown Timer\",\n\t\t\t\t\"number\" : 3027,\n\t\t\t\t\"offset\" : 6,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"L\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 0,\n\t\t\t\t\"bitSize\" : 4,\n\t\t\t\t\"name\" : \"Transmission Oil Level Countdown Timer\",\n\t\t\t\t\"number\" : 3028,\n\t\t\t\t\"offset\" : 7,\n\t\t\t\t\"type\" : 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 4,\n\t\t\t\t\"bitSize\" : 4,\n\t\t\t\t\"name\" : \"Transmission Oil Level Measurement Status\",\n\t\t\t\t\"number\" : 3026,\n\t\t\t\t\"offset\" : 7,\n\t\t\t\t\"type\" : 1\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"LFE\",\n\t\t\"pgn\" : 65266,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"byteSize\" : 2,\n\t\t\t\t\"formatGain\" : 0.05,\n\t\t\t\t\"formatOffset\" : 0,\n\t\t\t\t\"name\" : \"Fuel Rate\",\n\t\t\t\t\"number\" : 183,\n\t\t\t\t\"offset\" : 0,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"L/h\"\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"HRLFC\",\n\t\t\"pgn\" : 64777,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"byteSize\" : 4,\n\t\t\t\t\"formatGain\" : 0.001,\n\t\t\t\t\"formatOffset\" : 0,\n\t\t\t\t\"name\" : \"High resolution engine total fuel used\",\n\t\t\t\t\"number\" : 5054,\n\t\t\t\t\"offset\" : 4,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"L\"\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"EEC2\",\n\t\t\"pgn\" : 61443,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 0.4,\n\t\t\t\t\"formatOffset\" : 0,\n\t\t\t\t\"name\" : \"Accelerator pedal position 1\",\n\t\t\t\t\"number\" : 91,\n\t\t\t\t\"offset\" : 1,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"%\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 1,\n\t\t\t\t\"formatOffset\" : 0,\n\t\t\t\t\"name\" : \"Engine Percent Load At Current Speed\",\n\t\t\t\t\"number\" : 92,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"%\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 0,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"Accelerator pedal 1 not in low idle condition\",\n\t\t\t\t\t\"Accelerator pedal 1 in low idle condition\",\n\t\t\t\t\t\"Error\",\n\t\t\t\t\t\"Not available\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"Accelerator Pedal 1 Low Idle Switch\",\n\t\t\t\t\"number\" : 558,\n\t\t\t\t\"offset\" : 0,\n\t\t\t\t\"type\" : 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 6,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"Accelerator pedal 2 not in low idle condition\",\n\t\t\t\t\t\"Accelerator pedal 2 in low idle condition\",\n\t\t\t\t\t\"Error\",\n\t\t\t\t\t\"Not available\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"Accelerator Pedal 2 Low Idle Switch\",\n\t\t\t\t\"number\" : 2970,\n\t\t\t\t\"offset\" : 0,\n\t\t\t\t\"type\" : 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 2,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"Kickdown passive\",\n\t\t\t\t\t\"Kickdown active\",\n\t\t\t\t\t\"Error\",\n\t\t\t\t\t\"Not available\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"Accelerator Pedal Kickdown Switch\",\n\t\t\t\t\"number\" : 559,\n\t\t\t\t\"offset\" : 0,\n\t\t\t\t\"type\" : 1\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"TCO1\",\n\t\t\"pgn\" : 65132,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 0,\n\t\t\t\t\"bitSize\" : 3,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"Rest\",\n\t\t\t\t\t\"Driver Available\",\n\t\t\t\t\t\"Work\",\n\t\t\t\t\t\"Drive\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"Driver 1 Working State\",\n\t\t\t\t\"number\" : 1612,\n\t\t\t\t\"offset\" : 0,\n\t\t\t\t\"type\" : 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 3,\n\t\t\t\t\"bitSize\" : 3,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"Rest\",\n\t\t\t\t\t\"Driver Available\",\n\t\t\t\t\t\"Work\",\n\t\t\t\t\t\"Drive\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"Driver 2 Working State\",\n\t\t\t\t\"number\" : 1613,\n\t\t\t\t\"offset\" : 0,\n\t\t\t\t\"type\" : 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 4,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"Card not present\",\n\t\t\t\t\t\"Card present\",\n\t\t\t\t\t\"Error\",\n\t\t\t\t\t\"Not available\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"Driver 1 Card\",\n\t\t\t\t\"number\" : 1615,\n\t\t\t\t\"offset\" : 1,\n\t\t\t\t\"type\" : 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 4,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"Card not present\",\n\t\t\t\t\t\"Card present\",\n\t\t\t\t\t\"Error\",\n\t\t\t\t\t\"Not available\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"Driver 2 Card\",\n\t\t\t\t\"number\" : 1616,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 1\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"DC1\",\n\t\t\"pgn\" : 65102,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 6,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"all bus doors disabled\",\n\t\t\t\t\t\"at least 1 bus door enabled\",\n\t\t\t\t\t\"Error\",\n\t\t\t\t\t\"Not available\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"Status 2 of doors\",\n\t\t\t\t\"number\" : 3411,\n\t\t\t\t\"offset\" : 0,\n\t\t\t\t\"type\" : 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 4,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"inside bus\",\n\t\t\t\t\t\"outside bus\",\n\t\t\t\t\t\"Error\",\n\t\t\t\t\t\"Not available\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"Ramp/Wheel chairlift\",\n\t\t\t\t\"number\" : 1820,\n\t\t\t\t\"offset\" : 0,\n\t\t\t\t\"type\" : 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 0,\n\t\t\t\t\"bitSize\" : 4,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"at least 1 door is open\",\n\t\t\t\t\t\"closing last door\",\n\t\t\t\t\t\"all doors closed\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"Position of doors\",\n\t\t\t\t\"number\" : 1821,\n\t\t\t\t\"offset\" : 0,\n\t\t\t\t\"type\" : 1\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"AS\",\n\t\t\"pgn\" : 65237,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 0,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"Alternator 1 not charging\",\n\t\t\t\t\t\"Alternator 1 charging\",\n\t\t\t\t\t\"Error\",\n\t\t\t\t\t\"Not available\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"Alternator 1 Status\",\n\t\t\t\t\"number\" : 3353,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 2,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"Alternator 2 not charging\",\n\t\t\t\t\t\"Alternator 2 charging\",\n\t\t\t\t\t\"Error\",\n\t\t\t\t\t\"Not available\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"Alternator 2 Status\",\n\t\t\t\t\"number\" : 3354,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 4,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"Alternator 3 not charging\",\n\t\t\t\t\t\"Alternator 3 charging\",\n\t\t\t\t\t\"Error\",\n\t\t\t\t\t\"Not available\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"Alternator 3 Status\",\n\t\t\t\t\"number\" : 3355,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 6,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"Alternator 4 not charging\",\n\t\t\t\t\t\"Alternator 4 charging\",\n\t\t\t\t\t\"Error\",\n\t\t\t\t\t\"Not available\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"Alternator 4 Status\",\n\t\t\t\t\"number\" : 3356,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 1\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"CCVS\",\n\t\t\"pgn\" : 65265,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 0,\n\t\t\t\t\"bitSize\" : 5,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"Off\",\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"Set\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"PTO State\",\n\t\t\t\t\"number\" : 976,\n\t\t\t\t\"offset\" : 6,\n\t\t\t\t\"type\" : 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"byteSize\" : 2,\n\t\t\t\t\"formatGain\" : 0.00390625,\n\t\t\t\t\"formatOffset\" : 0,\n\t\t\t\t\"name\" : \"Wheel Speed\",\n\t\t\t\t\"number\" : 84,\n\t\t\t\t\"offset\" : 1,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"km/h\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 4,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"Pedal released\",\n\t\t\t\t\t\"Pedal depressed\",\n\t\t\t\t\t\"Error\",\n\t\t\t\t\t\"Not available\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"Brake Switch\",\n\t\t\t\t\"number\" : 597,\n\t\t\t\t\"offset\" : 3,\n\t\t\t\t\"type\" : 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 6,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"Pedal released\",\n\t\t\t\t\t\"Pedal depressed\",\n\t\t\t\t\t\"Error\",\n\t\t\t\t\t\"Not available\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"Clutch Switch\",\n\t\t\t\t\"number\" : 598,\n\t\t\t\t\"offset\" : 3,\n\t\t\t\t\"type\" : 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 2,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"Parking brake not set\",\n\t\t\t\t\t\"Parking brake set\",\n\t\t\t\t\t\"Error\",\n\t\t\t\t\t\"Not available\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"Parking Brake Switch\",\n\t\t\t\t\"number\" : 70,\n\t\t\t\t\"offset\" : 0,\n\t\t\t\t\"type\" : 1\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"PTODE\",\n\t\t\"pgn\" : 64932,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 0,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"No PTO drive is engaged\",\n\t\t\t\t\t\"At least one PTO drive is engaged\",\n\t\t\t\t\t\"Error\",\n\t\t\t\t\t\"Not available\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"At least one PTO engaged\",\n\t\t\t\t\"number\" : 3948,\n\t\t\t\t\"offset\" : 6,\n\t\t\t\t\"type\" : 1\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"EEC1\",\n\t\t\"pgn\" : 61444,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"byteSize\" : 2,\n\t\t\t\t\"formatGain\" : 0.125,\n\t\t\t\t\"formatOffset\" : 0,\n\t\t\t\t\"name\" : \"Engine Speed\",\n\t\t\t\t\"number\" : 190,\n\t\t\t\t\"offset\" : 3,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"rpm\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 1.0,\n\t\t\t\t\"formatOffset\" : -125,\n\t\t\t\t\"name\" : \"Percent Torque\",\n\t\t\t\t\"number\" : 513,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"%\"\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"AMB\",\n\t\t\"pgn\" : 65269,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 0.5,\n\t\t\t\t\"formatOffset\" : 0,\n\t\t\t\t\"name\" : \"Barometric Pressure\",\n\t\t\t\t\"number\" : 108,\n\t\t\t\t\"offset\" : 0,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"kPa\"\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"SERV\",\n\t\t\"pgn\" : 65216,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"byteSize\" : 2,\n\t\t\t\t\"formatGain\" : 5,\n\t\t\t\t\"formatOffset\" : -160635,\n\t\t\t\t\"name\" : \"Service distance\",\n\t\t\t\t\"number\" : 914,\n\t\t\t\t\"offset\" : 1,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"km\"\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"DC2\",\n\t\t\"pgn\" : 64933,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 2,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"Closed\",\n\t\t\t\t\t\"Open\",\n\t\t\t\t\t\"Error\",\n\t\t\t\t\t\"Not available\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"Open Status Door 1\",\n\t\t\t\t\"number\" : 3413,\n\t\t\t\t\"offset\" : 0,\n\t\t\t\t\"type\" : 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 0,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"Closed\",\n\t\t\t\t\t\"Open\",\n\t\t\t\t\t\"Error\",\n\t\t\t\t\t\"Not available\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"Open Status Door 2\",\n\t\t\t\t\"number\" : 3416,\n\t\t\t\t\"offset\" : 1,\n\t\t\t\t\"type\" : 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 6,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"Closed\",\n\t\t\t\t\t\"Open\",\n\t\t\t\t\t\"Error\",\n\t\t\t\t\t\"Not available\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"Open Status Door 3\",\n\t\t\t\t\"number\" : 3419,\n\t\t\t\t\"offset\" : 1,\n\t\t\t\t\"type\" : 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 4,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"Closed\",\n\t\t\t\t\t\"Open\",\n\t\t\t\t\t\"Error\",\n\t\t\t\t\t\"Not available\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"Open Status Door 3\",\n\t\t\t\t\"number\" : 3422,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 1\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"VDC2\",\n\t\t\"pgn\" : 61449,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"byteSize\" : 2,\n\t\t\t\t\"formatGain\" : 0.00048828125,\n\t\t\t\t\"formatOffset\" : -15.687,\n\t\t\t\t\"name\" : \"Lateral Acceleration\",\n\t\t\t\t\"number\" : 1809,\n\t\t\t\t\"offset\" : 5,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"m/s2\"\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"EBC2\",\n\t\t\"pgn\" : 65215,\n\t\t\"length\" : 8,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"byteSize\" : 2,\n\t\t\t\t\"formatGain\" : 0.00390625,\n\t\t\t\t\"formatOffset\" : 0,\n\t\t\t\t\"name\" : \"Front Axe Speed\",\n\t\t\t\t\"number\" : 904,\n\t\t\t\t\"offset\" : 0,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"kph\"\n\t\t\t},{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 0.0625,\n\t\t\t\t\"formatOffset\" : -7.18125,\n\t\t\t\t\"name\" : \"Relative Speed; Front Axle, Left Wheel\",\n\t\t\t\t\"number\" : 905,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"kph\"\n\t\t\t},{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 0.0625,\n\t\t\t\t\"formatOffset\" : -7.18125,\n\t\t\t\t\"name\" : \"Relative Speed; Front Axle, Right Wheel\",\n\t\t\t\t\"number\" : 906,\n\t\t\t\t\"offset\" : 3,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"kph\"\n\t\t\t},{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 0.0625,\n\t\t\t\t\"formatOffset\" : -7.18125,\n\t\t\t\t\"name\" : \"Relative Speed; Rear Axle 1, Left Wheel\",\n\t\t\t\t\"number\" : 907,\n\t\t\t\t\"offset\" : 4,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"kph\"\n\t\t\t},{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 0.0625,\n\t\t\t\t\"formatOffset\" : -7.18125,\n\t\t\t\t\"name\" : \"Relative Speed; Rear Axle 1, Right Wheel\",\n\t\t\t\t\"number\" : 908,\n\t\t\t\t\"offset\" : 5,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"kph\"\n\t\t\t},{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 0.0625,\n\t\t\t\t\"formatOffset\" : -7.18125,\n\t\t\t\t\"name\" : \"Relative Speed; Rear Axle 2, Left Wheel\",\n\t\t\t\t\"number\" : 909,\n\t\t\t\t\"offset\" : 6,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"kph\"\n\t\t\t},{\n\t\t\t\t\"byteSize\" : 1,\n\t\t\t\t\"formatGain\" : 0.0625,\n\t\t\t\t\"formatOffset\" : -7.18125,\n\t\t\t\t\"name\" : \"Relative Speed; Rear Axle 2, Right Wheel\",\n\t\t\t\t\"number\" : 910,\n\t\t\t\t\"offset\" : 7,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"kph\"\n\t\t\t}\n\t\t]\n\t}\n]\n"
  },
  {
    "path": "GUI_WEB/README.md",
    "content": "![alt text](https://github.com/famez/J1939-Framework/blob/master/GUI_WEB/J1939GUI.png)\n"
  },
  {
    "path": "GUI_WEB/backend/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.5)\n\nproject(j1939GUI)\n\nset (GUI_SERVER_DIR \"/var/www/j1939gui\")\n\nadd_definitions(-DHTTP_DIR=\"${GUI_SERVER_DIR}\")\n\nprotobuf_generate_cpp(PROTO_SRCS PROTO_HDRS graph.proto)\n\nadd_executable(j1939GUI \n    src/J1939GUI.cpp\n    src/graph.cpp\n    ${PROTO_SRCS}\n    ${PROTO_HDRS}\n)\n\n\n#Visible for frontend\nconfigure_file(graph.proto ../frontend/graph.proto COPYONLY)\n\ntarget_include_directories(j1939GUI\n    PUBLIC \n        . ${J1939_SOURCE_DIR}/include ${Can_SOURCE_DIR}/include ${Common_SOURCE_DIR}/include ${LIBWEBSOCKETS_INCLUDE_DIR} ${Protobuf_INCLUDE_DIRS}\n)\n\nlink_directories(${LIBWEBSOCKETS_LIBRARY_DIR})\n\n\ntarget_link_libraries(j1939GUI\n    PUBLIC\n        J1939 Can rt -rdynamic jsoncpp ${LIBWEBSOCKETS_LIBRARIES} ${Protobuf_LIBRARIES}\n)\n\ninstall (TARGETS j1939GUI\n    DESTINATION bin)\n\ninstall (DIRECTORY ../frontend/\n\tDESTINATION ${GUI_SERVER_DIR})\n    "
  },
  {
    "path": "GUI_WEB/backend/graph.proto",
    "content": "syntax = \"proto3\";\n\nmessage Graph {\n\n\tstring title = 1;\n\tint32 number = 2;\n\tAxis axisX = 3;\n\tAxis axisY = 4;\n\trepeated Sample samples = 5;\n\n\tmessage Sample {\n\t\tdouble x = 1;\n\t\tdouble y = 2;\n\t}\n\n}\n\nmessage Axis {\n\tstring units = 1;\n\tdouble max = 2;\n\tdouble min = 3;\n}\n"
  },
  {
    "path": "GUI_WEB/backend/src/J1939GUI.cpp",
    "content": "extern \"C\" {\n\n#include <stdio.h>\n#include <libwebsockets.h>\n\n}\n\n\n#include <string>\n#include <iostream>\n#include <sstream>\n#include <map>\n#include <vector>\n#include <thread>\n#include <mutex>\n#include <queue>\n\n#include <json/json.h>\n\n//J1939 libraries\n#include <J1939DataBase.h>\n#include <J1939Factory.h>\n#include <GenericFrame.h>\n#include <Transport/BAM/BamFragmenter.h>\n#include <Transport/BAM/BamReassembler.h>\n#include <Diagnosis/Frames/DM1.h>\n#include <SPN/SPNNumeric.h>\n#include <SPN/SPNStatus.h>\n#include <SPN/SPNString.h>\n#include <Utils.h>\n\n\n//Can includes\n#include <CanEasy.h>\n\n#include \"graph.h\"\n\n\n#ifndef DATABASE_PATH\n#define DATABASE_PATH\t\t\"/etc/j1939/frames.json\"\n#endif\n\n\n#define J1939_RX_BUFFER_BYTES (1024)\n\n//Bitrate for J1939 protocol\n#define BAUD_250K\t\t\t250000\n\n#define LIST_FRAMES_REQUEST\t\t\"list frames\"\n#define ADD_FRAME_REQUEST\t\t\"add frame\"\n#define SET_FRAME_REQUEST\t\t\"set frame\"\n#define DELETE_FRAME_REQUEST\t\"delete frame\"\n#define LIST_INTERFACES\t\t\t\"list interfaces\"\n#define SHOW_RAW\t\t\t\t\"show raw\"\n\n\nbool processRequest(const Json::Value& request, Json::Value& response);\n\nvoid resetReceiver();\n\nbool sentFramesToJson(Json::Value& jsonVal);\n\nint callback_http(struct lws *wsi, enum lws_callback_reasons reason,\n\t\tvoid *user, void *in, size_t len);\n\nint callback_j1939(struct lws *wsi, enum lws_callback_reasons reason,\n\t\tvoid *user, void *in, size_t len);\n\n\nstd::string rcvRequest;\nstd::queue<Json::Value> jsonResponses;\n\nJson::Value rxFrames;\n\nbool showRaw;\t\t//Option to show packets not able to decode\n\n\nstatic struct lws_protocols protocols[] = {\n\t/* The first protocol must always be the HTTP handler */\n\t{\n\t\t\t\"http-only\", /* name */\n\t\t\tcallback_http, /* callback */\n\t\t\t0, /* No per session data. */\n\t\t\t0, /* max frame size / rx buffer */\n\t}, {\n\t\t\t\"j1939-protocol\", callback_j1939, 0,\n\t\t\tJ1939_RX_BUFFER_BYTES,\n\t}, {\n\t\t\t\"graph-protocol\", callback_graph, sizeof(void*),\t\t//Enough to store our pointer to graph\n\t\t\tJ1939_RX_BUFFER_BYTES,\n\t},\n\t{ NULL, NULL, 0, 0 } /* terminator */\n};\n\n\nusing namespace J1939;\nusing namespace Can;\nusing namespace Utils;\n\nbool isFrameSent(const J1939Frame* frame, const std::string& interface);\nvoid sendFrameThroughInterface(const J1939Frame* j1939Frame, u32 period, const std::string& interface);\nvoid unsendFrameThroughInterface(const J1939Frame* j1939Frame, const std::string& interface);\n\nJson::Value frameToJson(const J1939Frame* frame);\n\n\nvoid onRcv(const CanFrame& frame, const TimeStamp&, const std::string& interface, void*);\nbool onTimeout();\n\n\n//Map of the created frames to be sent to the CAN interface\nstd::vector<J1939Frame*> framesToSend;\n\n//Map to specify the period for the different frames (in millis)\nstd::map<J1939Frame*, u32> framePeriods;\n\n//To reassemble frames fragmented by means of Broadcast Announce Message protocol\nBamReassembler reassembler;\n\n//Thread in charge of sniffing the Can Network\nstd::unique_ptr<std::thread> rxThread = nullptr;\nstd::mutex rxLock;\n\n//Cached received frames to avoid processing frames that did not change\nstd::map<u32/*Can ID*/, CanFrame> rcvFramesCache;\n\n//To track how many frames have been received\nstd::map<u32/*Can ID*/, u32/*Count*/> rcvFramesCount;\n\nstatic const lws_protocol_vhost_options mimetypes= {\n\t\tnullptr,\n\t\tnullptr,\n\t\t\".proto\",\n\t\t\"application/x-protobuf\"\n};\n\n//Used to serve files from http server\nstatic lws_http_mount mount;\n\n\nint callback_http(lws *wsi, enum lws_callback_reasons reason,\n\t\tvoid *user, void *in, size_t len) {\n\tswitch (reason) {\n\tcase LWS_CALLBACK_HTTP:\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\n\treturn 0;\n}\n\nint callback_j1939(lws *wsi, enum lws_callback_reasons reason,\n\t\tvoid *user, void *in, size_t len) {\n\n\n\tswitch (reason) {\n\n\tcase LWS_CALLBACK_ESTABLISHED: {\n\n\t\tresetReceiver();\n\n\t}\tbreak;\n\n\tcase LWS_CALLBACK_RECEIVE: {\n\n\t\tJson::Value rcvjson;\n\t\tJson::Value respjson;\n\n\t\tJson::CharReaderBuilder builder;\n\t\tJson::CharReader *jSonReader = builder.newCharReader();\n\t\tstd::string errs;\n\n\t\trcvRequest.append((char*)in, len);\n\n\t\tif(jSonReader->parse(rcvRequest.c_str(), rcvRequest.c_str() + rcvRequest.size(), &rcvjson, &errs)) {\t\t//Verify if we received the whole Json string\n\n\t\t\tlwsl_info(\"Json request: %s\\n\", rcvRequest.c_str());\n\n\t\t\trcvRequest.clear();\n\n\t\t\tif(rcvjson.isMember(\"command\") && rcvjson[\"command\"].isString()) {\n\t\t\t\t\n\t\t\t\tif(rcvjson[\"command\"] == \"reset rx\") {\n\n\t\t\t\t\tresetReceiver();\n\n\t\t\t\t} else if(rcvjson[\"command\"] == \"check rx\") {\n\n\t\t\t\t\trxLock.lock();\n\t\t\t\t\tjsonResponses.push(rxFrames);\n\t\t\t\t\trxFrames[\"rx\"].clear();\n\t\t\t\t\trxLock.unlock();\n\n\t\t\t\t\tlws_callback_on_writable_all_protocol(lws_get_context(wsi),\n\t\t\t\t\t\t\t\t\t\t\t\tlws_get_protocol(wsi));\n\n\n\t\t\t\t} else if(processRequest(rcvjson, respjson)) {\n\n\n\t\t\t\t\tsentFramesToJson(respjson[\"frames\"]);\n\n\t\t\t\t\tjsonResponses.push(respjson);\n\n\n\t\t\t\t\tlws_callback_on_writable_all_protocol(lws_get_context(wsi),\n\t\t\t\t\t\t\t\t\t\t\t\tlws_get_protocol(wsi));\n\t\t\t\t}\n\t\t\t\t\n\t\t\t}\n\n\t\t}\n\n\t\tdelete jSonReader;\n\n\n\t}\tbreak;\n\n\tcase LWS_CALLBACK_SERVER_WRITEABLE: {\n\n\n\n\t\tif(!jsonResponses.empty()) {\t\t\t//Check if there are enqueued responses to send\n\n\t\t\tstd::stringstream sstr;\n\n\t\t\tsstr << jsonResponses.front();\n\t\t\t\n\t\t\tlwsl_info(\"Response: %s\", sstr.str().c_str());\n\n\t\t\tchar *buff = new char[LWS_SEND_BUFFER_PRE_PADDING + sstr.str().size() + LWS_SEND_BUFFER_POST_PADDING];\n\n\t\t\tmemcpy(buff + LWS_SEND_BUFFER_PRE_PADDING, sstr.str().c_str(), sstr.str().size());\n\n\t\t\tlws_write(wsi, (unsigned char*)(buff + LWS_SEND_BUFFER_PRE_PADDING),\n\t\t\t\t\tsstr.str().size(), LWS_WRITE_TEXT);\n\n\t\t\tjsonResponses.pop();\n\n\t\t\tdelete[] buff;\n\n\t\t}\n\t\t\n\t\tif(!jsonResponses.empty()) {\t\t\t\t\t\t\t\t\t//Check again if there are enqueued responses to have another chance to send them\t\t\n\t\t\tlws_callback_on_writable_all_protocol(lws_get_context(wsi),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlws_get_protocol(wsi));\n\t\t}\n\n\n\t}\tbreak;\n\n\tdefault:\n\t\tbreak;\n\t}\n\n\treturn 0;\n}\n\n\nbool processRequest(const Json::Value& request, Json::Value& response) {\n\n\n\tresponse[\"command\"] = request[\"command\"].asString();\n\n\tunsigned int i = 0;\n\t\n\t\n\t//Activate show raw functionality\n\tif(request[\"command\"] == SHOW_RAW) {\n\t\t\n\t\tif(request.isMember(\"raw\") && request[\"raw\"].isBool()) {\n\t\t\tshowRaw = request[\"raw\"].asBool();\n\t\t}\n\t\t\n\t\treturn false;\t\t//No need to send a response\n\t}\n\n\tif(request[\"command\"] == LIST_FRAMES_REQUEST) {\n\n\t\tstd::set<u32> pgns = J1939Factory::getInstance().getAllRegisteredPGNs();\n\n\n\t\tfor(auto pgn = pgns.begin(); pgn != pgns.end(); ++pgn) {\n\n\t\t\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(*pgn);\n\n\t\t\t//Only add to the list if it is a generic frame\n\n\t\t\tif(frame->isGenericFrame()) {\n\t\t\t\tresponse[\"data\"][i][\"pgn\"] = std::to_string(*pgn);\n\t\t\t\tresponse[\"data\"][i][\"name\"] = frame->getName();\n\t\t\t\t++i;\n\t\t\t}\n\n\t\t}\n\t\treturn true;\n\t}\n\n\tif(request[\"command\"] == ADD_FRAME_REQUEST) {\n\n\t\tif(!request.isMember(\"data\") || !request[\"data\"].isUInt())\treturn false;\n\n\t\tu32 pgn = request[\"data\"].asUInt();\n\n\t\tstd::unique_ptr<J1939Frame> frameToAdd = J1939Factory::getInstance().getJ1939Frame(pgn);\n\n\t\tif(!frameToAdd || !frameToAdd->isGenericFrame()) {\n\t\t\tlwsl_err(\"Frame not recognized...\\n\");\n\t\t\treturn false;\n\t\t}\n\n\t\tframesToSend.push_back(frameToAdd.release());\n\n\t\treturn true;\n\t}\n\n\n\t//Delete frame\n\tif(request[\"command\"] == DELETE_FRAME_REQUEST) {\n\n\t\t//Sanity checks...\n\n\t\tif(!request.isMember(\"index\") || !request[\"index\"].isUInt()) {\n\t\t\tlwsl_err(\"Index not specified\");\n\t\t\treturn false;\n\t\t}\n\n\t\tsize_t index = request[\"index\"].asUInt();\n\n\t\tif(index >= framesToSend.size()) {\n\t\t\tlwsl_err(\"Index out of range... Someone is playing maliciously with the frontend...\");\n\t\t\treturn false;\n\t\t}\n\n\t\tJ1939Frame *frame = framesToSend[index];\n\n\t\t//At this point, if the frame is being sent, refresh the information to the sender\n\t\tconst std::set<std::string>& ifaces = CanEasy::getInitializedCanIfaces();\n\n\t\tfor(auto iter = ifaces.begin(); iter != ifaces.end(); ++iter) {\n\t\t\tstd::shared_ptr<ICanSender> sender = CanEasy::getSender(*iter);\n\n\t\t\tif(isFrameSent(frame, *iter)) {\n\n\t\t\t\tauto period = framePeriods.find(frame);\n\n\t\t\t\tif(period != framePeriods.end()) {\n\n\t\t\t\t\tunsendFrameThroughInterface(frame, *iter);\n\n\t\t\t\t} else {\n\n\t\t\t\t\tlwsl_err(\"Period not defined\");\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tframesToSend.erase(framesToSend.begin() + index);\n\n\t\treturn true;\n\t}\n\n\tif(request[\"command\"] == SET_FRAME_REQUEST) {\n\n\t\t//Sanity checks...\n\n\t\tif(!request.isMember(\"index\") || !request[\"index\"].isUInt()) {\n\t\t\tlwsl_err(\"Index not specified\");\n\t\t\treturn false;\n\t\t}\n\n\t\tsize_t index = request[\"index\"].asUInt();\n\n\t\tif(index >= framesToSend.size()) {\n\t\t\tlwsl_err(\"Index out of range... Someone is playing maliciously with the frontend...\");\n\t\t\treturn false;\n\t\t}\n\n\t\tJ1939Frame *frame = framesToSend[index];\n\n\n\t\t//Change priority\n\t\tif(request.isMember(\"prio\") && request[\"prio\"].isUInt() && ((request[\"prio\"].asUInt() & J1939_PRIORITY_MASK) == request[\"prio\"].asUInt())) {\n\n\t\t\tu8 prio = request[\"prio\"].asUInt();\n\n\t\t\tframe->setPriority(prio);\n\n\t\t\tlwsl_info(\"Prio set\");\n\n\t\t}\n\n\t\t//Change source\n\t\tif(request.isMember(\"src\") && request[\"src\"].isUInt() && ((request[\"src\"].asUInt() & J1939_SRC_ADDR_MASK) == request[\"src\"].asUInt())) {\n\n\t\t\tu8 src = request[\"src\"].asUInt();\n\n\t\t\tframe->setSrcAddr(src);\n\n\t\t\tlwsl_info(\"Src set\");\n\n\t\t}\n\n\n\t\t//Change destination\n\t\tif(request.isMember(\"dest\") && request[\"dest\"].isUInt() && ((request[\"dest\"].asUInt() & J1939_DST_ADDR_MASK) == request[\"dest\"].asUInt())) {\n\n\t\t\tu8 dest = request[\"dest\"].asUInt();\n\n\t\t\tframe->setDstAddr(dest);\n\n\t\t\tlwsl_info(\"Dest set\");\n\n\t\t}\n\n\t\t//Change period\n\t\tif(request.isMember(\"period\") && request[\"period\"].isUInt()) {\n\n\t\t\tu32 period = request[\"period\"].asUInt();\n\n\t\t\tframePeriods[frame] = period;\n\n\t\t\tlwsl_info(\"Period set\");\n\n\t\t}\n\n\n\t\t//Change spn value\n\n\t\tif(frame->isGenericFrame()) {\t\t//Sanity check...\n\n\t\t\tGenericFrame *genFrame = static_cast<GenericFrame *>(frame);\n\n\n\t\t\tif(request.isMember(\"spn\") && request[\"spn\"].isUInt() && genFrame->hasSPN(request[\"spn\"].asUInt())) {\n\n\t\t\t\tSPN *spn = genFrame->getSPN(request[\"spn\"].asUInt());\n\n\n\t\t\t\tswitch(spn->getType()) {\n\n\t\t\t\tcase SPN::SPN_STATUS: {\n\n\t\t\t\t\tSPNStatus * status = static_cast<SPNStatus *>(spn);\n\n\t\t\t\t\tif(request.isMember(\"value\") && request[\"value\"].isUInt() && ((request[\"value\"].asUInt() & 0xFF) == request[\"value\"].asUInt())) {\n\n\t\t\t\t\t\tu8 value = request[\"value\"].asUInt();\n\t\t\t\t\t\tstatus->setValue(value);\n\n\t\t\t\t\t}\n\n\t\t\t\t}\tbreak;\n\n\t\t\t\tcase SPN::SPN_NUMERIC: {\n\n\t\t\t\t\tSPNNumeric *numeric = static_cast<SPNNumeric *>(spn);\n\n\t\t\t\t\tif(request.isMember(\"value\") && request[\"value\"].isDouble()) {\n\n\t\t\t\t\t\tdouble value = request[\"value\"].asDouble();\n\t\t\t\t\t\tnumeric->setFormattedValue(value);\n\n\t\t\t\t\t}\n\n\t\t\t\t}\tbreak;\n\n\t\t\t\tcase SPN::SPN_STRING: {\n\n\t\t\t\t\tSPNString *strSpn = static_cast<SPNString *>(spn);\n\n\t\t\t\t\tif(request.isMember(\"value\") && request[\"value\"].isString()) {\n\n\t\t\t\t\t\tstd::string value = request[\"value\"].asString();\n\t\t\t\t\t\tstrSpn->setValue(value);\n\n\t\t\t\t\t}\n\n\t\t\t\t}\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\n\t\t\t}\n\n\t\t}\n\n\n\t\t//At this point, if the frame is being sent, refresh the information to the sender\n\n\t\tconst std::set<std::string>& ifaces = CanEasy::getInitializedCanIfaces();\n\n\t\tfor(auto iter = ifaces.begin(); iter != ifaces.end(); ++iter) {\n\t\t\tstd::shared_ptr<ICanSender> sender = CanEasy::getSender(*iter);\n\n\t\t\tif(isFrameSent(frame, *iter)) {\n\n\t\t\t\tauto period = framePeriods.find(frame);\n\n\t\t\t\tif(period != framePeriods.end()) {\n\n\t\t\t\t\tsendFrameThroughInterface(frame, period->second, *iter);\n\n\t\t\t\t} else {\n\n\t\t\t\t\tlwsl_err(\"Period not defined\");\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\n\t\t//Send/unsend frame through the interface\n\t\tif(request.isMember(\"interface\") && request[\"interface\"].isObject()) {\n\n\t\t\tstd::vector<JSONCPP_STRING> members = request[\"interface\"].getMemberNames();\n\n\t\t\tfor(auto member = members.begin(); member != members.end(); ++member) {\n\n\t\t\t\tif(request[\"interface\"][*member].isBool()) {\n\n\t\t\t\t\tif(request[\"interface\"][*member].asBool()) {\t\t\t//Send frame through interface\n\n\t\t\t\t\t\tauto period = framePeriods.find(frame);\n\n\t\t\t\t\t\tif(period != framePeriods.end()) {\n\n\t\t\t\t\t\t\tsendFrameThroughInterface(frame, period->second, *member);\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\tlwsl_err(\"Period not defined\");\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\t\t\t\t\t\t\t\t\t\t\t\t//Unsend frame\n\t\t\t\t\t\tunsendFrameThroughInterface(frame, *member);\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\n\t\t\tlwsl_info(\"Period set\");\n\n\t\t}\n\n\n\t\treturn true;\n\n\t}\n\n\n\n\treturn false;\n\n}\n\nint main(int argc, char *argv[]) {\n\t\n\tlws_context_creation_info info;\n\t\n\tshowRaw = false;\n\t\n\tmemset(&info, 0, sizeof(info));\n\n\tmemset(&mount, 0, sizeof(mount));\n\n\tmount.mountpoint = \"/\";\n\tmount.origin = HTTP_DIR;\n\tmount.def = \"index.html\";\n\tmount.extra_mimetypes = &mimetypes;\n\tmount.origin_protocol = LWSMPRO_FILE;\n\tmount.mountpoint_len = 1;\n\n\tinfo.port = 8000;\n\tinfo.protocols = protocols;\n\tinfo.mounts = &mount;\n\tinfo.gid = -1;\n\tinfo.uid = -1;\n\n\tlws_context *context = lws_create_context(&info);\n\n\t//lws_set_log_level(LLL_INFO | LLL_ERR | LLL_WARN | LLL_NOTICE, NULL);\n\n\tlwsl_info(\"LWSMPRO_FILE: %d\", LWSMPRO_FILE);\n\n\t//Initialization of J1939 Framework\n\n\t//Read database if available\n\tJ1939DataBase database;\n\n\tif(!database.parseJsonFile(DATABASE_PATH)) {\n\t\tstd::cerr << \"Database not found in \" << DATABASE_PATH << std::endl;\n\t\treturn 1;\n\t}\n\n\tconst std::vector<GenericFrame>& ddbbFrames = database.getParsedFrames();\n\n\t//Register all the frames listed in the database\n\tfor(auto iter = ddbbFrames.begin(); iter != ddbbFrames.end(); ++iter) {\n\t\tJ1939Factory::getInstance().registerFrame(*iter);\n\t}\n\n\n\t//Initialize can\n\tCanEasy::initialize(BAUD_250K, onRcv, onTimeout);\n\n\tconst std::set<std::string>& ifaces = CanEasy::getInitializedCanIfaces();\n\n\tif(ifaces.empty()) {\n\t\tstd::cerr << \"No interfaces initialized\" << std::endl;\n\t\treturn 2;\n\t}\n\n\n\t\n\trxFrames[\"command\"] = \"check rx\";\n\t\n\t//Websockets work \n\tint n;\n\n\tdo {\n\t\tn = lws_service(context, /* timeout_ms = */1000);\n\t\trcvRequest.clear();\t\t\t//Clean the request string\n\t}\twhile(n >= 0);\n\n\tlws_context_destroy(context);\n\n\treturn 0;\n}\n\n\n\nbool sentFramesToJson(Json::Value& jsonVal) {\n\n\tunsigned int i = 0;\n\n\tfor(auto iter = framesToSend.begin(); iter != framesToSend.end(); ++iter) {\n\n\t\tJ1939Frame* frame = *iter;\n\t\t\n\t\tjsonVal[i] = frameToJson(frame);\n\t\t\n\t\tauto period = framePeriods.find(frame);\n\n\t\tif(period != framePeriods.end()) {\n\t\t\tjsonVal[i][\"period\"] = period->second;\n\t\t}\n\n\n\t\tconst std::set<std::string>& ifaces = CanEasy::getInitializedCanIfaces();\n\n\t\tfor(auto iface = ifaces.begin(); iface != ifaces.end(); ++iface) {\n\t\t\tjsonVal[i][\"interfaces\"][*iface] = isFrameSent(frame, *iface);\n\t\t}\n\n\t\t++i;\n\n\t}\n\n\treturn true;\n\n}\n\n\nbool listInterfaces(Json::Value& response) {\n\n\tunsigned int i = 0;\n\n\tconst std::set<std::string>& ifaces = CanEasy::getInitializedCanIfaces();\n\n\tfor(auto iface = ifaces.begin(); iface != ifaces.end(); ++iface) {\n\t\tresponse[\"interfaces\"][i++] = *iface;\n\t}\n\n\n\treturn true;\n\n}\n\n\n\nbool isFrameSent(const J1939Frame* frame, const std::string& interface) {\n\n\tstd::vector<u32> ids;\n\n\tstd::shared_ptr<ICanSender> sender = CanEasy::getSender(interface);\n\n\tif(!sender)\t\treturn false;\n\n\t//If the frame is bigger than 8 bytes, we use BAM\n\tif(frame->getDataLength() > MAX_CAN_DATA_SIZE) {\n\n\t\tBamFragmenter fragmenter;\n\t\tfragmenter.fragment(*frame);\n\n\t\tconst TPCMFrame& connFrame = fragmenter.getConnFrame();\n\n\t\tids.push_back(connFrame.getIdentifier());\n\n\t\tstd::vector<TPDTFrame> dataFrames = fragmenter.getDataFrames();\n\n\t\tfor(auto iter = dataFrames.begin(); iter != dataFrames.end(); ++iter) {\n\n\t\t\tids.push_back(iter->getIdentifier());\n\n\t\t}\n\n\t} else {\t\t\t//Can be sent in one frame\n\n\t\tids.push_back(frame->getIdentifier());\n\t}\n\n\treturn sender->isSent(ids);\n\n}\n\n\nvoid sendFrameThroughInterface(const J1939Frame* j1939Frame, u32 period, const std::string& interface) {\n\n\t//Sanity check. We do not trust the foreground app\n\tstd::shared_ptr<ICanSender> sender = CanEasy::getSender(interface);\n\n\tif(!sender)\t\treturn;\n\n\t//Send the frame with the configured periodicity\n\n\tsize_t length = j1939Frame->getDataLength();\n\tCanFrame canFrame;\n\tu32 id;\n\tu8* buff;\n\tstd::string data;\n\n\t//J1939 data is always transmitted in extended format\n\tcanFrame.setExtendedFormat(true);\n\n\t//If the frame is bigger than 8 bytes, we use BAM\n\tif(length > MAX_CAN_DATA_SIZE) {\n\n\t\tstd::vector<CanFrame> canFrames;\n\t\tBamFragmenter fragmenter;\n\t\tfragmenter.fragment(*j1939Frame);\n\n\t\tconst TPCMFrame& connFrame = fragmenter.getConnFrame();\n\t\tlength = connFrame.getDataLength();\n\n\t\tbuff = new u8[length];\n\n\t\tconnFrame.encode(id, buff, length);\n\n\t\t//Set identifier\n\t\tcanFrame.setId(id);\n\n\t\t//Set data\n\t\tstd::string data;\n\t\tdata.append((char*)buff, length);\n\n\t\tcanFrame.setData(data);\n\n\t\tdelete[] buff;\n\n\t\tcanFrames.push_back(canFrame);\n\n\t\tstd::vector<TPDTFrame> dataFrames = fragmenter.getDataFrames();\n\n\t\tfor(auto iter = dataFrames.begin(); iter != dataFrames.end(); ++iter) {\n\n\t\t\tlength = iter->getDataLength();\n\t\t\tbuff = new u8[length];\n\t\t\titer->encode(id, buff, length);\n\n\t\t\t//Set identifier\n\t\t\tcanFrame.setId(id);\n\n\t\t\t//Set data\n\t\t\tstd::string data;\n\t\t\tdata.append((char*)buff, length);\n\n\t\t\tcanFrame.setData(data);\n\n\t\t\tdelete[] buff;\n\n\t\t\tcanFrames.push_back(canFrame);\n\n\t\t}\n\n\t\tsender->sendFrames(canFrames, period);\n\n\n\t} else {\t\t\t//Can be sent in one frame\n\n\t\tbuff = new u8[length];\n\n\t\tj1939Frame->encode(id, buff, length);\n\n\t\t//Set identifier\n\t\tcanFrame.setId(id);\n\n\t\t//Set data\n\t\tstd::string data;\n\t\tdata.append((char*)buff, length);\n\n\t\tcanFrame.setData(data);\n\n\t\tdelete[] buff;\n\n\t\tsender->sendFrame(canFrame, period);\n\n\t}\n\n}\n\n\nvoid unsendFrameThroughInterface(const J1939Frame* j1939Frame, const std::string& interface) {\n\n\n\tstd::vector<u32> ids;\n\tbool found = false;\n\n\n\t//If the frame is bigger than 8 bytes, we use BAM\n\tif(j1939Frame->getDataLength() > MAX_CAN_DATA_SIZE) {\n\n\t\tBamFragmenter fragmenter;\n\t\tfragmenter.fragment(*j1939Frame);\n\n\t\tconst TPCMFrame& connFrame = fragmenter.getConnFrame();\n\n\t\tids.push_back(connFrame.getIdentifier());\n\n\t\tstd::vector<TPDTFrame> dataFrames = fragmenter.getDataFrames();\n\n\t\tfor(auto iter = dataFrames.begin(); iter != dataFrames.end(); ++iter) {\n\n\t\t\tids.push_back(iter->getIdentifier());\n\n\t\t}\n\n\n\t} else {\t\t\t//Can be sent in one frame\n\n\t\tids.push_back(j1939Frame->getIdentifier());\n\t}\n\n\tconst std::set<std::string>& ifaces = CanEasy::getInitializedCanIfaces();\n\n\tfor(auto iter = ifaces.begin(); iter != ifaces.end(); ++iter) {\n\t\tstd::shared_ptr<ICanSender> sender = CanEasy::getSender(*iter);\n\n\t\tif(interface.empty() || interface == *iter) {\n\n\t\t\tsender->unSendFrames(ids);\n\t\t\tfound = true;\n\t\t}\n\n\t}\n\n\n\tif(!found) {\n\t\tstd::cerr << \"Frame not sent through the given interface...\" << std::endl;\n\t}\n\n}\n\n\nvoid onRcv(const CanFrame& frame, const TimeStamp& ts, const std::string& interface, void*) {\n\t\n\trxLock.lock();\n\trxFrames[\"rx\"][std::to_string(frame.getId())][\"count\"] = ++rcvFramesCount[frame.getId()];\n\trxLock.unlock();\n\t\n\tif(rcvFramesCache.find(frame.getId()) != rcvFramesCache.end() && \n\t\t\tframe.getData() == rcvFramesCache[frame.getId()].getData()) {\n\t\t\n\t\t//The raw data is exactly the same.\n\t\treturn;\n\t}\n\t\n\t//At least a SPN has changed\n\t\n\tstd::unique_ptr<J1939Frame> j1939Frame = J1939Factory::getInstance().\n\t\t\t\tgetJ1939Frame(frame.getId(), (const u8*)(frame.getData().c_str()), frame.getData().size());\n\n\tif(!j1939Frame.get()) {\t\t\t//Frame not registered in the factory.\n\t\t\n\t\tif(showRaw) {\n\t\t\tstd::unique_lock<std::mutex> lock(rxLock);\n\t\t\trxFrames[\"rx\"][std::to_string(frame.getId())][\"raw\"] = frame.hexDump();\n\t\t\trcvFramesCache[frame.getId()] = frame;\n\t\t}\n\t\t\n\t\t\n\t\treturn;\t\t\t\t\t\t\n\t}\n\n\tif(reassembler.toBeHandled(*j1939Frame)) {\t\t\t\t//Check if the frame is part of a fragmented frame (BAM protocol)\n\t\t//Actually it is, reassembler will handle it.\n\t\treassembler.handleFrame(*j1939Frame);\n\n\t\tif(reassembler.reassembledFramesPending()) {\n\n\t\t\tj1939Frame = reassembler.dequeueReassembledFrame();\n\t\t\t\n\t\t\t//For frames that have been decoded from BAM protocol.\n\t\t\trxLock.lock();\n\t\t\trxFrames[\"rx\"][std::to_string(j1939Frame->getIdentifier())][\"count\"] = ++rcvFramesCount[j1939Frame->getIdentifier()];\n\t\t\trxLock.unlock();\n\t\t\t\n\n\t\t} else {\n\t\t\treturn;\t\t\t\t//Frame handled by reassembler but the original frame to be reassembled is not complete.\n\t\t}\n\n\t} else {\n\n\t\t//Store in the history\n\t\tif(j1939Frame->isGenericFrame()) {\n\t\t\tGenericFrame *genFrame = static_cast<GenericFrame *>(j1939Frame.get());\n\n\t\t\tstd::set<SPN*> spns = genFrame->compare(frame.getData(), rcvFramesCache[frame.getId()].getData());\n\n\t\t\tfor(auto iter = spns.begin(); iter != spns.end(); ++iter) {\n\t\t\t\tsaveToHistory(j1939Frame->getIdentifier(), **iter, ts);\n\t\t\t}\n\t\t}\n\n\t\t//Only save in cache unfragmented frames to avoid filtering frames that are part of BAM protocol. \n\t\t//Frames whose length is bigger than 8 bytes are not cached, because the TX rate is usually several seconds. \n\t\trcvFramesCache[frame.getId()] = frame;\n\t}\n\t\n\t//At this point we have either a simple frame or a reassembled frame.\n\n\n\tu32 j1939ID = j1939Frame->getIdentifier();\n\t\n\trxLock.lock();\n\trxFrames[\"rx\"][std::to_string(j1939ID)][\"frame\"] = frameToJson(j1939Frame.get());\n\trxLock.unlock();\n\t\n\n}\n\n\nbool onTimeout() {\n\t\n\treturn true;\n\t\n}\n\n\nJson::Value frameToJson(const J1939Frame* frame) {\n\t\n\tJson::Value jsonVal;\n\t\n\tjsonVal[\"pgn\"] = (u32)(frame->getPGN());\n\tjsonVal[\"name\"] = frame->getName();\n\tjsonVal[\"priority\"] = frame->getPriority();\n\tjsonVal[\"source\"] = frame->getSrcAddr();\n\n\t//Only the first froup has destination address\n\tif(frame->getPDUFormatGroup() == PDU_FORMAT_1) {\n\t\tjsonVal[\"dest\"] = frame->getDstAddr();\n\t}\n\n\t//If generic frame, list SPNs\n\tif(frame->isGenericFrame()) {\n\n\t\tunsigned int j = 0;\n\n\t\tconst GenericFrame *genFrame = static_cast<const GenericFrame *>(frame);\n\n\t\tstd::set<u32> spnNumbers = genFrame->getSPNNumbers();\n\n\t\tfor(auto spnNumber = spnNumbers.begin(); spnNumber != spnNumbers.end(); ++spnNumber) {\n\n\t\t\tconst SPN *spn = genFrame->getSPN(*spnNumber);\n\n\t\t\tjsonVal[\"spns\"][j][\"number\"] = *spnNumber;\n\t\t\tjsonVal[\"spns\"][j][\"name\"] = spn->getName();\n\t\t\tjsonVal[\"spns\"][j][\"type\"] = spn->getType();\n\n\t\t\tswitch(spn->getType()) {\n\t\t\tcase SPN::SPN_NUMERIC: {\n\n\t\t\t\tconst SPNNumeric *spnNum = static_cast<const SPNNumeric *>(spn);\n\n\t\t\t\tjsonVal[\"spns\"][j][\"value\"] = spnNum->getFormattedValue();\n\t\t\t\tjsonVal[\"spns\"][j][\"units\"] = spnNum->getUnits();\n\n\t\t\t}\tbreak;\n\t\t\tcase SPN::SPN_STATUS: {\n\n\t\t\t\tconst SPNStatus *spnStat = static_cast<const SPNStatus *>(spn);\n\n\t\t\t\tjsonVal[\"spns\"][j][\"value\"] = spnStat->getValue();\n\n\t\t\t\tSPNStatus::DescMap descriptions = spnStat->getValueDescriptionsMap();\n\n\t\t\t\tfor(auto desc = descriptions.begin(); desc != descriptions.end(); ++desc) {\n\n\t\t\t\t\tjsonVal[\"spns\"][j][\"descriptions\"][desc->first] = desc->second;\n\n\t\t\t\t}\n\n\t\t\t}\tbreak;\n\n\t\t\tcase SPN::SPN_STRING: {\n\n\t\t\t\tconst SPNString *spnStr = static_cast<const SPNString *>(spn);\n\n\t\t\t\tjsonVal[\"spns\"][j][\"value\"] = spnStr->getValue();\n\n\n\t\t\t}\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t\t++j;\n\n\t\t}\n\n\t}\n\n\tif(frame->getPGN() == DM1_PGN) {\n\n\t\tconst DM1* dm1 = static_cast<const DM1*>(frame);\n\n\t\tconst std::vector<DTC>& dtcs = dm1->getDTCs();\n\n\t\tunsigned int i = 0;\n\n\t\tfor(auto dtc = dtcs.begin(); dtc != dtcs.end(); ++dtc) {\n\n\t\t\tjsonVal[\"dtcs\"][i][\"spn\"] = dtc->getSpn();\n\t\t\tjsonVal[\"dtcs\"][i][\"fmi\"] = static_cast<u32>(dtc->getFmi());\n\t\t\tjsonVal[\"dtcs\"][i][\"oc\"] = static_cast<u32>(dtc->getOc());\n\n\t\t\t++i;\n\n\t\t}\n\n\t}\n\n\treturn jsonVal;\n\t\n}\n\n\nvoid resetReceiver() {\n\n\tCanSniffer& sniffer = CanEasy::getSniffer();\n\n\t//Stop receive thread to clean the cache of received frames. Not done the first time.\n\tif(rxThread.get()) {\n\n\t\tsniffer.finish();\n\t\trxThread->join();\n\n\t\trcvFramesCache.clear();\n\t\trcvFramesCount.clear();\n\n\t}\n\n\t//Once the cache is cleaned or it it the first initialization, reinitialize a new thread\n\tsniffer.reset();\n\n\trxThread = std::unique_ptr<std::thread>(new std::thread([&sniffer](){\n\n\t\tsniffer.sniff(1000);\n\n\t}));\n\n}\n"
  },
  {
    "path": "GUI_WEB/backend/src/graph.cpp",
    "content": "#include <SPN/SPNHistory.h>\n#include <Utils.h>\n\n#include <unordered_map>\n#include <json/json.h>\n\n#include \"graph.h\"\n#include \"graph.pb.h\"\n\nGraph getGraphFromSPN(u32 id, u32 spn, u32 samples, u32 period, double time);\n\nusing namespace J1939;\nusing namespace Utils;\n\nstd::unordered_map<u64/*canid | spnNumber >> 32*/,SPNHistory> historyMap;\n\ntypedef struct {\n\tGraph graph;\n\tbool toSend;\n} UserData;\n\nTimeStamp startUpTime = TimeStamp::now();\n\nvoid saveToHistory(u32 id, const SPN& spn, const TimeStamp& timestamp) {\n\n\t//Compose the key for the map. Key = canid + spnNumber\n\tu64 key = (u64)(id) | ((u64)(spn.getSpnNumber()) << 32);\n\n\tSPNHistory& history = historyMap[key];\n\n\thistory.addSample(TimeStamp::now() ,spn);\n\n}\n\n\nint callback_graph(struct lws *wsi, enum lws_callback_reasons reason,\n\t\tvoid *user, void *in, size_t len) {\n\n\tswitch (reason) {\n\n\tcase LWS_CALLBACK_ESTABLISHED: {\n\n\t\tGOOGLE_PROTOBUF_VERIFY_VERSION;\n\n\t\tUserData *userData = new UserData();\n\n\t\t*(static_cast<UserData**>(user)) = userData;\n\n\t}\tbreak;\n\n\tcase LWS_CALLBACK_CLOSED: {\n\n\t\tUserData *userData = (*(static_cast<UserData**>(user)));\n\t\tdelete userData;\n\n\t}\tbreak;\n\n\n\tcase LWS_CALLBACK_RECEIVE: {\n\n\t\tJson::Value rcvjson;\n\t\tJson::Value respjson;\n\n\t\tJson::CharReaderBuilder builder;\n\t\tJson::CharReader *jSonReader = builder.newCharReader();\n\t\tstd::string errs;\n\n\t\tUserData *userData = (*(static_cast<UserData**>(user)));\n\n\t\tstd::string graphRequest;\n\n\t\tgraphRequest.append((char*)in, len);\n\n\t\tif(jSonReader->parse(graphRequest.c_str(), graphRequest.c_str() + graphRequest.size(), &rcvjson, &errs)) {\t\t//Verify if we received the whole Json string\n\n\t\t\tlwsl_info(\"Json request: %s\\n\", graphRequest.c_str());\n\n\t\t\tgraphRequest.clear();\n\n\t\t\tif(rcvjson.isMember(\"command\") && rcvjson[\"command\"].isString()) {\n\n\t\t\t\t//Checks if graphis requested\n\t\t\t\tif(rcvjson[\"command\"] == \"get graph\") {\n\n\t\t\t\t\t//Check corresponding fields\n\t\t\t\t\tif(rcvjson.isMember(\"id\") && rcvjson[\"id\"].isUInt() &&\n\t\t\t\t\t\t\trcvjson.isMember(\"spn\") && rcvjson[\"spn\"].isUInt() &&\n\t\t\t\t\t\t\trcvjson.isMember(\"samples\") && rcvjson[\"samples\"].isUInt() &&\n\t\t\t\t\t\t\trcvjson.isMember(\"period\") && rcvjson[\"period\"].isUInt()\n\t\t\t\t\t\t\t) {\n\n\t\t\t\t\t\tif(rcvjson[\"samples\"] > 10000)\trcvjson[\"samples\"] = 10000;\t\t//No more than 10000 samples\n\n\t\t\t\t\t\tdouble time = 0;\n\n\t\t\t\t\t\tif(rcvjson.isMember(\"time\") && rcvjson[\"time\"].isDouble()) {\n\t\t\t\t\t\t\ttime = rcvjson[\"time\"].asDouble();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tuserData->graph = getGraphFromSPN(rcvjson[\"id\"].asUInt(), rcvjson[\"spn\"].asUInt(), rcvjson[\"samples\"].asUInt(), rcvjson[\"period\"].asUInt(),\n\t\t\t\t\t\t\t\ttime);\n\t\t\t\t\t\tuserData->toSend = true;\n\t\t\t\t\t\tlws_callback_on_writable_all_protocol(lws_get_context(wsi),\n\t\t\t\t\t\t\t\tlws_get_protocol(wsi));\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tdelete jSonReader;\n\n\t}\tbreak;\n\n\tcase LWS_CALLBACK_SERVER_WRITEABLE: {\n\n\t\tUserData *userData = (*(static_cast<UserData**>(user)));\n\n\t\tif(!userData->toSend)\treturn 0;\t\t\t//We have to ensure that this callback is not called by the library with this flag.\n\n\n\t\tuserData->toSend = false;\n\t\tstd::string output;\n\t\tuserData->graph.SerializeToString(&output);\n\n\t\tchar *buff = new char[LWS_SEND_BUFFER_PRE_PADDING + output.size() + LWS_SEND_BUFFER_POST_PADDING];\n\n\t\tmemcpy(buff + LWS_SEND_BUFFER_PRE_PADDING, output.c_str(), output.size());\n\n\t\tint written = lws_write(wsi, (unsigned char*)(buff + LWS_SEND_BUFFER_PRE_PADDING),\n\t\t\t\toutput.size(), LWS_WRITE_BINARY);\n\n\n\t\tdelete[] buff;\n\n\n\t}\tbreak;\n\n\tdefault:\n\t\tbreak;\n\t}\n\n\treturn 0;\n\n}\n\n\nGraph getGraphFromSPN(u32 id, u32 spn, u32 number, u32 period, double time) {\n\n\tGraph graph;\n\n\t//Compose the key for the map. Key = canid + spnNumber\n\tu64 key = (u64)(id) | ((u64)(spn) << 32);\n\n\n\tauto iter = historyMap.find(key);\n\n\t//No history for SPN\n\tif(iter == historyMap.end())\t\treturn graph;\n\n\n\tSPNHistory& history = iter->second;\n\n\t//At the moment, only visualize Numeric SPN\n\tif(history.getNumericSpec() == nullptr)\t\treturn graph;\n\n\n\tstd::shared_ptr<const SPNNumericSpec> spec = history.getNumericSpec();\n\n\tAxis *axisX = graph.mutable_axisx();\n\n\t//Timestamps since epoch\n\tTimeStamp current;\n\n\tif(time > 0) {\t\t//A specific time has been requested\n\t\t//Time is relative to the start up of the program. Current is relative to the epoch time.\n\t\t//We need to add startUpTime.\n\t\tcurrent = startUpTime + TimeStamp(time, (u32)(time * 1000000) % 1000000);\n\t} else {\n\t\t//Retrieve the last stored values\n\t\tcurrent = TimeStamp::now();\n\t}\n\n\tTimeStamp start = current - period;\n\n\tstd::cout << \"current. Sec: \" << current.getSeconds() << \"Micro: \" << current.getMicroSec() << std::endl;\n\t//Timestamps since the beginning of the application\n\tTimeStamp relCurrent = current - startUpTime;\n\tTimeStamp relStart = start - startUpTime;\n\n\t//X axis which is the timestamp in seconds.\n\taxisX->set_units(\"s\");\n\taxisX->set_max((double)(relCurrent.getSeconds()) +\n\t\t\t(double)(relCurrent.getMicroSec()) /1000000);\n\taxisX->set_min((double)(relStart.getSeconds()) +\n\t\t\t(double)(relStart.getMicroSec()) /1000000);\n\n\tAxis *axisY = graph.mutable_axisy();\n\n\taxisY->set_units(spec->getUnits());\n\taxisY->set_max(spec->getMaxFormattedValue());\n\taxisY->set_min(spec->getMinFormattedValue());\n\n\tstd::vector<SPNHistory::Sample> samples = history.getWindow(current, period, number);\n\t\n\n\tfor(auto iter = samples.begin(); iter != samples.end(); ++iter) {\n\n\n\t\tGraph_Sample *sample = graph.add_samples();\n\n\t\tTimeStamp relTime = iter->getTimeStamp() - startUpTime;\n\n\t\tsample->set_x((double)(relTime.getSeconds()) +\n\t\t\t\t(double)(relTime.getMicroSec()) /1000000);\n\n\t\tsample->set_y(iter->getNumeric());\n\n\t}\n\n\treturn graph;\n\n}\n"
  },
  {
    "path": "GUI_WEB/backend/src/graph.h",
    "content": "#ifndef GRAPH_H_\n#define GRAPH_H_\n\nextern \"C\" {\n\n#include <libwebsockets.h>\n\n}\n\nnamespace J1939 {\n\tclass SPN;\n};\n\nnamespace Utils {\n\tclass TimeStamp;\n};\n\nvoid saveToHistory(u32 id, const J1939::SPN& spn, const Utils::TimeStamp& timestamp);\n\nint callback_graph(struct lws *wsi, enum lws_callback_reasons reason,\n\t\tvoid *user, void *in, size_t len);\n\n\n#endif\n"
  },
  {
    "path": "GUI_WEB/frontend/graph.html",
    "content": "<!doctype html>\r\n<html lang=en>\r\n<head>\r\n\t<meta charset=\"utf-8\">\r\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\r\n\t<meta name=\"description\" content=\"\">\r\n\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n\t<title>Graph</title>\r\n\t<script src=\"//cdn.rawgit.com/dcodeIO/protobuf.js/6.8.6/dist/protobuf.js\"></script>\r\n\t<script src=\"js/graph.js\"></script>\r\n\r\n\t<style>\r\n\t\thtml, body {\r\n\t\t\twidth:  100%;\r\n\t\t\theight: 100%;\r\n\t\t\tmargin: 0;\r\n\t\t\toverflow: hidden;\r\n\t\t}\r\n\r\n\t\tbutton {\r\n\t\t     margin-top: 1px;\r\n\t\t     margin-right: 2px;\r\n\t\t     position:absolute;\r\n\t\t     top:0;\r\n\t\t     right:0px;\r\n\t\t}\r\n\t</style>\r\n\r\n</head>\r\n<body>\r\n\r\n\r\n<canvas id=\"myCanvas\" onmousedown=\"mouseDown()\" onmouseup=\"mouseUp()\" onmousemove=\"mouseMove(event)\">\r\nYour browser does not support the HTML5 canvas tag.\r\n</canvas>\r\n\r\n<button type=\"button\" onclick=\"periodic_graph_request()\">Auto Refresh</button>\r\n\r\n</body>\r\n<script type=\"text/javascript\">\r\n\t\r\n\tvar mouse_down = false;\r\n\tvar scroll_time;\r\n\tvar interval;\r\n\tvar prev_pos;\r\n\r\n\tvar proto_grath;\r\n\tvar proto_axis;\r\n\tvar proto_array;\r\n\tvar array_buffer;\r\n\r\n\tvar my_graph = new spn_graph(70, \"myCanvas\");\r\n\r\n\tvar file_reader = new FileReader();\r\n\r\n\tfunction periodic_graph_request() {\r\n\t\tgraph_request();\r\n\t\t\r\n\t\tif (typeof interval === 'undefined') {\r\n\t\t\tinterval = setInterval(graph_request, 2000);\r\n\t\t}\r\n\t\t\r\n\t}\r\n\r\n\tfunction graph_request(time) {\r\n\r\n\t\ttime = time || 0;\r\n\t\t//JSon request\r\n\t\tvar request = { \"command\" : \"get graph\", \r\n\t\t\t\t\"spn\" : spn,\r\n\t\t\t\t\"id\" : id,\t\t\t\t\t\r\n\t\t\t\t\"period\" : 100000,\r\n\t\t\t\t\"samples\" : 500,\r\n\t\t\t\t\"time\" : time\t\t\t\r\n\t\t\t\t };\r\n\t\tvar jsonReq = JSON.stringify(request);\r\n\t\twebSocket.send(jsonReq);\r\n\t}\r\n\r\n\r\n\tfunction mouseDown() {\r\n\t\tconsole.log(\"mouseDown\");\r\n\r\n\t\tvar spec = my_graph.get_xspec();\r\n\r\n\t\t//Graph not printed even once\r\n\t\tif (typeof spec === 'undefined') {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tmouse_down = true;\r\n\t\t\r\n\t\tprev_pos = {x: event.clientX, y: event.clientY};\r\n\r\n\t\tscroll_time = spec.max;\r\n\r\n\t\t//Do not show plots, only the axis which change\r\n\t\tmy_graph.clear_plots();\r\n\t\t\r\n\t\t//Stop periodic request\r\n\t\tif (typeof interval !== 'undefined') {\r\n\t\t\tclearInterval(interval);\r\n\t\t\tinterval =  undefined;\r\n\t\t}\r\n\t}\r\n\r\n\tfunction mouseUp() {\r\n\t\tconsole.log(\"mouseUp\");\r\n\t\t\r\n\t\tif(mouse_down) {\r\n\t\t\t\r\n\t\t\t//Refresh the graph with the correct time\r\n\t\t\tgraph_request(scroll_time);\r\n\t\t\tmouse_down = false;\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tfunction mouseMove(event) {\r\n\t\tconsole.log(\"mouseMove\");\r\n\t\tif(mouse_down) {\r\n\t\t\tvar spec = my_graph.get_xspec();\r\n\t\t\tvar graphRect = my_graph.get_graphRect();\r\n\t\t\tvar diff_time = spec.max - spec.min;\r\n\t\t\tscroll_time = diff_time * (prev_pos.x - event.clientX) / graphRect.w + spec.max;\r\n\r\n\t\t\t//Modify graph spec reference directly\r\n\t\t\tspec.min = scroll_time - diff_time;\t\t\t\r\n\t\t\tspec.max = scroll_time;\r\n\r\n\t\t\t//Do not show plots, only the axis which change\r\n\t\t\tmy_graph.draw();\r\n\r\n\t\t\tprev_pos = {x: event.clientX, y: event.clientY};\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tfunction findGetParameter(parameterName) {\r\n\t\tvar result = null,\r\n\t\ttmp = [];\r\n\t\tlocation.search\r\n\t\t.substr(1)\r\n\t\t.split(\"&\")\r\n\t\t.forEach(function (item) {\r\n\t\t\ttmp = item.split(\"=\");\r\n\t\t\tif (tmp[0] === parameterName) result = decodeURIComponent(tmp[1]);\r\n\t\t});\r\n\t\treturn result;\r\n\t}\r\n\r\n\t\r\n\r\n\tfile_reader.onload = function(event) {\r\n\t\tarray_buffer = event.target.result;\r\n\t\tproto_array = new Uint8Array(array_buffer);\r\n\t\t// Decode an Uint8Array\r\n\t\ttry {\r\n\t\t\tvar message = proto_grath.decode(proto_array);\r\n\t\t\tdrawGraph(message);\r\n\t\t\treturn;\r\n\t\t} catch (e) {\r\n\t\t\t//Not a graph message\r\n\t\t}\r\n\r\n\t\ttry {\r\n\t\t\tvar message = proto_axis.decode(proto_array);\r\n\t\t\treturn;\r\n\t\t} catch (e) {\r\n\t\t\t//Not an axis message\r\n\t\t}\r\n\r\n\t};\r\n\r\n\r\n\tprotobuf.load(\"graph.proto\", function(err, root) {\r\n\t\tif (err) \r\n\t\t\tthrow err;\r\n\t\r\n\t\t// Obtain a message type\r\n\t\tproto_grath = root.lookupType(\"Graph\");\r\n\t\tproto_axis = root.lookupType(\"Axis\");\r\n\r\n\t});\r\n\r\n\r\n\t//Get get parameters (everything is verified in server side, we just forward)\r\n\tvar spn = Number(findGetParameter(\"spn\"));\r\n\tvar id = Number(findGetParameter(\"id\"));\r\n\r\n\tdocument.title = \"SPN \" + spn;\r\n\r\n\tvar webSocket;\r\n\r\n\tvar hostName = window.location.hostname;\r\n\r\n\tif(hostName.length == 0) { hostName = \"127.0.0.1\"; }\r\n    \r\n    \tconsole.log(\"openWSConnection::Connecting to --> ws://\" + hostName + \":8000\");\r\n    \ttry {\r\n\r\n\t\twebSocket = new WebSocket(\"ws://\" + hostName + \":8000\", \"graph-protocol\");\r\n\t\twebSocket.onopen = function(openEvent) {\r\n\r\n\t\t    \tconsole.log(\"WebSocket OPEN: \" + JSON.stringify(openEvent, null, 4));\r\n\r\n\t\t\t//Request graph painting every 2000 millis\r\n\r\n\t\t\tinterval = setInterval(graph_request, 2000);\r\n\t\t   \r\n\t\t};\r\n\r\n\t\twebSocket.onclose = function (closeEvent) {\r\n\r\n\t\t    console.log(\"WebSocket CLOSE: \" + JSON.stringify(closeEvent, null, 4));\r\n\t\t    \r\n\t\t};\r\n\r\n\t\twebSocket.onerror = function (errorEvent) {\r\n\t\t    console.log(\"WebSocket ERROR: \" + JSON.stringify(errorEvent, null, 4));\r\n\t\t};\r\n\r\n\t\twebSocket.onmessage = function (messageEvent) {\r\n\r\n\t\t\tconsole.log(\"WebSocket MESSAGE received\");\r\n\r\n\t\t\tfile_reader.readAsArrayBuffer(messageEvent.data);\r\n\r\n\r\n\t\t};\r\n\t\t\r\n\r\n    \t} catch (exception) {\r\n\t\tconsole.error(\"Error \" + exception.message);\r\n    \t}\r\n\r\n\r\n\tfunction drawGraph(message) {\r\n\t\t\r\n\t\tif(message.samples.length == 0) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tmy_graph.set_xspec(message.axisX);\r\n\t\tmy_graph.set_yspec(message.axisY);\r\n\r\n\t\tmy_graph.set_plots(message.samples.map(\r\n\t\t\r\n\t\t\tfunction(value) {\r\n\t\t\t\treturn [value.x, value.y];\r\n\t\t\t}\r\n\t\t));\r\n\r\n\t\tmy_graph.draw();\r\n\r\n\t}\r\n\r\n\r\n</script>\r\n\r\n</html>\r\n"
  },
  {
    "path": "GUI_WEB/frontend/index.html",
    "content": "<!doctype html>\r\n<html lang=en>\r\n<head>\r\n\t<meta charset=\"utf-8\">\r\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\r\n\t<meta name=\"description\" content=\"\">\r\n\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n\t<title>J1939GUI</title>\r\n\t<script src=\"https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js\"></script>\r\n\r\n\t<style>\r\n\r\n\t\tbody {\r\n\r\n\t\t\tfont-family: \"Lucida Sans Unicode\", \"Lucida Grande\", sans-serif;\t\t\r\n\r\n\t\t}\r\n\r\n\t\tul {\r\n\t\t  \tlist-style-type: none;\r\n\t\t}\r\n\r\n\t\t.caret {\r\n\t\t\t  cursor: pointer;\r\n\t\t\t  -webkit-user-select: none; /* Safari 3.1+ */\r\n\t\t\t  -moz-user-select: none; /* Firefox 2+ */\r\n\t\t\t  -ms-user-select: none; /* IE 10+ */\r\n\t\t\t  user-select: none;\r\n\t\t\t  font-size: 16px;\r\n\t\t  \t\r\n\t\t}\r\n\r\n\t\t.caret::before {\r\n\t\t\t  content: \"\\25B6\";\r\n\t\t\t  color: black;\r\n\t\t\t  display: inline-block;\r\n\t\t\t  margin-right: 6px;\r\n\t\t}\r\n\r\n\r\n\t\t.nested {\r\n\t\t\t  display: block;\r\n\t\t\t  font-size: 14px;\r\n\t\t}\r\n\r\n\r\n\t\t.win_container {\t\r\n\r\n\t\t\tborder: 3px solid #F1F1F1;\r\n\t\t\tborder-top-left-radius: 4px;\r\n\t\t\tborder-top-left-radius: 4px;\r\n\r\n\t\t}\r\n\r\n\t\r\n\t\t.win_title {\t\r\n\r\n\t\t\tpadding: 5px;\r\n\t\t\tborder-top-left-radius: 4px;\r\n\t\t\tborder-top-left-radius: 4px;\r\n\t\t\tbackground: #F1F1F1;\r\n\t\t\t\r\n\r\n\r\n\t\t}\r\n\r\n\t\ttd, label {\r\n\t\t\r\n\t\t\tpadding-right: 30px;\t\t\r\n\r\n\t\t}\r\n\r\n\t</style>\r\n\r\n</head>\r\n<body>\r\n\r\n<div ng-app=\"J1939Gui\" ng-controller=\"J1939\">\r\n\r\n\t\r\n\r\n\t<div class=\"win_container\" id=transmission>\r\n\r\n\t\t<div class=\"win_title\">\r\n\t\t\t<div id=tx_text>Transmission</div> \r\n\t\t</div>\r\n\r\n\r\n\t\t<select ng-model=\"selFrame\">\r\n\t\t\t<option ng-repeat=\"pgn in pgns\" value=\"{{ pgn.pgn }}\">{{ pgn.name }} : {{ pgn.pgn | hex | uppercase }}</option>\r\n\t\t</select>\r\n\r\n\t\t <button ng-click=\"addFrame()\" ng-init=\"count=0\">Add frame</button> \r\n\r\n\t\t  <ul>\r\n\r\n\t\t    <li ng-repeat=\"frame in tx_frames\">\r\n\t\t\t<span class=\"caret\" ng-click=\"showSpns[$index] = !showSpns[$index]\">\r\n\t\t\t\t<span>{{ frame.name }} ({{ frame.pgn | hex | uppercase }})</span>\r\n\t\t\t\t<span>\r\n\t\t\t\t\tPriority: \r\n\t\t\t\t\t<input type=\"number\" number-mask=\"\" ng-enter=\"changePrio($index)\" ng-click=\"$event.stopPropagation();\" ng-model=\"frame.priority\">\r\n\t\t\t\t</span>\t\r\n\t\t\t\t<span>\r\n\t\t\t\t\tSource: \r\n\t\t\t\t\t<input type=\"number\" number-mask=\"\" ng-enter=\"changeSrc($index)\" ng-click=\"$event.stopPropagation();\" ng-model=\"frame.source\">\r\n\t\t\t\t</span>\t\r\n\t\t\t\t<span ng-show=\"frame.dest\">\r\n\t\t\t\t\tDest: \r\n\t\t\t\t\t<input type=\"number\" number-mask=\"\" ng-enter=\"changeDest($index)\" ng-click=\"$event.stopPropagation();\" ng-model=\"frame.dest\">\r\n\t\t\t\t</span>\t\t\r\n\t\t\t\t<span>\r\n\t\t\t\t\tPeriod: \r\n\t\t\t\t\t<input type=\"number\" number-mask=\"\" ng-enter=\"changePeriod($index)\" ng-click=\"$event.stopPropagation();\" ng-model=\"frame.period\">\r\n\t\t\t\t</span>\t\r\n\r\n\r\n\t\t\t\t<span ng-repeat=\"(iface, isChecked) in frame.interfaces\">\r\n\t\t\t\t\t{{ iface }}\r\n\t\t\t\t\t<input type=\"checkbox\" ng-click=\"$event.stopPropagation();\" ng-change=\"ifaceChecked($parent.$index, iface)\" ng-model=\"frame.interfaces[iface]\" value=\"{{ isChecked }}\">\r\n\t\t\t\t</span>\r\n\t\t\t\t<button ng-click=\"deleteFrame($index, $event)\">\r\n\t\t\t\t\tDelete \r\n\t\t\t\t\t\r\n\t\t\t\t</button>\t\r\n\t\t\t\t\r\n\t\t\t</span>\r\n\t\t\t <ul ng-show=\"showSpns[$index]\" class=\"nested\">\r\n\t\t\t\t\r\n\t\t\t\t<li  ng-repeat=\"spn in frame.spns\">\r\n\t\t\t\t\t<span>SPN {{ spn.number }} ({{ spn.name }})</span>\r\n\t\t\t\t\t<span ng-switch on=\"spn.type\">\r\n\t\t\t\t\t\tValue: \r\n\t\t\t\t\t\t<span ng-switch-when=\"1\"> <!-- Type Status -->\r\n\t\t\t\t\t\t\t<select ng-model=\"spn.value\" ng-change=\"updateSpn($parent.$parent.$index, $parent.$index)\">\r\n\t\t\t\t\t\t\t\t<option ng-repeat=\"desc in spn.descriptions | filter:emptyOrNull\" value=\"{{$index}}\" ng-selected=\"$index == spn.value\">{{ desc }}</option>\r\n\t\t\t\t\t\t\t</select>\r\n\t\t\t\t\t\t</span>\r\n\t\t\t\t\t\t<span ng-switch-default> <!-- Type String, Numeric or Unknown -->\r\n\t\t\t\t\t\t\t<input type=\"text\" ng-enter=\"updateSpn($parent.$parent.$index, $parent.$index)\" ng-model=\"spn.value\">\r\n\t\t\t\t\t\t\t<span ng-show=\"spn.units\">{{ spn.units }}</span>\r\n\t\t\t\t\t\t</span>\r\n\t\t\t\t\t</span>\r\n\t\t\t\t\r\n\t\t\t\t</li>\r\n\t\t\t</ul>\r\n\t\t\t  \r\n\t\t    </li>\r\n\t\t  </ul>\r\n\r\n\t</div>\r\n\r\n\t<br>\r\n\r\n\r\n\t \r\n\t<div class=\"win_container\" id=\"reception\">\r\n\r\n\t\t<div class=\"win_title\">\r\n\t\t\t<div id=rx_text>Reception</div> \r\n\t\t</div>\r\n\r\n\t\t<label>PGN: <input ng-model=\"search_pgn\"></label>\r\n\t\t<label>Name: <input ng-model=\"search_name\"></label>\r\n\t\t<label>SPN: <input ng-model=\"search_spn\"></label>\r\n\r\n\t\t  <ul>\r\n\r\n\t\t    <li ng-repeat=\"(id, frame) in filterRxFrames(rx_frames, search_pgn, search_name, search_spn)\">\r\n\t\t\t<span class=\"caret\" ng-click=\"showRxSpns[id] = !showRxSpns[id]\">\r\n\t\t\t\t<span>{{ frame.name }} ({{ frame.pgn | hex | uppercase }})</span>\r\n\t\t\t\t<span>\r\n\t\t\t\t\tPriority: {{ frame.priority }}\r\n\t\t\t\t</span>\t\r\n\t\t\t\t<span>\r\n\t\t\t\t\tSource: {{ frame.source }}\r\n\t\t\t\t</span>\t\r\n\t\t\t\t<span ng-show=\"frame.dest\">\r\n\t\t\t\t\tDest: {{ frame.dest }}\r\n\t\t\t\t</span>\t\r\n\t\t\t\t<span ng-show=\"frame.count\">\r\n\t\t\t\t\tCount: {{ frame.count }}\r\n\t\t\t\t</span>\t\r\n\r\n\t\t\t</span>\r\n\t\t\t <table ng-show=\"showRxSpns[id]\" class=\"nested\">\r\n\t\t\t\t\r\n\t\t\t\t<tr ng-repeat=\"spn in frame.spns | filter:{'number':search_spn}\">\r\n\t\t\t\t\t<td>SPN {{ spn.number }} ({{ spn.name }})</td>\r\n\t\t\t\t\t<td ng-switch on=\"spn.type\">\r\n\t\t\t\t\t\tValue: \r\n\t\t\t\t\t\t<span style='color: {{ ($even != $parent.$even) ? \"blue\" : \"red\" }};'>\r\n\t\t\t\t\t\t\t<span ng-switch-when=\"1\"> <!-- Type Status -->\r\n\t\t\t\t\t\t\t\t{{ spn.descriptions[spn.value] }} ({{spn.value}})\r\n\t\t\t\t\t\t\t</span>\r\n\t\t\t\t\t\t\t<span ng-switch-default> <!-- Type String, Numeric or Unknown -->\r\n\t\t\t\t\t\t\t\t{{ spn.value }}\r\n\t\t\t\t\t\t\t</span>\r\n\t\t\t\t\t\t</span>\r\n\t\t\t\t\t\t<span ng-show=\"spn.units\">{{ spn.units }}</span>\r\n\t\t\t\t\t</td>\r\n\t\t\t\t\t<td>\r\n\t\t\t\t\t\t<button ng-click=\"showGraph(id, spn.number, spn.name)\">Graph</button>\r\n\t\t\t\t\t</td>\r\n\t\t\t\t\r\n\t\t\t\t</tr>\r\n\t\t\t\t\r\n\t\t\t\t<tr ng-repeat=\"dtc in frame.dtcs\">\r\n\t\t\t\t\t<td>DTC</td>\r\n\t\t\t\t\t<td>SPN: {{ dtc.spn }}</td>\r\n\t\t\t\t\t<td>FMI: {{ dtc.fmi }}</td>\r\n\t\t\t\t\t<td>OC: {{ dtc.oc }}</td>\r\n\t\t\t\t</tr>\r\n\t\t\t\t\r\n\t\t\t</table>\r\n\t\t\t  \r\n\t\t    </li>\r\n\t\t  </ul>\r\n\t\t\r\n\t\t  <div>Show raw<input type=\"checkbox\" ng-change=\"show_raw()\" ng-model=\"showRaw\"></div>\r\n\r\n\t\t  <ul ng-show=\"showRaw\">\r\n\t\t\t<table>\r\n\t\t\t    <tr ng-repeat=\"(id, raw) in rx_raw\">\r\n\t\t\t\t<td style='font-weight: bold; color: {{ $even ? \"blue\" : \"red\" }};'>{{ id | hex }}:</td> <td>{{ raw.data }}</td>\r\n\t\t\t\t<td ng-show=\"raw.count\">\r\n\t\t\t\t\tCount: {{ raw.count }}\r\n\t\t\t\t</td>\t\r\n\t\t\t\t  \r\n\t\t\t    </tr>\r\n\t\t\t</table>\r\n\t\t  </ul>\r\n\r\n\t\t  <button ng-click=\"reset_rx_frame($event)\">\r\n\t\t\t\t\tReset \r\n\t\t  </button>\r\n\r\n\t</div>\r\n\r\n</div>\r\n\r\n</body>\r\n<script type=\"text/javascript\">\r\n\r\nvar app = angular.module(\"J1939Gui\", []);\r\n\r\n\r\napp.directive('ngEnter', function () {\r\n    return function (scope, element, attrs) {\r\n        element.bind(\"keydown keypress\", function (event) {\r\n            if (event.which === 13) {\r\n                scope.$apply(function () {\r\n                    scope.$eval(attrs.ngEnter);\r\n                });\r\n                event.preventDefault();\r\n            }\r\n        });\r\n    };\r\n})\r\n\r\napp.filter('hex', function () {\r\n  \r\n  return function(input) {\r\n    return Number(input).toString(16);\r\n  };\r\n});\r\n\r\napp.controller('J1939', ['$scope', '$interval', '$filter', function($scope, $interval, $filter) {\r\n\r\n\tvar SPN_TYPES = {\r\n\t\tNUMERIC : 0,\r\n\t\tSTATUS : 1,\r\n\t\tSTRING : 2\r\n\t}\r\n\t\r\n\t$scope.showSpns = [];\r\n\t$scope.showRxSpns = {};\r\n\t$scope.rx_frames = {};\r\n\t$scope.rx_raw = {};\r\n\r\n\t$scope.addFrame = function() {\r\n\t\r\n\t\tvar request = { \"command\" : \"add frame\" , \"data\" : Number($scope.selFrame) };\r\n\t\tvar jsonReq = JSON.stringify(request);\r\n\t\twebSocket.send(jsonReq);\t\t\r\n\r\n\t};\r\n\r\n\t$scope.changePrio = function(index) {\r\n\t\r\n\t\tvar request = { \"command\" : \"set frame\", \"prio\" : Number($scope.tx_frames[index].priority), \"index\" : index};\r\n\t\tvar jsonReq = JSON.stringify(request);\r\n\t\twebSocket.send(jsonReq);\t\t\r\n\r\n\t };\r\n\r\n\r\n\t$scope.changeSrc = function(index) {\r\n\r\n\t\r\n\t\tvar request = { \"command\" : \"set frame\", \"src\" : Number($scope.tx_frames[index].source), \"index\" : index};\r\n\t\tvar jsonReq = JSON.stringify(request);\r\n\t\twebSocket.send(jsonReq);\t\t\r\n\r\n\t};\r\n\r\n\r\n\t$scope.changeDest = function(index) {\r\n\r\n\t\r\n\t\tvar request = { \"command\" : \"set frame\", \"dest\" : Number($scope.tx_frames[index].dest), \"index\" : index};\r\n\t\tvar jsonReq = JSON.stringify(request);\r\n\t\twebSocket.send(jsonReq);\t\t\r\n\r\n\t};\r\n\r\n\r\n\t$scope.changePeriod = function(index) {\r\n\r\n\t\r\n\t\tvar request = { \"command\" : \"set frame\", \"period\" : Number($scope.tx_frames[index].period), \"index\" : index};\r\n\t\tvar jsonReq = JSON.stringify(request);\r\n\t\twebSocket.send(jsonReq);\t\r\n\r\n\t};\r\n\r\n\t$scope.ifaceChecked = function(index, iface) {\r\n\t\t\r\n\t\t\r\n\t\tvar request = { \"command\" : \"set frame\", \"interface\" : {}, \"index\" : index };\r\n\t\trequest.interface[iface] = $scope.tx_frames[index]['interfaces'][iface];\r\n\r\n\t\tvar jsonReq = JSON.stringify(request);\r\n\t\twebSocket.send(jsonReq);\t\r\n\r\n\t};\r\n\r\n\r\n\t$scope.updateSpn = function(frameIndex, spnIndex) {\r\n\r\n\t\tvar spn = $scope.tx_frames[frameIndex].spns[spnIndex];\r\n\t\t\r\n\t\tvar value = spn.value;\r\n\r\n\t\tif(spn.type !== SPN_TYPES.STRING) {\r\n\t\t\r\n\t\t\tvalue = Number(value);\r\n\t\t\t\r\n\t\t}\r\n\t\t\t\r\n\t\tvar request = { \"command\" : \"set frame\", \"spn\" : spn.number, \"value\" :  value, \"index\" : frameIndex };\r\n\t\tvar jsonReq = JSON.stringify(request);\r\n\t\twebSocket.send(jsonReq);\t\r\n\r\n\t};\r\n\r\n\t$scope.deleteFrame = function(frameIndex, $event) {\r\n\t\t\r\n\t\tvar request = { \"command\" : \"delete frame\", \"index\" : frameIndex };\r\n\t\tvar jsonReq = JSON.stringify(request);\r\n\t\twebSocket.send(jsonReq);\r\n\r\n\t\t$scope.showSpns.splice(frameIndex, 1);\r\n\r\n\t\t$event.stopPropagation();\r\n\r\n\t}\r\n\r\n\r\n\t$scope.emptyOrNull = function(item) {\r\n\t\t\r\n\t\treturn !(item === null || item.length === 0);\r\n\r\n\t};\r\n\r\n\t//Reset the reception of frames\r\n\t$scope.reset_rx_frame = function($event) {\r\n\t\r\n\t\t$scope.rx_frames = {};\r\n\t\t\t\r\n\t\tvar request = { \"command\" : \"reset rx\"};\r\n\t\tvar jsonReq = JSON.stringify(request);\r\n\t\twebSocket.send(jsonReq);\r\n\r\n\t\t$event.stopPropagation();\r\n\r\n\t}\r\n\r\n\t//To filter received frames by its PGN, Name or SPN.\r\n\t$scope.filterRxFrames = function(rx_frames, search_pgn, search_name, search_spn) {\r\n\r\n\t\tvar filtered_frames = {};\r\n\t\t\r\n\t\tsearch_pgn = $filter('lowercase')(search_pgn);\r\n\t\tsearch_name = $filter('lowercase')(search_name);\r\n\r\n\t\tfor(key in rx_frames) {\r\n\r\n\t\t\tvar pgn = $filter('lowercase')($filter('hex')(rx_frames[key].pgn));\r\n\t\t\tvar name = $filter('lowercase')(rx_frames[key].name);\r\n\r\n\t\t\tif(search_pgn && !pgn.includes(search_pgn))\tcontinue;\r\n\t\t\tif(search_name && !name.includes(search_name))\tcontinue;\r\n\r\n\r\n\t\t\tvar spn_filter_pass = false;\r\n\r\n\t\t\tif(search_spn) {\r\n\t\t\t\tfor(i in rx_frames[key].spns) {\r\n\t\t\t\t\tvar spn = rx_frames[key].spns[i];\r\n\t\t\t\t\tif(spn.number.toString().includes(search_spn)) {\r\n\t\t\t\t\t\tspn_filter_pass = true;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\t\t\t\t\r\n\r\n\t\t\t\t}\r\n\t\t\t} else {\t\r\n\t\t\t\tspn_filter_pass = true;\r\n\t\t\t}\r\n\r\n\r\n\t\t\tif(spn_filter_pass) {\r\n\t\t\t\r\n\t\t\t\tfiltered_frames[key] = rx_frames[key];\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn filtered_frames;\r\n\r\n\t}\r\n\r\n\t//Show undecoded frames?\r\n\t$scope.show_raw = function() {\r\n\r\n\t\tvar request = { \"command\" : \"show raw\", \"raw\" : $scope.showRaw };\r\n\t\tvar jsonReq = JSON.stringify(request);\r\n\t\twebSocket.send(jsonReq);\r\n\r\n\t}\r\n\r\n\t$scope.showGraph = function(id, spn, name) {\r\n\r\n\t\twindow.open('graph.html?id=' + id + '&spn=' + spn,'targetWindow',\r\n\t\t   'toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=800,height=500');\r\n\t}\r\n\r\n\tvar webSocket;\r\n\r\n\tvar hostName = window.location.hostname;\r\n\r\n\tif(hostName.length == 0) { hostName = \"127.0.0.1\"; }\r\n    \r\n    \tconsole.log(\"openWSConnection::Connecting to --> ws://\" + hostName + \":8000\");\r\n    \ttry {\r\n\t\twebSocket = new WebSocket(\"ws://\" + hostName + \":8000\", \"j1939-protocol\");\r\n\r\n\t\t\r\n\t\twebSocket.onopen = function(openEvent) {\r\n\r\n\t\t    \tconsole.log(\"WebSocket OPEN: \" + JSON.stringify(openEvent, null, 4));\r\n\t\t\t\r\n\r\n\t\t\tvar request = { \"command\" : \"list frames\" };\r\n\t\t\tvar jsonReq = JSON.stringify(request);\r\n\t\t\twebSocket.send(jsonReq);\r\n\r\n\t\t\trequest  = { \"command\" : \"list interfaces\" };\r\n\t\t\tjsonReq = JSON.stringify(request);\r\n\t\t\twebSocket.send(jsonReq);\r\n\r\n\r\n\t\t\t//Every 200 milliseconds we request the new incoming frames.\r\n\t\t\t$interval(function(){\r\n\t\t\t\tvar request = { \"command\" : \"check rx\" };\r\n\t\t\t\tvar jsonReq = JSON.stringify(request);\r\n\t\t\t\twebSocket.send(jsonReq);\t\t\t\r\n\t\t\r\n\r\n\t\t\t}, 200);\r\n\t\t   \r\n\t\t};\r\n\t\twebSocket.onclose = function (closeEvent) {\r\n\r\n\t\t    console.log(\"WebSocket CLOSE: \" + JSON.stringify(closeEvent, null, 4));\r\n\t\t    \r\n\t\t};\r\n\t\twebSocket.onerror = function (errorEvent) {\r\n\t\t    console.log(\"WebSocket ERROR: \" + JSON.stringify(errorEvent, null, 4));\r\n\t\t};\r\n\t\twebSocket.onmessage = function (messageEvent) {\r\n\r\n\t\t    \tvar wsMsg = messageEvent.data;\r\n\t\t    \tconsole.log(\"WebSocket MESSAGE: \" + wsMsg);\r\n\r\n\t\t\tvar response = JSON.parse(wsMsg);\r\n\r\n\t\t\t//Check if we received new frames\r\n\t\t\tif(response.command == \"check rx\") {\r\n\t\t\t\r\n\t\t\t\t$scope.$apply(function(x) { \r\n\r\n\t\t\t\t\tfor(id in response.rx) {\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t//Decoded frames\r\n\t\t\t\t\t\tif(response.rx[id].hasOwnProperty(\"frame\")) {\t\r\n\t\t\t\t\t\t\tx.rx_frames[id] = response.rx[id].frame; \t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tif(x.rx_frames.hasOwnProperty(id)) {\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\tx.rx_frames[id].count = response.rx[id].count;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t//Raw\r\n\t\t\t\t\t\tif(response.rx[id].hasOwnProperty(\"raw\")) {\t\r\n\t\t\t\t\t\t\tx.rx_raw[id] =  { data: response.rx[id].raw }; \t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tif(x.rx_raw.hasOwnProperty(id)) {\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\tx.rx_raw[id].count = response.rx[id].count;\r\n\r\n\t\t\t\t\t\t}\t\r\n\t\t\t\t\t\t\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\r\n\r\n\t\t\t\t});\r\n\r\n\r\n\t\t\t}\r\n\r\n\r\n\t\t\tif(response.hasOwnProperty(\"frames\")) {\r\n\r\n\t\t\t\tconsole.log(\"Setting frames\");\r\n\t\t\t\t\r\n\t\t\t\t$scope.$apply(function(x) { x.tx_frames = response.frames; });\r\n\t\t\t\t\r\n\t\t\t}\r\n\r\n\t\t\tif(response.command == \"list frames\") {\r\n\r\n\t\t\t\t$scope.$apply(function(x) { x.pgns = response.data; });\r\n\r\n\t\t\t} else if (response.command == \"add frame\"){\r\n\r\n\t\t\t\tconsole.log(\"Adding frame\");\r\n\t\t\t\t\r\n\t\t\t} else if (response.command == \"list interfaces\"){\r\n\r\n\t\t\t\tconsole.log(\"List interfaces\");\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t$scope.$apply(function(x) { x.listedIfaces = response.interfaces; });\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t\t\r\n\r\n    \t} catch (exception) {\r\n\t\tconsole.error(\"Error \" + exception.message);\r\n    \t}\r\n\r\n}]);  \r\n\r\n\r\n</script>\r\n\r\n</html>\r\n"
  },
  {
    "path": "GUI_WEB/frontend/js/graph.js",
    "content": "var max_plots = 5000;\n\nfunction spn_graph(margin, dom_canvas_id) {\n\n\t\n\tthis.graphRect = { x: margin, y: margin, w: window.innerWidth - 2*margin, h: window.innerHeight - 2*margin };\n\tthis.plots = [];\n\tthis.canvas = document.getElementById(dom_canvas_id);\n\tthis.canvas.width  = window.innerWidth;\n\tthis.canvas.height = window.innerHeight;\n}\n\nspn_graph.prototype.set_plots = function(plots) {\n\n\tif(this.plots.length <= max_plots) {\n\t\tthis.plots = plots;\n\t}\n\n}\n\nspn_graph.prototype.clear_plots = function(plots) {\n\tthis.plots = [];\n}\n\n\nspn_graph.prototype.get_xspec = function() {\n\treturn this.xspec;\n}\n\nspn_graph.prototype.get_graphRect = function() {\n\treturn this.graphRect;\n}\n\nspn_graph.prototype.set_xspec = function(xspec) {\t\t//To change the minumum and maximum values of the x axis\n\n\tif(xspec.min < xspec.max) {\n\t\tthis.xspec = xspec;\n\t}\n}\n\nspn_graph.prototype.set_yspec = function(yspec) {\t\t//To change the minumum and maximum values of the y axis\n\n\tif(yspec.min < yspec.max) {\n\t\tthis.yspec = yspec;\n\t}\n}\n\nspn_graph.prototype.draw = function() {\n\n\tvar ctx = this.canvas.getContext(\"2d\");\n\n\tvar maxAxisX = this.xspec.max - this.xspec.min;\n\tvar maxAxisY = this.yspec.max - this.yspec.min;\n\tvar i;\n\n\tctx.font = \"20px Arial\";\n\t\n\t//Clear canvas for redrawing\n\tctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n\n\tctx.lineWidth = 1;\n\tctx.strokeStyle = \"grey\";\n\n\t//Draw X axis\n\tctx.beginPath();\n\tctx.moveTo(this.graphRect.x, this.graphRect.y);\n\tctx.lineTo(this.graphRect.x, this.graphRect.y + this.graphRect.h);\n\tctx.stroke();\n\n\t\n\t//Draw x units\n\tctx.fillText(this.xspec.units, 3/2 * this.graphRect.x + this.graphRect.w, this.graphRect.y + this.graphRect.h);\n\n\t//Draw y units\n\tctx.fillText(this.yspec.units, this.graphRect.x/3, this.graphRect.y/2);\n\n\tctx.font = \"15px Arial\";\n\n\t//Draw some values along the y axis\n\tvar numYVal = 5;\n\tfor(i = 0; i <= numYVal; ++i) {\n\t\tctx.fillText(\"\" + (Math.round((i * maxAxisY / numYVal + this.yspec.min) * 100) / 100), this.graphRect.x/4, this.graphRect.y + this.graphRect.h * (1 - i/numYVal));\n\t}\n\n\t//Draw Y axis\n\tctx.beginPath();\n\tctx.moveTo(this.graphRect.x, this.graphRect.y + this.graphRect.h);\n\tctx.lineTo(this.graphRect.x + this.graphRect.w, this.graphRect.y + this.graphRect.h);\n\tctx.stroke();\n\n\n\t//Draw some values along the x axis\n\tvar numXVal = 7;\n\tfor(i = 0; i <= numXVal; ++i) {\n\t\tctx.fillText(\"\" + (Math.round((i * maxAxisX / numXVal + this.xspec.min) * 1000) / 1000), this.graphRect.x + this.graphRect.w * i/numYVal, \n\t\t\t3/2 * this.graphRect.y + this.graphRect.h);\n\t}\n\n\t//Draw plots\n\tctx.lineWidth = 2;\n\tctx.strokeStyle = \"black\";\n\t\n\t\n\n\tfor (i = 0; i < this.plots.length - 1; i++) {\n\t\n\t\tvar offsets = { \n\t\t\tx1: this.plots[i][0] - this.xspec.min, \n\t\t\ty1: this.plots[i][1] - this.yspec.min,\n\t\t\tx2: this.plots[i+1][0] - this.xspec.min,\n\t\t\ty2: this.plots[i+1][1] - this.yspec.min,\n\t\t}\n\n\t\tif( offsets.x1 < 0 || offsets.x1 > maxAxisX )\t\tcontinue;\n\t\tif( offsets.y1 < 0 || offsets.y1 > maxAxisY )\t\tcontinue;\n\t\tif( offsets.x2 < 0 || offsets.x2 > maxAxisX )\t\tcontinue;\n\t\tif( offsets.y2 < 0 || offsets.y2 > maxAxisY )\t\tcontinue;\n\t\t\n\t\tvar line = {};\n\t\tline.x1 = this.graphRect.x + offsets.x1 * this.graphRect.w / maxAxisX;\n\t\tline.y1 = this.graphRect.y + this.graphRect.h - (offsets.y1 * this.graphRect.h / maxAxisY);\n\t\tline.x2 = this.graphRect.x + offsets.x2 * this.graphRect.w / maxAxisX;\n\t\tline.y2 = this.graphRect.y + this.graphRect.h - (offsets.y2 * this.graphRect.h / maxAxisY);\n\t\t\n\t\t//Draw line\n\t\tctx.beginPath();\n\t\tctx.moveTo(line.x1, line.y1);\n\t\tctx.lineTo(line.x2, line.y2);\n\t\tctx.stroke();\n\t\t\t\n\t}\n\n}\n\n"
  },
  {
    "path": "J1939/.cproject",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<?fileVersion 4.0.0?><cproject storage_type_id=\"org.eclipse.cdt.core.XmlProjectDescriptionStorage\">\n\t<storageModule moduleId=\"org.eclipse.cdt.core.settings\">\n\t\t<cconfiguration id=\"cdt.managedbuild.config.gnu.cross.so.debug.2004021346\">\n\t\t\t<storageModule buildSystemId=\"org.eclipse.cdt.managedbuilder.core.configurationDataProvider\" id=\"cdt.managedbuild.config.gnu.cross.so.debug.2004021346\" moduleId=\"org.eclipse.cdt.core.settings\" name=\"Debug\">\n\t\t\t\t<externalSettings>\n\t\t\t\t\t<externalSetting>\n\t\t\t\t\t\t<entry flags=\"VALUE_WORKSPACE_PATH\" kind=\"includePath\" name=\"/J1939\"/>\n\t\t\t\t\t\t<entry flags=\"VALUE_WORKSPACE_PATH\" kind=\"libraryPath\" name=\"/J1939/Debug\"/>\n\t\t\t\t\t\t<entry flags=\"RESOLVED\" kind=\"libraryFile\" name=\"J1939\" srcPrefixMapping=\"\" srcRootPath=\"\"/>\n\t\t\t\t\t</externalSetting>\n\t\t\t\t</externalSettings>\n\t\t\t\t<extensions>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.ELF\" point=\"org.eclipse.cdt.core.BinaryParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GmakeErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.CWDLocator\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GCCErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GASErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GLDErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t</extensions>\n\t\t\t</storageModule>\n\t\t\t<storageModule moduleId=\"cdtBuildSystem\" version=\"4.0.0\">\n\t\t\t\t<configuration artifactExtension=\"so\" artifactName=\"${ProjName}\" buildArtefactType=\"org.eclipse.cdt.build.core.buildArtefactType.sharedLib\" buildProperties=\"org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.sharedLib,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug\" cleanCommand=\"rm -rf\" description=\"\" id=\"cdt.managedbuild.config.gnu.cross.so.debug.2004021346\" name=\"Debug\" parent=\"cdt.managedbuild.config.gnu.cross.so.debug\" postbuildStep=\"\">\n\t\t\t\t\t<folderInfo id=\"cdt.managedbuild.config.gnu.cross.so.debug.2004021346.\" name=\"/\" resourcePath=\"\">\n\t\t\t\t\t\t<toolChain id=\"cdt.managedbuild.toolchain.gnu.base.1591819094\" name=\"Linux GCC\" superClass=\"cdt.managedbuild.toolchain.gnu.base\">\n\t\t\t\t\t\t\t<targetPlatform archList=\"all\" binaryParser=\"org.eclipse.cdt.core.ELF\" id=\"cdt.managedbuild.target.gnu.platform.base.702992405\" name=\"Debug Platform\" osList=\"linux,hpux,aix,qnx\" superClass=\"cdt.managedbuild.target.gnu.platform.base\"/>\n\t\t\t\t\t\t\t<builder buildPath=\"${workspace_loc:/J1939}/Debug\" id=\"cdt.managedbuild.target.gnu.builder.base.1753937503\" keepEnvironmentInBuildfile=\"false\" name=\"Gnu Make Builder\" superClass=\"cdt.managedbuild.target.gnu.builder.base\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.archiver.base.88804547\" name=\"GCC Archiver\" superClass=\"cdt.managedbuild.tool.gnu.archiver.base\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.cpp.compiler.base.151091325\" name=\"GCC C++ Compiler\" superClass=\"cdt.managedbuild.tool.gnu.cpp.compiler.base\">\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.option.optimization.level.1636575476\" name=\"Optimization Level\" superClass=\"gnu.cpp.compiler.option.optimization.level\" useByScannerDiscovery=\"false\" value=\"gnu.cpp.compiler.optimization.level.none\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.option.debugging.level.976150367\" name=\"Debug Level\" superClass=\"gnu.cpp.compiler.option.debugging.level\" useByScannerDiscovery=\"false\" value=\"gnu.cpp.compiler.debugging.level.max\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.option.include.paths.1918069668\" name=\"Include paths (-I)\" superClass=\"gnu.cpp.compiler.option.include.paths\" useByScannerDiscovery=\"false\" valueType=\"includePath\">\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"&quot;${workspace_loc:/Common}&quot;\"/>\n\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.option.dialect.std.1556420515\" name=\"Language standard\" superClass=\"gnu.cpp.compiler.option.dialect.std\" useByScannerDiscovery=\"true\" value=\"gnu.cpp.compiler.dialect.c++11\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.option.other.pic.11871352\" name=\"Position Independent Code (-fPIC)\" superClass=\"gnu.cpp.compiler.option.other.pic\" useByScannerDiscovery=\"false\" value=\"true\" valueType=\"boolean\"/>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.cpp.compiler.input.996243883\" superClass=\"cdt.managedbuild.tool.gnu.cpp.compiler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.c.compiler.base.731323459\" name=\"GCC C Compiler\" superClass=\"cdt.managedbuild.tool.gnu.c.compiler.base\">\n\t\t\t\t\t\t\t\t<option defaultValue=\"gnu.c.optimization.level.none\" id=\"gnu.c.compiler.option.optimization.level.2055418461\" name=\"Optimization Level\" superClass=\"gnu.c.compiler.option.optimization.level\" useByScannerDiscovery=\"false\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.c.compiler.option.debugging.level.1660787985\" name=\"Debug Level\" superClass=\"gnu.c.compiler.option.debugging.level\" useByScannerDiscovery=\"false\" value=\"gnu.c.debugging.level.max\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.c.compiler.option.dialect.std.978619213\" name=\"Language standard\" superClass=\"gnu.c.compiler.option.dialect.std\" useByScannerDiscovery=\"true\" value=\"gnu.c.compiler.dialect.c11\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.c.compiler.input.428024829\" superClass=\"cdt.managedbuild.tool.gnu.c.compiler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.c.linker.base.1636045919\" name=\"GCC C Linker\" superClass=\"cdt.managedbuild.tool.gnu.c.linker.base\">\n\t\t\t\t\t\t\t\t<option defaultValue=\"true\" id=\"gnu.c.link.option.shared.1506677396\" name=\"Shared (-shared)\" superClass=\"gnu.c.link.option.shared\" valueType=\"boolean\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.cpp.linker.base.1647439222\" name=\"GCC C++ Linker\" superClass=\"cdt.managedbuild.tool.gnu.cpp.linker.base\">\n\t\t\t\t\t\t\t\t<option defaultValue=\"true\" id=\"gnu.cpp.link.option.shared.86023543\" name=\"Shared (-shared)\" superClass=\"gnu.cpp.link.option.shared\" useByScannerDiscovery=\"false\" valueType=\"boolean\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.link.option.paths.371556488\" name=\"Library search path (-L)\" superClass=\"gnu.cpp.link.option.paths\" useByScannerDiscovery=\"false\" valueType=\"libPaths\">\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"&quot;${workspace_loc:/Common/Debug}&quot;\"/>\n\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.link.option.libs.1855113994\" name=\"Libraries (-l)\" superClass=\"gnu.cpp.link.option.libs\" useByScannerDiscovery=\"false\" valueType=\"libs\">\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"Common\"/>\n\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.link.option.flags.96203463\" name=\"Linker flags\" superClass=\"gnu.cpp.link.option.flags\" useByScannerDiscovery=\"false\" value=\"\" valueType=\"string\"/>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.cpp.linker.input.1054757266\" superClass=\"cdt.managedbuild.tool.gnu.cpp.linker.input\">\n\t\t\t\t\t\t\t\t\t<additionalInput kind=\"additionalinputdependency\" paths=\"$(USER_OBJS)\"/>\n\t\t\t\t\t\t\t\t\t<additionalInput kind=\"additionalinput\" paths=\"$(LIBS)\"/>\n\t\t\t\t\t\t\t\t</inputType>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.assembler.base.987040076\" name=\"GCC Assembler\" superClass=\"cdt.managedbuild.tool.gnu.assembler.base\">\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.assembler.input.1296550419\" superClass=\"cdt.managedbuild.tool.gnu.assembler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t</toolChain>\n\t\t\t\t\t</folderInfo>\n\t\t\t\t\t<sourceEntries>\n\t\t\t\t\t\t<entry excluding=\"Transport/RTSCTS|Diagnosis|Tests\" flags=\"VALUE_WORKSPACE_PATH|RESOLVED\" kind=\"sourcePath\" name=\"\"/>\n\t\t\t\t\t</sourceEntries>\n\t\t\t\t</configuration>\n\t\t\t</storageModule>\n\t\t\t<storageModule moduleId=\"org.eclipse.cdt.core.externalSettings\"/>\n\t\t</cconfiguration>\n\t\t<cconfiguration id=\"cdt.managedbuild.config.gnu.cross.so.release.919489308\">\n\t\t\t<storageModule buildSystemId=\"org.eclipse.cdt.managedbuilder.core.configurationDataProvider\" id=\"cdt.managedbuild.config.gnu.cross.so.release.919489308\" moduleId=\"org.eclipse.cdt.core.settings\" name=\"Release\">\n\t\t\t\t<externalSettings>\n\t\t\t\t\t<externalSetting>\n\t\t\t\t\t\t<entry flags=\"VALUE_WORKSPACE_PATH\" kind=\"includePath\" name=\"/J1939\"/>\n\t\t\t\t\t\t<entry flags=\"VALUE_WORKSPACE_PATH\" kind=\"libraryPath\" name=\"/J1939/Release\"/>\n\t\t\t\t\t\t<entry flags=\"RESOLVED\" kind=\"libraryFile\" name=\"J1939\" srcPrefixMapping=\"\" srcRootPath=\"\"/>\n\t\t\t\t\t</externalSetting>\n\t\t\t\t</externalSettings>\n\t\t\t\t<extensions>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.ELF\" point=\"org.eclipse.cdt.core.BinaryParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GmakeErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.CWDLocator\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GCCErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GASErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GLDErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\n\t\t\t\t</extensions>\n\t\t\t</storageModule>\n\t\t\t<storageModule moduleId=\"cdtBuildSystem\" version=\"4.0.0\">\n\t\t\t\t<configuration artifactExtension=\"so\" artifactName=\"${ProjName}\" buildArtefactType=\"org.eclipse.cdt.build.core.buildArtefactType.sharedLib\" buildProperties=\"org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.sharedLib,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release\" cleanCommand=\"rm -rf\" description=\"\" id=\"cdt.managedbuild.config.gnu.cross.so.release.919489308\" name=\"Release\" parent=\"cdt.managedbuild.config.gnu.cross.so.release\">\n\t\t\t\t\t<folderInfo id=\"cdt.managedbuild.config.gnu.cross.so.release.919489308.\" name=\"/\" resourcePath=\"\">\n\t\t\t\t\t\t<toolChain id=\"cdt.managedbuild.toolchain.gnu.cross.so.release.398065357\" name=\"Cross GCC\" superClass=\"cdt.managedbuild.toolchain.gnu.cross.so.release\">\n\t\t\t\t\t\t\t<targetPlatform archList=\"all\" binaryParser=\"org.eclipse.cdt.core.ELF\" id=\"cdt.managedbuild.targetPlatform.gnu.cross.237604448\" isAbstract=\"false\" osList=\"all\" superClass=\"cdt.managedbuild.targetPlatform.gnu.cross\"/>\n\t\t\t\t\t\t\t<builder buildPath=\"${workspace_loc:/J1939}/Release\" id=\"cdt.managedbuild.builder.gnu.cross.1932895334\" keepEnvironmentInBuildfile=\"false\" managedBuildOn=\"true\" name=\"Gnu Make Builder\" superClass=\"cdt.managedbuild.builder.gnu.cross\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.cross.c.compiler.1273931314\" name=\"Cross GCC Compiler\" superClass=\"cdt.managedbuild.tool.gnu.cross.c.compiler\">\n\t\t\t\t\t\t\t\t<option defaultValue=\"gnu.c.optimization.level.most\" id=\"gnu.c.compiler.option.optimization.level.23748400\" name=\"Optimization Level\" superClass=\"gnu.c.compiler.option.optimization.level\" useByScannerDiscovery=\"false\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.c.compiler.option.debugging.level.34325318\" name=\"Debug Level\" superClass=\"gnu.c.compiler.option.debugging.level\" useByScannerDiscovery=\"false\" value=\"gnu.c.debugging.level.none\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.c.compiler.input.94284660\" superClass=\"cdt.managedbuild.tool.gnu.c.compiler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.cross.cpp.compiler.475741211\" name=\"Cross G++ Compiler\" superClass=\"cdt.managedbuild.tool.gnu.cross.cpp.compiler\">\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.option.optimization.level.552450678\" name=\"Optimization Level\" superClass=\"gnu.cpp.compiler.option.optimization.level\" useByScannerDiscovery=\"false\" value=\"gnu.cpp.compiler.optimization.level.most\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.option.debugging.level.1921250648\" name=\"Debug Level\" superClass=\"gnu.cpp.compiler.option.debugging.level\" useByScannerDiscovery=\"false\" value=\"gnu.cpp.compiler.debugging.level.none\" valueType=\"enumerated\"/>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.cpp.compiler.input.913704311\" superClass=\"cdt.managedbuild.tool.gnu.cpp.compiler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.cross.c.linker.2094623053\" name=\"Cross GCC Linker\" superClass=\"cdt.managedbuild.tool.gnu.cross.c.linker\">\n\t\t\t\t\t\t\t\t<option defaultValue=\"true\" id=\"gnu.c.link.option.shared.2072524911\" name=\"Shared (-shared)\" superClass=\"gnu.c.link.option.shared\" valueType=\"boolean\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.cross.cpp.linker.6867928\" name=\"Cross G++ Linker\" superClass=\"cdt.managedbuild.tool.gnu.cross.cpp.linker\">\n\t\t\t\t\t\t\t\t<option defaultValue=\"true\" id=\"gnu.cpp.link.option.shared.115957123\" name=\"Shared (-shared)\" superClass=\"gnu.cpp.link.option.shared\" valueType=\"boolean\"/>\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.cpp.linker.input.1323975710\" superClass=\"cdt.managedbuild.tool.gnu.cpp.linker.input\">\n\t\t\t\t\t\t\t\t\t<additionalInput kind=\"additionalinputdependency\" paths=\"$(USER_OBJS)\"/>\n\t\t\t\t\t\t\t\t\t<additionalInput kind=\"additionalinput\" paths=\"$(LIBS)\"/>\n\t\t\t\t\t\t\t\t</inputType>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.cross.archiver.1450318434\" name=\"Cross GCC Archiver\" superClass=\"cdt.managedbuild.tool.gnu.cross.archiver\"/>\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.cross.assembler.319952839\" name=\"Cross GCC Assembler\" superClass=\"cdt.managedbuild.tool.gnu.cross.assembler\">\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.assembler.input.65859315\" superClass=\"cdt.managedbuild.tool.gnu.assembler.input\"/>\n\t\t\t\t\t\t\t</tool>\n\t\t\t\t\t\t</toolChain>\n\t\t\t\t\t</folderInfo>\n\t\t\t\t\t<sourceEntries>\n\t\t\t\t\t\t<entry excluding=\"Transport/RTSCTS|Diagnosis|Tests\" flags=\"VALUE_WORKSPACE_PATH|RESOLVED\" kind=\"sourcePath\" name=\"\"/>\n\t\t\t\t\t</sourceEntries>\n\t\t\t\t</configuration>\n\t\t\t</storageModule>\n\t\t\t<storageModule moduleId=\"org.eclipse.cdt.core.externalSettings\"/>\n\t\t</cconfiguration>\n\t</storageModule>\n\t<storageModule moduleId=\"cdtBuildSystem\" version=\"4.0.0\">\n\t\t<project id=\"J1939.cdt.managedbuild.target.gnu.cross.so.814813424\" name=\"Shared Library\" projectType=\"cdt.managedbuild.target.gnu.cross.so\"/>\n\t</storageModule>\n\t<storageModule moduleId=\"scannerConfiguration\">\n\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.config.gnu.cross.so.release.919489308;cdt.managedbuild.config.gnu.cross.so.release.919489308.;cdt.managedbuild.tool.gnu.cross.cpp.compiler.475741211;cdt.managedbuild.tool.gnu.cpp.compiler.input.913704311\">\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t</scannerConfigBuildInfo>\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.config.gnu.cross.so.debug.2004021346;cdt.managedbuild.config.gnu.cross.so.debug.2004021346.;cdt.managedbuild.tool.gnu.cross.cpp.compiler.2024762743;cdt.managedbuild.tool.gnu.cpp.compiler.input.1689573108\">\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t</scannerConfigBuildInfo>\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.config.gnu.cross.so.release.919489308;cdt.managedbuild.config.gnu.cross.so.release.919489308.;cdt.managedbuild.tool.gnu.cross.c.compiler.1273931314;cdt.managedbuild.tool.gnu.c.compiler.input.94284660\">\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t</scannerConfigBuildInfo>\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.config.gnu.cross.so.debug.2004021346;cdt.managedbuild.config.gnu.cross.so.debug.2004021346.;cdt.managedbuild.tool.gnu.cross.c.compiler.1285118725;cdt.managedbuild.tool.gnu.c.compiler.input.884951112\">\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"\"/>\n\t\t</scannerConfigBuildInfo>\n\t</storageModule>\n\t<storageModule moduleId=\"org.eclipse.cdt.core.LanguageSettingsProviders\"/>\n\t<storageModule moduleId=\"refreshScope\" versionNumber=\"2\">\n\t\t<configuration configurationName=\"Release\">\n\t\t\t<resource resourceType=\"PROJECT\" workspacePath=\"/J1939\"/>\n\t\t</configuration>\n\t\t<configuration configurationName=\"Debug\">\n\t\t\t<resource resourceType=\"PROJECT\" workspacePath=\"/J1939\"/>\n\t\t</configuration>\n\t</storageModule>\n\t<storageModule moduleId=\"org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings\"/>\n</cproject>\n"
  },
  {
    "path": "J1939/.gitignore",
    "content": "/Debug/\n"
  },
  {
    "path": "J1939/.settings/org.eclipse.cdt.codan.core.prefs",
    "content": "eclipse.preferences.version=1\norg.eclipse.cdt.codan.checkers.errnoreturn=Warning\norg.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},implicit\\=>false}\norg.eclipse.cdt.codan.checkers.errreturnvalue=Error\norg.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.checkers.noreturn=Error\norg.eclipse.cdt.codan.checkers.noreturn.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},implicit\\=>false}\norg.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=-Error\norg.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error\norg.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},no_break_comment\\=>\"no break\",last_case_param\\=>false,empty_case_param\\=>false}\norg.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning\norg.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},unknown\\=>false,exceptions\\=>()}\norg.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning\norg.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},skip\\=>true}\norg.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.InvalidArguments=-Error\norg.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info\norg.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},pattern\\=>\"^[a-z]\",macro\\=>true,exceptions\\=>()}\norg.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.OverloadProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning\norg.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning\norg.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},macro\\=>true,exceptions\\=>()}\norg.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},paramNot\\=>false}\norg.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},else\\=>false,afterelse\\=>false}\norg.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\norg.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},macro\\=>true}\norg.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},macro\\=>true}\norg.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning\norg.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},macro\\=>true,exceptions\\=>(\"@(\\#)\",\"$Id\")}\norg.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=-Error\norg.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\nuseParentScope=false\n"
  },
  {
    "path": "J1939/Addressing/AddressClaimFrame.cpp",
    "content": "/*\n * AdressClaimFrame.cpp\n *\n *  Created on: Oct 17, 2017\n *      Author: famez\n */\n\n#include <string>\n#include <sstream>\n#include <iostream>\n\n#include <Addressing/AddressClaimFrame.h>\n\n#define ADDRESS_CLAIM_NAME\t\t\"Address Claim\"\n\nnamespace J1939 {\n\nAddressClaimFrame::AddressClaimFrame() : J1939Frame(ADDRESS_CLAIM_PGN) {\n\t\tmName = ADDRESS_CLAIM_NAME;\n\n}\n\nAddressClaimFrame::AddressClaimFrame(EcuName name) : J1939Frame(ADDRESS_CLAIM_PGN), mEcuName(name) {\n\n\tmName = ADDRESS_CLAIM_NAME;\n\n}\n\nAddressClaimFrame::~AddressClaimFrame() {\n}\n\n\nvoid AddressClaimFrame::decodeData(const u8* buffer, size_t length) {\n\n\tif(length != ADDRESS_FRAME_LENGTH) {\t\t//Check the length first\n\t\tthrow  J1939DecodeException(\"[AdressClaimFrame::decodeData] Buffer length does \"\n\t\t\t\t\"not match the expected length. Buffer length:\" + std::to_string(length) + \". Expected length: \" + std::to_string(ADDRESS_FRAME_LENGTH));\n\t}\n\n\tu32 idNumber = ( buffer[0] |\n\t\t\t(buffer[1] << 8) |\n\t\t\t((buffer[2] & 0x1F) << 16));\n\n\n\tu16 manufacturerCode = (\n\t\t\t((buffer[2] & 0xE0) >> 5) |\n\t\t\t(buffer[3] << 3)\n\t);\n\n\tu8 ecuInstance = (buffer[4] & 0x07);\n\n\tu8 functionInstance = ((buffer[4] & 0xF8) >> 3);\n\n\tu8 function = buffer[5];\n\n\tu8 vehicleSystem = (buffer[6] >> 1);\n\n\tu8 vehicleSystemInstance = (buffer[7] & 0x0F);\n\n\tu8 industryGroup = ((buffer[7] >> 4) & 0x07);\n\n\tbool arbitraryAddressCapable = (buffer[7] >> 7);\n\n\tmEcuName = EcuName(idNumber, manufacturerCode, ecuInstance, functionInstance, function,\n\t\t\tvehicleSystem, vehicleSystemInstance, industryGroup, arbitraryAddressCapable);\n\n}\n\n\nvoid AddressClaimFrame::encodeData(u8* buffer, size_t length) const {\n\n\tbuffer[0] = (mEcuName.getIdNumber() & 0xFF);\n\tbuffer[1] = ((mEcuName.getIdNumber() >> 8) & 0xFF);\n\tbuffer[2] = ((mEcuName.getIdNumber() >> 16) & 0x1F) |\n\t\t\t((mEcuName.getManufacturerCode() << 5) & 0xFF);\n\tbuffer[3] = ((mEcuName.getManufacturerCode() >> 3) & 0xFF);\n\tbuffer[4] = ((mEcuName.getEcuInstance() & ECU_INSTANCE_MASK) | ((mEcuName.getFunctionInstance() << 3) & 0xFF));\n\n\tbuffer[5] = mEcuName.getFunction();\n\n\tbuffer[6] = (mEcuName.getVehicleSystem() << 1);\n\n\tbuffer[7] = (mEcuName.getVehicleSystemInstance() & VEHICLE_SYSTEM_INTERFACE_MASK) | ((mEcuName.getIndustryGroup() & INDUSTRY_GROUP_MASK) << 4) | ((mEcuName.isArbitraryAddressCapable() ? 1 : 0) << 7);\n\n}\n\nstd::string AddressClaimFrame::toString() const {\n\n\tstd::string retVal = J1939Frame::toString();\n\tstd::stringstream sstr;\n\n\tsstr << \"Id Number: \" << mEcuName.getIdNumber() << std::endl;\n\tsstr << \"Manufacturer Code: \" << static_cast<u32>(mEcuName.getManufacturerCode()) << std::endl;\n\tsstr << \"ECU Intance: \" << static_cast<u32>(mEcuName.getEcuInstance()) << std::endl;\n\tsstr << \"Function Instance: \" << static_cast<u32>(mEcuName.getFunctionInstance()) << std::endl;\n\tsstr << \"Function: \" << static_cast<u32>(mEcuName.getFunction()) << std::endl;\n\tsstr << \"Vehicle System: \" << static_cast<u32>(mEcuName.getVehicleSystem()) << std::endl;\n\tsstr << \"Vehicle System Instance: \" << static_cast<u32>(mEcuName.getVehicleSystemInstance()) << std::endl;\n\tsstr << \"Industry Group: \" << static_cast<u32>(mEcuName.getIndustryGroup()) << std::endl;\n\tsstr << \"Address Capable: \" << (mEcuName.isArbitraryAddressCapable() ? \"yes\" : \"no\") << std::endl;\n\n\treturn retVal + sstr.str();\n\n}\n\n\n} /* namespace J1939 */\n"
  },
  {
    "path": "J1939/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.5)\n\nproject(J1939)\n\nadd_library(J1939 SHARED \n    \t./J1939Common.cpp\n\t./Diagnosis/Frames/DM1.cpp\n\t./Diagnosis/DTC.cpp\n\t./FMS/TellTale/TellTale.cpp\n\t./FMS/TellTale/FMS1Frame.cpp\n\t./J1939Factory.cpp\n\t./GenericFrame.cpp\n\t./SPN/SPN.cpp\n\t./SPN/SPNString.cpp\n\t./SPN/SPNStatus.cpp\n\t./SPN/SPNNumeric.cpp\n\t./SPN/SPNSpec/SPNSpec.cpp\n\t./SPN/SPNSpec/SPNNumericSpec.cpp\n\t./SPN/SPNSpec/SPNStatusSpec.cpp\n\t./SPN/SPNHistory.cpp\n\t./J1939DataBase.cpp\n\t./J1939Frame.cpp\n\t./Addressing/AddressClaimFrame.cpp\n\t./Frames/RequestFrame.cpp\n\t./Transport/TPCMFrame.cpp\n\t./Transport/BAM/BamReassembler.cpp\n\t./Transport/BAM/BamFragmenter.cpp\n\t#./Transport/RTSCTS/RTSCTSConnectionManager.cpp\n\t./Transport/TPDTFrame.cpp\n\n)\n\ntarget_include_directories(J1939\n    PRIVATE \n        include ${Common_SOURCE_DIR}/include\n)\n\ntarget_link_libraries(J1939\n    PUBLIC\n        Common jsoncpp\n)\n\ninstall (TARGETS J1939 EXPORT J1939FrameworkTargets\n    LIBRARY DESTINATION lib)\n\n\ninstall(DIRECTORY include/ \n    DESTINATION include\nCOMPONENT\n    Devel\n)\n"
  },
  {
    "path": "J1939/Diagnosis/DTC.cpp",
    "content": "/*\n * DTC.cpp\n *\n *  Created on: Sep 2, 2018\n *      Author: fernado\n */\n\n#include <sstream>\n#include <iostream>\n\n#include <Diagnosis/DTC.h>\n#include <J1939Common.h>\n\nnamespace J1939 {\n\nDTC::DTC() : mSPN(0), mFMI(0), mOC(0) {\n\n}\n\nDTC::DTC(u32 spn, u8 fmi, u8 oc) : mSPN(spn), mFMI(fmi), mOC(oc) {\n\n}\n\nDTC::~DTC() {\n}\n\nvoid DTC::decode(const u8* buffer) {\n\n\tif(buffer[3] & DTC_CM_MASK) {\n\t\tthrow J1939DecodeException(\"Unknown conversion method\");\n\t}\n\n\tmSPN = buffer[0];\n\tmSPN |= (buffer[1] << 8);\n\tmSPN |= ((buffer[2] & (~DTC_FMI_MASK)) << 11);\n\n\tmFMI = (buffer[2] & DTC_FMI_MASK);\n\n\tmOC = (buffer[3] & DTC_OC_MASK);\n\n}\n\nvoid DTC::encode(u8* buffer) const {\n\n\tbuffer[0] = mSPN & 0xFF;\n\tbuffer[1] = (mSPN >> 8) & 0xFF;\n\tbuffer[2] = (mSPN >> 11) & (~DTC_FMI_MASK);\n\tbuffer[2] |= (mFMI & DTC_FMI_MASK);\n\tbuffer[3] = (mOC & DTC_OC_MASK) & (~DTC_CM_MASK);\n\n}\n\nstd::string DTC::toString() const {\n\n\tstd::stringstream sstr;\n\n\tsstr << \"Diagnosis Trouble Code -> Spn: \" << mSPN << \" Failure Mode Identifier: \" << static_cast<u32>(mFMI)\n\t\t\t<< \"Occurrence Count: \" << static_cast<u32>(mOC) << std::endl;\n\n\treturn sstr.str();\n}\n\n} /* namespace J1939 */\n"
  },
  {
    "path": "J1939/Diagnosis/Frames/DM1.cpp",
    "content": "/*\n * DM1.cpp\n *\n *  Created on: Oct 15, 2017\n *      Author: famez\n */\n\n#include <string.h>\n\n#include <Diagnosis/Frames/DM1.h>\n#include <SPN/SPNStatus.h>\n#include <Utils.h>\n\n#define DM1_MINIMUM_LENGTH\t\t8\n\nnamespace J1939 {\n\nDM1::DM1() : GenericFrame(DM1_PGN) {\n\n\t{\n\t\tSPNStatus lampStatus(1213, \"Malfunction indicator Lamp Status\", 0, 6, 2);\n\t\tregisterSPN(lampStatus);\n\t}\n\n\t{\n\t\tSPNStatus lampStatus(623, \"Red Stop Lamp Status\", 0, 4, 2);\n\t\tregisterSPN(lampStatus);\n\t}\n\n\t{\n\t\tSPNStatus lampStatus(624, \"Amber Warning Lamp Status\", 0, 2, 2);\n\t\tregisterSPN(lampStatus);\n\t}\n\n\t{\n\t\tSPNStatus lampStatus(987, \"Protect Lamp Status\", 0, 0, 2);\n\t\tregisterSPN(lampStatus);\n\t}\n\n\n\t{\n\t\tSPNStatus lampStatus(3038, \"Flash Malfunction indicator Lamp Status\", 1, 6, 2);\n\t\tregisterSPN(lampStatus);\n\t}\n\n\t{\n\t\tSPNStatus lampStatus(3039, \"Flash Red Stop Lamp Status\", 1, 4, 2);\n\t\tregisterSPN(lampStatus);\n\t}\n\n\t{\n\t\tSPNStatus lampStatus(3040, \"Flash Amber Warning Lamp Status\", 1, 2, 2);\n\t\tregisterSPN(lampStatus);\n\t}\n\n\t{\n\t\tSPNStatus lampStatus(3041, \"Flash Protect Lamp Status\", 1, 0, 2);\n\t\tregisterSPN(lampStatus);\n\t}\n\n\tmName = DM1_NAME;\n\n}\n\nDM1::~DM1() {\n}\n\nvoid DM1::decodeData(const u8* buffer, size_t length) {\n\n\n\tsize_t lampStatLength = GenericFrame::getDataLength();\n\n\t//Decode Lamp Status (SPNs)\n\tGenericFrame::decodeData(buffer, lampStatLength);\n\n\tsize_t offset = lampStatLength;\n\n\tDTC dtc;\n\n\twhile(offset + DTC_SIZE <= length) {\n\n\t\tdtc.decode(buffer + offset);\n\n\t\t//To avoid adding a DTC when there are no faults (a DTC set all to 0s is sent which is not a valid DTC)\n\t\tif(dtc.getSpn() != 0) {\n\t\t\tmDtcs.push_back(dtc);\n\t\t}\n\n\t\toffset += DTC_SIZE;\n\t}\n\n}\n\nvoid DM1::encodeData(u8* buffer, size_t length) const {\n\n\t//Encode SPNs for bytes 0-1\n\tsize_t lampStatLength = GenericFrame::getDataLength();\n\n\tGenericFrame::encodeData(buffer, lampStatLength);\n\n\tsize_t offset = lampStatLength;\t//Must be 2\n\n\tif(lampStatLength != 2) {\n\t\tthrow J1939EncodeException(\"[DM1::encodeData] SPNs are not expected to fit within \"\n\t\t\t\t\"more than 2 bytes\");\n\t}\n\n\tfor(auto dtc = mDtcs.begin(); dtc != mDtcs.end(); ++dtc) {\n\n\t\tdtc->encode(buffer + offset);\n\n\t\toffset += DTC_SIZE;\n\n\t}\n\n\t//According to the protocol, if there are no DTCs, we need to send the bytes 2-5 as 00 and bytes 6-7 as FF.\n\tif(mDtcs.empty()) {\n\t\tmemset(buffer + offset, 0x00, 4);\n\t\tmemset(buffer + offset + 4, 0xFF, 2);\n\t}\n\n}\n\nsize_t DM1::getDataLength() const {\n\n\t//The length of DM1 frame is at least 8 bytes\n\treturn J1939_MAX(GenericFrame::getDataLength() + DTC_SIZE * mDtcs.size(), DM1_MINIMUM_LENGTH);\n\n}\n\nstd::string DM1::toString() const {\n\n\tstd::string retVal = GenericFrame::toString();\n\n\tfor(auto dtc  = mDtcs.begin(); dtc != mDtcs.end(); ++dtc) {\n\t\tretVal += dtc->toString();\n\t}\n\n\n\treturn retVal;\n}\n\n\nvoid DM1::copy(const J1939Frame& other) {\n\n\tGenericFrame::copy(other);\n\n\t//Verify that we deal with a DM1 frame\n\tif(other.getPGN() == getPGN()) {\n\n\t\tconst DM1 *otherDM1 = static_cast<const DM1 *>(&other);\n\t\tmDtcs = otherDM1->mDtcs;\n\n\t}\n}\n\n} /* namespace J1939 */\n"
  },
  {
    "path": "J1939/FMS/TellTale/FMS1Frame.cpp",
    "content": "/*\n * FMS1Frame.cpp\n *\n *  Created on: Mar 11, 2018\n *      Author: famez\n */\n\n#include <string>\n#include <sstream>\n#include <iostream>\n\n#include <Assert.h>\n#include <Utils.h>\n\n#include <FMS/TellTale/FMS1Frame.h>\n\n#define FMS1_NAME\t\t\t\t\"FMS1\"\n\nnamespace J1939 {\n\nFMS1Frame::FMS1Frame() : J1939Frame(FMS1_PGN), mBlockID(NUMBER_OF_BLOCKS) {\n\tmName = FMS1_NAME;\n\n}\n\n\nFMS1Frame::FMS1Frame(u8 blockID) : J1939Frame(FMS1_PGN), mBlockID(blockID) {\n\n\tmName = FMS1_NAME;\n\n\tASSERT(mBlockID < NUMBER_OF_BLOCKS);\n\n\tfor(u8 i = mBlockID * TTSS_PER_BLOCK + 1; i < (mBlockID + 1) * TTSS_PER_BLOCK + 1; ++i) {\n\t\tmTTSs[i] = TellTale(i, TellTale::TTS_STATUS_NOT_AVAILABLE);\n\t}\n}\n\nFMS1Frame::~FMS1Frame() {\n}\n\nvoid FMS1Frame::decodeData(const u8* buffer, size_t length) {\n\n\tif(length != FMS1_FRAME_LENGTH) {\t\t//Check the length first\n\t\tthrow J1939DecodeException(\"[FMS1Frame::decodeData] Buffer length does \"\n\t\t\t\t\"not match the expected length. Buffer length:\" + std::to_string(length) + \". Expected length: \" + std::to_string(FMS1_FRAME_LENGTH));\n\t}\n\n\tu8 blockID = buffer[0] & BLOCKID_MASK;\n\n\tif(blockID >= NUMBER_OF_BLOCKS) {\n\t\tthrow J1939DecodeException(std::string(\"[FMS1Frame::decodeData] Block ID higher than the maximum permitted. Max: \") + std::to_string(NUMBER_OF_BLOCKS -1));\n\t}\n\n\t//If block ID changes, clear mTTSs to not accumulate the previous decoded TTSs\n\t//related to the previous block.\n\n\tif(mBlockID != blockID) {\n\t\tmTTSs.clear();\n\t}\n\n\tmBlockID = blockID;\n\n\tu8 tts1Number = TTSS_PER_BLOCK * mBlockID + 1;\n\tTellTale tts1(tts1Number, (buffer[0] >> TTS_HIGH_PART_SHIFT) & TTS_MASK);\n\tmTTSs[tts1Number] = tts1;\n\n\tfor(unsigned int i = 1; i < FMS1_FRAME_LENGTH; ++i) {\n\t\tu8 ttsLowPartNumber = TTSS_PER_BLOCK * mBlockID + 2*i;\n\t\tu8 ttsHighPartNumber = TTSS_PER_BLOCK * mBlockID + 2*i + 1;\n\n\t\tu8 ttsLowPartStatus = buffer[i] & TTS_MASK;\n\t\tu8 ttsHighPartStatus = (buffer[i] >> TTS_HIGH_PART_SHIFT) & TTS_MASK;\n\n\t\tmTTSs[ttsLowPartNumber] = TellTale(ttsLowPartNumber, ttsLowPartStatus);\n\t\tmTTSs[ttsHighPartNumber] = TellTale(ttsHighPartNumber, ttsHighPartStatus);\n\n\t}\n\n}\n\nvoid FMS1Frame::encodeData(u8* buffer, size_t length) const {\n\n\t//Not necessary to check length if getDataLength() returns the proper value as the base class will already do the check\n\n\tif(mTTSs.size() != TTSS_PER_BLOCK) {\t\t//Check if we have the right number of TTSs.\n\t\tthrow  J1939EncodeException(\"[FMS1Frame::encodeData] There are not \" + std::to_string(TTSS_PER_BLOCK) + \" defined\");\n\t}\n\n\t//Check if the number for every TTS is the right one.\n\tif(mTTSs.begin()->first <= mBlockID * TTSS_PER_BLOCK || mTTSs.rbegin()->first > (mBlockID + 1) * TTSS_PER_BLOCK) {\n\t\tthrow  J1939EncodeException(\"[FMS1Frame::encodeData] TTS numbers are not the proper ones for this block\");\n\t}\n\n\tu8 tts1Number = TTSS_PER_BLOCK * mBlockID + 1;\n\n\tbuffer[0] = (mBlockID & BLOCKID_MASK) | ((mTTSs.at(tts1Number).getStatus() | TTS_ENCODING_MASK) << TTS_HIGH_PART_SHIFT);\n\n\tfor(unsigned int i = 1; i < FMS1_FRAME_LENGTH; ++i) {\n\t\tu8 ttsLowPartNumber = TTSS_PER_BLOCK * mBlockID + 2*i;\n\t\tu8 ttsHighPartNumber = TTSS_PER_BLOCK * mBlockID + 2*i + 1;\n\n\t\tbuffer[i] = (mTTSs.at(ttsLowPartNumber).getStatus() | TTS_ENCODING_MASK) |\n\t\t\t\t((mTTSs.at(ttsHighPartNumber).getStatus() | TTS_ENCODING_MASK) << TTS_HIGH_PART_SHIFT);\n\t}\n\n}\n\nstd::string FMS1Frame::toString() const {\n\n\tstd::string retVal = J1939Frame::toString();\n\n\tstd::stringstream sstr;\n\n\tsstr << \"Block ID: \" << static_cast<int>(mBlockID) << std::endl;\n\n\tfor(auto tts = mTTSs.begin(); tts != mTTSs.end(); ++tts) {\n\t\tsstr << tts->second.toString();\n\t}\n\n\treturn retVal + sstr.str();\n\n}\n\nbool FMS1Frame::hasTTS(u8 number) {\n\n\treturn (mTTSs.find(number) != mTTSs.end());\n\n}\n\n\nTellTale FMS1Frame::getTTS(u8 number) {\n\n\tauto iter = mTTSs.find(number);\n\n\tif(iter != mTTSs.end()) {\n\t\treturn iter->second;\n\t}\n\n\treturn TellTale(number, TellTale::TTS_STATUS_NOT_AVAILABLE);\n\n}\n\nbool FMS1Frame::setTTS(u8 number, u8 status) {\n\n\tauto iter = mTTSs.find(number);\n\n\t//If tts number does not belong to FMS1 frame, the tts is not set\n\tif(iter != mTTSs.end()) {\n\t\titer->second = TellTale(number, status);\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n}\n"
  },
  {
    "path": "J1939/FMS/TellTale/TellTale.cpp",
    "content": "/*\n * TellTale.cpp\n *\n *  Created on: Mar 11, 2018\n *      Author: famez\n */\n\n#include <sstream>\n\n#include <FMS/TellTale/TellTale.h>\n\n\nTellTale::TellTale() : mNumber(0), mStatus(0) {\n\n}\n\nTellTale::TellTale(u8 number, u8 status) : mNumber(number), mStatus(status) {\n\n}\n\nTellTale::~TellTale() {\n}\n\n\nstd::string TellTale::toString() const {\n\n\tstd::stringstream sstr;\n\n\tsstr << \"TTS \" << static_cast<u32>(mNumber) << \": \" <<\n\t\t\t\t\tTellTale::getNameForTTSNumber(mNumber) << \" -> Status: \"\n\t\t\t\t\t<< TellTale::getSatusname(mStatus) << \" (\" << static_cast<u32>(mStatus) << \")\" << std::endl;\n\n\treturn sstr.str();\n\n}\n\nstd::map<u8, std::string> TellTale::initializeNTNMap() {\n\n\tstd::map<u8, std::string> retVal;\n\n\tretVal[1] = \"Cooling Air Conditioning\";\n\tretVal[2] = \"High beam, main beam\";\n\tretVal[3] = \"Low beam, dipped beam\";\n\tretVal[4] = \"Turn Signals\";\n\tretVal[5] = \"Hazard Warning\";\n\tretVal[6] = \"Provision for the disabled or handicapped persons\";\n\tretVal[7] = \"Parking Brake\";\n\tretVal[8] = \"Brake failure/brake system malfunction\";\n\tretVal[9] = \"Hatch open\";\n\tretVal[10] = \"Fuel level\";\n\tretVal[11] = \"Engine coolant temperature\";\n\tretVal[12] = \"Battery charging condition\";\n\tretVal[13] = \"Engine oil\";\n\tretVal[14] = \"Position lights,side lights\";\n\tretVal[15] = \"Front fog light\";\n\tretVal[16] = \"Rear fog light\";\n\tretVal[17] = \"Park Heating\";\n\tretVal[18] = \"Engine / Mil indicator\";\n\tretVal[19] = \"Service, call for maintenance\";\n\tretVal[20] = \"Transmission fluid temperature\";\n\tretVal[21] = \"Transmission failure/malfunction\";\n\tretVal[22] = \"Anti-lock brake system failure\";\n\tretVal[23] = \"Worn brake linings\";\n\tretVal[24] = \"Windscreen washer fluid/windshield\";\n\tretVal[25] = \"Tire failure/malfunction\";\n\tretVal[26] = \"Malfunction/general failure\";\n\tretVal[27] = \"Engine oil temperature\";\n\tretVal[28] = \"Engine oil level\";\n\tretVal[29] = \"Engine coolant level\";\n\tretVal[30] = \"Steering fluid level\";\n\tretVal[31] = \"Steering failure\";\n\tretVal[32] = \"Height Control (Levelling)\";\n\tretVal[33] = \"Retarder\";\n\tretVal[34] = \"Engine Emission system failure (Mil indicator)\";\n\tretVal[35] = \"ESC indication\";\n\tretVal[36] = \"Brake lights\";\n\tretVal[37] = \"Articulation\";\n\tretVal[38] = \"Stop Request\";\n\tretVal[39] = \"Pram request\";\n\tretVal[40] = \"Bus stop brake\";\n\tretVal[41] = \"AdBlue level\";\n\tretVal[42] = \"Raising\";\n\tretVal[43] = \"Lowering\";\n\tretVal[44] = \"Kneeling\";\n\tretVal[45] = \"Engine compartment temperature\";\n\tretVal[46] = \"Auxillary air pressure\";\n\tretVal[47] = \"Air filter clogged\";\n\tretVal[48] = \"Fuel filter differential pressure\";\n\tretVal[49] = \"Seat belt\";\n\tretVal[50] = \"EBS\";\n\tretVal[51] = \"Lane departure indication\";\n\tretVal[52] = \"Advanced emergency braking system\";\n\tretVal[53] = \"ACC\";\n\tretVal[54] = \"Trailer connected  washer fluid\";\n\tretVal[55] = \"ABS Trailer\";\n\tretVal[56] = \"Airbag\";\n\tretVal[57] = \"EBS Trailer\";\n\tretVal[58] = \"Tachograph indication\";\n\tretVal[59] = \"ESC switched off\";\n\tretVal[60] = \"Lane departure warning switched off\";\n\n\n\n\treturn retVal;\n\n}\n\nstd::map<u8, std::string> TellTale::initializeSNMap() {\n\n\tstd::map<u8, std::string> retVal;\n\n\tretVal[TTS_STATUS_OFF] = \"OFF\";\n\tretVal[TTS_STATUS_RED] = \"RED\";\n\tretVal[TTS_STATUS_YELLOW] = \"YELLOW\";\n\tretVal[TTS_STATUS_INFO] = \"INFO\";\n\tretVal[TTS_STATUS_NOT_AVAILABLE] = \"NOT AVAILABLE\";\n\n\treturn retVal;\n\n}\n\n\nstd::map<u8, std::string> TellTale::mNumberToName = initializeNTNMap();\n\n\nstd::map<u8, std::string> TellTale::mStatusName = initializeSNMap();\n"
  },
  {
    "path": "J1939/Frames/RequestFrame.cpp",
    "content": "/*\n * RequestFrame.cpp\n *\n *  Created on: Dec 20, 2018\n *      Author: famez\n */\n\n#include <string>\n#include <sstream>\n#include <iostream>\n\n\n#include <Frames/RequestFrame.h>\n#include <J1939Factory.h>\n\n#define REQUEST_FRAME_NAME\t\t\"Request\"\n\nnamespace J1939 {\n\nRequestFrame::RequestFrame() : J1939Frame(REQUEST_PGN) {\n\tmName = REQUEST_FRAME_NAME;\n}\n\nRequestFrame::RequestFrame(u32 requestPGN) : RequestFrame() {\n\tmRequestPGN = requestPGN;\n}\n\nRequestFrame::~RequestFrame() {\n}\n\n\nvoid RequestFrame::decodeData(const u8* buffer, size_t length) {\n\n\tif(length != REQUEST_FRAME_LENGTH) {\t\t//Check the length first\n\t\tthrow  J1939DecodeException(\"[RequestFrame::decodeData] Buffer length does \"\n\t\t\t\t\"not match the expected length. Buffer length:\" + std::to_string(length) + \". Expected length: \" + std::to_string(REQUEST_FRAME_LENGTH));\n\t}\n\n\tmRequestPGN = buffer[0];\n\tmRequestPGN |= (buffer[1] << 8);\n\tmRequestPGN |= (buffer[2] << 16);\n\tmRequestPGN &= J1939_PGN_MASK;\n\n}\n\n\nvoid RequestFrame::encodeData(u8* buffer, size_t length) const {\n\n\tbuffer[0] = (mRequestPGN & 0xFF);\n\tbuffer[1] = ((mRequestPGN >> 8) & 0xFF);\n\tbuffer[2] = ((mRequestPGN >> 16) & (J1939_PGN_MASK >> 16));\n\n}\n\nstd::string RequestFrame::toString() const {\n\n\tstd::string retVal = J1939Frame::toString();\n\tstd::stringstream sstr;\n\n\t//Try to get information related to the PGN.\n\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(mRequestPGN);\n\n\tsstr << \"Request PGN: \" << std::hex << mRequestPGN << \" \" << (frame.get() ? frame->getName() : \"\") << std::endl;\n\n\treturn retVal + sstr.str();\n\n}\n\n} /* namespace J1939 */\n"
  },
  {
    "path": "J1939/GenericFrame.cpp",
    "content": "/*\n * GenericFrame.cpp\n *\n *  Created on: Nov 3, 2017\n *      Author: root\n */\n\n#include <string.h>\n#include <string>\n#include <sstream>\n#include <iostream>\n\n#include <Utils.h>\n#include <Assert.h>\n\n#include \"GenericFrame.h\"\n\nnamespace J1939 {\n\n\n\nGenericFrame::GenericFrame(u32 pgn) : J1939Frame(pgn), mLength(0) {\n\n}\n\n\nGenericFrame::GenericFrame(const GenericFrame& other) : J1939Frame(other), mLength(other.mLength) {\n\n    for(auto spn = other.mSPNs.begin(); spn != other.mSPNs.end(); ++spn) {\n\t\tmSPNs[spn->first] = spn->second->clone();\n\t\tmSPNs[spn->first]->setOwner(this);\n\t}\n}\n\nGenericFrame::~GenericFrame() {\n\n    for(auto spn = mSPNs.begin(); spn != mSPNs.end(); ++spn) {\n\n\t\tdelete spn->second;\n\n\t}\n\n}\n\nvoid GenericFrame::recalculateStringOffsets() {\n\n\tfor(auto spn = mSPNs.begin(); spn != mSPNs.end(); ++spn) {\n\n\t\tauto nextSpn = spn;\n\t\t++nextSpn;\n\t\tif(nextSpn != mSPNs.end()) {\n\t\t\tnextSpn->second->setOffset(spn->second->getOffset() + spn->second->getByteSize());\n\t\t}\n\n\t}\n\n}\n\nvoid GenericFrame::decodeData(const u8* buffer, size_t length) {\n\n\tconst u8* spnBuf;\n\tsize_t offset;\n\n    for(auto spn = mSPNs.begin(); spn != mSPNs.end(); ++spn) {\n\n    \toffset = spn->second->getOffset();\n\n    \tif(offset >= length) {\n\t\t\tthrow J1939DecodeException(\"[GenericFrame::decodeData] Offset of spn is higher than frame length\");\n\t\t}\n\n        spnBuf = buffer + offset;\n        spn->second->decode(spnBuf, length - offset);\n\t}\n\n}\n\n\nvoid GenericFrame::encodeData(u8* buffer, size_t length) const {\n\n    u8* spnBuf;\n\tsize_t offset;\n\n    for(auto spn = mSPNs.begin(); spn != mSPNs.end(); ++spn) {\n\n    \toffset = spn->second->getOffset();\n\n        if(offset >= length) {\n            throw J1939EncodeException(\"[GenericFrame::encodeData] Offset of spn is higher than frame length: SPN number: \" + std::to_string(spn->second->getSpnNumber()) +\n            \t\t\" offset: \" + std::to_string(offset) + \" length: \" + std::to_string(length));\n        }\n\n        spnBuf = buffer + offset;\n        spn->second->encode(spnBuf, length - offset);\n\n\t}\n\n}\n\nsize_t GenericFrame::getDataLength() const {\n\n\tsize_t maxOffset = 0;\n\tsize_t sizeLastSpn = 1;\n\n\n    for(auto spn = mSPNs.rbegin(); spn != mSPNs.rend(); ++spn) {\n\n\t\tif(maxOffset > spn->second->getOffset()) continue;\n\n\t\tmaxOffset = spn->second->getOffset();\n\t\tsizeLastSpn = spn->second->getByteSize();\n\n\t}\n\n    //If we have specified a length, return the maximum value between the real size and the specified one.\n    //This is done if not all spns for this frame are defined and we can have a length smaller than the one necessary to transmit the frame.\n\treturn J1939_MAX(mLength, maxOffset + sizeLastSpn);\n}\n\n\nSPN *GenericFrame::registerSPN(const SPN& spn) {\n\n    SPN* retVal = NULL;\n    auto spnIter = mSPNs.find(spn.getSpnNumber());\n\n    //Assertion to ensure that a generic frame only contains\n    //either SPNs of type string or SPNs of another type than string\n\n    ASSERT(mSPNs.empty() ? true : ((mSPNs.begin()->second->getType() == SPN::SPN_STRING) ==\n    \t\t(spn.getType() == SPN::SPN_STRING)));\n\n    if(spnIter == mSPNs.end()) {\n        retVal = spn.clone();\n        retVal->setOwner(this);\n        mSPNs[spn.getSpnNumber()] = retVal;\n    } else {\n        retVal = spnIter->second;\n    }\n\n    if(spn.getType() == SPN::SPN_STRING) {\n    \trecalculateStringOffsets();\n    }\n\n    return retVal;\n}\n\nSPN* GenericFrame::getSPN(u32 number) {\n\tSPN* ret = NULL;\n\n    auto spn = mSPNs.find(number);\n\n\tif(spn != mSPNs.end()) {\n\t\treturn spn->second;\n\t}\n\n\treturn ret;\n\n}\n\n\nconst SPN* GenericFrame::getSPN(u32 number) const {\n\tSPN* ret = NULL;\n\n    auto spn = mSPNs.find(number);\n\n\tif(spn != mSPNs.end()) {\n\t\treturn spn->second;\n\t}\n\n\treturn ret;\n\n}\n\nstd::set<u32> GenericFrame::getSPNNumbers() const {\n\n\tstd::set<u32> ret;\n\n\n    for(auto iter = mSPNs.begin(); iter != mSPNs.end(); ++iter) {\n\t\tret.insert(iter->first);\n\t}\n\n\treturn ret;\n\n}\n\n\nbool GenericFrame::deleteSPN(u32 number) {\n\n    auto iter = mSPNs.find(number);\n    if(iter != mSPNs.end()) {\n        delete iter->second;\n        mSPNs.erase(iter);\n        return true;\n    }\n    return false;\n}\n\nstd::string GenericFrame::toString() const {\n\n\tstd::string retVal = J1939Frame::toString();\n\n\tfor(auto iter = mSPNs.begin(); iter != mSPNs.end(); ++iter) {\n\t\tretVal += iter->second->toString();\n\t}\n\treturn retVal;\n}\n\nstd::set<SPN*> GenericFrame::compare(const std::string& newData, const std::string oldData) {\n\n\tstd::set<SPN*> retVal;\n\n\tfor(auto iter = mSPNs.begin(); iter != mSPNs.end(); ++iter) {\n\n\t\tsize_t maxLength = iter->second->getOffset() + iter->second->getByteSize();\n\n\t\tif(newData.size() >= maxLength || oldData.size() >= maxLength) {\n\n\t\t\tif(memcmp(newData.c_str() + iter->second->getOffset(), oldData.c_str() + iter->second->getOffset(),\n\t\t\t\t\titer->second->getByteSize()) != 0) {\t\t//SPNs differ\n\n\t\t\t\tretVal.insert(iter->second);\n\n\t\t\t}\n\n\t\t} else {\n\t\t\t//If length not respected we consider the SPN has changed\n\t\t\t//(there are missing bytes in one of the strings)\n\n\t\t\tretVal.insert(iter->second);\n\t\t}\n\n\t}\n\n\treturn retVal;\n\n}\n\nvoid GenericFrame::copy(const J1939Frame& other) {\n\n\tif(!other.isGenericFrame()) {\t\t//Nothing to do\n\t\treturn;\n\t}\n\n\tconst GenericFrame *genOther = static_cast<const GenericFrame*>(&other);\n\n\tauto otherIter = genOther->mSPNs.begin();\n\n\tfor(auto iter = mSPNs.begin(); iter != mSPNs.end(); ++iter) {\n\n\t\tif(otherIter == genOther->mSPNs.end() || otherIter->second->getSpec() != iter->second->getSpec()) {\n\t\t\treturn;\n\t\t}\n\n\t\titer->second->copy(*(otherIter->second));\n\n\t\t++otherIter;\n\n\t}\n\n}\n\n} /* namespace J1939 */\n"
  },
  {
    "path": "J1939/J1939Common.cpp",
    "content": "#include \"J1939Common.h\"\n"
  },
  {
    "path": "J1939/J1939DataBase.cpp",
    "content": "/*\n * JsonParser.cpp\n *\n *  Created on: Nov 7, 2017\n *      Author: root\n */\n\n#include \"J1939DataBase.h\"\n\n#include <string>\n#include <fstream>\n#include <streambuf>\n\n#include <Diagnosis/Frames/DM1.h>\n\n#include \"GenericFrame.h\"\n#include \"SPN/SPNNumeric.h\"\n#include \"SPN/SPNStatus.h\"\n#include \"SPN/SPNString.h\"\n\n#include <json/json.h>\n\n#define PGN_KEY\t\t\t\t\t\t\"pgn\"\n#define SPNS_KEY\t\t\t\t\t\"spns\"\n#define NAME_KEY\t\t\t\t\t\"name\"\n#define NUMBER_KEY\t\t\t\t\t\"number\"\n#define TYPE_KEY\t\t\t\t\t\"type\"\n#define OFFSET_KEY\t\t\t\t\t\"offset\"\n#define LENGTH_KEY\t\t\t\t\t\"length\"\n\n\n#define NUM_FORMAT_GAIN_KEY\t\t\t\"formatGain\"\n#define NUM_FORMAT_OFFSET_KEY\t\t\"formatOffset\"\n#define NUM_BYTE_SIZE_KEY\t\t\t\"byteSize\"\n#define NUM_UNITS_KEY\t\t\t\t\"units\"\n\n#define STAT_BIT_OFFSET_KEY\t\t\t\"bitOffset\"\n#define STAT_BIT_SIZE_KEY\t\t\t\"bitSize\"\n\n#define STAT_DESCRIPTIONS_KEY       \"descriptions\"\n\n\n\n\n\nnamespace J1939 {\n\nJ1939DataBase::J1939DataBase() : mErrorCode(ERROR_OK) {\n\n}\n\nJ1939DataBase::~J1939DataBase() {\n}\n\n\nbool J1939DataBase::parseJsonFile(const std::string& file) {\n\n\tJson::Value data;\n\tstd::ifstream fileStream(file.c_str());\n\n\n\tif(!fileStream.is_open()) {\n\t\tmErrorCode = ERROR_FILE_NOT_FOUND;\n\t\treturn false;\n\t}\n\n\n\tJson::CharReaderBuilder rbuilder;\n\n\tstd::string errs;\n\tif(!Json::parseFromStream(rbuilder, fileStream, &data, &errs)) {\n\t\tmErrorCode = ERROR_JSON_SYNTAX;\n\t\treturn false;\n\t}\n\n\n\t//If we return in the middle of the method, there was a problem with some of the tokens\n\tmErrorCode = ERROR_UNEXPECTED_TOKENS;\n\n\tif(!data.isArray()) {\n\t\treturn false;\n\t}\n\n\tfor(unsigned int i = 0; i < data.size(); ++i) {\n\n\t\tconst Json::Value& jsonFrame = data[i];\n\n        if(!jsonFrame.isMember(PGN_KEY) || !jsonFrame[PGN_KEY].isUInt()) {\n\t\t\treturn false;\n\t\t}\n\n        u32 pgn = jsonFrame[PGN_KEY].asUInt();\n\n        switch(pgn) {\n        case DM1_PGN:\t\t//Not permitted this token. Dangerous for the good performance of the software.\n        \tmErrorCode = ERROR_FORBIDDEN_TOKEN;\n        \treturn false;\n        default:\n        \tbreak;\n\n        }\n\n\t\tGenericFrame frame(pgn);\n\n        if(jsonFrame.isMember(NAME_KEY) && jsonFrame[NAME_KEY].isString()) {      //Optional\n            frame.setName(jsonFrame[NAME_KEY].asString());\n        }\n\n        if(jsonFrame.isMember(LENGTH_KEY) && jsonFrame[LENGTH_KEY].isUInt()) {\t\t//Optional\n        \tframe.setLength(jsonFrame[LENGTH_KEY].asUInt());\n        }\n\n\n\n\t\tif(jsonFrame.isMember(SPNS_KEY)) {\n\t\t\tconst Json::Value& spns = jsonFrame[SPNS_KEY];\n\n\t\t\tif(!spns.isArray()) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tfor(unsigned int j = 0; j < spns.size(); ++j) {\n\t\t\t\tconst Json::Value& spn = spns[j];\n\n\t\t\t\tif(!spn.isMember(NAME_KEY) || !spn.isMember(NUMBER_KEY) || !spn.isMember(TYPE_KEY)) {\n\t\t\t\t\treturn false;\n\n\t\t\t\t}\n\n\t\t\t\tconst Json::Value& name = spn[NAME_KEY];\n\t\t\t\tconst Json::Value& number = spn[NUMBER_KEY];\n\t\t\t\tconst Json::Value& type = spn[TYPE_KEY];\n\t\t\t\tconst Json::Value offset = spn[OFFSET_KEY];\n\n\n\t\t\t\tif(!name.isString() || !number.isUInt() || !type.isUInt()) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\n\t\t\t\tswitch(type.asUInt()) {\n\n\t\t\t\tcase SPN::SPN_NUMERIC:\n\n\t\t\t\t\tif(!parseSPNNumeric(frame, spn)) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\n\t\t\t\tcase SPN::SPN_STATUS:\n\n\t\t\t\t\tif(!parseSPNStatus(frame, spn)) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase SPN::SPN_STRING:\n\n\t\t\t\t\tif(!parseSPNString(frame, spn)) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tmErrorCode = ERROR_UNKNOWN_SPN_TYPE;\n\t\t\t\t\treturn false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\n            }\n\n\t\t}\n        mFrames.push_back(frame);\n\n\n\t}\n\n\tmErrorCode = ERROR_OK;\n\n\treturn true;\n\n}\n\n\nbool J1939DataBase::writeJsonFile(const std::string& file) {\n\n\tJson::Value data;\n\n    std::ofstream ofs (file.c_str(), std::ofstream::out | std::ofstream::trunc);\n\n\tif(!ofs.is_open()) {\n\t\treturn false;\n\t}\n\n\tunsigned int pos;\n\n\tfor(std::vector<GenericFrame>::const_iterator frame = mFrames.begin(); frame != mFrames.end(); ++frame) {\n\n\n\t\tpos = frame - mFrames.begin();\n\t\tJson::Value& jsonFrame = data[pos];\n\n\t\tjsonFrame[PGN_KEY] = frame->getPGN();\n        jsonFrame[NAME_KEY] = frame->getName();\n        jsonFrame[LENGTH_KEY] = frame->getDataLength();\n\n\n\n\t\tstd::set<u32> spns = frame->getSPNNumbers();\n\n\n        if(!spns.empty()) {\n            Json::Value& jsonSPNs = jsonFrame[SPNS_KEY];\n            int i = 0;\n            for(std::set<u32>::const_iterator iter = spns.begin(); iter != spns.end(); ++iter) {\n\n                Json::Value& jsonSPN = jsonSPNs[i++];\n\n                const SPN* spn = frame->getSPN(*iter);\n\n\n                jsonSPN[TYPE_KEY] = \t\tspn->getType();\n                jsonSPN[NUMBER_KEY] = \t\tspn->getSpnNumber();\n                jsonSPN[NAME_KEY] = \t\tspn->getName();\n                jsonSPN[OFFSET_KEY] = \t\tspn->getOffset();\n\n                switch(spn->getType()) {\n                case SPN::SPN_NUMERIC:\n                    writeSPNNumeric(spn, jsonSPN);\n                    break;\n\n                case SPN::SPN_STATUS:\n                    writeSPNStatus(spn, jsonSPN);\n                    break;\n                default:\n                    break;\n                }\n\n            }\n        }\n\n\t}\n\n    ofs << data;\n\n\n\treturn true;\n\n}\n\n\nconst std::vector<GenericFrame>& J1939DataBase::getParsedFrames() const {\n\treturn mFrames;\n}\n\n\nbool J1939DataBase::parseSPNNumeric(GenericFrame& frame, const Json::Value& spn) {\n\n\tif(!spn.isMember(NUM_FORMAT_GAIN_KEY)\n\t\t\t|| !spn.isMember(NUM_FORMAT_OFFSET_KEY) || !spn.isMember(NUM_BYTE_SIZE_KEY) || !spn.isMember(NUM_UNITS_KEY) || !spn.isMember(OFFSET_KEY)) {\n\t\treturn false;\n\t}\n\n\tconst Json::Value& name = \t\t\t\tspn[NAME_KEY];\n\tconst Json::Value& number =\t \t\t\tspn[NUMBER_KEY];\n\tconst Json::Value& offset = \t\t\tspn[OFFSET_KEY];\n\tconst Json::Value& formatGain = \t\tspn[NUM_FORMAT_GAIN_KEY];\n\tconst Json::Value& formatOffset = \t\tspn[NUM_FORMAT_OFFSET_KEY];\n\tconst Json::Value& byteSize = \t\t\tspn[NUM_BYTE_SIZE_KEY];\n\tconst Json::Value& units = \t\t\t\tspn[NUM_UNITS_KEY];\n\n\tif(!formatGain.isDouble() || !formatOffset.isDouble() || !byteSize.isUInt() || !units.isString() || !offset.isUInt()) {\n\t\treturn false;\n\t}\n\n\t//Check if bytesize does not exceed the permitted values\n\tif(byteSize.asUInt() > SPN_NUMERIC_MAX_BYTE_SYZE || byteSize.asUInt() == 0) {\n\t\tmErrorCode = ERROR_OUT_OF_RANGE;\n\t\treturn false;\n\t}\n\n\n    SPNNumeric spnNum(number.asUInt(), name.asString(), offset.asUInt(), formatGain.asDouble(), formatOffset.asDouble(), byteSize.asUInt(), units.asString());\n\n\tframe.registerSPN(spnNum);\n\n\treturn true;\n\n}\n\n\nbool J1939DataBase::parseSPNStatus(GenericFrame& frame, const Json::Value& spn) {\n\n\tif(!spn.isMember(STAT_BIT_OFFSET_KEY) || !spn.isMember(STAT_BIT_SIZE_KEY) || !spn.isMember(OFFSET_KEY)) {\n\t\treturn false;\n\t}\n\n\tconst Json::Value& name = spn[NAME_KEY];\n\tconst Json::Value& number = spn[NUMBER_KEY];\n\tconst Json::Value& offset = spn[OFFSET_KEY];\n\tconst Json::Value& bitOffset = spn[STAT_BIT_OFFSET_KEY];\n\tconst Json::Value& bitSize = spn[STAT_BIT_SIZE_KEY];\n\n\n\tif(!bitOffset.isUInt() || !bitSize.isUInt() || !offset.isUInt()) {\n\t\treturn false;\n\t}\n\n\t//Check the limits of the input values\n\tif(bitSize.asUInt() == 0 || (bitSize.asUInt() + bitOffset.asUInt()) > 8) {\n\t\tmErrorCode = ERROR_OUT_OF_RANGE;\n\t\treturn false;\n\t}\n\n\n    //Check for added descriptions\n\n    SPNStatusSpec::DescMap valueToDesc;\n\n    if(spn.isMember(STAT_DESCRIPTIONS_KEY)) {\n        const Json::Value& descriptions = spn[STAT_DESCRIPTIONS_KEY];\n\n        for(unsigned int i = 0; i < descriptions.size(); ++i) {\n            if(descriptions[i].isNull()){\n                continue;\n            }\n\n            valueToDesc[i] = descriptions[i].asString();\n        }\n    }\n\n    SPNStatus spnStat(number.asUInt(), name.asString(), offset.asUInt(), bitOffset.asUInt(), bitSize.asUInt(), valueToDesc);\n\n\tframe.registerSPN(spnStat);\n\n\treturn true;\n\n}\n\nbool J1939DataBase::parseSPNString(GenericFrame& frame, const Json::Value& spn) {\n\n\tconst Json::Value& name = spn[NAME_KEY];\n\tconst Json::Value& number = spn[NUMBER_KEY];\n\n\tSPNString spnStr(number.asUInt(), name.asString());\n\n\tframe.registerSPN(spnStr);\n\n\treturn true;\n}\n\nvoid J1939DataBase::writeSPNNumeric(const SPN* spn, Json::Value& jsonSpn) {\n\n\tconst SPNNumeric* spnNum = (SPNNumeric*)spn;\n\n\tjsonSpn[NUM_BYTE_SIZE_KEY] = spnNum->getByteSize();\n\tjsonSpn[NUM_FORMAT_GAIN_KEY] = spnNum->getFormatGain();\n\tjsonSpn[NUM_FORMAT_OFFSET_KEY] = spnNum->getFormatOffset();\n\tjsonSpn[NUM_UNITS_KEY] = spnNum->getUnits();\n}\n\n\nvoid J1939DataBase::writeSPNStatus(const SPN* spn, Json::Value& jsonSpn) {\n\n\tconst SPNStatus* spnStat = (SPNStatus*)spn;\n\n\tjsonSpn[STAT_BIT_OFFSET_KEY] = spnStat->getBitOffset();\n\tjsonSpn[STAT_BIT_SIZE_KEY] = spnStat->getBitSize();\n\n    //Check if there are descriptions defined for the different status numbers\n    SPNStatus::DescMap descriptions = spnStat->getValueDescriptionsMap();\n\n    if(descriptions.empty()) {\n        return;\n    }\n\n    Json::Value& description = jsonSpn[STAT_DESCRIPTIONS_KEY];\n\n    for(auto iter = descriptions.begin(); iter != descriptions.end(); ++iter) {\n        description[iter->first] = iter->second;\n    }\n\n}\n\nvoid J1939DataBase::addFrame(const GenericFrame& frame) {\n\n\tmFrames.push_back(frame);\n\n}\n\nvoid J1939DataBase::clear() {\n\n\tmFrames.clear();\n\tmErrorCode = ERROR_OK;\n\n}\n\n} /* namespace J1939 */\n//Json::CharReaderBuilder rbuilder;\n"
  },
  {
    "path": "J1939/J1939Factory.cpp",
    "content": "/*\n * J1939Factory.cpp\n *\n *  Created on: Sep 23, 2017\n *      Author: famez\n */\n\n#include <J1939Factory.h>\n#include <J1939Frame.h>\n#include <J1939DataBase.h>\n\n#include <Transport/TPCMFrame.h>\n#include <Transport/TPDTFrame.h>\n#include <Diagnosis/Frames/DM1.h>\n#include <Addressing/AddressClaimFrame.h>\n#include <Frames/RequestFrame.h>\n#include <FMS/TellTale/FMS1Frame.h>\n#include <Diagnosis/Frames/DM1.h>\n\n\n\n\nnamespace J1939 {\n\n\nJ1939Factory::J1939Factory() {\n\tregisterPredefinedFrames();\n}\n\n\nJ1939Factory::~J1939Factory() {\n\n    unregisterAllFrames();\n\n}\n\nvoid J1939Factory::unregisterAllFrames() {\n    for(std::map<u32, J1939Frame*>::const_iterator iter = mFrames.begin(); iter != mFrames.end(); iter++) {\n        if(iter->second)\n            delete iter->second;\n    }\n    mFrames.clear();\n}\n\nstd::unique_ptr<J1939Frame> J1939Factory::getJ1939Frame(u32 id, const u8* data, size_t length) {\n\n\tJ1939Frame* frame = NULL, *retFrame = NULL;\n\n\tu32 pgn = ((id >> J1939_PGN_OFFSET) & J1939_PGN_MASK);\n\n\t//Check if PDU format belongs to the first group\n\tif(((pgn >> J1939_PDU_FMT_OFFSET) & J1939_PDU_FMT_MASK) < PDU_FMT_DELIMITER) {\n\t\tpgn &= (J1939_PDU_FMT_MASK << J1939_PDU_FMT_OFFSET);\n\t}\n\n\tstd::map<u32, J1939Frame*>::iterator iter = mFrames.find(pgn);\n\n\tif(iter == mFrames.end() || ((frame = iter->second) == NULL)) {\n        return std::unique_ptr<J1939Frame>(nullptr);\n\t}\n\n\tretFrame = frame->clone();\n\n\tif(retFrame) {\n\t\tretFrame->decode(id, data, length);\n\t}\n    return std::unique_ptr<J1939Frame>(retFrame);\n\n}\n\n\nstd::unique_ptr<J1939Frame> J1939Factory::getJ1939Frame(u32 pgn) {\n\n\n\tJ1939Frame* frame = nullptr, *retFrame = nullptr;\n\n\tstd::map<u32, J1939Frame*>::iterator iter = mFrames.find(pgn);\n\n\tif(iter == mFrames.end() || ((frame = iter->second) == NULL)) {\n\t\t//printf(\"Pgn: %u not found\", pgn);\n\t\treturn std::unique_ptr<J1939Frame>(nullptr);\n\t}\n\n\tretFrame = frame->clone();\n\n\treturn std::unique_ptr<J1939Frame>(retFrame);\n\n}\n\nstd::unique_ptr<J1939Frame> J1939Factory::getJ1939Frame(const std::string& name) {\n\n\n\tfor(auto iter = mFrames.begin(); iter != mFrames.end(); ++iter) {\n\t\tif(iter->second != nullptr && iter->second->getName() == name) {\n\n\t\t\treturn std::unique_ptr<J1939Frame>(iter->second->clone());\n\n\t\t}\n\t}\n\n\treturn std::unique_ptr<J1939Frame>(nullptr);\n}\n\n\nbool J1939Factory::registerFrame(const J1939Frame& frame) {\n\n\tif(mFrames.find(frame.getPGN()) == mFrames.end()) {\n\t\tmFrames[frame.getPGN()] = frame.clone();\n        return true;\n    } else {\n        return false;\n    }\n}\n\n\n\nvoid J1939Factory::registerPredefinedFrames() {\n\n\t{\n\t\tTPCMFrame frame;\n\t\tregisterFrame(frame);\n\t}\n\n\t{\n\t\tTPDTFrame frame;\n\t\tregisterFrame(frame);\n\t}\n\n    {\n    \tFMS1Frame frame;\n    \tregisterFrame(frame);\n    }\n\n\n\t{\n\t\tDM1 frame;\n\t\tregisterFrame(frame);\n\t}\n\n\t{\n\t\tAddressClaimFrame frame;\n\t\tregisterFrame(frame);\n\t}\n\n\t{\n\t\tRequestFrame frame;\n\t\tregisterFrame(frame);\n\t}\n\n}\n\nstd::set<u32> J1939Factory::getAllRegisteredPGNs() const {\n\n\tstd::set<u32> pgns;\n\n\n\tfor(std::map<u32, J1939Frame*>::const_iterator iter = mFrames.begin(); iter != mFrames.end(); iter++) {\n\t\tpgns.insert(iter->first);\n\t}\n\n\treturn pgns;\n\n}\n\nvoid J1939Factory::unRegisterFrame(u32 pgn) {\n\n\tauto iter = mFrames.find(pgn);\n\n\tif(iter != mFrames.end()) {\n\n\t\tdelete iter->second;\n\t\tmFrames.erase(iter);\n\n\t}\n\n}\n\nbool J1939Factory::registerDatabaseFrames(const std::string& file) {\n\n\t//Read database if available\n\tJ1939DataBase database;\n\n\tif(!database.parseJsonFile(file)) {\n\t\treturn false;\n\t}\n\n\tconst std::vector<GenericFrame>& ddbbFrames = database.getParsedFrames();\n\n\t//Register all the frames listed in the database\n\tfor(auto iter = ddbbFrames.begin(); iter != ddbbFrames.end(); ++iter) {\n\t\tregisterFrame(*iter);\n\t}\n\n\treturn true;\n}\n\n} /* namespace J1939 */\n"
  },
  {
    "path": "J1939/J1939Frame.cpp",
    "content": "/*\n * J1939Frame.cpp\n *\n *  Created on: Sep 23, 2017\n *      Author: famez\n */\n\n#include <string.h>\n#include <string>\n#include <sstream>\n#include <iostream>\n\n#include <Utils.h>\n#include <Assert.h>\n\n#include <J1939Frame.h>\n\n#define UNKNOWN_FRAME       \"Unknown\"\n\nnamespace std {\n  template <typename _CharT, typename _Traits>\n  inline basic_ostream<_CharT, _Traits> &\n  tab(basic_ostream<_CharT, _Traits> &__os) {\n    return __os.put(__os.widen('\\t'));\n  }\n}\n\nnamespace J1939 {\n\nJ1939Frame::J1939Frame(u32 pgn) : mPriority(0), mSrcAddr(J1939_INVALID_ADDRESS), mPgn(pgn), mDstAddr(J1939_INVALID_ADDRESS), mName(UNKNOWN_FRAME) {\n\n\tASSERT((getPDUFormatGroup() == PDU_FORMAT_2) ? true : ((((mPgn & J1939_DST_ADDR_MASK)) >> J1939_DST_ADDR_OFFSET) == 0))\n\n}\n\nJ1939Frame::~J1939Frame() {\n}\n\n\n\nvoid J1939Frame::decode(u32 identifier, const u8* buffer, size_t length) {\n\n\tu32 pgn = ((identifier >> J1939_PGN_OFFSET) & J1939_PGN_MASK);\n\n\t//Check if PDU format belongs to the fisrt group\n\tif(((pgn >> J1939_PDU_FMT_OFFSET) & J1939_PDU_FMT_MASK) < PDU_FMT_DELIMITER) {\n\n\t\tmDstAddr = ((pgn >> J1939_DST_ADDR_OFFSET) & J1939_DST_ADDR_MASK);\n\t\tpgn &= (J1939_PDU_FMT_MASK << J1939_PDU_FMT_OFFSET);\n\t}\n\n\tif(pgn != mPgn)\n\t{\n        throw J1939DecodeException(\"[J1939Frame::decode] Pgn does not match\");\n\t}\n\n\tmSrcAddr = identifier & J1939_SRC_ADDR_MASK;\n\tidentifier >>= J1939_PRIORITY_OFFSET;\n\n\tmPriority = identifier & J1939_PRIORITY_MASK;\n\n\n\t//Leave data decoding to inherited class\n\tdecodeData(buffer, length);\n\n}\nvoid J1939Frame::encode(u32& identifier, u8* buffer, size_t& length) const {\n\n\tu8 prio = (mPriority & J1939_PRIORITY_MASK);\n\n\tif(prio != mPriority) {\n        throw J1939EncodeException(\"[J1939Frame::encode] Priority exceeded its range\");\n\t}\n\n\tif(length < getDataLength()) {\n        throw J1939EncodeException(\"[J1939Frame::encode] Length smaller than expected\");\n\t}\n\n\tidentifier = mSrcAddr;\n\n\tu32 aux = mPgn;\n\n\tif(getPDUFormatGroup() == PDU_FORMAT_1) {\t\t\t\t\t\t\t//Group 1\n\t\taux = mPgn | ((mDstAddr & J1939_DST_ADDR_MASK) << J1939_DST_ADDR_OFFSET);\n\t}\n\n\tidentifier |= ((aux & J1939_PGN_MASK) << J1939_PGN_OFFSET);\n\n\tidentifier |= (prio << J1939_PRIORITY_OFFSET);\n\n\tmemset(buffer, 0xFF, length);\n\n\tencodeData(buffer, length);\n\n\tlength = getDataLength();\n\n}\n\nu32 J1939Frame::getIdentifier() const {\n\n\tu32 identifier;\n\n\tidentifier = mSrcAddr;\n\n\tu32 aux = mPgn;\n\n\tif(getPDUFormatGroup() == PDU_FORMAT_1) {\t\t\t\t\t\t\t//Group 1\n\t\taux = mPgn | ((mDstAddr & J1939_DST_ADDR_MASK) << J1939_DST_ADDR_OFFSET);\n\t}\n\n\tidentifier |= ((aux & J1939_PGN_MASK) << J1939_PGN_OFFSET);\n\n\tidentifier |= (mPriority << J1939_PRIORITY_OFFSET);\n\n\treturn identifier;\n\n}\n\n\nvoid J1939Frame::copy(const J1939Frame& other) {\n\n    u8* buffer;\n\n    size_t length = other.getDataLength();\n    u32 identifier;\n\n    buffer = new u8[length];\n\n    other.encode(identifier, buffer, length);\n\n    decode(identifier, buffer, length);\n\n    delete[] buffer;\n\n}\n\nstd::string J1939Frame::getHeader() const {\n\n\tstd::stringstream sstr;\n\n\tsstr << \"Name\" << std::tab <<\n\t\t\t\"PGN\" << std::tab <<\n\t\t\t\"Source Address\" << std::tab <<\n\t\t\t\"PDU format\" << std::tab;\n\n\tif(getPDUFormatGroup() == PDU_FORMAT_1) {\n\t\tsstr << \"Dest Address\" << std::tab;\n\t}\n\n\tsstr << \"Priority\" << std::tab;\n\n\tsstr << std::endl;\n\n\n\tsstr << mName << std::tab <<\n\t\t\tstd::uppercase << std::hex << mPgn << std::tab <<\n\t\t\tstatic_cast<u32>(mSrcAddr) << std::tab << std::tab <<\n\t\t\t((getPDUFormatGroup() == PDU_FORMAT_1) ? \"1\" : \"2\") << std::tab << std::tab;\n\n\tif(getPDUFormatGroup() == PDU_FORMAT_1) {\n\t\tsstr << static_cast<u32>(mDstAddr) << std::tab;\n\t}\n\n\tsstr << static_cast<u32>(mPriority) << std::tab;\n\n\tsstr << std::endl;\n\n\treturn sstr.str();\n\n}\n\n} /* namespace J1939 */\n"
  },
  {
    "path": "J1939/README.md",
    "content": "# Developing with libJ1939\n\n\n## Loading the database\n\n```c++\n\n#include <J1939Factory.h>\nusing namespace J1939;\n\n#ifndef DATABASE_PATH\n#define DATABASE_PATH\t\t\"/usr/local/etc/j1939/frames.json\"\n#endif\n\nvoid main() {\n\n\tif(!J1939Factory::getInstance().registerDatabaseFrames(DATABASE_PATH)) {\n\t\tstd::cerr << \"Database not found in \" << DATABASE_PATH << std::endl;\n\t\texit(1);\n\t}\n\t\n}\n\n```\n\n\n## Obtaining a frame\n\n```c++\n\n#include <J1939Factory.h>\nusing namespace J1939;\n\nvoid main() {\n\n\t//Loading the database\n\t....\n\n\tu8 encodedCCVS[] = {0xFF, 0x00, 0x50, 0x9F, 0xFF, 0xFF, 0x1F, 0xFF};\n\tu32 id = 0x18FEF120;\n\t\n\t//CCVS frame\n\t\n\t//A J1939Frame represents a frame specified in the protocol J1939. All frames inherit from this one.\n\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(id, encodedCCVS, sizeof(encodedCCVS));\n\t\n\tif(!frame->isGenericFrame()) {\n\t\texit(2);\n\t}\n\t\n\t\n\t//A GenericFrame is a frame defined in the database which is generic in the sense that it contains fields called SPNs\n\tconst GenericFrame *ccvsFrame = static_cast<GenericFrame *>(frame.get());\n\t\n\t\n\t//One can obtain the source address, dest address if any, priority, values for SPNs...\n\t\n\tu8 src = ccvsFrame->getSrcAddr();\n\tu8 prio = ccvsFrame->getPriority();\n\t\n\tu32 pgn = ccvsFrame->getPGN();\n\t\n\tconst SPNNumeric* wheelSpeed = static_cast<SPNNumeric*>(ccvs.getSPN(84));\n\t\n\t\n\t//Vehicle Speed\n\tdouble speed = wheelSpeed->getFormattedValue();\n\n}\n\n```\n\n\n\n## Encoding a frame\n\n```c++\n\n#include <J1939Factory.h>\nusing namespace J1939;\n\nvoid main() {\n\n\t//Loading the database\n\t....\n\n\t//Obtain frame to encode\n\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(\"CCVS\");\n\t\n\tif(!frame->isGenericFrame()) {\n\t\texit(2);\n\t}\n\t\n\tconst GenericFrame *ccvsFrame = static_cast<GenericFrame *>(frame.get());\n\t\n\tSPNNumeric* wheelSpeed = static_cast<SPNNumeric*>(ccvs.getSPN(84));\n\n\twheelSpeed->setFormattedValue(50);\t\t//50 kph\n\t\n\tccvsFrame->setSrcAddr(0x50);\n\tccvsFrame->setPriority(7);\n\t\n\tu32 id;\n\tsize_t length = ccvsFrame->getDataLength();\n\n\n\tu8* buff = new u8[length];\n\n\ttry {\n\t\tccvsFrame->encode(id, buff, length);\n\t\t\n\t} catch(J1939EncodeException &) {\n\t\t//\n\t}\n\t\n\t//Work with buff... For example send as payload of a CanFrame.\n\t\n\tdelete[] buff;\n\n}\n\n```\n\n\n### J1939/\nThis folder contains the core of the framework. The project is configured to be compiled as a dynamic library. This library is composed by the following components:\n- #### J1939Frame \nAbstract class that represents a frame with the common attributes to all the frames (PGN, Source Address, Priority, etc). All the frames should inherit from this base class. This class provides two methods to be overloaded by the inherited classes: encodeData when it is required that the frame encodes the data into a buffer (probably used to send the data to the CAN bus) and decodeData when the data must be extracted from a buffer (likely, data from a CAN interface).\n\n- #### GenericFrame \nThis class inherits from J1939Frame and lets define the 90% of the frames defined in J1939 protocol with the help of a Json database that is loaded (or written) by the class J1939Database. \n- ##### SPN\nAn abstract class that represents a SPN (Suspect Parameter Number). A GenericFrame is composed by several SPNs.\n- ###### SPN/SPNStatus\nAn implementation of the class SPN that represents the SPNs that reports the status of a component (for example, brake released, depressed).\n- ###### SPN/SPNNumeric\nAn implementation of the class SPN that represents the SPNs which reports a quantity (for example, wheel speed).\n- ###### SPN/SPNString\nAn implementation of the class SPN that represents the SPNs which reports a string of characters (for example, VIN, Vehicle Number Identifier).\n\n- ##### Transport/\nImplementation of the transport layer of the J1939 protocol\n- ###### Transport/Bam\nImplementation of the Broadcast Announcement Message protocol that belongs to the transport layer of the J1939 protocol\n- ##### Diagnosis/\nImplementation of the Dianosis specification that belongs to the transport layer of the J1939 protocol.\n- ###### Diagnosis/Frames/DM1\nImplementation of DM1 diagnosis message\n- ##### FMS/TellTale/\nImplementation of the frame whose PGN is FDE7 (FMS1), with the status of the different Tell Tales. \n"
  },
  {
    "path": "J1939/SPN/SPN.cpp",
    "content": "/*\n * ISPN.cpp\n *\n *  Created on: Oct 24, 2017\n *      Author: root\n */\n\n\n#include <string.h>\n#include <string>\n#include <sstream>\n#include <iostream>\n\n#include <Assert.h>\n\n\n#include <J1939Common.h>\n#include <SPN/SPN.h>\n\n\n\nnamespace J1939 {\n\nSPN::SPN(u32 number, const std::string& name, size_t offset) {\n\n\t//When calling the copy constructor, spec object will be passed by reference to keep only one copy of\n\t//the characteristics of the SPN which are the same for the SPN to be cloned as well as for the cloned SPN.\n\n\n\tmSpec = std::make_shared<SPNSpec>(\n\t\t\tSPNSpec(number, name, offset)\n\t\t\t);\n}\n\nSPN::~SPN() {\n\n}\n\nstd::string SPN::toString() const {\n\n\tstd::stringstream sstr;\n\n\tsstr << \"SPN \" << getSpnNumber() << \": \" << getName();\n\n\treturn sstr.str();\n\n}\n\n} /* namespace J1939 */\n"
  },
  {
    "path": "J1939/SPN/SPNHistory.cpp",
    "content": "/*\n * SPNHistory.cpp\n *\n *  Created on: 12 Feb 2019\n *      Author: fernando\n */\n\n#include <algorithm>\n\n#include <SPN/SPNHistory.h>\n#include <SPN/SPNNumeric.h>\n#include <SPN/SPNStatus.h>\n\n#define MAX_NUMBER_OF_SAMPLES\t\t50000\n\nnamespace J1939 {\n\nSPNHistory::SPNHistory() {\n\tmSamples.reserve(MAX_NUMBER_OF_SAMPLES);\n}\n\nSPNHistory::~SPNHistory() {\n}\n\n\nvoid SPNHistory::addSample(const Utils::TimeStamp& timeStamp, const SPN& spn) {\n\n\t//We assume that the timestamp is always increasing\n\n\tif(mSamples.size() == mSamples.capacity())\t\treturn;\t\t//Capacity exceeded\n\n\tif(!mGeneralSpec) {\t\t//First time we add a SPN\n\t\tmGeneralSpec = spn.getSpec();\n\n\t\tswitch(spn.getType()) {\n\n\t\tcase SPN::SPN_NUMERIC: {\n\t\t\tconst SPNNumeric *spnNum = static_cast<const SPNNumeric *>(&spn);\n\t\t\tmSpecificSpec.numeric = spnNum->getNumericSpec();\n\t\t}\tbreak;\n\t\tcase SPN::SPN_STATUS: {\n\t\t\tconst SPNStatus *spnStat = static_cast<const SPNStatus *>(&spn);\n\t\t\tmSpecificSpec.status = spnStat->getStatusSpec();\n\t\t}\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\n\t\t}\n\t}\n\n\tif(mGeneralSpec != spn.getSpec()) {\n\t\treturn;\t\t//Not the same spn\n\t}\n\n\t//Build the sample\n\tSample sample;\n\n\tswitch(spn.getType()) {\n\n\tcase SPN::SPN_NUMERIC: {\n\t\tconst SPNNumeric *spnNum = static_cast<const SPNNumeric *>(&spn);\n\n\t\tif(!mSamples.empty() && mSamples.back().getNumeric() == spnNum->getFormattedValue())\t\treturn;\t\t//Value did not change\n\n\t\tsample = Sample(timeStamp, spnNum->getFormattedValue());\n\t}\tbreak;\n\tcase SPN::SPN_STATUS: {\n\t\tconst SPNStatus *spnStat = static_cast<const SPNStatus *>(&spn);\n\n\t\tif(!mSamples.empty() && mSamples.back().getStatus() == spnStat->getValue())\t\t\t\t\treturn;\t\t//Value did not change\n\n\t\tsample = Sample(timeStamp, spnStat->getValue());\n\t}\tbreak;\n\tdefault:\n\t\treturn;\t\t//Unknown, nothing to do\n\t\tbreak;\n\n\t}\n\n\tmSamples.push_back(sample);\n\n}\n\nstd::vector<SPNHistory::Sample> SPNHistory::getWindow(const Utils::TimeStamp& timeStamp, u32 milliseconds, u32 samples) const {\n\n\tstd::vector<Sample> window;\n\n\n\tif(mSamples.size() < 2)\t\t\treturn window;\n\n\tu32 period = milliseconds / samples;\n\n\n\tUtils::TimeStamp current = timeStamp - milliseconds;\n\n\n\t//Get the beginning\n\tSample sample(current, static_cast<u8>(0));\n\n\tsize_t pos = std::upper_bound(mSamples.begin(), mSamples.end(), sample) - mSamples.begin();\n\n\tif(pos != 0)\t--pos;\t\t//Start with the sample whose timestamp is lower or equals to the beginning of the window\n\n\n\twhile(current <= timeStamp) {\n\n\t\tSample mySample(mSamples[pos]);\n\t\tmySample.setTimeStamp(current);\t\t//Modify timestamp\n\n\t\twindow.push_back(mySample);\n\n\t\tcurrent = current + period;\n\n\t\twhile(pos+1 < mSamples.size() && current >= mSamples[pos+1].getTimeStamp()) {\n\n\t\t\t//TODO check variation of more of 10% and maximums and minimums.\n\t\t\t++pos;\n\t\t}\n\n\t}\n\n\treturn window;\n}\n\n} /* namespace J1939 */\n"
  },
  {
    "path": "J1939/SPN/SPNNumeric.cpp",
    "content": "/*\n * SPNNumeric.cpp\n *\n *  Created on: Oct 24, 2017\n *      Author: root\n */\n\n\n#include <string.h>\n#include <string>\n#include <sstream>\n#include <iostream>\n\n#include <Utils.h>\n#include <Assert.h>\n\n#include <J1939Common.h>\n#include <SPN/SPNNumeric.h>\n\n\nnamespace J1939 {\n\nSPNNumeric::SPNNumeric(u32 number, const std::string& name,\n\t\tsize_t offset, double formatGain, double formatOffset, u8 byteSize, const std::string& units) :\n    SPN(number, name, offset), mValue(0xFFFFFFFF) {\n\n\tmNumSpec = std::make_shared<SPNNumericSpec>(\n\t\tSPNNumericSpec(formatGain, formatOffset, byteSize, units)\n\t);\n\n}\n\nSPNNumeric::~SPNNumeric() {\n\n}\n\n\nvoid SPNNumeric::decode(const u8* buffer, size_t length) {\n\n    if(getByteSize() > length || getByteSize() > SPN_NUMERIC_MAX_BYTE_SYZE) {       //mValue can hold only 4 bytes cause it is of type u32\n        throw J1939DecodeException(\"[SPNNumeric::decode] Spn length is bigger than expected\");\n    }\n\tmValue = 0;\n    for(int i = 0; i < getByteSize(); ++i) {\n\t\tmValue |= (buffer[i] << (i * 8));\n\t}\n}\n\n\nvoid SPNNumeric::encode(u8* buffer, size_t length) const {\n\n    if(getByteSize() > length || getByteSize() > SPN_NUMERIC_MAX_BYTE_SYZE) {       //mValue can hold only 4 bytes cause it is of type u32\n        throw J1939EncodeException(\"[SPNNumeric::encode] Spn length is bigger than expected\");\n    }\n\n    for(int i = 0; i < getByteSize(); ++i) {\n        buffer[i] = ((mValue >> (i * 8)) & 0xFF);\n    }\n\n}\n\ndouble SPNNumeric::getFormattedValue() const {\n\tdouble aux = mValue;\n\n\t//Apply gain and offset\n\treturn aux * getFormatGain() + getFormatOffset();\n}\n\nbool SPNNumeric::setFormattedValue(double value) {\n\n\tdouble aux = (value - getFormatOffset()) / getFormatGain();\n\n\tu64 threshold = (((u64)(1)) << (getByteSize()*8));\n\n\tif(aux >= 0 && (aux < threshold)) {\n\t\tmValue = static_cast<u32>(aux);\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nstd::string SPNNumeric::toString() const {\n\n\tstd::string retval = SPN::toString();\n\n\tstd::stringstream sstr;\n\n\tsstr << \" -> Value: \" << std::fixed << getFormattedValue() << \" \" << getUnits() << std::endl;\n\n\tretval += sstr.str();\n\treturn retval;\n\n}\n\nvoid SPNNumeric::copy(const SPN& other) {\n\n\tconst SPNNumeric *numOther = static_cast<const SPNNumeric *>(&other);\n\n\tmValue = numOther->mValue;\n\n}\n\n} /* namespace J1939 */\n"
  },
  {
    "path": "J1939/SPN/SPNSpec/SPNNumericSpec.cpp",
    "content": "/*\n * SPNNumericSpec.cpp\n *\n *  Created on: Oct 24, 2017\n *      Author: root\n */\n\n\n#include <string.h>\n#include <string>\n#include <sstream>\n#include <iostream>\n\n#include <Utils.h>\n#include <Assert.h>\n\n#include <J1939Common.h>\n#include <SPN/SPNSpec/SPNNumericSpec.h>\n\n\nnamespace J1939 {\n\nSPNNumericSpec::SPNNumericSpec(double formatGain, double formatOffset, u8 byteSize, const std::string& units) :\n\t mFormatGain(formatGain), mFormatOffset(formatOffset), mByteSize(byteSize), mUnits(units) {\n\n\tASSERT(byteSize > 0)\n\tASSERT(byteSize <= SPN_NUMERIC_MAX_BYTE_SYZE)\n\n}\n\nSPNNumericSpec::~SPNNumericSpec() {\n\n}\n\nu32 SPNNumericSpec::getMaxValue() const {\n    return 0xFAFFFFFF >> (4 - mByteSize) * 8;\n}\n\n\ndouble SPNNumericSpec::formatValue(u32 value) const {\n\n\tdouble aux = value;\n\n\t//Apply gain and offset\n\treturn aux * mFormatGain + mFormatOffset;\n\n}\n\n\n} /* namespace J1939 */\n"
  },
  {
    "path": "J1939/SPN/SPNSpec/SPNSpec.cpp",
    "content": "/*\n * SPNSpec.cpp\n *\n *  Created on: Oct 24, 2017\n *      Author: root\n */\n\n\n#include <string.h>\n#include <string>\n#include <sstream>\n#include <iostream>\n\n#include <Assert.h>\n\n\n#include <J1939Common.h>\n#include <SPN/SPNSpec/SPNSpec.h>\n\n\n\nnamespace J1939 {\n\nSPNSpec::SPNSpec(u32 number, const std::string& name, size_t offset) : mSPNNumber(number), mName(name), mOffset(offset) {\n\n\tASSERT((number < (1 << SPN_NUMBER_MAX_BITS)))\n\n}\n\nSPNSpec::~SPNSpec() {\n\n}\n\n} /* namespace J1939 */\n"
  },
  {
    "path": "J1939/SPN/SPNSpec/SPNStatusSpec.cpp",
    "content": "/*\n * SPNStatusSpec.cpp\n *\n *  Created on: Oct 24, 2017\n *      Author: root\n */\n\n#include <stdio.h>\n#include <string.h>\n#include <string>\n#include <sstream>\n#include <iostream>\n\n#include <Assert.h>\n\n\n#include <J1939Common.h>\n#include <SPN/SPNSpec/SPNStatusSpec.h>\n\nnamespace J1939 {\n\nSPNStatusSpec::SPNStatusSpec(u8 bitOffset, u8 bitSize, SPNStatusSpec::DescMap valueToDesc) : mBitOffset(bitOffset), mBitSize(bitSize) {\n\n\tASSERT(mBitSize > 0)\n\tASSERT(mBitOffset + mBitSize <= 8)\n\n\tmValueToDesc = valueToDesc;\n}\n\nSPNStatusSpec::~SPNStatusSpec() {\n}\n\n\n\nvoid SPNStatusSpec::setValueDescription(u8 value, const std::string& desc) {\n\n    mValueToDesc[value] = desc;\n\n}\n\n\nstd::string SPNStatusSpec::getValueDescription(u8 value) const {\n\n    std::string retVal;\n\n    auto iter = mValueToDesc.find(value);\n\n    if(iter != mValueToDesc.end()) {\n        retVal = iter->second;\n    }\n\n    return retVal;\n}\n\nvoid SPNStatusSpec::clearValueDescriptions() {\n\n    mValueToDesc.clear();\n\n}\n\n\nSPNStatusSpec::DescMap SPNStatusSpec::getValueDescriptionsMap() const {\n    return mValueToDesc;\n}\n\n} /* namespace J1939 */\n"
  },
  {
    "path": "J1939/SPN/SPNStatus.cpp",
    "content": "/*\n * SPNStatus.cpp\n *\n *  Created on: Oct 24, 2017\n *      Author: root\n */\n\n#include <stdio.h>\n#include <string.h>\n#include <string>\n#include <sstream>\n#include <iostream>\n\n#include <Assert.h>\n\n\n#include <J1939Common.h>\n#include <SPN/SPNStatus.h>\n\nnamespace J1939 {\n\nSPNStatus::SPNStatus(u32 number, const std::string& name, size_t offset, u8 bitOffset, u8 bitSize, SPNStatusSpec::DescMap valueToDesc) : SPN(number, name, offset) {\n\n\tmStatSpec = std::make_shared<SPNStatusSpec>(\n\t\t\tSPNStatusSpec(bitOffset, bitSize, valueToDesc)\n\t\t\t);\n\n\tmValue = (0xFF >> (8 - getBitSize()));\t\t//Always initialized to invalid value\n\n}\n\nSPNStatus::~SPNStatus() {\n}\n\n\nvoid SPNStatus::decode(const u8* buffer, size_t) {\n\n    if(getBitOffset() > 7 || getBitSize() > 8 || getBitOffset() + getBitSize() > 8) {\n        throw J1939DecodeException(\"[SPNStatus::decode] Format incorrect to decode properly this spn\");\n    }\n\n\tu8 mask = 0xFF >> (8 - getBitSize());\n\tmValue = ((*buffer >> getBitOffset()) & mask);\n}\n\n\nvoid SPNStatus::encode(u8* buffer, size_t) const {\n\n    if(getBitOffset() > 7 || getBitSize() > 8 || getBitOffset() + getBitSize() > 8) {\n        throw J1939EncodeException(\"[SPNStatus::encode] Format incorrect to encode properly this spn\");\n    }\n\n    u8 mask = (0xFF >> (8 - getBitSize())) << getBitOffset();\n    u8 value = mValue << getBitOffset();\n\n    if((value & mask) != value) {\n        throw J1939EncodeException(\"[SPNStatus::encode] Value to encode is bigger than expected\");\n    }\n\n    //Clear the bits from the buffer\n    *buffer = *buffer & ~mask;\n\n    //Set the new value\n    *buffer = *buffer | value;\n\n}\n\n\nstd::string SPNStatus::toString() const {\n\n\tstd::string retval = SPN::toString();\n\n\tstd::stringstream sstr;\n\n\tSPNStatusSpec::DescMap valueToDesc = getValueDescriptionsMap();\n\n\tsstr << \" -> Status: \" << ((valueToDesc.find(mValue) != valueToDesc.end()) ? valueToDesc[mValue] : \"\") <<\n\t\t\t\" (\" << static_cast<u32>(mValue) << \")\" << std::endl;\n\n\tretval += sstr.str();\n\treturn retval;\n\n}\n\nbool SPNStatus::setValue(u8 value) {\n\n\tif(value < (1 << getBitSize())) {\n\t\tmValue = value;\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nvoid SPNStatus::copy(const SPN& other) {\n\n\tconst SPNStatus *numOther = static_cast<const SPNStatus *>(&other);\n\n\tmValue = numOther->mValue;\n\n}\n\n} /* namespace J1939 */\n"
  },
  {
    "path": "J1939/SPN/SPNString.cpp",
    "content": "/*\n * SPNString.cpp\n *\n *  Created on: 6 juil. 2018\n *      Author: fernando\n */\n\n#include <string.h>\n#include <string>\n#include <sstream>\n#include <iostream>\n\n\n#include <J1939Common.h>\n#include <SPN/SPNString.h>\n#include <GenericFrame.h>\n\n\nnamespace J1939 {\n\nSPNString::SPNString(u32 number, const std::string& name) : SPN(number, name, 0/*Stub, not used by SPNString*/) {\n\n}\n\nSPNString::~SPNString() {\n}\n\nvoid SPNString::setValue(std::string value)\n{\n\n\tfor(char c : value) {\n\t    if(c & 0x80) {\n\t    \treturn;\t\t\t//This is not ASCII. We cannot assign a string that is not an ASCII string...\n\t    }\n\t}\n\n\tmValue = value;\n\n\tif(mOwner) {\t\t//The offsets for SPN of type string may have changed.\n\t\tmOwner->recalculateStringOffsets();\n\t}\n}\n\nvoid SPNString::decode(const u8* buffer, size_t length) {\n\n\tchar *terminator = (char*) memchr(buffer, J1939_STR_TERMINATOR, length);\n\n\tmValue.clear();\n\n\tif(!terminator) {\n\t\tthrow J1939DecodeException(\"[SPNString::decode] '*' terminator not found\");\n\t}\n\n\tfor(const char *c = (const char*)(buffer); c != terminator; ++c) {\n\t\tif(*c & 0x80) {\n\t\t\tthrow J1939DecodeException(\"[SPNString::decode] String is not ASCII\");\n\t\t}\n\t}\n\n\tsize_t strLength = terminator - (const char*)(buffer);\n\n\tmValue.append((const char*)(buffer), strLength);\n\n\tif(mOwner) {\t\t//The size of this SPN has changed, the offsets must be recalculated\n\t\tmOwner->recalculateStringOffsets();\n\t}\n\n}\n\nvoid SPNString::encode(u8* buffer, size_t length) const {\n\n\tif(mValue.size() >= length) {\n\t\tthrow J1939EncodeException(\"[SPNString::encode] Not enough length to encode the string\");\n\t}\n\n\t//Copy string to the buffer\n\tstrcpy((char*)(buffer), mValue.c_str());\n\n\t//Add string terminator to need of the string\n\tbuffer[mValue.size()] = J1939_STR_TERMINATOR;\n\n}\n\n\nstd::string SPNString::toString() const {\n\n\tstd::string retval = SPN::toString();\n\n\tstd::stringstream sstr;\n\n\tsstr << \" -> Value: \" << mValue << std::endl;\n\n\tretval += sstr.str();\n\treturn retval;\n\n}\n\n\nvoid SPNString::copy(const SPN& other) {\n\n\tconst SPNString *numOther = static_cast<const SPNString *>(&other);\n\n\tmValue = numOther->mValue;\n\n}\n\n} /* namespace J1939 */\n"
  },
  {
    "path": "J1939/Transport/BAM/BamFragmenter.cpp",
    "content": "/*\n * BamFragmenter.cpp\n *\n *  Created on: Apr 22, 2018\n *      Author: fernado\n */\n\n#include <Utils.h>\n#include <Transport/BAM/BamFragmenter.h>\n\n\nnamespace J1939 {\n\nBamFragmenter::BamFragmenter() {\n\n\n}\n\nBamFragmenter::~BamFragmenter() {\n}\n\nbool BamFragmenter::fragment(const J1939Frame& frame) {\n\n\tsize_t length = frame.getDataLength();\n\n\tif(length <= J1939_MAX_SIZE) {\t\t\t//Not necessary to fragment the frame\n\t\treturn false;\n\t}\n\n\n\t//Clear previous fragmented frames\n\tclear();\n\n\n\t//Bam type\n\tmCMFrame.setCtrlType(CTRL_TPCM_BAM);\n\n\n\t//Same source and priority as the original frame\n\tmCMFrame.setPriority(frame.getPriority());\n\tmCMFrame.setSrcAddr(frame.getSrcAddr());\n\n\n\t//Encoded pgn\n\tmCMFrame.setDataPgn(frame.getPGN());\n\n\t//Always broadcast\n\tmCMFrame.setDstAddr(J1939_BROADCAST_ADDRESS);\n\n\tsize_t sq = 0;\n\n\tu8* data = new u8[length];\n\n\tu32 unused;\n\n\tframe.encode(unused, data, length);\n\n\tfor(size_t offset = 0 ; offset < length; offset += TP_DT_PACKET_SIZE) {\n\n\t\tTPDTFrame dataFrame(++sq, data + offset, J1939_MIN(TP_DT_PACKET_SIZE, length - offset));\n\n\t\t//Same source and priority as the original frame\n\t\tdataFrame.setPriority(frame.getPriority());\n\t\tdataFrame.setSrcAddr(frame.getSrcAddr());\n\n\t\t//Always broadcast\n\t\tdataFrame.setDstAddr(J1939_BROADCAST_ADDRESS);\n\n\t\tmDTFrames[sq] = dataFrame;\n\n\t}\n\n\tdelete[] data;\n\n\tmCMFrame.setTotalPackets(mDTFrames.size());\n\n\tmCMFrame.setTotalMsgSize(length);\n\n\treturn true;\n}\n\nstd::vector<TPDTFrame> BamFragmenter::getDataFrames() const {\n\n\tstd::vector<TPDTFrame> frames;\n\n\tfor(auto iter = mDTFrames.begin(); iter != mDTFrames.end(); ++iter) {\n\t\tframes.push_back(iter->second);\n\t}\n\n\treturn frames;\n\n}\n\n} /* namespace J1939 */\n"
  },
  {
    "path": "J1939/Transport/BAM/BamReassembler.cpp",
    "content": "/*\n * BamFrameSet.cpp\n *\n *  Created on: Oct 2, 2017\n *      Author: famez\n */\n\n#include <string.h>\n\n//Common\n#include <Utils.h>\n#include <Assert.h>\n\n//J1939\n#include <J1939Factory.h>\n#include <Transport/BAM/BamReassembler.h>\n\nnamespace J1939 {\n\nu8 BamReassembler::BAMFragments::getLastSQ() const{\n\n\tif(mDTFrames.empty())\n\t{\n\t\treturn 0;\n\t}\n\n\treturn mDTFrames.back().getSq();\n\n}\n\n\n\nBamReassembler::BamReassembler() : mLastError(BAM_ERROR_OK) {\n\n}\n\nBamReassembler::~BamReassembler() {\n\tclear();\n}\n\nvoid BamReassembler::reassemble(const BAMFragments& fragments, u8** data, size_t& length) {\n\n\tsize_t offset = 0;\n\n\tlength = fragments.getCmFrame().getTotalMsgSize();\n\t*data = new u8[length];\n\n\tfor(std::vector<TPDTFrame>::const_iterator iter = fragments.getDtFrames().begin(); iter != fragments.getDtFrames().end(); iter++) {\n\t\tmemcpy((void*)(*data + offset), (void*)iter->getData(), J1939_MIN(length - offset, TP_DT_PACKET_SIZE));\n\t\toffset += TP_DT_PACKET_SIZE;\n\t\tif(offset >= length)\n\t\t{\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nbool BamReassembler::toBeHandled(const J1939Frame& frame) const {\n\n\tconst TPCMFrame* conn;\n\n\tif(frame.getDstAddr() != J1939_BROADCAST_ADDRESS) {\t\t//Does not have a broadcast address\n\t\treturn false;\n\t}\n\n\tswitch(frame.getPGN()) {\n\tcase TP_CM_PGN:\n\t{\n\t\tconn = static_cast<const TPCMFrame*>(&frame);\n\t\treturn (conn->getCtrlType() == CTRL_TPCM_BAM);\t\t//If the ctrl type is not BAM, discard it.\n\t}\tbreak;\n\tcase TP_DT_PGN:\n\t{\n\t\treturn true;\n\t}\tbreak;\n\tdefault:\n\t{\n\t\treturn false;\n\t}\tbreak;\n\n\t}\n\n}\n\n\nsize_t BamReassembler::handleFrame(const J1939Frame& frame) {\n\n\tconst TPDTFrame* data = NULL;\n\tconst TPCMFrame* conn = NULL;\n\n\tsize_t expectedSize = 0;\n\n\tu8 srcAddr = frame.getSrcAddr();\n\n\n\tif(frame.getDstAddr() != J1939_BROADCAST_ADDRESS) {\t\t//The frame does not have a broadcast address\n\t\tsetError(BAM_ERROR_NOT_BCAST_ADDR);\n\t\treturn 0;\n\t}\n\n\tswitch(frame.getPGN()) {\n\tcase TP_CM_PGN:\t\t\t\t\t//Conn management reception\n\t{\n\t\tconn = static_cast<const TPCMFrame*>(&frame);\n\n\t\t//Not the right Connection Manager frame...\n\t\tif(conn->getCtrlType() != CTRL_TPCM_BAM) {\n\n\t\t\tsetError(BAM_ERROR_UNEXPECTED_FRAME);\n\t\t\tbreak;\n\t\t}\n\n\t\t//New TP.CM frame but not all previous TP.DT frames were received\n\t\tif(mFragments.find(srcAddr) != mFragments.end()) {\n\t\t\tmFragments.erase(srcAddr);\n\t\t\tsetError(BAM_ERROR_INCOMPLETE_FRAME);\n\t\t} else {\n\t\t\tsetError(BAM_ERROR_OK);\n\t\t}\n\n\t\tmFragments[srcAddr].setCmFrame(*conn);\n\n\t\texpectedSize = conn->getTotalMsgSize();\n\n\t}\tbreak;\n\n\tcase TP_DT_PGN:\t\t\t\t\t//Data reception\n\t{\n\n\t\tif(mFragments.find(srcAddr) == mFragments.end()) {\n\t\t\tsetError(BAM_ERROR_UNEXPECTED_FRAME);\n\t\t\tbreak;\n\t\t}\n\n\t\tdata = static_cast<const TPDTFrame*>(&frame);\n\n\t\tu8 sq = data->getSq();\n\n\t\tconst TPCMFrame& connFrame = mFragments[srcAddr].getCmFrame();\n\n\t\texpectedSize = connFrame.getTotalMsgSize();\n\n\t\tif((connFrame.getTotalPackets() >= sq) && (mFragments[srcAddr].getLastSQ() + 1 == sq) ) {\n\t\t\tmFragments[srcAddr].addDtFrame(*data);\n\t\t} else {\n\t\t\tsetError(BAM_ERROR_UNEXPECTED_FRAME);\n\t\t\tbreak;\n\t\t}\n\n\t\tif(sq == connFrame.getTotalPackets()) {\t\t//Time to reassemble the packet\n\n\t\t\tu8* fullData;\n\t\t\tsize_t length;\n\t\t\treassemble(mFragments[srcAddr], &fullData, length);\n\t\t\tu32 newId = (((connFrame.getPriority() & J1939_PRIORITY_MASK) << J1939_PRIORITY_OFFSET) |\n\t\t\t\t\t(connFrame.getDataPgn() << J1939_PGN_OFFSET) | (connFrame.getSrcAddr() & J1939_SRC_ADDR_MASK));\n\n\t\t\tstd::unique_ptr<J1939Frame> decodedFrame = J1939Factory::getInstance().getJ1939Frame(newId, fullData, length);\n\t\t\tdelete[] fullData;\n\n\t\t\t//Fragments reassembled, we can destroy the fragments\n\t\t\tmFragments.erase(srcAddr);\n\n\t\t\tif(decodedFrame.get()) {\n\t\t\t\tmReassembledFrames.push(decodedFrame.release());\n\t\t\t} else {\n\t\t\t\tsetError(BAM_ERROR_DECODING);\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\tsetError(BAM_ERROR_OK);\n\t\t}\n\n\t}\tbreak;\n\n\tdefault:\n\t{\n\t\t//Not a frame for BAM protocol\n\t\tsetError(BAM_ERROR_UNEXPECTED_FRAME);\n\n\t}\tbreak;\n\n\t}\n\n\treturn expectedSize;\n\n}\n\n\nstd::unique_ptr<J1939Frame> BamReassembler::dequeueReassembledFrame() {\n\n\tJ1939Frame* retVal = NULL;\n\n\tretVal = mReassembledFrames.front();\n\tmReassembledFrames.pop();\n\n\n\treturn std::unique_ptr<J1939Frame>(retVal);\n\n}\n\nvoid BamReassembler::clear() {\n\n\tmFragments.clear();\n\n\tmLastError = BAM_ERROR_OK;\n\n\t//Clear queue\n\twhile(!mReassembledFrames.empty()) {\n\t\tdelete mReassembledFrames.front();\n\t\tmReassembledFrames.pop();\n\t}\n\n}\n\n} /* namespace J1939 */\n"
  },
  {
    "path": "J1939/Transport/RTSCTS/RTSCTSConnectionManager.cpp",
    "content": "/*\n * RTSCTSConnectionManager.cpp\n *\n *  Created on: Oct 15, 2017\n *      Author: famez\n */\n\n#include \"RTSCTSConnectionManager.h\"\n\nnamespace J1939 {\n\nRTSCTSConnectionManager::RTSCTSConnectionManager() {\n\t// TODO Auto-generated constructor stub\n\n}\n\nRTSCTSConnectionManager::~RTSCTSConnectionManager() {\n\t// TODO Auto-generated destructor stub\n}\n\n\nvoid RTSCTSConnectionManager::consumeFrame(const J1939Frame&) {\n\n}\n\n} /* namespace J1939 */\n"
  },
  {
    "path": "J1939/Transport/TPCMFrame.cpp",
    "content": "/*\n * BAMHeaderFrame.cpp\n *\n *  Created on: Oct 2, 2017\n *      Author: famez\n */\n\n#include <string.h>\n\n#include <Transport/TPCMFrame.h>\n\n\n\n#define TPCM_NAME       \"Transport Connection Management\"\n\n\nnamespace J1939 {\n\nTPCMFrame::TPCMFrame() : J1939Frame(TP_CM_PGN), mCtrlType(0), mTotalMsgSize(0), mTotalPackets(0), mMaxPackets(0),\n\t\t mPacketsToTx(0), mNextPacket(0), mAbortReason(0), mDataPgn(0){\n\n    mName = TPCM_NAME;\n\n}\n\nTPCMFrame::~TPCMFrame() {\n\n}\n\nvoid TPCMFrame::decodeData(const u8* buffer, size_t length) {\n\n\n\tif(length != TP_CM_SIZE) {\n\t\tthrow J1939DecodeException(\"[TPCMFrame::decodeData] Buffer length does not match the expected \"\n\t\t\t\t\"length. Buffer length:\" + std::to_string(length) + \". Expected length: \" + std::to_string(TP_CM_SIZE));\n\t}\n\n\tmCtrlType = buffer[0];\n\n\n\tswitch(mCtrlType) {\n\n\tcase CTRL_TPCM_RTS:\n\t\tdecodeRTS(buffer + 1);\n\t\tbreak;\n\n\tcase CTRL_TPCM_CTS:\n\t\tdecodeCTS(buffer + 1);\n\t\tbreak;\n\tcase CTRL_TPCM_ACK:\n\t\tdecodeEndOfMsgACK(buffer + 1);\n\t\tbreak;\n\tcase CTRL_TPCM_ABORT:\n\t\tdecodeConnAbort(buffer + 1);\n\t\tbreak;\n\tcase CTRL_TPCM_BAM:\n\t\tdecodeBAM(buffer + 1);\n\t\tbreak;\n\tdefault:\n        throw J1939DecodeException(\"[TPCMFrame::decodeData] Unknown Ctrl type\");\n\t\tbreak;\n\t}\n\n\n\tmDataPgn = buffer[5] | (buffer[6] << 8) | (buffer[7] << 16);\n\n\n}\n\nvoid TPCMFrame::encodeData(u8* buffer, size_t ) const {\n\n\t/*\n\t * If reserved, set to 0xFF\n\t */\n\tmemset(buffer, 0xFF, TP_CM_SIZE);\n\n\tbuffer[0] = mCtrlType;\n\n\n\tswitch(mCtrlType) {\n\tcase CTRL_TPCM_RTS:\n\t\tencodeRTS(buffer + 1);\n\t\tbreak;\n\n\tcase CTRL_TPCM_CTS:\n\t\tencodeCTS(buffer + 1);\n\t\tbreak;\n\tcase CTRL_TPCM_ACK:\n\t\tencodeEndOfMsgACK(buffer + 1);\n\t\tbreak;\n\tcase CTRL_TPCM_ABORT:\n\t\tencodeConnAbort(buffer + 1);\n\t\tbreak;\n\tcase CTRL_TPCM_BAM:\n\t\tencodeBAM(buffer + 1);\n\t\tbreak;\n\tdefault:\n        throw J1939DecodeException(\"[TPCMFrame::encodeData] Unknown Ctrl Type\");\n\t\tbreak;\n\t}\n\n\n\tbuffer[5] = mDataPgn & 0xFF;\n\tbuffer[6] = (mDataPgn >> 8) & 0xFF;\n\tbuffer[7] = (mDataPgn >> 16) & 0xFF;\n\n}\n\nvoid TPCMFrame::clear() {\n\tmCtrlType = 0;\n\tmTotalMsgSize = 0;\n\tmTotalPackets = 0;\n\tmMaxPackets = 0;\n\tmPacketsToTx = 0;\n\tmNextPacket = 0;\n\tmAbortReason = 0;\n\n\tmDataPgn = 0;\n\n\tsetPriority(0);\n\tsetSrcAddr(0);\n\tsetDstAddr(J1939_BROADCAST_ADDRESS);\n\n}\n\n\nvoid TPCMFrame::decodeRTS(const u8* buffer) {\n\n\tmTotalMsgSize = buffer[0] | (buffer[1] << 8);\n\tmTotalPackets = buffer[2];\n\tmMaxPackets = buffer[3];\n\n}\n\nvoid TPCMFrame::decodeCTS(const u8* buffer) {\n\n\tmPacketsToTx = buffer[0];\n\tmNextPacket = buffer[1];\n}\n\nvoid TPCMFrame::decodeEndOfMsgACK(const u8* buffer) {\n\tmTotalMsgSize = buffer[0] | (buffer[1] << 8);\n\tmTotalPackets = buffer[2];\n\n}\n\nvoid TPCMFrame::decodeConnAbort(const u8* buffer) {\n\tmAbortReason = buffer[0];\n}\n\n\nvoid TPCMFrame::decodeBAM(const u8* buffer) {\n\tmTotalMsgSize = buffer[0] | (buffer[1] << 8);\n\tmTotalPackets = buffer[2];\n}\n\n\nvoid TPCMFrame::encodeRTS(u8* buffer) const {\n\n\tbuffer[0] = mTotalMsgSize & 0xFF;\n\tbuffer[1] = (mTotalMsgSize >> 8) & 0xFF;\n\tbuffer[2] = mTotalPackets;\n\tbuffer[3] = mMaxPackets;\n\n}\nvoid TPCMFrame::encodeCTS(u8* buffer) const {\n\n\tbuffer[0] = mPacketsToTx;\n\tbuffer[1] = mNextPacket;\n\n}\nvoid TPCMFrame::encodeEndOfMsgACK(u8* buffer) const {\n\n\tbuffer[0] = mTotalMsgSize & 0xFF;\n\tbuffer[1] = (mTotalMsgSize >> 8) & 0xFF;\n\tbuffer[2] = mTotalPackets;\n\n}\nvoid TPCMFrame::encodeConnAbort(u8* buffer) const {\n\n\tbuffer[0] = mAbortReason;\n\n}\nvoid TPCMFrame::encodeBAM(u8* buffer) const {\n\n\tbuffer[0] = mTotalMsgSize & 0xFF;\n\tbuffer[1] = (mTotalMsgSize >> 8) & 0xFF;\n\tbuffer[2] = mTotalPackets;\n\n}\n\n\n} /* namespace J1939 */\n"
  },
  {
    "path": "J1939/Transport/TPDTFrame.cpp",
    "content": "/*\n * BamDataframe.cpp\n *\n *  Created on: Oct 2, 2017\n *      Author: famez\n */\n\n#include <string.h>\n#include <Utils.h>\n\n#include <Transport/TPDTFrame.h>\n\n\n#define TPDT_NAME      \"Transport Data\"\n\nnamespace J1939 {\n\nTPDTFrame::TPDTFrame() : J1939Frame(TP_DT_PGN), mSQ(0) {\n\tmemset(mData, 0xFF, TP_DT_PACKET_SIZE);\n    mName = TPDT_NAME;\n}\n\n\nTPDTFrame::TPDTFrame(u8 sq, u8* data, size_t length) : TPDTFrame() {\n\tmSQ = sq;\n\tmemcpy(mData, data, J1939_MIN(length, TP_DT_PACKET_SIZE));\n}\n\nTPDTFrame::~TPDTFrame() {\n}\n\nvoid TPDTFrame::decodeData(const u8* buffer, size_t length) {\n\n\tif(length != BAM_DT_SIZE) {\n\t\tthrow J1939DecodeException(\"[TPDTFrame::decodeData] Buffer length does not match the expected length. Buffer length:\" + std::to_string(length)\n\t\t+ \". Expected length: \" + std::to_string(TP_DT_PACKET_SIZE));\n\t}\n\tmSQ = *buffer++;\n\n\tmemcpy(mData, buffer, TP_DT_PACKET_SIZE);\n\n}\nvoid TPDTFrame::encodeData(u8* buffer, size_t) const {\n\n\t*buffer++ = mSQ;\n\n\tmemcpy(buffer, mData, TP_DT_PACKET_SIZE);\n\n}\n\n\n} /* namespace J1939 */\n"
  },
  {
    "path": "J1939/include/Addressing/AddressClaimFrame.h",
    "content": "/*\n * AdressClaimFrame.h\n *\n *  Created on: Oct 17, 2017\n *      Author: famez\n */\n\n#ifndef ADDRESSING_ADRESSCLAIMFRAME_H_\n#define ADDRESSING_ADRESSCLAIMFRAME_H_\n\n#include <J1939Frame.h>\n\n\n#define ADDRESS_CLAIM_PGN\t\t0x00EE00\n#define ADDRESS_FRAME_LENGTH\t8\n\n#define ARBITRARY_ADDR_CAPABLE_MASK\t\t0x1\n#define ARBITRARY_ADDR_CAPABLE_OFFSET\t63\n#define INDUSTRY_GROUP_MASK\t\t\t\t0x7\n#define INDUSTRY_GROUP_OFFSET\t\t\t60\n#define VEHICLE_SYSTEM_INTERFACE_MASK\t0xF\n#define VEHICLE_SYSTEM_INTERFACE_OFFSET\t56\n#define VEHICLE_SYSTEM_MASK\t\t\t\t0x7F\n#define VEHICLE_SYSTEM_OFFSET\t\t\t49\n#define FUNCTION_MASK\t\t\t\t\t0xFF\n#define FUNCTION_OFFSET\t\t\t\t\t40\n#define FUNCTION_INSTANCE_MASK\t\t\t0x1F\n#define FUNCTION_INSTANCE_OFFSET\t\t35\n#define ECU_INSTANCE_MASK\t\t\t\t0x7\n#define ECU_INSTANCE_OFFSET\t\t\t\t32\n#define MANUFACTURER_CODE_MASK\t\t\t0x7FF\n#define MANUFACTURER_CODE_OFFSET\t\t21\n#define IDENTITY_NUMBER_MASK\t\t\t0x1FFFFF\n#define IDENTITY_NUMBER_OFFSET\t\t\t0\n\n\n\nnamespace J1939 {\n\n\nclass EcuName {\nprivate:\n\n\tu32 mIdNumber = 0;\n\tu16 mManufacturerCode = 0;\n\tu8 mEcuInstance = 0;\n\tu8 mFunctionInstance = 0;\n\tu8 mFunction = 0;\n\tu8 mVehicleSystem = 0;\n\tu8 mVehicleSystemInstance = 0;\n\tu8 mIndustryGroup = 0;\n\tbool mArbitraryAddressCapable = false;\n\npublic:\n\n\tEcuName() {}\n\tEcuName(u32 idNumber, u16 manufacturerCode, u8 ecuInstance,\n\t\t\tu8 functionInstance, u8 function, u8 vehicleSystem,\n\t\t\tu8 vehicSystemInstance, u8 industryGroup,\n\t\t\tbool arbitraryAddressCapable) : mIdNumber(idNumber), mManufacturerCode(manufacturerCode),\n\t\t\tmEcuInstance(ecuInstance), mFunctionInstance(functionInstance), mFunction(function),\n\t\t\tmVehicleSystem(vehicleSystem), mVehicleSystemInstance(vehicSystemInstance), mIndustryGroup(industryGroup),\n\t\t\tmArbitraryAddressCapable(arbitraryAddressCapable){\n\n\t}\n\tvirtual ~EcuName() {}\n\n\tu64 getValue() const {\n\n\t\treturn ((u64)(mArbitraryAddressCapable ? ARBITRARY_ADDR_CAPABLE_MASK : 0) << ARBITRARY_ADDR_CAPABLE_OFFSET) |\n\t\t\t\t((u64)(mIndustryGroup & INDUSTRY_GROUP_MASK) << INDUSTRY_GROUP_OFFSET) |\n\t\t\t\t((u64)(mVehicleSystemInstance & VEHICLE_SYSTEM_INTERFACE_MASK) << VEHICLE_SYSTEM_INTERFACE_OFFSET) |\n\t\t\t\t((u64)(mVehicleSystem & VEHICLE_SYSTEM_MASK) << VEHICLE_SYSTEM_OFFSET) |\n\t\t\t\t((u64)(mFunction & FUNCTION_MASK) << FUNCTION_OFFSET) |\n\t\t\t\t((u64)(mFunctionInstance & FUNCTION_INSTANCE_MASK) << FUNCTION_INSTANCE_OFFSET) |\n\t\t\t\t((u64)(mEcuInstance & ECU_INSTANCE_MASK) << ECU_INSTANCE_OFFSET) |\n\t\t\t\t((u64)(mManufacturerCode & MANUFACTURER_CODE_MASK) << MANUFACTURER_CODE_OFFSET) |\n\t\t\t\t((u64)(mIdNumber & IDENTITY_NUMBER_MASK) << IDENTITY_NUMBER_OFFSET);\n\n\t}\n\n\tbool operator<(const EcuName& other) const {\n\n\t\treturn getValue() < other.getValue();\n\t}\n\n\tbool operator>(const EcuName& other) const {\n\t\treturn getValue() > other.getValue();\n\t}\n\n\tbool isArbitraryAddressCapable() const {\n\t\t\treturn mArbitraryAddressCapable;\n\t}\n\n\tvoid setArbitraryAddressCapable(bool arbitraryAddressCapable) {\n\t\tmArbitraryAddressCapable = arbitraryAddressCapable;\n\t}\n\n\tu8 getEcuInstance() const {\n\t\treturn mEcuInstance;\n\t}\n\n\tvoid setEcuInstance(u8 ecuInstance) {\n\t\tmEcuInstance = ecuInstance;\n\t}\n\n\tu8 getFunction() const {\n\t\treturn mFunction;\n\t}\n\n\tvoid setFunction(u8 function) {\n\t\tmFunction = function;\n\t}\n\n\tu8 getFunctionInstance() const {\n\t\treturn mFunctionInstance;\n\t}\n\n\tvoid setFunctionInstance(u8 functionInstance) {\n\t\tmFunctionInstance = functionInstance;\n\t}\n\n\tu32 getIdNumber() const {\n\t\treturn mIdNumber;\n\t}\n\n\tvoid setIdNumber(u32 idNumber) {\n\t\tmIdNumber = idNumber;\n\t}\n\n\tu8 getIndustryGroup() const {\n\t\treturn mIndustryGroup;\n\t}\n\n\tvoid setIndustryGroup(u8 industryGroup) {\n\t\tmIndustryGroup = industryGroup;\n\t}\n\n\tu16 getManufacturerCode() const {\n\t\treturn mManufacturerCode;\n\t}\n\n\tvoid setManufacturerCode(u16 manufacturerCode) {\n\t\tmManufacturerCode = manufacturerCode;\n\t}\n\n\tu8 getVehicleSystem() const {\n\t\treturn mVehicleSystem;\n\t}\n\n\tvoid setVehicleSystem(u8 vehicleSystem) {\n\t\tmVehicleSystem = vehicleSystem;\n\t}\n\n\tu8 getVehicleSystemInstance() const {\n\t\treturn mVehicleSystemInstance;\n\t}\n\n\tvoid setVehicleSystemInstance(u8 vehicleSystemInstance) {\n\t\tmVehicleSystemInstance = vehicleSystemInstance;\n\t}\n\n};\n\nclass AddressClaimFrame: public J1939Frame {\nprivate:\n\tEcuName mEcuName;\nprotected:\n\n\tvoid decodeData(const u8* buffer, size_t length);\n\tvoid encodeData(u8* buffer, size_t length) const;\n\npublic:\n\tAddressClaimFrame();\n\tAddressClaimFrame(EcuName name);\n\tvirtual ~AddressClaimFrame();\n\n\tsize_t getDataLength() const override { return ADDRESS_FRAME_LENGTH; }\n\n\tconst EcuName& getEcuName() { return mEcuName; }\n\n\tstd::string toString() const;\n\n\tIMPLEMENT_CLONEABLE(J1939Frame,AddressClaimFrame);\n\n};\n\n} /* namespace J1939 */\n\n#endif /* ADDRESSING_ADRESSCLAIMFRAME_H_ */\n"
  },
  {
    "path": "J1939/include/Diagnosis/DTC.h",
    "content": "/*\n * DTC.h\n *\n *  Created on: Sep 2, 2018\n *      Author: fernado\n */\n\n#ifndef DIAGNOSIS_DTC_H_\n#define DIAGNOSIS_DTC_H_\n\n#include <Types.h>\n#include <string>\n\n#define DTC_SIZE\t\t4\n#define DTC_CM_MASK\t\t0x80\n#define DTC_OC_MASK\t\t0x7F\n#define DTC_FMI_MASK\t0x1F\n\nnamespace J1939 {\n\nenum {\n\tFMI_DATA_ABOVE_RANGE,\n\tFMI_DATA_BELOW_RANGE,\n\tFMI_DATA_INTERMITENT_OR_INCORRECT,\n\tFMI_VOLTAGE_ABOVE_RANGE,\n\tFMI_VOLTAGE_BELOW_RANGE,\n\tFMI_CURRENT_BELOW_RANGE,\n\tFMI_CURRENT_ABOVE_RANGE,\n\tFMI_SYS_NOT_RESPONDING,\n\tFMI_ABNORMAL_FREQUENCY,\n\tFMI_ABNORMAL_UPDATE_RATE,\n\tFMI_ABNORMAL_RATE_OF_CHARGE,\n\tFMI_NOT_KNOWN,\n\tFMI_BAD_DEVICE,\n\tFMI_OUT_OF_CALIBRATION,\n\tFMI_SPECIAL_INSTRUCTIONS,\n\tFMI_DATA_VALID_BUT_ABOVE_RANGE_LEAST,\n\tFMI_DATA_VALID_BUT_ABOVE_RANGE_MODERATELY,\n\tFMI_DATA_VALID_BUT_BELOW_RANGE_LEAST,\n\tFMI_DATA_VALID_BUT_BELOW_RANGE_MODERATELY,\n\tFMI_RECEIVED_NETWORK_DATA_IN_ERROR,\n\tFMI_DATA_DRIFTED_HIGH,\n\tFMI_DATA_DRIFTED_LOW,\n\tFMI_CONDITION_EXISTS = 31\n\n};\n\nclass DTC {\n\nprivate:\n\tu32 mSPN;\n\tu8 mFMI;\n\tu8 mOC;\n\npublic:\n\tDTC();\n\tDTC(u32 spn, u8 fmi, u8 oc);\n\tvirtual ~DTC();\n\n\n\n\tvoid decode(const u8* buffer);\n\tvoid encode(u8* buffer) const;\n\n\tstd::string toString() const;\n\n\tu8 getFmi() const { return mFMI; }\n\tvoid setFmi(u8 fmi) { mFMI = fmi; }\n\n\tu8 getOc() const { return mOC; }\n\tvoid setOc(u8 oc) { mOC = oc; }\n\n\tu32 getSpn() const { return mSPN; }\n\tvoid setSpn(u32 spn) { mSPN = spn; }\n};\n\n} /* namespace J1939 */\n\n#endif /* DIAGNOSIS_DTC_H_ */\n"
  },
  {
    "path": "J1939/include/Diagnosis/Frames/DM1.h",
    "content": "/*\n * DM1.h\n *\n *  Created on: Oct 15, 2017\n *      Author: famez\n */\n\n#ifndef DIAGNOSIS_FRAMES_DM1_H_\n#define DIAGNOSIS_FRAMES_DM1_H_\n\n#include <vector>\n\n#include <GenericFrame.h>\n#include <Diagnosis/DTC.h>\n\n#define DM1_PGN\t\t\t0x00FECA\n#define DM1_NAME\t\t\"DM1\"\n\nnamespace J1939 {\n\nclass DM1: public GenericFrame {\nprivate:\n\n\tstd::vector<DTC> mDtcs;\n\nprotected:\n\tvoid decodeData(const u8* buffer, size_t length);\n\tvoid encodeData(u8* buffer, size_t length) const;\n\npublic:\n\tDM1();\n\tvirtual ~DM1();\n\n\tvoid addDTC(DTC&& dtc) { mDtcs.push_back(dtc); };\n\n\tbool deleteDTC(size_t pos) { if(pos >= mDtcs.size()) return false; mDtcs.erase(mDtcs.begin() + pos); return true; }\n\n\tbool setDTC(size_t pos, DTC&& dtc) { if(pos >= mDtcs.size()) return false; mDtcs[pos] = dtc; return true; }\n\n\tconst std::vector<DTC>& getDTCs() const { return mDtcs; }\n\n\tsize_t getDataLength() const override;\n\tstd::string toString() const override;\n\n\tvoid copy(const J1939Frame& other) override;\n\n\tIMPLEMENT_CLONEABLE(J1939Frame,DM1);\n};\n\n} /* namespace J1939 */\n\n#endif /* DIAGNOSIS_FRAMES_DM1_H_ */\n"
  },
  {
    "path": "J1939/include/FMS/TellTale/FMS1Frame.h",
    "content": "/*\n * FMS1Frame.h\n *\n *  Created on: Mar 11, 2018\n *      Author: famez\n */\n\n#ifndef TELLTALE_FMS1FRAME_H_\n#define TELLTALE_FMS1FRAME_H_\n\n#include <Types.h>\n#include <map>\n#include \"../../J1939Frame.h\"\n#include \"TellTale.h\"\n\n#define TTS_MASK\t\t\t\t0x7\n#define BLOCKID_MASK\t\t\t0xF\n#define TTS_HIGH_PART_SHIFT\t\t4\n#define TTSS_PER_BLOCK\t\t\t15\n#define TTS_ENCODING_MASK\t\t0x8\n\n#define NUMBER_OF_BLOCKS\t\t4\n\n#define FMS1_FRAME_LENGTH\t\t8\n\n#define FMS1_PGN\t\t\t\t0xFD7D\n\nnamespace J1939 {\n\nclass FMS1Frame : public J1939Frame {\n\nprivate:\n\tu8 mBlockID;\n\tstd::map<u8, TellTale> mTTSs;\n\nprotected:\n\n\tvoid decodeData(const u8* buffer, size_t length) override;\n\n\tvoid encodeData(u8* buffer, size_t length) const override;\n\npublic:\n\tFMS1Frame();\n\tFMS1Frame(u8 blockID);\n\n\tvirtual ~FMS1Frame();\n\n\tbool hasTTS(u8 number);\n\n\tTellTale getTTS(u8 number);\n\n\tbool setTTS(u8 number, u8 status);\n\n\tu8 getBlockID() const { return mBlockID; }\n\n\tsize_t getDataLength() const override { return FMS1_FRAME_LENGTH; }\n\n\tstd::string toString() const override;\n\n\tIMPLEMENT_CLONEABLE(J1939Frame,FMS1Frame);\n};\n\n\n}\n\n#endif /* TELLTALE_FMS1FRAME_H_ */\n"
  },
  {
    "path": "J1939/include/FMS/TellTale/TellTale.h",
    "content": "/*\n * TellTale.h\n *\n *  Created on: Mar 11, 2018\n *      Author: famez\n */\n\n#ifndef TELLTALE_TELLTALE_H_\n#define TELLTALE_TELLTALE_H_\n\n\n#include <string>\n#include <map>\n\n#include <Types.h>\n\n\nclass TellTale {\nprivate:\n\tu8 mNumber;\n\tu8 mStatus;\n\n\tstatic std::map<u8, std::string> mNumberToName;\n\tstatic std::map<u8, std::string> mStatusName;\n\n\tstatic std::map<u8, std::string> initializeNTNMap();\n\tstatic std::map<u8, std::string> initializeSNMap();\n\npublic:\n\n\n\tenum {\n\t\tTTS_STATUS_OFF,\n\t\tTTS_STATUS_RED,\n\t\tTTS_STATUS_YELLOW,\n\t\tTTS_STATUS_INFO,\n\t\tTTS_STATUS_NOT_AVAILABLE = 0x7,\n\t};\n\n\tTellTale(u8 number, u8 status);\n\tTellTale();\n\tvirtual ~TellTale();\n\n\tu8 getNumber() const {\n\t\treturn mNumber;\n\t}\n\n\tvoid setNumber(u8 number) {\n\t\tmNumber = number;\n\t}\n\n\tu8 getStatus() const {\n\t\treturn mStatus;\n\t}\n\n\tvoid setStatus(u8 status) {\n\t\tmStatus = status;\n\t}\n\n\tstd::string toString() const;\n\n\n\tstatic std::string getNameForTTSNumber(u8 number) { return (mNumberToName.find(number) != mNumberToName.end()) ? mNumberToName.at(number) : \"\"; }\n\tstatic std::string getSatusname(u8 status) { return (mStatusName.find(status) != mStatusName.end()) ? mStatusName.at(status) : \"RESERVED\"; }\n\n\n\n};\n\n#endif /* TELLTALE_TELLTALE_H_ */\n"
  },
  {
    "path": "J1939/include/Frames/RequestFrame.h",
    "content": "/*\n * RequestFrame.h\n *\n *  Created on: Dec 20, 2018\n *      Author: famez\n */\n\n#ifndef ADDRESSING_REQUESTFRAME_H_\n#define ADDRESSING_REQUESTFRAME_H_\n\n#include <J1939Frame.h>\n\n#define REQUEST_FRAME_LENGTH\t\t3\n#define REQUEST_PGN\t\t\t\t\t0xEA00\n\nnamespace J1939 {\n\nclass RequestFrame: public J1939Frame {\nprivate:\n\tu32 mRequestPGN = 0;\n\nprotected:\n\n\tvoid decodeData(const u8* buffer, size_t length);\n\tvoid encodeData(u8* buffer, size_t length) const;\n\npublic:\n\tRequestFrame();\n\tRequestFrame(u32 requestPGN);\n\tvirtual ~RequestFrame();\n\n\tsize_t getDataLength() const override { return REQUEST_FRAME_LENGTH; }\n\n\tu32 getRequestPGN() const { return mRequestPGN; }\n\n\tvoid setRequestPGN(u32 requestPGN) { mRequestPGN = requestPGN; }\n\n\tstd::string toString() const;\n\n\tIMPLEMENT_CLONEABLE(J1939Frame,RequestFrame);\n\n};\n\n} /* namespace J1939 */\n\n#endif /* ADDRESSING_REQUESTFRAME_H_ */\n"
  },
  {
    "path": "J1939/include/GenericFrame.h",
    "content": "/*\n * GenericFrame.h\n *\n *  Created on: Nov 3, 2017\n *      Author: root\n */\n\n#ifndef GENERICFRAME_H_\n#define GENERICFRAME_H_\n\n#include <map>\n#include <set>\n\n#include \"J1939Frame.h\"\n#include \"SPN/SPN.h\"\n\nnamespace J1939 {\n\nclass GenericFrame : public J1939Frame {\nprivate:\n\tsize_t mLength;\n\tstd::map<u32/*SpnNumber*/, SPN*> mSPNs;\nprotected:\n\tvirtual void decodeData(const u8* buffer, size_t length);\n\tvirtual void encodeData(u8* buffer, size_t length) const;\npublic:\n    GenericFrame(u32 pgn);\n\tGenericFrame(const GenericFrame& other);\n\tvirtual ~GenericFrame();\n\n\t//This method is called when there is a need to recalculate the offsets for SPNs of type String.\n\tvoid recalculateStringOffsets();\n\n\n\t/**\n\t * The copy-assingment and move-assignment are forbidden here. Use clone instead.\n\t */\n\tGenericFrame& operator=(const GenericFrame& other) = delete;\n\tGenericFrame& operator=(GenericFrame&& other) = delete;\n\n    SPN* registerSPN(const SPN& spn);\n\n    bool deleteSPN(u32 number);\n\n\tSPN* getSPN(u32);\n\n\tconst SPN* getSPN(u32) const;\n\n\tbool hasSPN(u32 number) const { return ( mSPNs.find(number) != mSPNs.end()); }\n\n\tstd::set<u32> getSPNNumbers() const;\n\n\tstd::map<u32/*SpnNumber*/, SPN*> getSPNs() { return mSPNs; };\n\n\tvirtual size_t getDataLength() const;\n\n\tvoid setLength(size_t length) { mLength = length; }\n\n    void setName(const std::string& name) { mName = name; }\n\n    bool isGenericFrame() const { return true; }\n\n    virtual std::string toString() const;\n\n    /*\n     * Returns a set of SPNs that have changed with respect to the data\n     */\n    std::set<SPN*> compare(const std::string& newData, const std::string oldData);\n\n    void copy(const J1939Frame& other) override;\n\n\tIMPLEMENT_CLONEABLE(J1939Frame,GenericFrame);\n};\n\n} /* namespace J1939 */\n\n#endif /* GENERICFRAME_H_ */\n"
  },
  {
    "path": "J1939/include/J1939Common.h",
    "content": "#ifndef J1939COMMON_H\n#define J1939COMMON_H\n\n\n#include <exception>\n#include <string>\n\n#define J1939_MAX_SIZE\t\t\t\t8\n\n#define J1939_PGN_OFFSET\t\t\t8\n#define J1939_PGN_MASK\t\t\t\t0x3FFFF\n\n#define J1939_PDU_SPECIFIC_MASK\t\t0xFF\n#define J1939_DST_ADDR_MASK\t\t\t0xFF\n#define J1939_SRC_ADDR_MASK\t\t\t0xFF\n\n\n#define J1939_SRC_ADDR_OFFSET\t\t0\n#define J1939_DST_ADDR_OFFSET\t\t0\n\n\n\n#define J1939_PDU_FMT_MASK\t\t\t0xFF\n#define J1939_PDU_FMT_OFFSET\t\t8\n\n#define J1939_DATA_PAGE_MASK\t\t1\n#define J1939_DATA_PAGE_OFFSET\t\t16\n\n#define J1939_EXT_DATA_PAGE_MASK\t1\n#define J1939_EXT_DATA_PAGE_OFFSET\t17\n\n#define J1939_PRIORITY_OFFSET\t\t26\n#define J1939_PRIORITY_MASK\t\t\t7\n\n#define J1939_STATUS_MASK\t\t\t3\n\n#define J1939_STR_TERMINATOR\t\t'*'\n#define\tNULL_TERMINATOR\t\t\t\t0\n\n#define TP_DT_PACKET_SIZE\t\t\t7\n\n#define PDU_FMT_DELIMITER\t\t\t0xF0\n\n#define J1939_INVALID_ADDRESS\t\t0xFE\n#define J1939_BROADCAST_ADDRESS\t\t0xFF\n\n#define SPN_NUMBER_MAX_BITS\t\t\t19\n\n#define SPN_NUMERIC_MAX_BYTE_SYZE\t4\n\n\nnamespace J1939 {\n\n\n\nclass J1939DecodeException : public std::exception {\nprivate:\n    std::string mMsg;\n\npublic:\n    J1939DecodeException(const std::string& msg) : mMsg(msg) {}\n    ~J1939DecodeException() throw() {}\n\n    const std::string& getMessage() const { return mMsg; }\n\n};\n\nclass J1939EncodeException : public std::exception {\n\nprivate:\n    std::string mMsg;\n\npublic:\n    J1939EncodeException(const std::string& msg) : mMsg(msg) {}\n    ~J1939EncodeException() throw() {}\n\n    const std::string& getMessage() const { return mMsg; }\n};\n\n\n}\n\n#endif // J1939COMMON_H\n"
  },
  {
    "path": "J1939/include/J1939DataBase.h",
    "content": "/*\n * JsonParser.h\n *\n *  Created on: Nov 7, 2017\n *      Author: root\n */\n\n#ifndef SRC_J1939DATABASE_H_\n#define SRC_J1939DATABASE_H_\n\n#include <vector>\n#include <string>\n\n\nnamespace Json {\nclass Value;\n}\n\n\nnamespace J1939 {\n\nclass GenericFrame;\nclass SPN;\n\nclass J1939DataBase {\n\npublic:\n\tenum EErrorCode {\n\t\tERROR_OK,\t\t\t\t\t//Everything ok\n\t\tERROR_FILE_NOT_FOUND,\t\t//The file is not found in the path or cannot be opened\n\t\tERROR_JSON_SYNTAX,\t\t\t//The syntax of the json file is not correct\n\t\tERROR_UNEXPECTED_TOKENS,\t//There are tokens in json file that do not match with the expected ones\n\t\tERROR_OUT_OF_RANGE,\t\t\t//There is at least one value that exceeds the permitted range of values\n\t\tERROR_UNKNOWN_SPN_TYPE,\t\t//The type of spn is not recognized\n\t\tERROR_FORBIDDEN_TOKEN,\t\t//A token that should not be present in the database which is reserved for internal use in the software\n\t\t\t\t\t\t\t\t\t//and could cause misbehaviour (example: PGN=FECA which corresponds to reserved PGN for DM1 frame, casts to this class are done after verifying the PGN)\n\t};\n\nprivate:\n\tstd::vector<GenericFrame> mFrames;\n\n\tEErrorCode mErrorCode;\n\n\tbool parseSPNNumeric(GenericFrame& frame, const Json::Value& spn);\n\tbool parseSPNStatus(GenericFrame& frame, const Json::Value& spn);\n\tbool parseSPNString(GenericFrame& frame, const Json::Value& spn);\n\n\tvoid writeSPNNumeric(const SPN* spn, Json::Value& jsonSpn);\n\tvoid writeSPNStatus(const SPN* spn, Json::Value& jsonSpn);\n\npublic:\n\tJ1939DataBase();\n\tvirtual ~J1939DataBase();\n\n\tbool parseJsonFile(const std::string& file);\n\n\tbool writeJsonFile(const std::string& file);\n\n\tconst std::vector<GenericFrame>& getParsedFrames() const;\n\n\tvoid addFrame(const GenericFrame&);\n\n\tEErrorCode getLastError() { return mErrorCode; }\n\n\tvoid clear();\n\n};\n\n} /* namespace J1939 */\n\n#endif /* SRC_JSONPARSER_H_ */\n"
  },
  {
    "path": "J1939/include/J1939Factory.h",
    "content": "/*\n * J1939Factory.h\n *\n *  Created on: Sep 23, 2017\n *      Author: famez\n */\n\n\n/*\nMIT License\n\nCopyright (c) 2018 Fernando Ámez García\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n*/\n\n#ifndef J1939FACTORY_H_\n#define J1939FACTORY_H_\n\n#include <memory>\n#include <map>\n#include <set>\n\n\n#include <Types.h>\n#include <Singleton.h>\n\n\n\nnamespace J1939 {\n\nclass J1939Frame;\n\nclass J1939Factory : public ISingleton<J1939Factory> {\n\n\tSINGLETON_ACCESS;\n\n\tvirtual ~J1939Factory();\n\nprivate:\n\tJ1939Factory();\n\tstd::map<u32, J1939Frame*> mFrames;\n\n\t /*\n\t * Registers the predefined frames that we can find in J1939Protocol\n\t */\n\tvoid registerPredefinedFrames();\n\n\npublic:\n\n\t/*\n\t * Returns the corresponding frame (if registered) from the given id and decodes the information from data and length\n\t */\n    std::unique_ptr<J1939Frame> getJ1939Frame(u32 id, const u8* data, size_t length);\n    /*\n     * Returns the corresponding frame (if registered) from the given PGN\n     */\n    std::unique_ptr<J1939Frame> getJ1939Frame(u32 pgn);\n\n\n    /*\n\t * Returns the corresponding frame (if registered) from the given name\n\t */\n    std::unique_ptr<J1939Frame> getJ1939Frame(const std::string& name);\n\n\n    /*\n     * Registers the given frame in the factory letting the factory to create a copy of it and, if neccesary, decoding it.\n     */\n    bool registerFrame(const J1939Frame&);\n\n    void unRegisterFrame(u32 pgn);\n\n    bool registerDatabaseFrames(const std::string& ddbbFile);\n\n    void unregisterAllFrames();\n\n\tstd::set<u32> getAllRegisteredPGNs() const;\n\n};\n\n} /* namespace J1939 */\n\n#endif /* J1939FACTORY_H_ */\n"
  },
  {
    "path": "J1939/include/J1939Frame.h",
    "content": "/*\n * J1939Frame.h\n *\n *  Created on: Sep 23, 2017\n *      Author: famez\n *\n *\n *\n */\n\n/*\nMIT License\n\nCopyright (c) 2018 Fernando Ámez García\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n*/\n\n\n\n#ifndef J1939FRAME_H_\n#define J1939FRAME_H_\n\n\n#include <string>\n\n#include <Types.h>\n#include <ICloneable.h>\n\n\n#include \"J1939Common.h\"\n\n\n\nnamespace J1939 {\n\nenum EJ1939Status {\n\tJ1939_STATUS_OFF = 0,\n\tJ1939_STATUS_ON = 1,\n\tJ1939_STATUS_ERROR = 2,\n\tJ1939_STATUS_NOT_AVAILABLE = 3,\n};\n\nenum EJ1939PduFormat {\n\tPDU_FORMAT_1,\n\tPDU_FORMAT_2\n};\n\n\n\nclass J1939Frame : public ICloneable<J1939Frame> {\n\n\nprivate:\n\tu8 mPriority;\n\tu8 mSrcAddr;\n\tu32 mPgn;\n\tu8 mDstAddr;\nprotected:\n    std::string mName;\n\npublic:\n\tJ1939Frame(u32 pgn);\n\tvirtual ~J1939Frame();\n\n\tu8 getPriority() const { return mPriority; }\n    bool setPriority(u8 priority) { mPriority = (priority & J1939_PRIORITY_MASK); return (mPriority == priority); }\n\n\tu8 getExtDataPage() const { return ((mPgn >> J1939_EXT_DATA_PAGE_OFFSET) & J1939_EXT_DATA_PAGE_MASK); }\n\n\tu8 getDataPage() const { return ((mPgn >> J1939_DATA_PAGE_OFFSET) & J1939_DATA_PAGE_MASK); }\n\n\tu8 getPDUFormat() const { return ((mPgn >> J1939_PDU_FMT_OFFSET) & J1939_PDU_FMT_MASK); }\n\n\tu8 getPDUSpecific() const { return mPgn & J1939_PDU_SPECIFIC_MASK; }\n\n\tu8 getSrcAddr() const { return mSrcAddr; }\n\tvoid setSrcAddr(u8 src) { mSrcAddr = src; }\n\n\n\t/*\n\t * If the value in the PDU Format segment is < 240, the content of PDU Specific is interpreted as the destination address.\n\t * One speaks here of a PGN in PDU Format 1 or of a specific PGN. A PGN in PDU Format 1 can be sent explicitly to a destination address\n\t * using point-to-point communication, but the global address (255) can also be used. In this way a specific PGN can also be transmitted globally, i.e., to all network nodes.\n\t * If the PDU Format segment has a value >= 240, the PDU Specific segment is interpreted as a group extension.\n\t * This means that there is no destination address and the message will always be transmitted to all network nodes.\n\t * PDU Format and PDU Specific represent a 16-bit value that corresponds to the PGN. In this case, the PGN has PDU Format 2 and is called global PGN.\n\t */\n\n\tEJ1939PduFormat getPDUFormatGroup() const\n\t{\n\t\tif(getPDUFormat() < PDU_FMT_DELIMITER) {\n\t\t\treturn PDU_FORMAT_1;\n\t\t}\n\t\treturn PDU_FORMAT_2;\n\t}\n\n\tu8 getDstAddr() const { return mDstAddr; }\n    bool setDstAddr(u8 dst) { if(getPDUFormatGroup() == PDU_FORMAT_1) { mDstAddr = dst; return true; } return false; }\n\n\t//Methods to decode/encode data\n\tvoid decode(u32 identifier, const u8* buffer, size_t length);\n\tvoid encode(u32& identifier, u8* buffer, size_t& length) const;\n\n\tu32 getIdentifier() const;\n\nprotected:\n\t/**\n\t * Decodes the given data\n\t */\n\tvirtual void decodeData(const u8* buffer, size_t length) = 0;\n\n\t/**\n\t * Encodes the data field in the given buffer\n\t * Length is used as input to check the length of the buffer and then set to the number of encoded bytes (which is always less or equal than the given length)\n\t */\n\tvirtual void encodeData(u8* buffer, size_t length) const = 0;\n\npublic:\n\tu32 getPGN() const { return mPgn; }\n\n\t/**\n\t * Method to know how long our buffer should be to encode properly this message\n\t */\n\tvirtual size_t getDataLength() const = 0;\n\n\n\n    /**\n     * Method to get the frame name\n     */\n    const std::string& getName() const { return mName; }\n\n    /**\n     * Method to copy one frame to another. The frames must be exactly of the same type\n     *\n     *\n     */\n\n    virtual void copy(const J1939Frame& other);\n\n    virtual bool isGenericFrame() const { return false; }\n\n    /*\n\t * Returns a string with the following information:\n\t * Name\n\t * PGN\n\t * Source Address\n\t * PDU format\n\t * Dest Address\n\t * Priority\n\t */\n\n\tstd::string getHeader() const;\n\n    /*\n     * Returns a string with the header and further details (generally the contents of the frame, such as SPNs if it applies)\n     */\n    virtual std::string toString() const { return getHeader(); }\n\n\n};\n\n} /* namespace J1939 */\n\n#endif /* J1939FRAME_H_ */\n"
  },
  {
    "path": "J1939/include/SPN/SPN.h",
    "content": "/*\n * SPN.h\n *\n *  Created on: Oct 24, 2017\n *      Author: root\n */\n\n#ifndef SPN_H_\n#define SPN_H_\n\n#include <memory>\n#include <string>\n\n#include <Types.h>\n#include <ICloneable.h>\n\n#include <SPN/SPNSpec/SPNSpec.h>\n\nnamespace J1939 {\n\nclass GenericFrame;\n\nclass SPN : public ICloneable<SPN> {\npublic:\n\tenum EType {\n\t\tSPN_NUMERIC = 0,\n\t\tSPN_STATUS = 1,\n\t\tSPN_STRING = 2\n\t};\n\nprivate:\n\tstd::shared_ptr<const SPNSpec> mSpec;\nprotected:\n\tGenericFrame *mOwner = nullptr;\t\t//Owner of this spn\n\npublic:\n    SPN(u32 number, const std::string& name, size_t offset);\n\tvirtual ~SPN();\n\n\tvirtual size_t getOffset() const {\n\t\treturn mSpec->getOffset();\n\t}\n\n\tvirtual void setOffset(size_t offset) {}\t\t//Do nothing\n\n\tu32 getSpnNumber() const {\n\t\treturn mSpec->getSpnNumber();\n\t}\n\n\tconst std::string& getName() const {\n\t\treturn mSpec->getName();\n\t}\n\n\tstd::shared_ptr<const SPNSpec> getSpec() const { return mSpec; }\n\n\tvoid setOwner(GenericFrame* owner) { mOwner = owner; }\n\n\t//To implement by inherited classes\n\n\tvirtual EType getType() const = 0;\n\n    virtual void decode(const u8* buffer, size_t length) = 0;\n    virtual void encode(u8* buffer, size_t length) const = 0;\n\n\tvirtual std::string toString() const;\n\n\tvirtual u8 getByteSize() const = 0;\n\n\tvirtual void copy(const SPN& other) = 0;\n\n};\n\n} /* namespace J1939 */\n\n#endif /* SPN_H_ */\n"
  },
  {
    "path": "J1939/include/SPN/SPNHistory.h",
    "content": "/*\n * SPNHistory.h\n *\n *  Created on: 12 Feb 2019\n *      Author: fernando\n *\n *      For the moment, it only supports history for SPN status and SPN numeric\n */\n\n#ifndef J1939_HISTORIC_SPNHISTORY_H_\n#define J1939_HISTORIC_SPNHISTORY_H_\n\n#include <memory>\n#include <vector>\n\n#include <Utils.h>\n#include <Types.h>\n\n#include <SPN/SPN.h>\n#include <SPN/SPNSpec/SPNSpec.h>\n#include <SPN/SPNSpec/SPNNumericSpec.h>\n#include <SPN/SPNSpec/SPNStatusSpec.h>\n\n\nnamespace J1939 {\n\nclass SPNHistory {\npublic:\n\tstd::shared_ptr<const SPNSpec> mGeneralSpec;\n\tstruct {\n\t\tstd::shared_ptr<const SPNNumericSpec> numeric;\n\t\tstd::shared_ptr<const SPNStatusSpec> status;\n\t} mSpecificSpec;\n\n\tclass Sample {\n\tprivate:\n\t\tUtils::TimeStamp mTimeStamp;\n\t\tunion {\n\t\t\tdouble numeric;\n\t\t\tu8 status;\n\t\t} mValue;\n\tpublic:\n\t\tSample() = default;\n\t\tSample(const Utils::TimeStamp timeStamp, double value) : mTimeStamp(timeStamp) {\n\t\t\tmValue.numeric = value;\n\t\t}\n\t\tSample(const Utils::TimeStamp timeStamp, u8 status) : mTimeStamp(timeStamp) {\n\t\t\tmValue.status = status;\n\t\t}\n\t\t\n\t\tvoid setTimeStamp(const Utils::TimeStamp& timestamp) { mTimeStamp = timestamp; }\n\n\t\tconst Utils::TimeStamp& getTimeStamp() const {\n\t\t\treturn mTimeStamp;\n\t\t}\n\n\t\tdouble getNumeric() const { return mValue.numeric; }\n\n\t\tu8 getStatus() const { return mValue.status; }\n\t\t\n\t\tbool operator<(const Sample& other) const { return mTimeStamp < other.mTimeStamp; }\n\n\t};\n\nprivate:\n\tstd::vector<Sample> mSamples;\t\t\t\t//All the samples that have been stored\npublic:\n\tSPNHistory();\n\tvirtual ~SPNHistory();\n\n\tvoid addSample(const Utils::TimeStamp& timeStamp, const SPN& spn);\n\n\t/*\n\t * Gets the window of stored samples.\n\t * [in] milliseconds indicates the duration of the window in millis\n\t * [in] samples indicates the number of samples contained in the window\n\t * [in] timeStamp indicates the final timestamp of the window\n\t */\n\tstd::vector<Sample> getWindow(const Utils::TimeStamp& timeStamp, u32 milliseconds, u32 samples) const;\n\n\tstd::shared_ptr<const SPNSpec> getGeneralSpec() const {\n\t\treturn mGeneralSpec;\n\t}\n\n\tstd::shared_ptr<const SPNNumericSpec> getNumericSpec() const {\n\t\treturn mSpecificSpec.numeric;\n\t}\n\n\tstd::shared_ptr<const SPNStatusSpec> getStatusSpec() const {\n\t\treturn mSpecificSpec.status;\n\t}\n\n};\n\n} /* namespace J1939 */\n\n#endif /* J1939_HISTORIC_SPNHISTORY_H_ */\n"
  },
  {
    "path": "J1939/include/SPN/SPNNumeric.h",
    "content": "/*\n * SPNNumeric.h\n *\n *  Created on: Oct 24, 2017\n *      Author: root\n */\n\n#ifndef SPN_SPNNUMERIC_H_\n#define SPN_SPNNUMERIC_H_\n\n#include <SPN/SPN.h>\n\n#include <SPN/SPNSpec/SPNNumericSpec.h>\n\nnamespace J1939 {\n\nclass SPNNumeric: public SPN {\nprivate:\n\tstd::shared_ptr<const SPNNumericSpec> mNumSpec;\n\tu32 mValue;\n\npublic:\n    SPNNumeric(u32 number, const std::string& name = \"\", size_t offset = 0,\n    \t\tdouble formatGain = 0, double formatOffset = 0, u8 byteSize = 0, const std::string& units = \"\");\n\tvirtual ~SPNNumeric();\n\n\tdouble getFormattedValue() const ;\n\n\tbool setFormattedValue(double value);\n\n    void decode(const u8* buffer, size_t length);\n    void encode(u8* buffer, size_t length) const;\n\n\tEType getType() const { return SPN_NUMERIC; }\n\n\tu8 getByteSize() const {\n\t\treturn mNumSpec->getByteSize();\n\t}\n\n\n\tdouble getFormatGain() const {\n\t\treturn mNumSpec->getFormatGain();\n\t}\n\n    double getFormatOffset() const {\n    \treturn mNumSpec->getFormatOffset();\n\t}\n\n\tconst std::string& getUnits() const {\n\t\treturn mNumSpec->getUnits();\n\t}\n\n\tu32 getValue() const {\n\t\treturn mValue;\n\t}\n\n    void setValue(u32 value) {\n        mValue = value;\n    }\n\n    /*\n     * Returns the maximum value for the given spn\n     */\n    u32 getMaxValue() const { return mNumSpec->getMaxValue(); }\n\n    std::string toString() const override;\n\n    std::shared_ptr<const SPNNumericSpec> getNumericSpec() const { return mNumSpec; }\n\n    void copy(const SPN& other) override;\n\n\tIMPLEMENT_CLONEABLE(SPN, SPNNumeric);\n\n};\n\n} /* namespace J1939 */\n\n#endif /* SPN_SPNNUMERIC_H_ */\n"
  },
  {
    "path": "J1939/include/SPN/SPNSpec/SPNNumericSpec.h",
    "content": "/*\n * SPNNumericSpec.h\n *\n *  Created on: Oct 24, 2017\n *      Author: root\n */\n\n#ifndef SPN_SPNNUMERIC_SPEC_H_\n#define SPN_SPNNUMERIC_SPEC_H_\n\n#include <string>\n\n#include <Types.h>\n\n\nnamespace J1939 {\n\nclass SPNNumericSpec {\nprivate:\n\tdouble mFormatGain;\n\tdouble mFormatOffset;\n\tu8 mByteSize;\n\tstd::string mUnits;\n\n\npublic:\n\tSPNNumericSpec(double formatGain = 0, double formatOffset = 0, u8 byteSize = 0, const std::string& units = \"\");\n\tvirtual ~SPNNumericSpec();\n\n\n\tu8 getByteSize() const {\n\t\treturn mByteSize;\n\t}\n\n    void setByteSize(u8 size) { mByteSize = size; }\n\n\tdouble getFormatGain() const {\n\t\treturn mFormatGain;\n\t}\n\n    void setFormatGain(double gain) { mFormatGain = gain; }\n\n    double getFormatOffset() const {\n\t\treturn mFormatOffset;\n\t}\n\n    void setFormatOffset(double formatOffset) { mFormatOffset = formatOffset; }\n\n\tconst std::string& getUnits() const {\n\t\treturn mUnits;\n\t}\n\n    void setUnits(const std::string& units) { mUnits = units; }\n\n    /*\n     * Returns the maximum value for the given spn\n     */\n    u32 getMaxValue() const;\n\n    double formatValue(u32 value) const;\n\n    double getMaxFormattedValue() const { return formatValue(getMaxValue()); }\n    double getMinFormattedValue() const { return formatValue(0); }\n\n\n};\n\n} /* namespace J1939 */\n\n#endif /* SPN_SPNNUMERIC_SPEC_H_ */\n"
  },
  {
    "path": "J1939/include/SPN/SPNSpec/SPNSpec.h",
    "content": "/*\n * SPNSpec.h\n *\n *  Created on: Oct 24, 2017\n *      Author: root\n */\n\n#ifndef SPN_SPEC_H_\n#define SPN_SPEC_H_\n\n#include <string>\n\n#include <Types.h>\n\nnamespace J1939 {\n\n\nclass SPNSpec {\n\nprivate:\n    u32 mSPNNumber;\n\tstd::string mName;\n\tsize_t mOffset;\n\npublic:\n\tSPNSpec(u32 number, const std::string& name, size_t offset);\n\tvirtual ~SPNSpec();\n\n\tsize_t getOffset() const {\n\t\treturn mOffset;\n\t}\n\n\tvoid setOffset(size_t offset) {\n\t\tmOffset = offset;\n\t}\n\n\tu32 getSpnNumber() const {\n\t\treturn mSPNNumber;\n\t}\n\n\tvoid setSpnNumber(u32 spnNumber) {\n\t\tmSPNNumber = spnNumber;\n\t}\n\n\tconst std::string& getName() const {\n\t\treturn mName;\n\t}\n\n\tvoid setName(const std::string& name) {\n\t\tmName = name;\n\t}\n\n};\n\n} /* namespace J1939 */\n\n#endif /* SPN_SPEC_H_ */\n"
  },
  {
    "path": "J1939/include/SPN/SPNSpec/SPNStatusSpec.h",
    "content": "/*\n * SPNStatusSpec.h\n *\n *  Created on: Oct 24, 2017\n *      Author: root\n */\n\n#ifndef SPN_SPNSTATUS_SPEC_H_\n#define SPN_SPNSTATUS_SPEC_H_\n\n#include <map>\n\n#include <Types.h>\n\nnamespace J1939 {\n\nclass SPNStatusSpec {\n\npublic:\n    typedef std::map<u8, std::string> DescMap;\nprivate:\n\tu8 mBitOffset;\n\tu8 mBitSize;\n\n    /*\n     * Convertion from the status number to its description\n     */\n    DescMap mValueToDesc;\n\npublic:\n    SPNStatusSpec(u8 bitOffset = 0, u8 bitSize = 0, SPNStatusSpec::DescMap valueToDesc = SPNStatusSpec::DescMap());\n\tvirtual ~SPNStatusSpec();\n\n\n\n\tu8 getBitOffset() const { return mBitOffset; }\n    void setBitOffset(u8 off) { mBitOffset = off; }\n\n\tu8 getBitSize() const { return mBitSize; }\n    void setBitSize(u8 size) { mBitSize = size; }\n\n\n\tu8 getBitMask() const { return (0xFF >> (8 - mBitSize)) << mBitOffset; }\n\n\n    /*\n     * Methods to add/get descriptions over the different status numbers\n     */\n    void setValueDescription(u8 value, const std::string& desc);\n    std::string getValueDescription(u8 value) const;\n    void clearValueDescriptions();\n    DescMap getValueDescriptionsMap() const;\n\n};\n\n} /* namespace J1939 */\n\n#endif /* SPN_SPNSTATUS_SPEC_H_ */\n\n"
  },
  {
    "path": "J1939/include/SPN/SPNStatus.h",
    "content": "\n/*\n * SPNStatus.h\n *\n *  Created on: Oct 24, 2017\n *      Author: root\n */\n\n#ifndef SPN_SPNSTATUS_H_\n#define SPN_SPNSTATUS_H_\n\n#include <map>\n\n#include <SPN/SPN.h>\n#include <SPN/SPNSpec/SPNStatusSpec.h>\n\nnamespace J1939 {\n\nclass SPNStatus: public SPN {\n\npublic:\n    typedef std::map<u8, std::string> DescMap;\nprivate:\n\tu8 mValue;\n\tstd::shared_ptr<const SPNStatusSpec> mStatSpec;\n\npublic:\n\tSPNStatus(u32 number, const std::string& name = \"\", size_t offset = 0, u8 bitOffset = 0, u8 bitSize = 0, SPNStatusSpec::DescMap valueToDesc = SPNStatusSpec::DescMap());\n\tvirtual ~SPNStatus();\n\n\n\tvoid decode(const u8* buffer, size_t length);\n\tvoid encode(u8* buffer, size_t length) const;\n\n\tEType getType() const { return SPN_STATUS; }\n\n\tu8 getBitOffset() const { return mStatSpec->getBitOffset(); }\n\n\tu8 getBitSize() const { return mStatSpec->getBitSize(); }\n\n\tu8 getValue() const { return mValue; }\n\tbool setValue(u8 value);\n\n\n\tstd::string toString() const override;\n\n\tu8 getByteSize() const override { return 1; }\t\t//Spn status has always size of 1\n\n\tstd::string getValueDescription(u8 value) const { return mStatSpec->getValueDescription(value); }\n\tDescMap getValueDescriptionsMap() const { return mStatSpec->getValueDescriptionsMap(); }\n\n\tstd::shared_ptr<const SPNStatusSpec> getStatusSpec() const { return mStatSpec; }\n\n\tvoid copy(const SPN& other) override;\n\n\tIMPLEMENT_CLONEABLE(SPN, SPNStatus);\n\n};\n\n} /* namespace J1939 */\n\n#endif /* SPN_SPNSTATUS_H_ */\n"
  },
  {
    "path": "J1939/include/SPN/SPNString.h",
    "content": "/*\n * SPNString.h\n *\n *  Created on: 6 juil. 2018\n *      Author: fernando\n */\n\n#ifndef SPN_SPNSTRING_H_\n#define SPN_SPNSTRING_H_\n\n#include <string>\n\n#include <SPN/SPN.h>\n\nnamespace J1939 {\n\nclass SPNString: public SPN {\nprivate:\n\tsize_t mOffset = 0;\n\tstd::string mValue;\n\npublic:\n\tSPNString(u32 number, const std::string& name);\n\tvirtual ~SPNString();\n\n\tvoid decode(const u8* buffer, size_t length) override;\n\tvoid encode(u8* buffer, size_t length) const override;\n\n\tEType getType() const { return SPN_STRING; }\n\n\tstd::string toString() const override;\n\n\tu8 getByteSize() const override { return mValue.size() + 1; }\t\t//Include the * terminator\n\n\tstd::string getValue() const { return mValue; }\n\n\tvoid setValue(std::string value);\n\n\tsize_t getOffset() const override {\t\t//SPNString have variable offsets\n\t\treturn mOffset;\n\t}\n\n\tvoid setOffset(size_t offset) override { mOffset = offset; }\n\n\tvoid copy(const SPN& other) override;\n\n\tIMPLEMENT_CLONEABLE(SPN, SPNString);\n\n};\n\n} /* namespace J1939 */\n\n#endif /* SPN_SPNSTRING_H_ */\n"
  },
  {
    "path": "J1939/include/Transport/BAM/BamFragmenter.h",
    "content": "/*\n * BamFragmenter.h\n *\n *  Created on: Apr 22, 2018\n *      Author: fernado\n */\n\n#ifndef TRANSPORT_BAM_BAMFRAGMENTER_H_\n#define TRANSPORT_BAM_BAMFRAGMENTER_H_\n\n#include <vector>\n#include <map>\n\n#include \"../TPCMFrame.h\"\n#include \"../TPDTFrame.h\"\n\nnamespace J1939 {\n\nclass BamFragmenter{\n\nprivate:\n\n\tTPCMFrame mCMFrame;\n\tstd::map<u8/*Sequence number*/, TPDTFrame> mDTFrames;\n\npublic:\n\tBamFragmenter();\n\tvirtual ~BamFragmenter();\n\n\tbool fragment(const J1939Frame& frame);\n\n\tvoid clear() { mDTFrames.clear(); mCMFrame.clear(); }\n\n\tconst TPCMFrame& getConnFrame() const { return mCMFrame; }\n\tstd::vector<TPDTFrame> getDataFrames() const;\n};\n\n} /* namespace J1939 */\n\n#endif /* TRANSPORT_BAM_BAMFRAGMENTER_H_ */\n"
  },
  {
    "path": "J1939/include/Transport/BAM/BamReassembler.h",
    "content": "/*\n *\n *  Created on: Oct 2, 2017\n *      Author: famez\n *\n *\n * Global communication – Broadcast Announce Message (BAM):\n * The sender alone manages the flow control.\n * The message is always sent to all nodes.\n * A receiver cannot intervene in the communication.\n * If the receiver misses a message, it cannot signal this.\n * The receiver must wait for a new message, if necessary.\n * Because the receiver is not able to influence the flow control in the BAM protocol, the sender must maintain a minimum interval between the individual packets.\n * This is 50-200 ms. This allows possible slow network nodes to follow the communication.\n *\n */\n\n#ifndef BAMFRAMESET_H_\n#define BAMFRAMESET_H_\n\n#include <vector>\n#include <map>\n#include <queue>\n#include <memory>\n\n\n#include \"../TPCMFrame.h\"\n#include \"../TPDTFrame.h\"\n\n\n\n\nnamespace J1939 {\n\nclass BamReassembler {\n\npublic:\n\n\tenum EBamError {\n\t    BAM_ERROR_INCOMPLETE_FRAME,\n\t    BAM_ERROR_UNEXPECTED_FRAME,\n\t\tBAM_ERROR_NOT_BCAST_ADDR,\n\t\tBAM_ERROR_DECODING,\n\t    BAM_ERROR_OK,\n\t};\n\nprivate:\n\n\tclass BAMFragments {\n\tprivate:\n\t\tTPCMFrame mCMFrame;\n\t\tstd::vector<TPDTFrame> mDTFrames;\n\n\tpublic:\n\t\tconst TPCMFrame& getCmFrame() const { return mCMFrame; }\n\t\tvoid setCmFrame(const TPCMFrame& cmFrame) { mCMFrame = cmFrame; }\n\t\tconst std::vector<TPDTFrame>& getDtFrames() const { return mDTFrames; }\n\t\tvoid addDtFrame(const TPDTFrame& dtFrame) { mDTFrames.push_back(dtFrame); }\n\t\tu8 getLastSQ() const;\n\t};\n\n\n\t//Fragments of frames sortered by Source Address\n\tstd::map<u8, BAMFragments> mFragments;\n\n    EBamError mLastError;\n\n    std::queue<J1939Frame*> mReassembledFrames;\n\n\n\tvoid reassemble(const BAMFragments& fragments, u8** data, size_t& length);\n\npublic:\n\n\tBamReassembler();\n\tvirtual ~BamReassembler();\n\n\tbool toBeHandled(const J1939Frame&) const;\n\n\tsize_t handleFrame(const J1939Frame&);\n\n\tvoid clear();\n    void setError(EBamError status) { mLastError = status; }\n\n    EBamError getLastError() { return mLastError; }\n\n    bool reassembledFramesPending() const { return !mReassembledFrames.empty(); }\n\n    std::unique_ptr<J1939Frame> dequeueReassembledFrame();\n\n\n};\n\n} /* namespace J1939 */\n\n#endif /* BAMFRAMESET_H_ */\n"
  },
  {
    "path": "J1939/include/Transport/RTSCTS/RTSCTSConnectionManager.h",
    "content": "/*\n * RTSCTSConnectionManager.h\n *\n *  Created on: Oct 15, 2017\n *      Author: famez\n *\n * Specific communication – Connection Mode Data Transfer:\n * With this protocol the sender establishes a connection to the receiver.\n * The receiver has the option of controlling and influencing the flow control of the individual data packets.\n * Both the receiver and sender can abort the connection (e.g. in case of errors).\n * The Connection Mode Data Transfer protocol is not subject to any time limitation.\n * All nodes potentially exchange their data with one another at their maximum possible speed.\n *\n */\n\n#ifndef TRANSPORT_RTSCTS_RTSCTSCONNECTIONMANAGER_H_\n#define TRANSPORT_RTSCTS_RTSCTSCONNECTIONMANAGER_H_\n\n#include \"../ConnectionManager.h\"\n\nnamespace J1939 {\n\nclass RTSCTSConnectionManager : public ConnectionManager {\npublic:\n\tRTSCTSConnectionManager();\n\tvirtual ~RTSCTSConnectionManager();\n\n\n\tvoid consumeFrame(const J1939Frame&);\n};\n\n} /* namespace J1939 */\n\n#endif /* TRANSPORT_RTSCTS_RTSCTSCONNECTIONMANAGER_H_ */\n"
  },
  {
    "path": "J1939/include/Transport/TPCMFrame.h",
    "content": "/*\n * BAMHeaderFrame.h\n *\n *  Created on: Oct 2, 2017\n *      Author: famez\n */\n\n#ifndef FRAMES_BAMHEADERFRAME_H_\n#define FRAMES_BAMHEADERFRAME_H_\n\n\n#include \"../J1939Frame.h\"\n\n#define TP_CM_PGN\t\t0x00EC00\n#define TP_CM_SIZE\t\t8\n\n\n//CM Types\n\n/*\n * The TP.CM_RTS message informs a node that another node on the network wishes to open a virtual connection with it.\n * The TP.CM_RTS is a message with the source address field set to that of the originating node, the destination address\n * field set to that of the intended recipient of a large message, and the remaining fields set appropriately for the Parameter\n * Group Number being sent.\n * Byte 5 of this message allows the originator to limit the responder’s number of packets specified in the Clear To Send\n * message. When the responder complies with this limit, it ensures that the\n * originator can always retransmit packets that the responder may have not received for whatever reason.\n * If multiple RTSs are received from the same source address for the same PGN, then the most recent RTS shall be acted\n * on and the previous RTSs will be abandoned. No abort message shall be sent for the abandoned RTSs in this specific\n * case.\n * TP.CM_RTS is only transmitted by the originator.\n */\n#define CTRL_TPCM_RTS\t\t16\n\n/*\n * The TP.CM_CTS message is used to respond to the Request To Send message. It informs the peer node that it is ready\nfor a certain amount of large message data. The amount of large message data cleared to send shall be no larger than\nthe smaller of the two values in byte 4 and byte 5 of the originator’s TP.CM_RTS message.\nIf multiple CTSs are received after a connection is already established, then the connection shall be aborted. When the\noriginator aborts the connection, it shall send the Connection Abort message with abort reason 4 from Table 7.\nThe responder will not send the next CTS until it has received the last data packet from the previous CTS or it has timed\nout. In the case of time out the responder has the choice whether to send a connection abort or to send a CTS.\nThe following cases exist when data transfer happens with errors:\n\nWhen the CTS is used to request the retransmission of data packet(s), it is recommended not to use more than 2\nretransmit requests. When this limit is reached, a connection abort with abort reason 5 from Table 7 shall be sent.\nIf a CTS is received while a connection is not established, it shall be ignored.\nCTSs not only control the flow but also confirm correct receipt of any data packet prior to that CTS packet’s number.\nTherefore if information for the previous CTS was corrupted, then a CTS for the corrupted information shall be sent before\ncontinuing on to the next sequential packets to be sent. Because of this requirement, the originator of a large message\ntransmission may use byte 5 of the TP.CM_RTS message as a way to ensure the possibility of retransmission of a packet\nwithin the last set of packets cleared to send.\n */\n#define CTRL_TPCM_CTS\t\t17\n\n/*\n * The TP.CM_EndOfMsgACK message is passed from the recipient of a large message to its originator indicating that the\nentire message was received and reassembled correctly. The responder can keep the connection open after the last\nData Transfer of the session by not immediately sending the TP.CM_EndOfMsgACK. This allows the responder to get a\npacket resent if necessary.\nIf an End of Message Acknowledgment is received by the originator prior to the final Data Transfer, then the originator\nignores it.\nOne End of Message Acknowledgment is sent to show the originator that the large message transfer has been received\nand assembled correctly.\nTP.CM_EndOfMsgACK is only transmitted by the responder.\n */\n#define CTRL_TPCM_ACK\t\t19\n\n/*\n * The TP.CM_BAM is used to inform all the nodes of the network that a large message is about to be broadcast. It defines\nthe parameter group and the number of bytes to be sent. After TP.CM_BAM is sent, the Data Transfer Messages are\nsent and they contain the packetized broadcast data.\nTP.CM_BAM is only transmitted by the originator.\n */\n#define CTRL_TPCM_BAM\t\t32\n\n/*\n * The TP.Conn_Abort message is used by either node involved in a virtual connection to close the connection without\ncompleting the transfer of the message or to prevent a connection from being initialized.\nUpon receipt of a Connection Mode Request To Send message, a node must determine if there are sufficient resources\navailable to deal with the message for which this connection is sought. For example if the device must acquire memory\nfrom the system heap, it may not be able to claim enough to accept the entire message; or a device may simply be too\noccupied doing other things to expend processor cycles to handle a large message. In these cases a Connection Abort\nmessage may be sent even though the connection has not been established. This may be done in order to allow the\noriginator to attempt another virtual connection without first having to wait for a timeout to occur.\nSAE J1939-21 DEC2010 Revised\n\n- A missing or errant packet(s) is detected and the last packet is successfully received, then the responder will send a\nCTS requesting retransmission starting from the missing packet.\n- Missing packet(s) including the last packet will lead to time out T1. In this case, the responder decides on sending a\nCTS or a connection abort.\n\n\nWhen either the originator or responder decides to close out a connection for any reason, prior to completing the data\ntransfer, including a timeout, it shall send a Connection Abort message with the appropriate Connection Abort reason.\n */\n#define CTRL_TPCM_ABORT\t\t255\n\n\n//Connection abort reason\n\n/*\n * Already in one or more connection managed sessions and cannot support another.\n */\n#define CONN_ABORT_NOT_SUPPORTED\t1\n\n/*\n * System resources were needed for another task so this connection managed session was terminated.\n */\n#define CONN_ABORT_TERMINATED\t\t2\n\n/*\n * A timeout occurred and this is the connection abort to close the session.\n */\n#define CONN_ABORT_TIMEOUT\t\t\t3\n\n/*\n * CTS messages received when data transfer is in progress.\n */\n#define CONN_ABORT_IN_PROGRESS\t\t4\n\n\n/*\n * Maximum retransmit request limit reached\n */\n#define CONN_ABORT_RTX_LIMIT\t\t5\n\n\nnamespace J1939 {\n\nclass TPCMFrame: public J1939Frame {\n\npublic:\n\nprivate:\n\n\t/*\n\t * Control byte\n\t */\n\n\tu8 mCtrlType;\n\n\t/*\n\t * Total message size, number of bytes\n\t */\n\tu16 mTotalMsgSize;\n\n\t/*\n\t * Total number of packets\n\t */\n\tu8 mTotalPackets;\n\n\n\t/*\n\t * Maximum number of packets that can be sent in response to one CTS. FF16 indicates that no limit exists for the originator.\n\t */\n\tu8 mMaxPackets;\n\n\t/*\n\t * Number of packets that can be sent. This value shall be no larger than the smaller of the two values in byte 4 and byte 5 of the RTS message.\n\t */\n\tu8 mPacketsToTx;\n\n\t/*\n\t * Next packet number to be sent\n\t */\n\tu8 mNextPacket;\n\n\t/*\n\t * Connection Abort reason\n\t */\n\tu8 mAbortReason;\n\n\t/*\n\t * Parameter Group Number of the packeted message\n\t */\n\tu32 mDataPgn;\n\n\n\tvoid decodeRTS(const u8* buffer);\n\tvoid decodeCTS(const u8* buffer);\n\tvoid decodeEndOfMsgACK(const u8* buffer);\n\tvoid decodeConnAbort(const u8* buffer);\n\tvoid decodeBAM(const u8* buffer);\n\n\tvoid encodeRTS(u8* buffer) const;\n\tvoid encodeCTS(u8* buffer) const;\n\tvoid encodeEndOfMsgACK(u8* buffer) const;\n\tvoid encodeConnAbort(u8* buffer) const;\n\tvoid encodeBAM(u8* buffer) const;\n\n\npublic:\n\tTPCMFrame();\n\n\tvirtual ~TPCMFrame();\n\n\n\tvoid clear();\n\n\t//Implements J1939Frame methods\n\tvoid decodeData(const u8* buffer, size_t length);\n\tvoid encodeData(u8* buffer, size_t length) const;\n\n\tsize_t getDataLength() const { return TP_CM_SIZE; }\n\t\n\t\n\tu8 getAbortReason() const {\n\t\treturn mAbortReason;\n\t}\n\n\tu8 getCtrlType() const {\n\t\treturn mCtrlType;\n\t}\n\n\tu32 getDataPgn() const {\n\t\treturn mDataPgn;\n\t}\n\n\tu8 getMaxPackets() const {\n\t\treturn mMaxPackets;\n\t}\n\n\tu8 getNextPacket() const {\n\t\treturn mNextPacket;\n\t}\n\n\tu8 getPacketsToTx() const {\n\t\treturn mPacketsToTx;\n\t}\n\n\tu16 getTotalMsgSize() const {\n\t\treturn mTotalMsgSize;\n\t}\n\n\tu8 getTotalPackets() const {\n\t\treturn mTotalPackets;\n\t}\n\n\tvoid setAbortReason(u8 abortReason) {\n\t\tmAbortReason = abortReason;\n\t}\n\n\tvoid setCtrlType(u8 ctrlType) {\n\t\tmCtrlType = ctrlType;\n\t}\n\n\tvoid setDataPgn(u32 dataPgn) {\n\t\tmDataPgn = dataPgn;\n\t}\n\n\tvoid setMaxPackets(u8 maxPackets) {\n\t\tmMaxPackets = maxPackets;\n\t}\n\n\tvoid setNextPacket(u8 nextPacket) {\n\t\tmNextPacket = nextPacket;\n\t}\n\n\tvoid setPacketsToTx(u8 packetsToTx) {\n\t\tmPacketsToTx = packetsToTx;\n\t}\n\n\tvoid setTotalMsgSize(u16 totalMsgSize) {\n\t\tmTotalMsgSize = totalMsgSize;\n\t}\n\n\tvoid setTotalPackets(u8 totalPackets) {\n\t\tmTotalPackets = totalPackets;\n\t}\n\n\tIMPLEMENT_CLONEABLE(J1939Frame,TPCMFrame);\n\n};\n\n\n} /* namespace J1939 */\n\n\n\n\n#endif /* FRAMES_BAMHEADERFRAME_H_ */\n"
  },
  {
    "path": "J1939/include/Transport/TPDTFrame.h",
    "content": "/*\n * BamDataframe.h\n *\n *  Created on: Oct 2, 2017\n *      Author: famez\n */\n\n#ifndef FRAMES_BAMDATAFRAME_H_\n#define FRAMES_BAMDATAFRAME_H_\n\n#include <string.h>\n\n#include \"../J1939Frame.h\"\n\n#define TP_DT_PGN\t\t0x00EB00\n#define BAM_DT_SIZE\t\t8\n\nnamespace J1939 {\n\nclass TPDTFrame : public J1939Frame {\nprivate:\n\tu8 mSQ;\n\tu8 mData[TP_DT_PACKET_SIZE];\n\npublic:\n\tTPDTFrame();\n\tTPDTFrame(u8 sq, u8* data, size_t length);\n\tvirtual ~TPDTFrame();\n\n\n\t//Implements J1939Frame methods\n\tvoid decodeData(const u8* buffer, size_t length);\n\tvoid encodeData(u8* buffer, size_t length) const;\n\n\tsize_t getDataLength() const { return BAM_DT_SIZE; }\n\n\tconst u8* getData() const { return mData; }\n\n\tvoid setData(u8* data) { memcpy(mData, data, TP_DT_PACKET_SIZE); }\n\n\tu8 getSq() const { return mSQ; }\n\tvoid setSq(u8 sq) { mSQ = sq; }\n\n\tIMPLEMENT_CLONEABLE(J1939Frame,TPDTFrame);\n};\n\n\n} /* namespace J1939 */\n\n#endif /* FRAMES_BAMDATAFRAME_H_ */\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2018 Fernando Ámez García (famez)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "[![Travis Build Status](https://travis-ci.org/famez/J1939-Framework.svg?branch=master)](https://travis-ci.com/famez/J1939-Framework)\n\n# J1939-Framework\nFramework to work with J1939 protocol. \n\nJ1939 protocol is a standard used in different systems compliant with CAN 2.0B specification.\n\nThe framework has been developed in C++ in a Linux distribution and compiled using the GNU toolchain. No dependencies are required for the compilation of any of the projects except from SocketCan compiled in the Linux Kernel.\n\n\n\n## What can you do with J1939-Framework\n\n- Save can frames from the Can Bus into recordings in TRC format with BinUtils/TRCDumper.\n- Play can frames from recordings in TRC format into the Can Bus with BinUtils/TRCPlayer.\n- Convert TRC files into pcap files readable by wireshark with BinUtils/TRCToCap.\n- Dissect pcap files with wireshark and the J1939 plugin dissector (wireshark/dissector).\n- Sniff frames from the Can Bus compliant with J1939 protocol with BinUtils/j1939Sniffer.\n- Decode raw J1939 data to human readable data with BinUtils/j1939Decoder.\n- Craft your own J1939 frames and send them to the Can Bus with BinUtils/j1939Sender. The functionality can be extended with the help of bash scripts located in Scripts (some examples are listed).\n- Visualize what is going on in the Can Bus with GUI_WEB. You will be able to craft, send and visualize the frames that are flowing in the Bus as well as visualizing graphics of their content (SPNs).\n- Discover J1939 devices with BinUtils/j1939AddressMapper.\n- Simulation of the Address Claim Process with BinUtils/j1939AddrClaim.\n\n### And of course, develop!!:\n\n- In CAN/ folder we can find a library in C++ (libCAN.so) with methods to generate and sniff can frames with support for PeakCan and SocketCan.\n- In J1939/ folder we can find a library in C++ (libJ1939.so) to easily manipulate J1939 frames and work with the J1939 protocol. Some features are:\n\tSupport of BAM protocol.\n\tA factory class in charge of generating the J1939 frames.\n\tA database loaded by the factory located in Database/frames.json with a list of the most used Application Layer frames (including the FMS protocol).\n\tCoding/Decoding DM1 (Diagnosis), FMS1 (TTS), Request and Address Claim frames.\n\tCoding/Decoding of SPNs (String, status and numeric).\n\n\n## Installing and compiling\n\n# Installation:\nUbuntu 18.10 or higher\n```bash\n\nsudo apt-get install libgtest-dev protobuf-compiler libprotobuf-dev libncurses-dev libwebsockets cmake\ncd /usr/src/gtest\nsudo env \"PATH=$PATH\" cmake CMakeLists.txt\nsudo make\nsudo cp *.a /usr/lib\ngit clone https://github.com/open-source-parsers/jsoncpp.git\n\n \ncd jsoncpp\ngit checkout 863aa36165acfdbaf22447f4934f5adc327692a0\ncmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON \nsudo make install\ncd ~\ngit clone https://github.com/famez/J1939-Framework.git\ncd J1939-Framework\ncmake . \ncmake --build .\nsudo make install\n\n```\n\n# Usage with SocketCan:\n\nTo make SocketCan available in your system, you should execute the following commands:\n\n```bash\nsudo apt-get install can-utils\n```\n\nTo enable the drivers if they not enabled by default:\n\n```bash\nsudo modprobe can\nsudo modprobe vcan\n```\n\nTo generate a virtual interface for test purposes.\n\n```bash\nsudo ip link add name vcan0 type vcan\n```\n\nTo test over vcan0.\n\n```bash\n./Scripts/gear_level.sh vcan0 | j1939Sender --silent --file Scripts/define_frames.j1939\ncandump vcan0\n```\n\n## TRCPlayer\n\n![alt text](https://github.com/famez/J1939-Framework/blob/master/BinUtils/TRCPlayer/TRCPlayer.png)\n\n    \n## Wireshark dissector\n\n![alt text](https://github.com/famez/J1939-Framework/blob/master/wireshark/dissector/J1939-plugin.png)\n\n## J1939GUI\n\n![alt text](https://github.com/famez/J1939-Framework/blob/master/Graph.png)\n\n![alt text](https://github.com/famez/J1939-Framework/blob/master/GUI_WEB/J1939GUI.png)\n"
  },
  {
    "path": "Scripts/Readme.md",
    "content": "To run a script (i.e gear_level.sh):\n\n```bash\n    ./gear_level.sh vcan0 | j1939Sender --silent --file define_frames.j1939 \n```\n"
  },
  {
    "path": "Scripts/define_frames.j1939",
    "content": "create frame name: ccvs title: CCVS\ncreate frame name: eec1 title: EEC1\ncreate frame name: lfc title: LFC\ncreate frame name: vdhr title: VDHR\ncreate frame name: dd title: DD\ncreate frame name: efl title: EFL\ncreate frame name: vin title: VI\ncreate frame name: di title: DI\ncreate frame name: tco1 title: TCO1\ncreate frame name: et1 title: ET1\ncreate frame name: trf1 title: TRF1\ncreate frame name: eec2 title: EEC2\ncreate frame name: vdc2 title: VDC2\ncreate frame name: ic1 title: IC1\ncreate frame name: amb title: AMB\ncreate frame name: rf title: RF\ncreate frame name: hours title: HOURS\ncreate frame name: etc1 title: ETC1\ncreate frame name: etc2 title: ETC2\ncreate frame name: erc1 title: ERC1\ncreate frame name: ebc1 title: EBC1\ncreate frame name: as title: AS\ncreate frame name: at1t1i title: AT1T1I\ncreate frame name: dc1 title: DC1\ncreate frame name: dc2 title: DC2\ncreate frame name: ptode title: PTODE\n\n\n\nset frame ccvs period: 100 priority: 2 source: 20\nset frame ptode period: 100 priority: 2 source: 20\nset frame eec1 period: 20 priority: 2 source: 20\nset frame lfc period: 1000 priority: 2 source: 20\nset frame vdhr period: 1000 priority: 2 source: 20\nset frame dd period: 1000 priority: 2 source: 20\nset frame dc1 period: 100 priority: 2 source: 20\nset frame dc2 period: 100 priority: 2 source: 20\nset frame efl period: 500 priority: 2 source: 20\nset frame et1 period: 1000 priority: 2 source: 20\nset frame tco1 period: 50 priority: 2 source: 20\nset frame vin period: 10000 priority: 2 source: 20\nset frame di period: 10000 priority: 2 source: 20\nset frame trf1 period: 1000 priority: 2 source: 20\nset frame eec2 period: 50 priority: 2 source: 20\nset frame vdc2 period: 10 priority: 2 source: 20\nset frame ic1 period: 500 priority: 2 source: 20\nset frame amb period: 1000 priority: 2 source: 20\nset frame rf period: 1000 priority: 2 source: 20\nset frame hours period: 5000 priority: 2 source: 20\nset frame etc1 period: 10 priority: 2 source: 20\nset frame etc2 period: 10 priority: 2 source: 20\nset frame erc1 period: 50 priority: 2 source: 20\nset frame ebc1 period: 100 priority: 2 source: 20\nset frame as period: 1000 priority: 2 source: 20\nset frame at1t1i period: 1000 priority: 2 source: 20\n"
  },
  {
    "path": "Scripts/gear_level.sh",
    "content": "echo \"set frame etc2 spn: 523 value: 0\"\necho \"send frame etc2 interface: ${1}\"\nsleep 5\necho \"set frame etc2 spn: 523 value: 1\"\nsleep 5\necho \"set frame etc2 spn: 523 value: 2\"\nsleep 5\necho \"set frame etc2 spn: 523 value: 3\"\nsleep 5\necho \"set frame etc2 spn: 523 value: 4\"\nsleep 5\necho \"set frame etc2 spn: 523 value: 5\"\nsleep 5\necho \"set frame etc2 spn: 523 value: 6\"\nsleep 5\necho \"set frame etc2 spn: 523 value: -1\"\nsleep 5\necho \"set frame etc2 spn: 523 value: -5\"\nsleep 5\n\n\n\n"
  },
  {
    "path": "Scripts/simulate_dtc.sh",
    "content": "#!/bin/bash\n\necho \"create frame name: dm1 title: DM1\"\n\necho \"set frame dm1 period: 1000 source: 10\"\n\necho \"add dtc dm1 oc: 3 fmi: 5 spn: 52\"\necho \"add dtc dm1 oc: 4 fmi: 6 spn: 78\"\necho \"add dtc dm1 oc: 0 fmi: 7 spn: 145\"\n\necho \"send frame dm1 interface: $1\"\n\nsleep 5\n\necho \"unsend frame dm1\"\n\necho \"set dtc dm1 2 oc: 3 fmi: 7 spn: 145\"\n\necho \"send frame dm1 interface: $1\"\n\nsleep 5\n\necho \"unsend frame dm1\"\n\necho \"delete dtc dm1 2\"\n\necho \"send frame dm1 interface: $1\"\n\nsleep 10\n"
  },
  {
    "path": "Scripts/simulate_fuel_cons.sh",
    "content": "#!/bin/bash\n\n\ncat <<EOF\n\n\nset frame vin vin: abcde012345678901\nset frame ccvs spn: 84 value: 40\nset frame eec1 spn: 190 value: 400\nset frame lfe spn: 183 value: 0\n\nsend frame ccvs interface: $1\nsend frame eec1 interface: $1\nsend frame vin interface: $1\nsend frame lfe interface: $1\n\nEOF\n\nsleep 15\n\necho \"set frame lfe spn: 183 value: 5\"\n\nsleep 10\n\necho \"set frame lfe spn: 183 value: 7\"\n\nsleep 10\n"
  },
  {
    "path": "Scripts/test_tco.sh",
    "content": "#!/bin/bash\n\n\necho \"set frame tco1 spn: 1615 value: 0\"\necho \"set frame tco1 spn: 1616 value: 0\"\n\necho \"set frame tco1 spn: 1612 value: 7\"\necho \"set frame tco1 spn: 1613 value: 7\"\n\necho \"send frame tco1 interface: $1\"\n\n\necho \"set frame tco1 spn: 1615 value: 1\"\t#Card 1 On\n\nsleep 45\n\necho \"set frame tco1 spn: 1612 value: 0\"\t#Driver 1 Rest\n\nsleep 2\n\necho \"set frame tco1 spn: 1612 value: 1\"\t#Driver 1 available\n\nsleep 2\n\necho \"set frame tco1 spn: 1612 value: 2\"\t#Driver 1 work\n\nsleep 2\n\necho \"set frame tco1 spn: 1612 value: 3\"\t#Driver 1 drive\n\nsleep 2\n\necho \"set frame tco1 spn: 1615 value: 0\"\t#Card 1 Off\n\nsleep 2\n\necho \"set frame tco1 spn: 1616 value: 1\"\t#Card 2 On\n\nsleep 45\n\necho \"set frame tco1 spn: 1613 value: 0\"\t#Driver 2 Rest\n\nsleep 2\n\necho \"set frame tco1 spn: 1613 value: 1\"\t#Driver 2 available\n\nsleep 2\n\necho \"set frame tco1 spn: 1613 value: 2\"\t#Driver 2 work\n\nsleep 2\n\necho \"set frame tco1 spn: 1616 value: 0\"\t#Card 2 Off\n\nsleep 5\n"
  },
  {
    "path": "Tests/BAM_test.cpp",
    "content": "#include <vector>\n\n\n#include <gtest/gtest.h>\n\n#include <TestFrame.h>\n\n#include <Transport/BAM/BamReassembler.h>\n#include <Transport/BAM/BamFragmenter.h>\n\n#include <J1939Factory.h>\n\n\nusing namespace J1939;\n\nBamReassembler reassembler;\n\nTEST(BAM_test, BamFragmenter) {\n\n\tTestFrame frame1(0xF005);\n\tu32 id;\n\n\t{\n\t\tid = 0x00F00550;\n\n\t\tu8 raw[] = {0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xAB, 0xCD, 0xEF, 0xAB, 0xCD, 0xEF, 0xAB, 0xCD, 0xEF};\n\n\n\t\tframe1.decode(id, raw, sizeof(raw));\n\t}\n\n\tBamFragmenter fragmenter;\n\tfragmenter.fragment(frame1);\n\n\tconst TPCMFrame& connFrame = fragmenter.getConnFrame();\n\n\t{\n\n\t\tASSERT_EQ(connFrame.getPGN(), TP_CM_PGN);\n\t\tASSERT_EQ(connFrame.getSrcAddr(), 0x50);\n\n\n\t\tu8 raw[] = {0x20, 0x14, 0x00, 0x03, 0xFF, 0x05, 0xF0, 0x00};\n\n\t\tsize_t length = connFrame.getDataLength();\n\n\t\tu8* buff = new u8[length];\n\n\t\tconnFrame.encode(id, buff, length);\n\n\t\tASSERT_EQ(id, 0x00ECFF50);\n\n\t\tASSERT_EQ(memcmp(raw, buff, length), 0);\n\n\t\tdelete[] buff;\n\n\t}\n\n\n\tstd::vector<TPDTFrame> dataFrames = fragmenter.getDataFrames();\n\n\tASSERT_EQ(dataFrames.size(), 3);\n\n\t{\n\n\t\tASSERT_EQ(dataFrames[0].getPGN(), TP_DT_PGN);\n\t\tASSERT_EQ(dataFrames[0].getSrcAddr(), 0x50);\n\n\n\t\tu8 raw[] = {0x01, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67};\n\n\t\tsize_t length = dataFrames[0].getDataLength();\n\n\t\tu8* buff = new u8[length];\n\n\t\tdataFrames[0].encode(id, buff, length);\n\n\t\tASSERT_EQ(id, 0x00EBFF50);\n\n\t\tASSERT_EQ(memcmp(raw, buff, length), 0);\n\n\t\tdelete[] buff;\n\n\t}\n\n\t{\n\n\t\tASSERT_EQ(dataFrames[1].getPGN(), TP_DT_PGN);\n\t\tASSERT_EQ(dataFrames[1].getSrcAddr(), 0x50);\n\n\n\t\tu8 raw[] = {0x02, 0x89, 0xAB, 0xCD, 0xEF, 0xAB, 0xCD, 0xEF};\n\n\t\tsize_t length = dataFrames[1].getDataLength();\n\n\t\tu8* buff = new u8[length];\n\n\t\tdataFrames[1].encode(id, buff, length);\n\n\t\tASSERT_EQ(id, 0x00EBFF50);\n\n\t\tASSERT_EQ(memcmp(raw, buff, length), 0);\n\n\t\tdelete[] buff;\n\n\t}\n\n\t{\n\n\t\tASSERT_EQ(dataFrames[2].getPGN(), TP_DT_PGN);\n\t\tASSERT_EQ(dataFrames[2].getSrcAddr(), 0x50);\n\n\n\t\tu8 raw[] = {0x03, 0xAB, 0xCD, 0xEF, 0xAB, 0xCD, 0xEF, 0xFF};\n\n\t\tsize_t length = dataFrames[2].getDataLength();\n\n\t\tu8* buff = new u8[length];\n\n\t\tdataFrames[2].encode(id, buff, length);\n\n\t\tASSERT_EQ(id, 0x00EBFF50);\n\n\t\tASSERT_EQ(memcmp(raw, buff, length), 0);\n\n\t\tdelete[] buff;\n\n\t}\n\n\n}\n\nTEST(BAM_test, BamReassembler_ok) {\n\n\n\tu32 id;\n\n\tTestFrame frame1(0xF005);\n\n\n\t//We need to register the frame in the factory so that it can be reassembled by the BamReassembler class\n\tJ1939Factory::getInstance().registerFrame(frame1);\n\n\n\t{\n\n\t\tid = 0x00ECFF50;\n\n\t\tu8 raw[] = {0x20, 0x14, 0x00, 0x03, 0xFF, 0x05, 0xF0, 0x00};\n\n\t\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(id, raw, sizeof(raw));\n\n\t\tASSERT_NE(frame, nullptr);\n\n\t\tASSERT_EQ(frame->getPGN(), TP_CM_PGN);\n\n\t\tASSERT_TRUE(reassembler.toBeHandled(*frame));\n\n\t\treassembler.handleFrame(*frame);\n\n\t\tASSERT_EQ(reassembler.getLastError(), BamReassembler::BAM_ERROR_OK);\n\n\t\tASSERT_FALSE(reassembler.reassembledFramesPending());\n\n\n\t}\n\n\n\t{\n\n\t\tid = 0x00EBFF50;\n\n\t\tu8 raw[] = {0x01, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67};\n\n\t\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(id, raw, sizeof(raw));\n\n\t\tASSERT_NE(frame, nullptr);\n\n\t\tASSERT_EQ(frame->getPGN(), TP_DT_PGN);\n\n\t\tASSERT_TRUE(reassembler.toBeHandled(*frame));\n\n\t\treassembler.handleFrame(*frame);\n\n\t\tASSERT_EQ(reassembler.getLastError(), BamReassembler::BAM_ERROR_OK);\n\n\t\tASSERT_FALSE(reassembler.reassembledFramesPending());\n\n\t}\n\n\n\t{\n\n\t\tid = 0x00EBFF50;\n\n\t\tu8 raw[] = {0x02, 0x89, 0xAB, 0xCD, 0xEF, 0xAB, 0xCD, 0xEF};\n\n\t\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(id, raw, sizeof(raw));\n\n\t\tASSERT_NE(frame, nullptr);\n\n\t\tASSERT_EQ(frame->getPGN(), TP_DT_PGN);\n\n\t\tASSERT_TRUE(reassembler.toBeHandled(*frame));\n\n\t\treassembler.handleFrame(*frame);\n\n\t\tASSERT_EQ(reassembler.getLastError(), BamReassembler::BAM_ERROR_OK);\n\n\t\tASSERT_FALSE(reassembler.reassembledFramesPending());\n\n\n\t}\n\n\n\t{\n\n\t\tid = 0x00EBFF50;\n\n\t\tu8 raw[] = {0x03, 0xAB, 0xCD, 0xEF, 0xAB, 0xCD, 0xEF, 0xFF};\n\n\t\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(id, raw, sizeof(raw));\n\n\t\tASSERT_NE(frame, nullptr);\n\n\t\tASSERT_EQ(frame->getPGN(), TP_DT_PGN);\n\n\t\tASSERT_TRUE(reassembler.toBeHandled(*frame));\n\n\t\treassembler.handleFrame(*frame);\n\n\t\tASSERT_EQ(reassembler.getLastError(), BamReassembler::BAM_ERROR_OK);\n\n\t\tASSERT_TRUE(reassembler.reassembledFramesPending());\n\n\t}\n\n\t//Clean up the factory for following tests...\n\tJ1939Factory::getInstance().unRegisterFrame(0xF005);\n\n}\n\n\n\nTEST(BAM_test, BamReassembler_ko1) {\n\n\n\tu32 id;\n\n\tTestFrame frame1(0xF005);\n\n\treassembler.clear();\n\n\n\t//We need to register the frame in the factory so that it can be reassembled by the BamReassembler class\n\tJ1939Factory::getInstance().registerFrame(frame1);\n\n\n\t{\n\n\t\tid = 0x00ECFF50;\n\n\t\tu8 raw[] = {0x20, 0x14, 0x00, 0x03, 0xFF, 0x05, 0xF0, 0x00};\n\n\t\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(id, raw, sizeof(raw));\n\n\t\tASSERT_NE(frame, nullptr);\n\n\t\tASSERT_EQ(frame->getPGN(), TP_CM_PGN);\n\n\t\tASSERT_TRUE(reassembler.toBeHandled(*frame));\n\n\t\treassembler.handleFrame(*frame);\n\n\t\tASSERT_EQ(reassembler.getLastError(), BamReassembler::BAM_ERROR_OK);\n\n\t\tASSERT_FALSE(reassembler.reassembledFramesPending());\n\n\n\t}\n\n\n\t{\n\n\t\tid = 0x00EBFF50;\n\n\t\tu8 raw[] = {0x02, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67};\n\n\t\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(id, raw, sizeof(raw));\n\n\t\tASSERT_NE(frame, nullptr);\n\n\t\tASSERT_EQ(frame->getPGN(), TP_DT_PGN);\n\n\t\tASSERT_TRUE(reassembler.toBeHandled(*frame));\n\n\t\treassembler.handleFrame(*frame);\n\n\t\tASSERT_EQ(reassembler.getLastError(), BamReassembler::BAM_ERROR_UNEXPECTED_FRAME);\n\n\t}\n\n\t//Clean up the factory for following tests...\n\tJ1939Factory::getInstance().unRegisterFrame(0xF005);\n\n}\n\nTEST(BAM_test, BamReassembler_ko2) {\n\n\n\tu32 id;\n\n\tTestFrame frame1(0xF005);\n\n\treassembler.clear();\n\n\n\t//We need to register the frame in the factory so that it can be reassembled by the BamReassembler class\n\tJ1939Factory::getInstance().registerFrame(frame1);\n\n\n\t{\n\n\t\tid = 0x00ECFF50;\n\n\t\tu8 raw[] = {0x20, 0x14, 0x00, 0x03, 0xFF, 0x05, 0xF0, 0x00};\n\n\t\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(id, raw, sizeof(raw));\n\n\t\tASSERT_NE(frame, nullptr);\n\n\t\tASSERT_EQ(frame->getPGN(), TP_CM_PGN);\n\n\t\tASSERT_TRUE(reassembler.toBeHandled(*frame));\n\n\t\treassembler.handleFrame(*frame);\n\n\t\tASSERT_EQ(reassembler.getLastError(), BamReassembler::BAM_ERROR_OK);\n\n\t\tASSERT_FALSE(reassembler.reassembledFramesPending());\n\n\n\t}\n\n\n\t{\n\n\t\tid = 0x00EBFF50;\n\n\t\tu8 raw[] = {0x01, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67};\n\n\t\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(id, raw, sizeof(raw));\n\n\t\tASSERT_NE(frame, nullptr);\n\n\t\tASSERT_EQ(frame->getPGN(), TP_DT_PGN);\n\n\t\tASSERT_TRUE(reassembler.toBeHandled(*frame));\n\n\t\treassembler.handleFrame(*frame);\n\n\t\tASSERT_EQ(reassembler.getLastError(), BamReassembler::BAM_ERROR_OK);\n\n\t}\n\n\t{\n\n\t\tid = 0x00EBFF50;\n\n\t\tu8 raw[] = {0x02, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67};\n\n\t\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(id, raw, sizeof(raw));\n\n\t\tASSERT_NE(frame, nullptr);\n\n\t\tASSERT_EQ(frame->getPGN(), TP_DT_PGN);\n\n\t\tASSERT_TRUE(reassembler.toBeHandled(*frame));\n\n\t\treassembler.handleFrame(*frame);\n\n\t\tASSERT_EQ(reassembler.getLastError(), BamReassembler::BAM_ERROR_OK);\n\n\t}\n\n\n\t{\n\n\t\tid = 0x00EBFF50;\n\n\t\tu8 raw[] = {0x03, 0xAB, 0xCD, 0xEF, 0xAB, 0xCD, 0xEF, 0xFF};\n\n\t\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(id, raw, sizeof(raw));\n\n\t\tASSERT_NE(frame, nullptr);\n\n\t\tASSERT_EQ(frame->getPGN(), TP_DT_PGN);\n\n\t\tASSERT_TRUE(reassembler.toBeHandled(*frame));\n\n\t\treassembler.handleFrame(*frame);\n\n\t\tASSERT_EQ(reassembler.getLastError(), BamReassembler::BAM_ERROR_OK);\n\n\t}\n\n\n\t{\n\n\t\tid = 0x00EBFF50;\n\n\t\tu8 raw[] = {0x04, 0x1B, 0xC4, 0x7F, 0x7B, 0xCD, 0xEF, 0xFF};\n\n\t\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(id, raw, sizeof(raw));\n\n\t\tASSERT_NE(frame, nullptr);\n\n\t\tASSERT_EQ(frame->getPGN(), TP_DT_PGN);\n\n\t\tASSERT_TRUE(reassembler.toBeHandled(*frame));\n\n\t\treassembler.handleFrame(*frame);\n\n\t\tASSERT_EQ(reassembler.getLastError(), BamReassembler::BAM_ERROR_UNEXPECTED_FRAME);\n\n\t}\n\n\t//Clean up the factory for following tests...\n\tJ1939Factory::getInstance().unRegisterFrame(0xF005);\n\n}\n\n\nTEST(BAM_test, BamReassembler_ko3) {\n\n\n\tu32 id;\n\n\tTestFrame frame1(0xF005);\n\n\treassembler.clear();\n\n\n\t//We need to register the frame in the factory so that it can be reassembled by the BamReassembler class\n\tJ1939Factory::getInstance().registerFrame(frame1);\n\n\n\t{\n\n\t\tid = 0x00ECFF50;\n\n\t\tu8 raw[] = {0x20, 0x14, 0x00, 0x03, 0xFF, 0x05, 0xF0, 0x00};\n\n\t\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(id, raw, sizeof(raw));\n\n\t\tASSERT_NE(frame, nullptr);\n\n\t\tASSERT_EQ(frame->getPGN(), TP_CM_PGN);\n\n\t\tASSERT_TRUE(reassembler.toBeHandled(*frame));\n\n\t\treassembler.handleFrame(*frame);\n\n\t\tASSERT_EQ(reassembler.getLastError(), BamReassembler::BAM_ERROR_OK);\n\n\t\tASSERT_FALSE(reassembler.reassembledFramesPending());\n\n\n\t}\n\n\n\t{\n\n\t\tid = 0x00EBFF50;\n\n\t\tu8 raw[] = {0x01, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67};\n\n\t\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(id, raw, sizeof(raw));\n\n\t\tASSERT_NE(frame, nullptr);\n\n\t\tASSERT_EQ(frame->getPGN(), TP_DT_PGN);\n\n\t\tASSERT_TRUE(reassembler.toBeHandled(*frame));\n\n\t\treassembler.handleFrame(*frame);\n\n\t\tASSERT_EQ(reassembler.getLastError(), BamReassembler::BAM_ERROR_OK);\n\n\t}\n\n\n\t//Receive a TP CM frame before receiving the rest of TP DT frames\n\t{\n\n\t\tid = 0x00ECFF50;\n\n\t\tu8 raw[] = {0x20, 0x14, 0x00, 0x03, 0xFF, 0x05, 0xF0, 0x00};\n\n\t\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(id, raw, sizeof(raw));\n\n\t\tASSERT_NE(frame, nullptr);\n\n\t\tASSERT_EQ(frame->getPGN(), TP_CM_PGN);\n\n\t\tASSERT_TRUE(reassembler.toBeHandled(*frame));\n\n\t\treassembler.handleFrame(*frame);\n\n\t\t//Error relative to the fact that the frame could not be assembled and we received another TP CM frame\n\t\t//that indicates the beginning of a frame to be reassembled.\n\n\t\tASSERT_EQ(reassembler.getLastError(), BamReassembler::BAM_ERROR_INCOMPLETE_FRAME);\n\n\t\tASSERT_FALSE(reassembler.reassembledFramesPending());\n\n\t}\n\n\t//Clean up the factory for following tests...\n\tJ1939Factory::getInstance().unRegisterFrame(0xF005);\n\n}\n\n\nTEST(BAM_test, BamReassembler_ko4) {\n\n\n\tu32 id;\n\n\tTestFrame frame1(0xF005);\n\n\treassembler.clear();\n\n\n\t//This time, we do not register the frame in the factory\n\n\t{\n\n\t\tid = 0x00ECFF50;\n\n\t\tu8 raw[] = {0x20, 0x14, 0x00, 0x03, 0xFF, 0x05, 0xF0, 0x00};\n\n\t\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(id, raw, sizeof(raw));\n\n\t\tASSERT_NE(frame, nullptr);\n\n\t\tASSERT_EQ(frame->getPGN(), TP_CM_PGN);\n\n\t\tASSERT_TRUE(reassembler.toBeHandled(*frame));\n\n\t\treassembler.handleFrame(*frame);\n\n\t\tASSERT_EQ(reassembler.getLastError(), BamReassembler::BAM_ERROR_OK);\n\n\t\tASSERT_FALSE(reassembler.reassembledFramesPending());\n\n\t}\n\n\n\t{\n\n\t\tid = 0x00EBFF50;\n\n\t\tu8 raw[] = {0x01, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67};\n\n\t\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(id, raw, sizeof(raw));\n\n\t\tASSERT_NE(frame, nullptr);\n\n\t\tASSERT_EQ(frame->getPGN(), TP_DT_PGN);\n\n\t\tASSERT_TRUE(reassembler.toBeHandled(*frame));\n\n\t\treassembler.handleFrame(*frame);\n\n\t\tASSERT_EQ(reassembler.getLastError(), BamReassembler::BAM_ERROR_OK);\n\n\t\tASSERT_FALSE(reassembler.reassembledFramesPending());\n\n\t}\n\n\n\t{\n\n\t\tid = 0x00EBFF50;\n\n\t\tu8 raw[] = {0x02, 0x89, 0xAB, 0xCD, 0xEF, 0xAB, 0xCD, 0xEF};\n\n\t\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(id, raw, sizeof(raw));\n\n\t\tASSERT_NE(frame, nullptr);\n\n\t\tASSERT_EQ(frame->getPGN(), TP_DT_PGN);\n\n\t\tASSERT_TRUE(reassembler.toBeHandled(*frame));\n\n\t\treassembler.handleFrame(*frame);\n\n\t\tASSERT_EQ(reassembler.getLastError(), BamReassembler::BAM_ERROR_OK);\n\n\t\tASSERT_FALSE(reassembler.reassembledFramesPending());\n\n\t}\n\n\n\t{\n\n\t\tid = 0x00EBFF50;\n\n\t\tu8 raw[] = {0x03, 0xAB, 0xCD, 0xEF, 0xAB, 0xCD, 0xEF, 0xFF};\n\n\t\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(id, raw, sizeof(raw));\n\n\t\tASSERT_NE(frame, nullptr);\n\n\t\tASSERT_EQ(frame->getPGN(), TP_DT_PGN);\n\n\t\tASSERT_TRUE(reassembler.toBeHandled(*frame));\n\n\t\treassembler.handleFrame(*frame);\n\n\t\tASSERT_EQ(reassembler.getLastError(), BamReassembler::BAM_ERROR_DECODING);\n\n\t\tASSERT_FALSE(reassembler.reassembledFramesPending());\n\n\t}\n\n}\n\nTEST(BAM_test, BamReassembler_ko5) {\n\n\n\tu32 id;\n\n\tTestFrame frame1(0xF005);\n\n\treassembler.clear();\n\n\n\t//We need to register the frame in the factory so that it can be reassembled by the BamReassembler class\n\tJ1939Factory::getInstance().registerFrame(frame1);\n\n\n\t{\n\n\t\tid = 0x00ECFF50;\n\n\t\tu8 raw[] = {0x20, 0x14, 0x00, 0x03, 0xFF, 0x05, 0xF0, 0x00};\n\n\t\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(id, raw, sizeof(raw));\n\n\t\tASSERT_NE(frame, nullptr);\n\n\t\tASSERT_EQ(frame->getPGN(), TP_CM_PGN);\n\n\t\tASSERT_TRUE(reassembler.toBeHandled(*frame));\n\n\t\treassembler.handleFrame(*frame);\n\n\t\tASSERT_EQ(reassembler.getLastError(), BamReassembler::BAM_ERROR_OK);\n\n\t\tASSERT_FALSE(reassembler.reassembledFramesPending());\n\n\n\t}\n\n\n\t//Receive frame from another source address\n\t{\n\n\t\tid = 0x00EBFF70;\n\n\t\tu8 raw[] = {0x01, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67};\n\n\t\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(id, raw, sizeof(raw));\n\n\t\tASSERT_NE(frame, nullptr);\n\n\t\tASSERT_EQ(frame->getPGN(), TP_DT_PGN);\n\n\t\tASSERT_TRUE(reassembler.toBeHandled(*frame));\n\n\t\treassembler.handleFrame(*frame);\n\n\t\tASSERT_EQ(reassembler.getLastError(), BamReassembler::BAM_ERROR_UNEXPECTED_FRAME);\n\n\t}\n\n\n\t//Clean up the factory for following tests...\n\tJ1939Factory::getInstance().unRegisterFrame(0xF005);\n\n}\n"
  },
  {
    "path": "Tests/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.5)\n\n# Locate GTest\nfind_package(GTest REQUIRED)\n\n\ninclude_directories(\n\t\t\tinclude\n\t\t\t${GTEST_INCLUDE_DIRS}\n\t\t\t${J1939_SOURCE_DIR}/include \n\t\t\t${Common_SOURCE_DIR}/include \n\t\t\t)\n \nadd_executable(execTests \n\t\t\tmain.cpp \n\t\t\tTestFrame.cpp\n\t\t\tSPNNumeric_test.cpp\n\t\t\tSPNStatus_test.cpp\n\t\t\tSPNString_test.cpp\n\t\t\tgenericframe_test.cpp\n\t\t\trequest_frame.cpp\n\t\t\tfms1_frame_test.cpp\n\t\t\taddress_claim_frame_test.cpp\n\t\t\tj1939Factory_test.cpp\n\t\t\tdatabase_test.cpp\n\t\t\tBAM_test.cpp\n\t\t\t)\n\t\t\t\n\t\t\t\ntarget_link_libraries(execTests \n\t\t\t${GTEST_LIBRARIES} \n\t\t\tpthread\n\t\t\tJ1939 \n\t\t\trt \n\t\t\tjsoncpp \n\t\t\t-rdynamic\n\t\t\t)\n"
  },
  {
    "path": "Tests/SPNNumeric_test.cpp",
    "content": "#include <gtest/gtest.h>\n\n#include <J1939Common.h>\n#include <SPN/SPNNumeric.h>\n\nusing namespace J1939;\n\n\nTEST(SPNNumeric_test, constructor) {\n\n\t//Test constructor\n\tSPNNumeric numeric(100, \"test_numeric\", 3, 2.5, -2, 2, \"%\");\n\n\tASSERT_EQ(numeric.getSpnNumber(), 100);\n\tASSERT_EQ(numeric.getName(), \"test_numeric\");\n\tASSERT_EQ(numeric.getOffset(), 3);\n\tASSERT_EQ(numeric.getFormatGain(), 2.5);\n\tASSERT_EQ(numeric.getFormatOffset(), -2);\n\tASSERT_EQ(numeric.getByteSize(), 2);\n\tASSERT_EQ(numeric.getUnits(), \"%\");\n\tASSERT_EQ(numeric.getType(), SPN::SPN_NUMERIC);\n\n}\n\n\n\nTEST(SPNNumeric_test, copy_constructor) {\n\n\tSPNNumeric numeric(100, \"test_numeric\", 3, 2.5, -2, 2, \"%\");\n\n\tnumeric.setFormattedValue(38);\n\n\n\t//Test copy constructor\n\tSPNNumeric numeric2(numeric);\n\n\tASSERT_EQ(numeric2.getSpnNumber(), 100);\n\tASSERT_EQ(numeric2.getName(), \"test_numeric\");\n\tASSERT_EQ(numeric2.getOffset(), 3);\n\tASSERT_EQ(numeric2.getFormatGain(), 2.5);\n\tASSERT_EQ(numeric2.getFormatOffset(), -2);\n\tASSERT_EQ(numeric2.getByteSize(), 2);\n\tASSERT_EQ(numeric2.getUnits(), \"%\");\n\tASSERT_EQ(numeric2.getType(), SPN::SPN_NUMERIC);\n\n\tASSERT_EQ(numeric2.getFormattedValue(), 38);\n\n\n}\n\n\nTEST(SPNNumeric_test, encode) {\n\n\tSPNNumeric numeric(10, \"test_byte_size_1\", 2, 2, -10, 1, \"L\");\n\n\tASSERT_EQ(numeric.getByteSize(), 1);\n\n\t//Test encoding\n\tnumeric.setFormattedValue(56);\n\n\t{\n\n\t\tsize_t length = numeric.getByteSize();\n\n\t\tu8* buff = new u8[length];\n\n\t\tnumeric.encode(buff, length);\n\n\t\tu8 raw[] = {0x21};\n\n\t\tASSERT_EQ(memcmp(buff, raw, length), 0);\n\n\t\tdelete[] buff;\n\n\t}\n\n\tSPNNumeric numeric1(100, \"test_byte_size_2\", 3, 2.5, -2, 2, \"%\");\n\n\tASSERT_EQ(numeric1.getByteSize(), 2);\n\n\t//Test encoding\n\tnumeric1.setFormattedValue(38);\n\n\t{\n\n\t\tsize_t length = numeric1.getByteSize();\n\n\t\tu8* buff = new u8[length];\n\n\t\tnumeric1.encode(buff, length);\n\n\t\tu8 raw[] = {0x10, 0x00};\n\n\t\tASSERT_EQ(memcmp(buff, raw, length), 0);\n\n\t\tdelete[] buff;\n\n\t}\n\n\tSPNNumeric numeric2(200, \"test_byte_size_3\", 3, 2.1, -225, 3, \"m\");\n\n\tASSERT_EQ(numeric2.getByteSize(), 3);\n\t//Test encoding\n\tnumeric2.setFormattedValue(5211937.2);\n\n\t{\n\n\t\tsize_t length = numeric2.getByteSize();\n\n\t\tu8* buff = new u8[length];\n\n\t\tnumeric2.encode(buff, length);\n\n\t\tu8 raw[] = {0x3E, 0xDF, 0x25};\n\n\t\tASSERT_EQ(memcmp(buff, raw, length), 0);\n\n\t\tdelete[] buff;\n\n\t}\n\n\tSPNNumeric numeric3(250, \"test_byte_size_4\", 4, 0.05, 3000, 4, \"Pa\");\n\n\tASSERT_EQ(numeric3.getByteSize(), 4);\n\n\t//Test encoding\n\tnumeric3.setFormattedValue(65495982.25);\n\n\t{\n\n\t\tsize_t length = numeric3.getByteSize();\n\n\t\tu8* buff = new u8[length];\n\n\t\tnumeric3.encode(buff, length);\n\n\t\tu8 raw[] = {0x3D, 0xDF, 0x12, 0x4E};\n\n\t\tASSERT_EQ(memcmp(buff, raw, length), 0);\n\n\t\tdelete[] buff;\n\n\t}\n\n}\n\n\nTEST(SPNNumeric_test, decode) {\n\n\ttry {\n\n\t\tSPNNumeric numeric(10, \"test_byte_size_1\", 2, 2, -10, 1, \"L\");\n\n\t\tASSERT_EQ(numeric.getByteSize(), 1);\n\n\t\t//Test decoding\n\n\t\t{\n\n\t\t\tu8 raw[] = {0x21};\n\n\t\t\tnumeric.decode(raw, sizeof(raw));\n\n\t\t\tASSERT_EQ(numeric.getFormattedValue(), 56);\n\n\n\t\t}\n\n\n\t\tSPNNumeric numeric1(100, \"test_byte_size_2\", 3, 2.5, -2, 2, \"%\");\n\n\t\tASSERT_EQ(numeric1.getByteSize(), 2);\n\n\t\t//Test decoding\n\n\t\t{\n\n\t\t\tu8 raw[] = {0x10, 0x00};\n\n\t\t\tnumeric1.decode(raw, sizeof(raw));\n\n\t\t\tASSERT_EQ(numeric1.getFormattedValue(), 38);\n\n\t\t}\n\n\t\tSPNNumeric numeric2(200, \"test_byte_size_3\", 3, 2.1, -225, 3, \"m\");\n\n\t\tASSERT_EQ(numeric2.getByteSize(), 3);\n\t\t//Test decoding\n\n\t\t{\n\n\t\t\tu8 raw[] = {0x3E, 0xDF, 0x25};\n\n\t\t\tnumeric2.decode(raw, sizeof(raw));\n\n\t\t\tASSERT_EQ(numeric2.getFormattedValue(), 5211937.2);\n\n\t\t}\n\n\n\t\tSPNNumeric numeric3(250, \"test_byte_size_4\", 4, 0.05, 3000, 4, \"Pa\");\n\n\t\tASSERT_EQ(numeric3.getByteSize(), 4);\n\n\t\t//Test decoding\n\n\t\t{\n\n\t\t\tu8 raw[] = {0x3D, 0xDF, 0x12, 0x4E};\n\n\t\t\tnumeric3.decode(raw, sizeof(raw));\n\n\t\t\tASSERT_EQ(numeric3.getFormattedValue(), 65495982.25);\n\n\t\t}\n\n\t\tSUCCEED();\n\n\t} catch(J1939DecodeException&) {\n\t\tFAIL();\n\t}\n\n\ttry {\n\n\t\tSPNNumeric numeric3(250, \"test_byte_size_4\", 4, 0.05, 3000, 4, \"Pa\");\n\n\t\tASSERT_EQ(numeric3.getByteSize(), 4);\n\n\t\t//Test decoding\n\n\t\t{\n\n\t\t\tu8 raw[] = {0x3D, 0xDF, 0x12, 0x4E};\n\n\t\t\tnumeric3.decode(raw, 3);\n\n\t\t\tASSERT_EQ(numeric3.getFormattedValue(), 65495982.25);\n\n\t\t}\n\n\t\tFAIL();\n\n\t} catch(J1939DecodeException&) {\n\t\tSUCCEED();\n\t}\n\n}\n\n"
  },
  {
    "path": "Tests/SPNStatus_test.cpp",
    "content": "#include <gtest/gtest.h>\n\n#include <J1939Common.h>\n#include <SPN/SPNStatus.h>\n\nusing namespace J1939;\n\n\nTEST(SPNStatus_test, constructor) {\n\n\t//Test constructor\n\n\tSPNStatusSpec::DescMap valueToDesc {\n\t\t{0, \"Desc 0\"},\n\t\t{1, \"Desc 1\"},\n\t\t{2, \"Desc 2\"},\n\t\t{3, \"Desc 3\"},\n\t};\n\n\n\tSPNStatus status(100, \"test_status\", 4, 2, 2, valueToDesc);\n\n\tASSERT_EQ(status.getSpnNumber(), 100);\n\tASSERT_EQ(status.getName(), \"test_status\");\n\tASSERT_EQ(status.getOffset(), 4);\n\tASSERT_EQ(status.getBitOffset(), 2);\n\tASSERT_EQ(status.getBitSize(), 2);\n\tASSERT_EQ(status.getType(), SPN::SPN_STATUS);\n\n\tASSERT_EQ(status.getValueDescription(0), \"Desc 0\");\n\tASSERT_EQ(status.getValueDescription(1), \"Desc 1\");\n\tASSERT_EQ(status.getValueDescription(2), \"Desc 2\");\n\tASSERT_EQ(status.getValueDescription(3), \"Desc 3\");\n\n}\n\n\nTEST(SPNStatus_test, copy_constructor) {\n\n\tSPNStatusSpec::DescMap valueToDesc {\n\t\t{0, \"Desc 0\"},\n\t\t{1, \"Desc 1\"},\n\t\t{2, \"Desc 2\"},\n\t\t{3, \"Desc 3\"},\n\t};\n\n\n\tSPNStatus status(100, \"test_status\", 4, 2, 2, valueToDesc);\n\n\tASSERT_EQ(status.getBitSize(), 2);\n\n\tstatus.setValue(3);\n\n\t//Test copy constructor\n\tSPNStatus status2(status);\n\n\n\tASSERT_EQ(status2.getSpnNumber(), 100);\n\tASSERT_EQ(status2.getName(), \"test_status\");\n\tASSERT_EQ(status2.getOffset(), 4);\n\tASSERT_EQ(status2.getBitOffset(), 2);\n\tASSERT_EQ(status2.getBitSize(), 2);\n\tASSERT_EQ(status2.getType(), SPN::SPN_STATUS);\n\n\tASSERT_EQ(status2.getValueDescription(0), \"Desc 0\");\n\tASSERT_EQ(status2.getValueDescription(1), \"Desc 1\");\n\tASSERT_EQ(status2.getValueDescription(2), \"Desc 2\");\n\tASSERT_EQ(status2.getValueDescription(3), \"Desc 3\");\n\n\tASSERT_EQ(status2.getValue(), 3);\n\n}\n\n\nTEST(SPNStatus_test, encode) {\n\n\ttry {\n\n\t\t{\n\t\t\tSPNStatus status1(1, \"test_status1\", 4, 0, 2);\n\t\t\tSPNStatus status2(2, \"test_status2\", 4, 2, 2);\n\t\t\tSPNStatus status3(3, \"test_status3\", 4, 4, 2);\n\t\t\tSPNStatus status4(4, \"test_status4\", 4, 6, 2);\n\n\t\t\tu8 val;\n\n\t\t\t//Test encoding\n\t\t\tstatus1.setValue(0);\n\t\t\tstatus2.setValue(1);\n\t\t\tstatus3.setValue(2);\n\t\t\tstatus4.setValue(3);\n\n\t\t\tstatus1.encode(&val, 1);\n\t\t\tstatus2.encode(&val, 1);\n\t\t\tstatus3.encode(&val, 1);\n\t\t\tstatus4.encode(&val, 1);\n\n\t\t\tASSERT_EQ(val, 0xE4);\n\n\t\t}\n\n\t\t{\n\t\t\tSPNStatus status1(10, \"test_status1\", 1, 0, 2);\n\t\t\tSPNStatus status2(20, \"test_status2\", 1, 2, 2);\n\t\t\tSPNStatus status3(30, \"test_status3\", 1, 4, 4);\n\n\t\t\tu8 val;\n\n\t\t\t//Test encoding\n\t\t\tstatus1.setValue(2);\n\t\t\tstatus2.setValue(1);\n\t\t\tstatus3.setValue(7);\n\n\t\t\tstatus1.encode(&val, 1);\n\t\t\tstatus2.encode(&val, 1);\n\t\t\tstatus3.encode(&val, 1);\n\n\t\t\tASSERT_EQ(val, 0x76);\n\n\t\t}\n\n\t\t{\n\t\t\tSPNStatus status1(10, \"test_status1\", 1, 0, 5);\n\t\t\tSPNStatus status2(20, \"test_status2\", 1, 5, 3);\n\n\t\t\tu8 val;\n\n\t\t\t//Test encoding\n\t\t\tstatus1.setValue(30);\n\t\t\tstatus2.setValue(6);\n\n\t\t\tstatus1.encode(&val, 1);\n\t\t\tstatus2.encode(&val, 1);\n\n\t\t\tASSERT_EQ(val, 0xDE);\n\n\t\t}\n\n\t\tSUCCEED();\n\n\t} catch(J1939EncodeException&) {\n\t\tFAIL();\n\t}\n\n\n}\n"
  },
  {
    "path": "Tests/SPNString_test.cpp",
    "content": "#include <gtest/gtest.h>\n\n#include <J1939Common.h>\n#include <SPN/SPNString.h>\n\nusing namespace J1939;\n\n\nTEST(SPNString_test, constructor) {\n\n\t//Test constructor\n\n\tSPNString string1(50, \"string_example\");\n\n\tASSERT_EQ(string1.getSpnNumber(), 50);\n\tASSERT_EQ(string1.getName(), \"string_example\");\n\tASSERT_EQ(string1.getType(), SPN::SPN_STRING);\n\n\tASSERT_TRUE(string1.getValue().empty());\n\n}\n\nTEST(SPNString_test, copy_constructor) {\n\n\tstd::string example = \"my_example\";\n\n\tSPNString string1(50, \"string_example\");\n\n\tstring1.setValue(example);\n\n\t//Test copy constructor\n\tSPNString string2(string1);\n\n\tASSERT_EQ(string2.getSpnNumber(), 50);\n\tASSERT_EQ(string2.getName(), \"string_example\");\n\tASSERT_EQ(string2.getType(), SPN::SPN_STRING);\n\n\tASSERT_EQ(string2.getValue(), example);\n\n\tASSERT_EQ(string2.getByteSize(), example.size() + 1);\n\n}\n\nTEST(SPNString_test, offset) {\n\n\tSPNString string1(50, \"string_example\");\n\n\tstring1.setOffset(5);\n\n\n\tASSERT_EQ(string1.getOffset(), 5);\n\n}\n\n\nTEST(SPNString_test, encode) {\n\n\tu8* buff;\n\n\tstd::string testStr = \"abcdefghijklmnopqrstuvwxyz\";\n\n\tSPNString string1(21, \"string_example\");\n\n\tstring1.setValue(testStr);\n\n\tsize_t length = string1.getByteSize();\n\n\tASSERT_EQ(length, testStr.size() + 1);\n\n\tbuff = new u8[length];\n\n\ttry {\n\n\t\tstring1.encode(buff, length);\n\n\t\tASSERT_EQ(memcmp(buff, (testStr + \"*\").c_str(), length), 0);\n\n\t\tSUCCEED();\n\n\t} catch(J1939EncodeException&) {\n\t\tFAIL();\n\t}\n\n\tdelete[] buff;\n\n\tlength = 5;\n\n\tbuff = new u8[length];\n\n\ttry {\n\n\t\tstring1.encode(buff, length);\n\n\t\tFAIL();\n\n\t} catch(J1939EncodeException&) {\n\t\tSUCCEED();\n\t}\n\n\tdelete[] buff;\n\n}\n\n\nTEST(SPNString_test, decode) {\n\n\n\tstd::string testStr = \"zyxwvutsrqponmlkjihgfedcba\";\n\n\tSPNString string1(14, \"string_example\");\n\n\n\ttry {\n\n\t\tstring1.decode((const u8*)((testStr +  \"*\").c_str()), (testStr + \"*\").size());\n\n\t\tASSERT_EQ(testStr, string1.getValue());\n\n\t\tSUCCEED();\n\n\t} catch(J1939DecodeException&) {\n\t\tFAIL();\n\t}\n\n\n\ttry {\n\n\t\tstring1.decode((const u8*)(testStr.c_str()), testStr.size());\n\n\t\tFAIL();\n\n\t} catch(J1939DecodeException&) {\n\t\tSUCCEED();\n\t}\n\n}\n"
  },
  {
    "path": "Tests/TestFrame.cpp",
    "content": "/*\n * TestFrame.cpp\n */\n\n\n\n#include <TestFrame.h>\n#include <string.h>\n\n\nnamespace J1939 {\n\nvoid TestFrame::decodeData(const u8* buffer, size_t length) {\n\n\tmRaw.clear();\n\tmRaw.append(buffer, length);\n\n}\n\nvoid TestFrame::encodeData(u8* buffer, size_t length) const {\n\tmemcpy(buffer, mRaw.c_str(), length);\n}\n\n\n\n\n} /* namespace J1939 */\n"
  },
  {
    "path": "Tests/address_claim_frame_test.cpp",
    "content": "#include <gtest/gtest.h>\n\n#include <Addressing/AddressClaimFrame.h>\n\nusing namespace J1939;\n\nTEST(AddressClaimFrame_test, encode) {\n\n\t{\n\n\t\tEcuName name(25898, 1256, 5, 16, 241, 90, 15, 2, false);\n\n\t\tAddressClaimFrame frame(name);\n\t\tu32 id;\n\n\t\tframe.setSrcAddr(0x35);\n\t\tframe.setDstAddr(0x25);\n\t\tframe.setPriority(5);\n\n\t\tsize_t length = frame.getDataLength();\n\n\t\tASSERT_EQ(length, 8);\n\n\t\tu8 raw[] = {0x2A, 0x65, 0x00, 0x9D, 0x85, 0xF1, 0xB4, 0x2F};\n\n\t\tu8 *buff = new u8[length];\n\n\t\tframe.encode(id, buff, length);\n\n\t\tASSERT_EQ(id, 0x14EE2535);\n\t\tASSERT_EQ(memcmp(raw, buff, length), 0);\n\n\t\tdelete[] buff;\n\n\t}\n\n}\n\n\nTEST(AddressClaimFrame_test, decode) {\n\n\t{\n\t\tAddressClaimFrame frame;\n\t\tu32 id = 0x14EE2535;\n\n\t\tsize_t length = frame.getDataLength();\n\n\t\tu8 raw[] = {0x2A, 0x65, 0x00, 0x9D, 0x85, 0xF1, 0xB4, 0x2F};\n\n\t\tframe.decode(id, raw, length);\n\n\n\t\tASSERT_EQ(frame.getDataLength(), 8);\n\n\t\tASSERT_EQ(frame.getSrcAddr(), 0x35);\n\t\tASSERT_EQ(frame.getDstAddr(), 0x25);\n\n\t\tASSERT_EQ(frame.getPriority(), 5);\n\n\t\tconst EcuName& name = frame.getEcuName();\n\n\t\tASSERT_EQ(name.getIdNumber(), 25898);\n\t\tASSERT_EQ(name.getManufacturerCode(), 1256);\n\t\tASSERT_EQ(name.getEcuInstance(), 5);\n\t\tASSERT_EQ(name.getFunctionInstance(), 16);\n\t\tASSERT_EQ(name.getFunction(), 241);\n\t\tASSERT_EQ(name.getVehicleSystem(), 90);\n\t\tASSERT_EQ(name.getVehicleSystemInstance(), 15);\n\t\tASSERT_EQ(name.getIndustryGroup(), 2);\n\t\tASSERT_EQ(name.getEcuInstance(), 5);\n\t\tASSERT_EQ(name.isArbitraryAddressCapable(), false);\n\n\t}\n\n}\n"
  },
  {
    "path": "Tests/database/test1.json",
    "content": "[\n\t{\n\t\t\"name\" : \"Frame1\",\n\t\t\"pgn\" : 65000,\n\t\t\"length\" : 0,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"name\" : \"spn_string1\",\n\t\t\t\t\"number\" : 30,\n\t\t\t\t\"type\" : 2\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"name\" : \"spn_string2\",\n\t\t\t\t\"number\" : 62,\n\t\t\t\t\"type\" : 2\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"name\" : \"spn_string3\",\n\t\t\t\t\"number\" : 72,\n\t\t\t\t\"type\" : 2\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"Frame2\",\n\t\t\"pgn\" : 65235,\n\t\t\"length\" : 0,\n\t\t\"spns\" : \n\t\t[\n\t\t\t\n\t\t\t{\n\t\t\t\t\"byteSize\" : 3,\n\t\t\t\t\"formatGain\" : 0.55,\n\t\t\t\t\"formatOffset\" : -200,\n\t\t\t\t\"name\" : \"spn_number1\",\n\t\t\t\t\"number\" : 260,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"%\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 2,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"description 1\",\n\t\t\t\t\t\"description 2\",\n\t\t\t\t\t\"description 3\",\n\t\t\t\t\t\"description 4\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"spn_status1\",\n\t\t\t\t\"number\" : 2323,\n\t\t\t\t\"offset\" : 5,\n\t\t\t\t\"type\" : 1\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"Frame3\",\n\t\t\"pgn\" : 65262,\n\t\t\"length\" : 0,\n\t\t\"spns\" : \n\t\t[\n\t\t\t\n\t\t\t{\n\t\t\t\t\"byteSize\" : 3,\n\t\t\t\t\"formatGain\" : 0.55,\n\t\t\t\t\"formatOffset\" : -200,\n\t\t\t\t\"name\" : \"spn_number2\",\n\t\t\t\t\"number\" : 150,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"%\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"byteSize\" : 2,\n\t\t\t\t\"formatGain\" : 10,\n\t\t\t\t\"formatOffset\" : 200,\n\t\t\t\t\"name\" : \"spn_number3\",\n\t\t\t\t\"number\" : 320,\n\t\t\t\t\"offset\" : 0,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"Pa\"\n\t\t\t}\n\t\t\n\t},\n\t{\n\t\t\"name\" : \"Frame4\",\n\t\t\"pgn\" : 44288,\n\t\t\"length\" : 6,\n\t\t\"spns\" : \n\t\t[\n\t\t\t\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 0,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"description 1\",\n\t\t\t\t\t\"description 2\",\n\t\t\t\t\t\"description 3\",\n\t\t\t\t\t\"description 4\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"spn_status2\",\n\t\t\t\t\"number\" : 2323,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 2,\n\t\t\t\t\"bitSize\" : 3,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"description 1\",\n\t\t\t\t\t\"description 2\",\n\t\t\t\t\t\"description 3\",\n\t\t\t\t\t\"description 4\",\n\t\t\t\t\t\"description 5\",\n\t\t\t\t\t\"description 6\",\n\t\t\t\t\t\"description 7\",\n\t\t\t\t\t\"description 8\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"spn_status3\",\n\t\t\t\t\"number\" : 2525,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 2,\n\t\t\t\t\"bitSize\" : 4,\n\t\t\t\t\"name\" : \"spn_status4\",\n\t\t\t\t\"number\" : 1515,\n\t\t\t\t\"offset\" : 1,\n\t\t\t\t\"type\" : 1\n\t\t\t},\n\n\n\t\t]\n\t}\n]\n"
  },
  {
    "path": "Tests/database/test2.json",
    "content": "[\n\t{\n\t\t\"name\" : \"Frame1\",\n\t\t\"pgn\" : 65000,\n\t\t\"length\" : 0,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"name\" : \"spn_string1\",\n\t\t\t\t\"number\" : 30,\n\t\t\t\t\"type\" : 2\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"name\" : \"spn_string2\",\n\t\t\t\t\"number\" : 62,\n\t\t\t\t\"type\" : 2\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"name\" : \"spn_string3\",\n\t\t\t\t\"number\" : 72,\n\t\t\t\t\"type\" : 2\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"Frame2\",\n\t\t\"pgn\" : 65235,\n\t\t\"length\" : 0,\n\t\t\"spns\" : \n\t\t[\n\t\t\t\n\t\t\t{\n\t\t\t\t\"byteSize\" : 3,\n\t\t\t\t\"formatGain\" : 0.55,\n\t\t\t\t\"formatOffset\" : -200,\n\t\t\t\t\"name\" : \"spn_number1\",\n\t\t\t\t\"number\" : 260,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"%\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 2,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"description 1\",\n\t\t\t\t\t\"description 2\",\n\t\t\t\t\t\"description 3\",\n\t\t\t\t\t\"description 4\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"spn_status1\",\n\t\t\t\t\"number\" : 2323,\n\t\t\t\t\"offset\" : 5,\n\t\t\t\t\"type\" : 1\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"Frame3\",\n\t\t\"length\" : 0,\n\t\t\"spns\" : \n\t\t{\n\t\t\t\"byteSize\" : 3,\n\t\t\t\"formatGain\" : 0.55,\n\t\t\t\"formatOffset\" : -200,\n\t\t\t\"name\" : \"spn_number2\",\n\t\t\t\"number\" : 150,\n\t\t\t\"offset\" : 2,\n\t\t\t\"type\" : 0,\n\t\t\t\"units\" : \"%\"\n\t\t}\n\t},\n\t{\n\t\t\"name\" : \"Frame4\",\n\t\t\"pgn\" : 44288,\n\t\t\"length\" : 6,\n\t\t\"spns\" : \n\t\t[\n\t\t\t\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 0,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"description 1\",\n\t\t\t\t\t\"description 2\",\n\t\t\t\t\t\"description 3\",\n\t\t\t\t\t\"description 4\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"spn_status2\",\n\t\t\t\t\"number\" : 2323,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 2,\n\t\t\t\t\"bitSize\" : 3,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"description 1\",\n\t\t\t\t\t\"description 2\",\n\t\t\t\t\t\"description 3\",\n\t\t\t\t\t\"description 4\",\n\t\t\t\t\t\"description 5\",\n\t\t\t\t\t\"description 6\",\n\t\t\t\t\t\"description 7\",\n\t\t\t\t\t\"description 8\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"spn_status3\",\n\t\t\t\t\"number\" : 2525,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 2,\n\t\t\t\t\"bitSize\" : 4,\n\t\t\t\t\"name\" : \"spn_status4\",\n\t\t\t\t\"number\" : 1515,\n\t\t\t\t\"offset\" : 1,\n\t\t\t\t\"type\" : 1\n\t\t\t}\n\n\n\t\t]\n\t}\n]\n"
  },
  {
    "path": "Tests/database/test3.json",
    "content": "[\n\t{\n\t\t\"name\" : \"Frame1\",\n\t\t\"pgn\" : 65000,\n\t\t\"length\" : 0,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"name\" : \"spn_string1\",\n\t\t\t\t\"number\" : 30,\n\t\t\t\t\"type\" : 2\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"name\" : \"spn_string2\",\n\t\t\t\t\"number\" : 62,\n\t\t\t\t\"type\" : 2\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"name\" : \"spn_string3\",\n\t\t\t\t\"number\" : 72,\n\t\t\t\t\"type\" : 2\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"Frame2\",\n\t\t\"pgn\" : 65235,\n\t\t\"length\" : 0,\n\t\t\"spns\" : \n\t\t[\n\t\t\t\n\t\t\t{\n\t\t\t\t\"byteSize\" : 3,\n\t\t\t\t\"formatGain\" : 0.55,\n\t\t\t\t\"formatOffset\" : -200,\n\t\t\t\t\"name\" : \"spn_number1\",\n\t\t\t\t\"number\" : 260,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"%\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 2,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"description 1\",\n\t\t\t\t\t\"description 2\",\n\t\t\t\t\t\"description 3\",\n\t\t\t\t\t\"description 4\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"spn_status1\",\n\t\t\t\t\"number\" : 2323,\n\t\t\t\t\"offset\" : 5,\n\t\t\t\t\"type\" : 1\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"Frame3\",\n\t\t\"pgn\" : 65262,\n\t\t\"length\" : 0,\n\t\t\"spns\" : \n\t\t[\n\t\t\t\n\t\t\t{\n\t\t\t\t\"byteSize\" : 8,\n\t\t\t\t\"formatGain\" : 0.55,\n\t\t\t\t\"formatOffset\" : -200,\n\t\t\t\t\"name\" : \"spn_number2\",\n\t\t\t\t\"number\" : 150,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"%\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"byteSize\" : 9,\n\t\t\t\t\"formatGain\" : 10,\n\t\t\t\t\"formatOffset\" : 200,\n\t\t\t\t\"name\" : \"spn_number3\",\n\t\t\t\t\"number\" : 320,\n\t\t\t\t\"offset\" : 0,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"Pa\"\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"Frame4\",\n\t\t\"pgn\" : 44288,\n\t\t\"length\" : 6,\n\t\t\"spns\" : \n\t\t[\n\t\t\t\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 0,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"description 1\",\n\t\t\t\t\t\"description 2\",\n\t\t\t\t\t\"description 3\",\n\t\t\t\t\t\"description 4\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"spn_status2\",\n\t\t\t\t\"number\" : 2323,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 2,\n\t\t\t\t\"bitSize\" : 3,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"description 1\",\n\t\t\t\t\t\"description 2\",\n\t\t\t\t\t\"description 3\",\n\t\t\t\t\t\"description 4\",\n\t\t\t\t\t\"description 5\",\n\t\t\t\t\t\"description 6\",\n\t\t\t\t\t\"description 7\",\n\t\t\t\t\t\"description 8\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"spn_status3\",\n\t\t\t\t\"number\" : 2525,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 2,\n\t\t\t\t\"bitSize\" : 4,\n\t\t\t\t\"name\" : \"spn_status4\",\n\t\t\t\t\"number\" : 1515,\n\t\t\t\t\"offset\" : 1,\n\t\t\t\t\"type\" : 1\n\t\t\t}\n\n\n\t\t]\n\t}\n]\n"
  },
  {
    "path": "Tests/database/test4.json",
    "content": "[\n\t{\n\t\t\"name\" : \"Frame1\",\n\t\t\"pgn\" : 65000,\n\t\t\"length\" : 0,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"name\" : \"spn_string1\",\n\t\t\t\t\"number\" : 30,\n\t\t\t\t\"type\" : 2\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"name\" : \"spn_string2\",\n\t\t\t\t\"number\" : 62,\n\t\t\t\t\"type\" : 2\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"name\" : \"spn_string3\",\n\t\t\t\t\"number\" : 72,\n\t\t\t\t\"type\" : 2\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"Frame2\",\n\t\t\"pgn\" : 65235,\n\t\t\"length\" : 0,\n\t\t\"spns\" : \n\t\t[\n\t\t\t\n\t\t\t{\n\t\t\t\t\"byteSize\" : 3,\n\t\t\t\t\"formatGain\" : 0.55,\n\t\t\t\t\"formatOffset\" : -200,\n\t\t\t\t\"name\" : \"spn_number1\",\n\t\t\t\t\"number\" : 260,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 4,\n\t\t\t\t\"units\" : \"%\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 2,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"description 1\",\n\t\t\t\t\t\"description 2\",\n\t\t\t\t\t\"description 3\",\n\t\t\t\t\t\"description 4\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"spn_status1\",\n\t\t\t\t\"number\" : 2323,\n\t\t\t\t\"offset\" : 5,\n\t\t\t\t\"type\" : 1\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"Frame3\",\n\t\t\"pgn\" : 65262,\n\t\t\"length\" : 0,\n\t\t\"spns\" : \n\t\t[\n\t\t\t\n\t\t\t{\n\t\t\t\t\"byteSize\" : 3,\n\t\t\t\t\"formatGain\" : 0.55,\n\t\t\t\t\"formatOffset\" : -200,\n\t\t\t\t\"name\" : \"spn_number2\",\n\t\t\t\t\"number\" : 150,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"%\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"byteSize\" : 2,\n\t\t\t\t\"formatGain\" : 10,\n\t\t\t\t\"formatOffset\" : 200,\n\t\t\t\t\"name\" : \"spn_number3\",\n\t\t\t\t\"number\" : 320,\n\t\t\t\t\"offset\" : 0,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"Pa\"\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"Frame4\",\n\t\t\"pgn\" : 44288,\n\t\t\"length\" : 6,\n\t\t\"spns\" : \n\t\t[\n\t\t\t\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 0,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"description 1\",\n\t\t\t\t\t\"description 2\",\n\t\t\t\t\t\"description 3\",\n\t\t\t\t\t\"description 4\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"spn_status2\",\n\t\t\t\t\"number\" : 2424,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 2,\n\t\t\t\t\"bitSize\" : 3,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"description 1\",\n\t\t\t\t\t\"description 2\",\n\t\t\t\t\t\"description 3\",\n\t\t\t\t\t\"description 4\",\n\t\t\t\t\t\"description 5\",\n\t\t\t\t\t\"description 6\",\n\t\t\t\t\t\"description 7\",\n\t\t\t\t\t\"description 8\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"spn_status3\",\n\t\t\t\t\"number\" : 2525,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 2,\n\t\t\t\t\"bitSize\" : 4,\n\t\t\t\t\"name\" : \"spn_status4\",\n\t\t\t\t\"number\" : 5151,\n\t\t\t\t\"offset\" : 1,\n\t\t\t\t\"type\" : 1\n\t\t\t}\n\n\n\t\t]\n\t}\n]\n"
  },
  {
    "path": "Tests/database/test5.json",
    "content": "[\n\t{\n\t\t\"name\" : \"Frame1\",\n\t\t\"pgn\" : 65000,\n\t\t\"length\" : 0,\n\t\t\"spns\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"name\" : \"spn_string1\",\n\t\t\t\t\"number\" : 30,\n\t\t\t\t\"type\" : 2\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"name\" : \"spn_string2\",\n\t\t\t\t\"number\" : 62,\n\t\t\t\t\"type\" : 2\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"name\" : \"spn_string3\",\n\t\t\t\t\"number\" : 72,\n\t\t\t\t\"type\" : 2\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"Frame2\",\n\t\t\"pgn\" : 65235,\n\t\t\"length\" : 0,\n\t\t\"spns\" : \n\t\t[\n\t\t\t\n\t\t\t{\n\t\t\t\t\"byteSize\" : 3,\n\t\t\t\t\"formatGain\" : 0.55,\n\t\t\t\t\"formatOffset\" : -200,\n\t\t\t\t\"name\" : \"spn_number1\",\n\t\t\t\t\"number\" : 260,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"%\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 2,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"description 1\",\n\t\t\t\t\t\"description 2\",\n\t\t\t\t\t\"description 3\",\n\t\t\t\t\t\"description 4\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"spn_status1\",\n\t\t\t\t\"number\" : 2323,\n\t\t\t\t\"offset\" : 5,\n\t\t\t\t\"type\" : 1\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"Frame3\",\n\t\t\"pgn\" : 65262,\n\t\t\"length\" : 0,\n\t\t\"spns\" : \n\t\t[\n\t\t\t\n\t\t\t{\n\t\t\t\t\"byteSize\" : 3,\n\t\t\t\t\"formatGain\" : 0.55,\n\t\t\t\t\"formatOffset\" : -200,\n\t\t\t\t\"name\" : \"spn_number2\",\n\t\t\t\t\"number\" : 150,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"%\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"byteSize\" : 2,\n\t\t\t\t\"formatGain\" : 10,\n\t\t\t\t\"formatOffset\" : 200,\n\t\t\t\t\"name\" : \"spn_number3\",\n\t\t\t\t\"number\" : 320,\n\t\t\t\t\"offset\" : 0,\n\t\t\t\t\"type\" : 0,\n\t\t\t\t\"units\" : \"Pa\"\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\t\"name\" : \"Frame4\",\n\t\t\"pgn\" : 44288,\n\t\t\"length\" : 6,\n\t\t\"spns\" : \n\t\t[\n\t\t\t\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 0,\n\t\t\t\t\"bitSize\" : 2,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"description 1\",\n\t\t\t\t\t\"description 2\",\n\t\t\t\t\t\"description 3\",\n\t\t\t\t\t\"description 4\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"spn_status2\",\n\t\t\t\t\"number\" : 2424,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 2,\n\t\t\t\t\"bitSize\" : 3,\n\t\t\t\t\"descriptions\" : \n\t\t\t\t[\n\t\t\t\t\t\"description 1\",\n\t\t\t\t\t\"description 2\",\n\t\t\t\t\t\"description 3\",\n\t\t\t\t\t\"description 4\",\n\t\t\t\t\t\"description 5\",\n\t\t\t\t\t\"description 6\",\n\t\t\t\t\t\"description 7\",\n\t\t\t\t\t\"description 8\"\n\t\t\t\t],\n\t\t\t\t\"name\" : \"spn_status3\",\n\t\t\t\t\"number\" : 2525,\n\t\t\t\t\"offset\" : 2,\n\t\t\t\t\"type\" : 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"bitOffset\" : 2,\n\t\t\t\t\"bitSize\" : 4,\n\t\t\t\t\"name\" : \"spn_status4\",\n\t\t\t\t\"number\" : 5151,\n\t\t\t\t\"offset\" : 1,\n\t\t\t\t\"type\" : 1\n\t\t\t}\n\n\n\t\t]\n\t}\n]\n"
  },
  {
    "path": "Tests/database_test.cpp",
    "content": "#include <gtest/gtest.h>\n\n#include <GenericFrame.h>\n#include <J1939DataBase.h>\n#include <SPN/SPNNumeric.h>\n#include <SPN/SPNStatus.h>\n#include <SPN/SPNString.h>\n\nusing namespace J1939;\n\nTEST(J1939DataBase_test, readDataBase) {\n\n\t//Load database\n\tJ1939DataBase ddbb;\n\n\tASSERT_FALSE(ddbb.parseJsonFile(\"Tests/database/test_not_found.json\"));\n\n\tASSERT_EQ(ddbb.getLastError(), J1939DataBase::ERROR_FILE_NOT_FOUND);\n\n\tddbb.clear();\n\n\n\t//Right bracket removed in line 86 and comma added in line 136.\n\tASSERT_FALSE(ddbb.parseJsonFile(\"Tests/database/test1.json\"));\n\n\tASSERT_EQ(ddbb.getLastError(), J1939DataBase::ERROR_JSON_SYNTAX);\n\n\tddbb.clear();\n\n\n\t//PGN key removed in line 61 and SPNs is an object in line 63 instead of array\n\tASSERT_FALSE(ddbb.parseJsonFile(\"Tests/database/test2.json\"));\n\n\tASSERT_EQ(ddbb.getLastError(), J1939DataBase::ERROR_UNEXPECTED_TOKENS);\n\n\tddbb.clear();\n\n\n\t//Bytesize = 8 in line 67 and bytesize = 9 in line 77.\n\tASSERT_FALSE(ddbb.parseJsonFile(\"Tests/database/test3.json\"));\n\n\tASSERT_EQ(ddbb.getLastError(), J1939DataBase::ERROR_OUT_OF_RANGE);\n\n\tddbb.clear();\n\n\n\t//Type 4 in line 39\n\tASSERT_FALSE(ddbb.parseJsonFile(\"Tests/database/test4.json\"));\n\n\tASSERT_EQ(ddbb.getLastError(), J1939DataBase::ERROR_UNKNOWN_SPN_TYPE);\n\n\tddbb.clear();\n\n\n\t//Database OK\n\tASSERT_TRUE(ddbb.parseJsonFile(\"Tests/database/test5.json\"));\n\n\tASSERT_EQ(ddbb.getLastError(), J1939DataBase::ERROR_OK);\n\n\tconst std::vector<GenericFrame>& frames = ddbb.getParsedFrames();\n\n\tASSERT_EQ(frames.size(), 4);\n\n\tASSERT_EQ(frames[0].getPGN(), 65000);\n\tASSERT_EQ(frames[0].getName(), \"Frame1\");\n\n\n\t{\n\t\tstd::set<u32> spnNumbers = frames[0].getSPNNumbers();\n\n\t\tauto iter = spnNumbers.begin();\n\n\t\tASSERT_EQ(spnNumbers.size(), 3);\n\n\t\tASSERT_EQ(*iter, 30);\n\n\t\tconst SPN *spn1 = frames[0].getSPN(*iter++);\n\n\t\tASSERT_EQ(spn1->getSpnNumber(), 30);\n\n\t\tASSERT_EQ(spn1->getType(), SPN::SPN_STRING);\n\n\t\tASSERT_EQ(spn1->getName(), \"spn_string1\");\n\n\t\tASSERT_EQ(*iter, 62);\n\n\t\tconst SPN *spn2 = frames[0].getSPN(*iter++);\n\n\t\tASSERT_EQ(spn2->getSpnNumber(), 62);\n\n\t\tASSERT_EQ(spn2->getType(), SPN::SPN_STRING);\n\n\t\tASSERT_EQ(spn2->getName(), \"spn_string2\");\n\n\t\tASSERT_EQ(*iter, 72);\n\n\t\tconst SPN *spn3 = frames[0].getSPN(*iter++);\n\n\t\tASSERT_EQ(spn3->getSpnNumber(), 72);\n\n\t\tASSERT_EQ(spn3->getType(), SPN::SPN_STRING);\n\n\t\tASSERT_EQ(spn3->getName(), \"spn_string3\");\n\n\t}\n\n\tASSERT_EQ(frames[1].getPGN(), 65235);\n\tASSERT_EQ(frames[1].getName(), \"Frame2\");\n\n\t{\n\t\tstd::set<u32> spnNumbers = frames[1].getSPNNumbers();\n\n\t\tauto iter = spnNumbers.begin();\n\n\t\tASSERT_EQ(spnNumbers.size(), 2);\n\n\t\tASSERT_EQ(*iter, 260);\n\n\t\tconst SPN *spn1 = frames[1].getSPN(*iter++);\n\n\t\tASSERT_EQ(spn1->getSpnNumber(), 260);\n\n\t\tASSERT_EQ(spn1->getType(), SPN::SPN_NUMERIC);\n\n\t\tASSERT_EQ(spn1->getName(), \"spn_number1\");\n\n\t\tconst SPNNumeric *spnNum = static_cast<const SPNNumeric*>(spn1);\n\n\t\tASSERT_EQ(spnNum->getOffset(), 2);\n\t\tASSERT_EQ(spnNum->getFormatGain(), 0.55);\n\t\tASSERT_EQ(spnNum->getFormatOffset(), -200);\n\t\tASSERT_EQ(spnNum->getByteSize(), 3);\n\t\tASSERT_EQ(spnNum->getUnits(), \"%\");\n\n\t\tASSERT_EQ(*iter, 2323);\n\n\t\tconst SPN *spn2 = frames[1].getSPN(*iter++);\n\n\t\tASSERT_EQ(spn2->getSpnNumber(), 2323);\n\n\t\tASSERT_EQ(spn2->getType(), SPN::SPN_STATUS);\n\n\t\tASSERT_EQ(spn2->getName(), \"spn_status1\");\n\n\t\tconst SPNStatus *spnStat = static_cast<const SPNStatus*>(spn2);\n\n\t\tASSERT_EQ(spnStat->getOffset(), 5);\n\t\tASSERT_EQ(spnStat->getBitOffset(), 2);\n\t\tASSERT_EQ(spnStat->getBitSize(), 2);\n\n\t\tASSERT_EQ(spnStat->getValueDescription(0), \"description 1\");\n\t\tASSERT_EQ(spnStat->getValueDescription(1), \"description 2\");\n\t\tASSERT_EQ(spnStat->getValueDescription(2), \"description 3\");\n\t\tASSERT_EQ(spnStat->getValueDescription(3), \"description 4\");\n\n\t}\n\n\n\tASSERT_EQ(frames[2].getPGN(), 65262);\n\tASSERT_EQ(frames[2].getName(), \"Frame3\");\n\n\t{\n\t\tstd::set<u32> spnNumbers = frames[2].getSPNNumbers();\n\n\t\tauto iter = spnNumbers.begin();\n\n\t\tASSERT_EQ(spnNumbers.size(), 2);\n\n\t\tASSERT_EQ(*iter, 150);\n\n\t\tconst SPN *spn1 = frames[2].getSPN(*iter++);\n\n\t\tASSERT_EQ(spn1->getSpnNumber(), 150);\n\n\t\tASSERT_EQ(spn1->getType(), SPN::SPN_NUMERIC);\n\n\t\tASSERT_EQ(spn1->getName(), \"spn_number2\");\n\n\t\tconst SPNNumeric *spnNum1 = static_cast<const SPNNumeric*>(spn1);\n\n\t\tASSERT_EQ(spnNum1->getOffset(), 2);\n\t\tASSERT_EQ(spnNum1->getFormatGain(), 0.55);\n\t\tASSERT_EQ(spnNum1->getFormatOffset(), -200);\n\t\tASSERT_EQ(spnNum1->getByteSize(), 3);\n\t\tASSERT_EQ(spnNum1->getUnits(), \"%\");\n\n\t\tASSERT_EQ(*iter, 320);\n\n\t\tconst SPN *spn2 = frames[2].getSPN(*iter++);\n\n\t\tASSERT_EQ(spn2->getSpnNumber(), 320);\n\n\t\tASSERT_EQ(spn2->getType(), SPN::SPN_NUMERIC);\n\n\t\tASSERT_EQ(spn2->getName(), \"spn_number3\");\n\n\t\tconst SPNNumeric *spnNum2 = static_cast<const SPNNumeric*>(spn2);\n\n\t\tASSERT_EQ(spnNum2->getOffset(), 0);\n\t\tASSERT_EQ(spnNum2->getFormatGain(), 10);\n\t\tASSERT_EQ(spnNum2->getFormatOffset(), 200);\n\t\tASSERT_EQ(spnNum2->getByteSize(), 2);\n\t\tASSERT_EQ(spnNum2->getUnits(), \"Pa\");\n\n\t}\n\n\n\tASSERT_EQ(frames[3].getPGN(), 44288);\n\tASSERT_EQ(frames[3].getName(), \"Frame4\");\n\n\t{\n\t\tstd::set<u32> spnNumbers = frames[3].getSPNNumbers();\n\n\t\tauto iter = spnNumbers.begin();\n\n\t\tASSERT_EQ(spnNumbers.size(), 3);\n\n\t\tASSERT_EQ(*iter, 2424);\n\n\t\tconst SPN *spn1 = frames[3].getSPN(*iter++);\n\n\t\tASSERT_EQ(spn1->getSpnNumber(), 2424);\n\t\tASSERT_EQ(spn1->getType(), SPN::SPN_STATUS);\n\n\t\tASSERT_EQ(spn1->getName(), \"spn_status2\");\n\n\t\tconst SPNStatus *spnStat1 = static_cast<const SPNStatus*>(spn1);\n\n\t\tASSERT_EQ(spnStat1->getOffset(), 2);\n\t\tASSERT_EQ(spnStat1->getBitOffset(), 0);\n\t\tASSERT_EQ(spnStat1->getBitSize(), 2);\n\n\t\tASSERT_EQ(spnStat1->getValueDescription(0), \"description 1\");\n\t\tASSERT_EQ(spnStat1->getValueDescription(1), \"description 2\");\n\t\tASSERT_EQ(spnStat1->getValueDescription(2), \"description 3\");\n\t\tASSERT_EQ(spnStat1->getValueDescription(3), \"description 4\");\n\n\n\t\tASSERT_EQ(*iter, 2525);\n\n\t\tconst SPN *spn2 = frames[3].getSPN(*iter++);\n\n\t\tASSERT_EQ(spn2->getSpnNumber(), 2525);\n\t\tASSERT_EQ(spn2->getType(), SPN::SPN_STATUS);\n\n\t\tASSERT_EQ(spn2->getName(), \"spn_status3\");\n\n\t\tconst SPNStatus *spnStat2 = static_cast<const SPNStatus*>(spn2);\n\n\t\tASSERT_EQ(spnStat2->getOffset(), 2);\n\t\tASSERT_EQ(spnStat2->getBitOffset(), 2);\n\t\tASSERT_EQ(spnStat2->getBitSize(), 3);\n\n\t\tASSERT_EQ(spnStat2->getValueDescription(0), \"description 1\");\n\t\tASSERT_EQ(spnStat2->getValueDescription(1), \"description 2\");\n\t\tASSERT_EQ(spnStat2->getValueDescription(2), \"description 3\");\n\t\tASSERT_EQ(spnStat2->getValueDescription(3), \"description 4\");\n\t\tASSERT_EQ(spnStat2->getValueDescription(4), \"description 5\");\n\t\tASSERT_EQ(spnStat2->getValueDescription(5), \"description 6\");\n\t\tASSERT_EQ(spnStat2->getValueDescription(6), \"description 7\");\n\t\tASSERT_EQ(spnStat2->getValueDescription(7), \"description 8\");\n\n\n\t\tASSERT_EQ(*iter, 5151);\n\n\t\tconst SPN *spn3 = frames[3].getSPN(*iter++);\n\n\t\tASSERT_EQ(spn3->getSpnNumber(), 5151);\n\t\tASSERT_EQ(spn3->getType(), SPN::SPN_STATUS);\n\n\t\tASSERT_EQ(spn3->getName(), \"spn_status4\");\n\n\t\tconst SPNStatus *spnStat3 = static_cast<const SPNStatus*>(spn3);\n\n\t\tASSERT_EQ(spnStat3->getOffset(), 1);\n\t\tASSERT_EQ(spnStat3->getBitOffset(), 2);\n\t\tASSERT_EQ(spnStat3->getBitSize(), 4);\n\n\t}\n\n}\n\n"
  },
  {
    "path": "Tests/fms1_frame_test.cpp",
    "content": "#include <gtest/gtest.h>\n\n#include <FMS/TellTale/FMS1Frame.h>\n\nusing namespace J1939;\n\nTEST(FMS1Frame_test, encode) {\n\n\t{\n\t\tFMS1Frame frame(0);\n\t\tu32 id;\n\n\t\tframe.setSrcAddr(0x35);\n\t\tframe.setPriority(5);\n\n\t\tASSERT_EQ(frame.getDataLength(), 8);\n\n\t\tASSERT_EQ(frame.getBlockID(), 0);\n\n\t\tASSERT_TRUE(frame.hasTTS(5));\n\t\tASSERT_FALSE(frame.hasTTS(16));\n\t\tASSERT_FALSE(frame.hasTTS(35));\n\t\tASSERT_FALSE(frame.hasTTS(50));\n\n\t\tASSERT_TRUE(frame.setTTS(5, TellTale::TTS_STATUS_RED));\n\t\tASSERT_TRUE(frame.setTTS(4, TellTale::TTS_STATUS_OFF));\n\t\tASSERT_TRUE(frame.setTTS(8, TellTale::TTS_STATUS_YELLOW));\n\t\tASSERT_TRUE(frame.setTTS(1, TellTale::TTS_STATUS_INFO));\n\n\t\tsize_t length = frame.getDataLength();\n\n\t\tu8 raw[] = {0xB0, 0xFF, 0x98, 0xFF, 0xFA, 0xFF, 0xFF, 0xFF};\n\n\t\tu8 *buff = new u8[length];\n\n\t\tframe.encode(id, buff, length);\n\n\t\tASSERT_EQ(id, 0x14FD7D35);\n\t\tASSERT_EQ(memcmp(raw, buff, length), 0);\n\n\t\tdelete[] buff;\n\n\t}\n\n\t{\n\t\tFMS1Frame frame(1);\n\t\tu32 id;\n\n\t\tframe.setSrcAddr(0x44);\n\t\tframe.setPriority(1);\n\n\t\tASSERT_EQ(frame.getDataLength(), 8);\n\n\t\tASSERT_EQ(frame.getBlockID(), 1);\n\n\t\tASSERT_FALSE(frame.hasTTS(5));\n\t\tASSERT_TRUE(frame.hasTTS(16));\n\t\tASSERT_FALSE(frame.hasTTS(35));\n\t\tASSERT_FALSE(frame.hasTTS(50));\n\n\t\tASSERT_TRUE(frame.setTTS(20, TellTale::TTS_STATUS_RED));\n\t\tASSERT_TRUE(frame.setTTS(21, TellTale::TTS_STATUS_OFF));\n\t\tASSERT_TRUE(frame.setTTS(17, TellTale::TTS_STATUS_YELLOW));\n\t\tASSERT_TRUE(frame.setTTS(30, TellTale::TTS_STATUS_INFO));\n\n\t\tsize_t length = frame.getDataLength();\n\n\t\tu8 raw[] = {0xF1, 0xFA, 0x9F, 0xF8, 0xFF, 0xFF, 0xFF, 0xBF};\n\n\t\tu8 *buff = new u8[length];\n\n\t\tframe.encode(id, buff, length);\n\n\t\tASSERT_EQ(id, 0x04FD7D44);\n\t\tASSERT_EQ(memcmp(raw, buff, length), 0);\n\n\t\tdelete[] buff;\n\n\t}\n\n\t{\n\t\tFMS1Frame frame(2);\n\t\tu32 id;\n\n\t\tframe.setSrcAddr(0x36);\n\t\tframe.setPriority(7);\n\n\t\tASSERT_EQ(frame.getDataLength(), 8);\n\n\t\tASSERT_EQ(frame.getBlockID(), 2);\n\n\t\tASSERT_FALSE(frame.hasTTS(5));\n\t\tASSERT_FALSE(frame.hasTTS(16));\n\t\tASSERT_TRUE(frame.hasTTS(35));\n\n\t\tASSERT_TRUE(frame.setTTS(35, TellTale::TTS_STATUS_RED));\n\t\tASSERT_TRUE(frame.setTTS(40, TellTale::TTS_STATUS_OFF));\n\t\tASSERT_TRUE(frame.setTTS(41, TellTale::TTS_STATUS_YELLOW));\n\t\tASSERT_TRUE(frame.setTTS(45, TellTale::TTS_STATUS_INFO));\n\n\t\tsize_t length = frame.getDataLength();\n\n\t\tu8 raw[] = {0xF2, 0xFF, 0x9F, 0xFF, 0xFF, 0xA8, 0xFF, 0xBF};\n\n\t\tu8 *buff = new u8[length];\n\n\t\tframe.encode(id, buff, length);\n\n\t\tASSERT_EQ(id, 0x1CFD7D36);\n\t\tASSERT_EQ(memcmp(raw, buff, length), 0);\n\n\t\tdelete[] buff;\n\n\t}\n\n\t{\n\t\tFMS1Frame frame(3);\n\t\tu32 id;\n\n\t\tframe.setSrcAddr(0x25);\n\t\tframe.setPriority(5);\n\n\t\tASSERT_EQ(frame.getDataLength(), 8);\n\n\t\tASSERT_EQ(frame.getBlockID(), 3);\n\n\t\tASSERT_FALSE(frame.hasTTS(5));\n\t\tASSERT_FALSE(frame.hasTTS(16));\n\t\tASSERT_FALSE(frame.hasTTS(35));\n\t\tASSERT_TRUE(frame.hasTTS(50));\n\n\t\tASSERT_TRUE(frame.setTTS(46, TellTale::TTS_STATUS_RED));\n\t\tASSERT_TRUE(frame.setTTS(49, TellTale::TTS_STATUS_OFF));\n\t\tASSERT_TRUE(frame.setTTS(50, TellTale::TTS_STATUS_YELLOW));\n\t\tASSERT_TRUE(frame.setTTS(60, TellTale::TTS_STATUS_INFO));\n\n\t\tsize_t length = frame.getDataLength();\n\n\t\tu8 raw[] = {0x93, 0xFF, 0xA8, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF};\n\n\t\tu8 *buff = new u8[length];\n\n\t\tframe.encode(id, buff, length);\n\n\t\tASSERT_EQ(id, 0x14FD7D25);\n\t\tASSERT_EQ(memcmp(raw, buff, length), 0);\n\n\t\tdelete[] buff;\n\n\t}\n}\n\n\nTEST(FMS1Frame_test, decode) {\n\n\t{\n\t\tFMS1Frame frame;\n\t\tu32 id = 0x14FD7D35;\n\n\t\tu8 raw[] = {0xB0, 0xFF, 0x98, 0xFF, 0xFA, 0xFF, 0xFF, 0xFF};\n\n\t\tframe.decode(id, raw, sizeof(raw));\n\n\t\tASSERT_EQ(frame.getSrcAddr(), 0x35);\n\t\tASSERT_EQ(frame.getPriority(), 5);\n\n\t\tASSERT_EQ(frame.getBlockID(), 0);\n\n\t\tASSERT_EQ(frame.getTTS(5).getStatus(), TellTale::TTS_STATUS_RED);\n\t\tASSERT_EQ(frame.getTTS(4).getStatus(), TellTale::TTS_STATUS_OFF);\n\t\tASSERT_EQ(frame.getTTS(8).getStatus(), TellTale::TTS_STATUS_YELLOW);\n\t\tASSERT_EQ(frame.getTTS(1).getStatus(), TellTale::TTS_STATUS_INFO);\n\n\t}\n\n\t{\n\t\tFMS1Frame frame;\n\t\tu32 id = 0x04FD7D44;\n\n\t\tu8 raw[] = {0xF1, 0xFA, 0x9F, 0xF8, 0xFF, 0xFF, 0xFF, 0xBF};\n\n\t\tframe.decode(id, raw, sizeof(raw));\n\n\t\tASSERT_EQ(frame.getSrcAddr(), 0x44);\n\t\tASSERT_EQ(frame.getPriority(), 1);\n\n\t\tASSERT_EQ(frame.getBlockID(), 1);\n\n\t\tASSERT_EQ(frame.getTTS(20).getStatus(), TellTale::TTS_STATUS_RED);\n\t\tASSERT_EQ(frame.getTTS(21).getStatus(), TellTale::TTS_STATUS_OFF);\n\t\tASSERT_EQ(frame.getTTS(17).getStatus(), TellTale::TTS_STATUS_YELLOW);\n\t\tASSERT_EQ(frame.getTTS(30).getStatus(), TellTale::TTS_STATUS_INFO);\n\n\t}\n\n\t{\n\n\t\tFMS1Frame frame;\n\t\tu32 id = 0x1CFD7D36;\n\n\t\tu8 raw[] = {0xF2, 0xFF, 0x9F, 0xFF, 0xFF, 0xA8, 0xFF, 0xBF};\n\n\t\tframe.decode(id, raw, sizeof(raw));\n\n\t\tASSERT_EQ(frame.getSrcAddr(), 0x36);\n\t\tASSERT_EQ(frame.getPriority(), 7);\n\n\t\tASSERT_EQ(frame.getBlockID(), 2);\n\n\t\tASSERT_EQ(frame.getTTS(35).getStatus(), TellTale::TTS_STATUS_RED);\n\t\tASSERT_EQ(frame.getTTS(40).getStatus(), TellTale::TTS_STATUS_OFF);\n\t\tASSERT_EQ(frame.getTTS(41).getStatus(), TellTale::TTS_STATUS_YELLOW);\n\t\tASSERT_EQ(frame.getTTS(45).getStatus(), TellTale::TTS_STATUS_INFO);\n\n\t}\n\n\t{\n\n\t\tFMS1Frame frame;\n\t\tu32 id = 0x14FD7D25;\n\n\t\tu8 raw[] = {0x93, 0xFF, 0xA8, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF};\n\n\t\tframe.decode(id, raw, sizeof(raw));\n\n\t\tASSERT_EQ(frame.getSrcAddr(), 0x25);\n\t\tASSERT_EQ(frame.getPriority(), 5);\n\n\t\tASSERT_EQ(frame.getBlockID(), 3);\n\n\t\tASSERT_EQ(frame.getTTS(46).getStatus(), TellTale::TTS_STATUS_RED);\n\t\tASSERT_EQ(frame.getTTS(49).getStatus(), TellTale::TTS_STATUS_OFF);\n\t\tASSERT_EQ(frame.getTTS(50).getStatus(), TellTale::TTS_STATUS_YELLOW);\n\t\tASSERT_EQ(frame.getTTS(60).getStatus(), TellTale::TTS_STATUS_INFO);\n\n\t}\n\n}\n"
  },
  {
    "path": "Tests/genericframe_test.cpp",
    "content": "#include <gtest/gtest.h>\n\n#include <GenericFrame.h>\n#include <SPN/SPNNumeric.h>\n#include <SPN/SPNStatus.h>\n#include <SPN/SPNString.h>\n\nusing namespace J1939;\n\nclass GenericFrame_test : public testing::Test\n{\npublic:\n\tGenericFrame ccvs;\n\tGenericFrame vin;\n\tGenericFrame_test() : ccvs(0xFEF1), vin(0xFEEC) {}\n\nvirtual void SetUp()\n{\n\t//Create frame CCVS\n\n\tccvs.setName(\"CCVS\");\n\tccvs.setLength(8);\n\n\n\tSPNNumeric spnNum(84, \"Wheel Speed\", 1, 0.00390625, 0, 2, \"km/h\");\n\n\tccvs.registerSPN(spnNum);\n\n\t{\n\t\tSPNStatusSpec::DescMap valueToDesc;\n\t\tvalueToDesc[0] = \"Pedal Released\";\n\t\tvalueToDesc[1] = \"Pedal Depressed\";\n\t\tvalueToDesc[2] = \"Error\";\n\t\tvalueToDesc[3] = \"Not Available\";\n\n\t\tSPNStatus spnStat(597, \"Brake Switch\", 3, 4, 2, valueToDesc);\n\n\t\tccvs.registerSPN(spnStat);\n\t}\n\n\t{\n\n\t\tSPNStatusSpec::DescMap valueToDesc;\n\n\t\tvalueToDesc[0] = \"Pedal Released\";\n\t\tvalueToDesc[1] = \"Pedal Depressed\";\n\t\tvalueToDesc[2] = \"Error\";\n\t\tvalueToDesc[3] = \"Not Available\";\n\n\t\tSPNStatus spnStat(598, \"Clutch Switch\", 3, 6, 2, valueToDesc);\n\n\t\tccvs.registerSPN(spnStat);\n\t}\n\n\t{\n\n\t\tSPNStatusSpec::DescMap valueToDesc;\n\n\t\tvalueToDesc[0] = \"Off\";\n\t\tvalueToDesc[5] = \"Set\";\n\n\t\tSPNStatus spnStat(976, \"PTO State\", 6, 0, 5, valueToDesc);\n\n\n\t\tccvs.registerSPN(spnStat);\n\t}\n\n\tvin.setName(\"VIN\");\n\n\tSPNString vinSpn(237, \"Vehicle Number Identifier\");\n\n\tvin.registerSPN(vinSpn);\n\n}\n\nvirtual void TearDown()\n{\n}\n};\n\nTEST_F(GenericFrame_test, spn) {\n\n\tASSERT_TRUE(ccvs.hasSPN(84));\n\tASSERT_EQ(ccvs.getSPN(84)->getType(), SPN::SPN_NUMERIC);\n\tASSERT_TRUE(ccvs.hasSPN(597));\n\tASSERT_EQ(ccvs.getSPN(597)->getType(), SPN::SPN_STATUS);\n\tASSERT_TRUE(ccvs.hasSPN(598));\n\tASSERT_EQ(ccvs.getSPN(598)->getType(), SPN::SPN_STATUS);\n\tASSERT_TRUE(ccvs.hasSPN(976));\n\tASSERT_EQ(ccvs.getSPN(976)->getType(), SPN::SPN_STATUS);\n\n\tASSERT_TRUE(vin.hasSPN(237));\n\n\tASSERT_EQ(vin.getSPN(237)->getType(), SPN::SPN_STRING);\n\n}\n\nTEST_F(GenericFrame_test, encode) {\n\n\tSPNNumeric* wheelSpeed = static_cast<SPNNumeric*>(ccvs.getSPN(84));\n\n\twheelSpeed->setFormattedValue(50);\t\t//50 kph\n\n\t{\n\t\tSPNStatus* brakeSwitch = static_cast<SPNStatus*>(ccvs.getSPN(597));\n\n\t\tbrakeSwitch->setValue(2);\t\t//Error\n\t}\n\n\t{\n\t\tSPNStatus* clutchSwitch = static_cast<SPNStatus*>(ccvs.getSPN(598));\n\n\t\tclutchSwitch->setValue(1);\t\t//Pedal Depressed\n\t}\n\n\t{\n\t\tSPNStatus* ptoState = static_cast<SPNStatus*>(ccvs.getSPN(976));\n\n\t\tptoState->setValue(5);\t\t\t//Set\n\t}\n\n\tccvs.setSrcAddr(0x50);\n\tccvs.setPriority(7);\n\n\tu32 id;\n\tsize_t length = ccvs.getDataLength();\n\n\tASSERT_EQ(length, 8);\n\n\tu8* buff = new u8[length];\n\n\ttry {\n\t\tccvs.encode(id, buff, length);\t\t//Everything should work fine\n\t\tSUCCEED();\n\t} catch(J1939EncodeException &) {\n\t\tFAIL();\n\t}\n\n\tASSERT_EQ(id, 0x1CFEF150);\n\n\tu8 encodedCCVS[] = {0xFF, 0x00, 0x32, 0x6F, 0xFF, 0xFF, 0xE5, 0xFF};\n\n\tASSERT_EQ(memcmp(buff, encodedCCVS, length), 0);\n\n\ttry {\n\t\tsize_t length2 = 7;\n\t\tccvs.encode(id, buff, length2);\n\t\tFAIL();\n\t} catch(J1939EncodeException &) {\t\t//Length not enough\n\t\tSUCCEED();\n\t}\n\n\tdelete[] buff;\n\n\n\tSPNString* vinSpn = static_cast<SPNString*>(vin.getSPN(237));\n\n\tvinSpn->setValue(\"abcdefghjk1234\");\n\n\tlength = vin.getDataLength();\n\n\tASSERT_EQ(length, 15);\t\t//Size of string + '*' terminator\n\n\tvin.setSrcAddr(0x30);\n\tvin.setPriority(6);\n\n\tbuff = new u8[length];\n\n\ttry {\n\t\tvin.encode(id, buff, length);\t\t//Everything should work fine\n\t\tSUCCEED();\n\t} catch(J1939EncodeException &) {\n\t\tFAIL();\n\t}\n\n\tASSERT_EQ(id, 0x18FEEC30);\n\n\tASSERT_EQ(memcmp(buff, \"abcdefghjk1234*\", length), 0);\n\n\tdelete[] buff;\n\n}\n\n\nTEST_F(GenericFrame_test, decode) {\n\tu8 encodedCCVS[] = {0xFF, 0x00, 0x50, 0x9F, 0xFF, 0xFF, 0x1F, 0xFF};\n\tu32 id = 0x18FEF120;\n\n\ttry {\n\t\tccvs.decode(id, encodedCCVS, sizeof(encodedCCVS));\n\t\tSUCCEED();\n\t} catch (J1939DecodeException &) {\n\t\tFAIL();\n\t}\n\n\tASSERT_EQ(ccvs.getSrcAddr(), 0x20);\n\n\tASSERT_EQ(ccvs.getPriority(), 6);\n\n\tconst SPNNumeric* wheelSpeed = static_cast<SPNNumeric*>(ccvs.getSPN(84));\n\n\tASSERT_EQ(wheelSpeed->getFormattedValue(), 80);\n\n\t{\n\t\tconst SPNStatus* brakeSwitch = static_cast<SPNStatus*>(ccvs.getSPN(597));\n\n\t\tASSERT_EQ(brakeSwitch->getValue(), 1);\t\t//Error\n\t}\n\n\t{\n\t\tconst SPNStatus* clutchSwitch = static_cast<SPNStatus*>(ccvs.getSPN(598));\n\n\t\tASSERT_EQ(clutchSwitch->getValue(), 2);\t\t//Pedal Depressed\n\t}\n\n\t{\n\t\tconst SPNStatus* ptoState = static_cast<SPNStatus*>(ccvs.getSPN(976));\n\n\t\tASSERT_EQ(ptoState->getValue(), 0x1F);\t\t\t//Set\n\t}\n\n\n\tid = 0x18FEF320;\n\n\t//Throw exception if we try to decode an id whose PGN does not correspond to the PGN of the frame\n\ttry {\n\t\tccvs.decode(id, encodedCCVS, sizeof(encodedCCVS));\n\t\tFAIL();\n\t} catch (J1939DecodeException& e) {\n\t\tSUCCEED();\n\t}\n\n\tid = 0x04FEEC15;\n\n\ttry {\n\t\tvin.decode(id, (u8 *)(\"ghijklmnopqrs*\"), sizeof(\"ghijklmnopqrs*\"));\n\t\tSUCCEED();\n\t} catch (J1939DecodeException &) {\n\t\tFAIL();\n\t}\n\n\tASSERT_EQ(vin.getSrcAddr(), 0x15);\n\n\tASSERT_EQ(vin.getPriority(), 1);\n\n\tconst SPNString* vinSpn = static_cast<SPNString*>(vin.getSPN(237));\n\n\tASSERT_EQ(strncmp(vinSpn->getValue().c_str(), \"ghijklmnopqrs\", sizeof(\"ghijklmnopqrs\")), 0);\n\n}\n\n\n"
  },
  {
    "path": "Tests/include/TestFrame.h",
    "content": "#ifndef TESTFRAME_H_\n#define TESTFRAME_H_\n\n#include <J1939Frame.h>\n\n\nnamespace J1939 {\n\n\nclass TestFrame : public J1939Frame {\nprivate:\n\tstd::basic_string<u8> mRaw;\nprotected:\n\n\tvoid decodeData(const u8* buffer, size_t length) override;\n\n\tvoid encodeData(u8* buffer, size_t length) const  override;\n\npublic:\n\n\tTestFrame(u32 pgn) : J1939Frame(pgn) {}\n\tvirtual ~TestFrame() {}\n\n\tconst std::basic_string<u8> getRaw() const { return mRaw; }\n\n\tsize_t getDataLength() const override { return mRaw.size(); }\n\n\tIMPLEMENT_CLONEABLE(J1939Frame,TestFrame);\n};\n\n\n\n} /* namespace J1939 */\n\n#endif /* TESTFRAME_H_ */\n"
  },
  {
    "path": "Tests/j1939Factory_test.cpp",
    "content": "#include <gtest/gtest.h>\n\n#include <J1939Factory.h>\n#include <TestFrame.h>\n\nusing namespace J1939;\n\nclass J1939Factory_test : public testing::Test\n{\npublic:\n\n\tJ1939Factory_test() {}\n\nvirtual void SetUp()\n{\n\n\tTestFrame frame1(0xDE00);\n\tTestFrame frame2(0xAF00);\n\tTestFrame frame3(0xFEEF);\n\n\t//Now, our factory is able to build our custom frames\n\tJ1939Factory::getInstance().registerFrame(frame1);\n\tJ1939Factory::getInstance().registerFrame(frame2);\n\tJ1939Factory::getInstance().registerFrame(frame3);\n\n}\n\nvirtual void TearDown()\n{\n\n\t//Keep a clear state for the factory\n\tJ1939Factory::getInstance().unRegisterFrame(0xDE00);\n\tJ1939Factory::getInstance().unRegisterFrame(0xAF00);\n\tJ1939Factory::getInstance().unRegisterFrame(0xFEEF);\n\n}\n};\n\nTEST_F(J1939Factory_test, getJ1939Frame) {\n\n\tu32 id;\n\n\ttry {\n\n\t\t{\n\t\t\tid = 0x00DEAA50;\n\t\t\tu8 raw[] = {0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67, 0x89};\n\t\t\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(id, raw, sizeof(raw));\n\n\t\t\tASSERT_EQ(frame->getPGN(), 0xDE00);\n\t\t\tASSERT_EQ(frame->getSrcAddr(), 0x50);\n\t\t\tASSERT_EQ(frame->getDstAddr(), 0xAA);\n\n\t\t\tTestFrame *testFrame = static_cast<TestFrame*>(frame.get());\n\n\t\t\tASSERT_EQ(memcmp(raw, testFrame->getRaw().c_str(), sizeof(raw)), 0);\n\t\t}\n\n\t\t{\n\t\t\tid = 0x00AFCC60;\n\t\t\tu8 raw[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0x23, 0x45, 0x67, 0x89, 0x67, 0x89, 0x67, 0x89};\n\t\t\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(id, raw, sizeof(raw));\n\n\t\t\tASSERT_EQ(frame->getPGN(), 0xAF00);\n\t\t\tASSERT_EQ(frame->getSrcAddr(), 0x60);\n\t\t\tASSERT_EQ(frame->getDstAddr(), 0xCC);\n\n\t\t\tTestFrame *testFrame = static_cast<TestFrame*>(frame.get());\n\n\t\t\tASSERT_EQ(memcmp(raw, testFrame->getRaw().c_str(), sizeof(raw)), 0);\n\t\t}\n\n\t\t{\n\t\t\tid = 0x00FEEF40;\n\t\t\tu8 raw[] = {0xBA, 0xDC, 0xFE, 0x10, 0x32, 0x54, 0x76, 0x98, 0x67, 0xAA, 0xBB, 0xEE, 0xDD};\n\t\t\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(id, raw, sizeof(raw));\n\n\t\t\tASSERT_EQ(frame->getPGN(), 0xFEEF);\n\t\t\tASSERT_EQ(frame->getSrcAddr(), 0x40);\n\n\t\t\tTestFrame *testFrame = static_cast<TestFrame*>(frame.get());\n\n\t\t\tASSERT_EQ(memcmp(raw, testFrame->getRaw().c_str(), sizeof(raw)), 0);\n\n\t\t}\n\n\t} catch(J1939DecodeException &) {\n\t\tFAIL();\n\t}\n\n}\n"
  },
  {
    "path": "Tests/main.cpp",
    "content": "#include <gtest/gtest.h>\n\nint main(int argc, char **argv) {\n    testing::InitGoogleTest(&argc, argv);\n    return RUN_ALL_TESTS();\n}\n"
  },
  {
    "path": "Tests/request_frame.cpp",
    "content": "#include <gtest/gtest.h>\n\n#include <Frames/RequestFrame.h>\n\nusing namespace J1939;\n\nTEST(RequestFrame_test, encode) {\n\n\tRequestFrame frame(0xFE05);\n\tu32 id;\n\n\tframe.setSrcAddr(0x30);\n\tframe.setDstAddr(0x24);\n\tframe.setPriority(4);\n\n\tASSERT_EQ(frame.getDataLength(), 3);\n\tASSERT_EQ(frame.getRequestPGN(), 0xFE05);\n\n\tsize_t length = 3;\n\n\tu8 raw[] = {0x05, 0xFE, 0x00};\n\n\tu8 *buff = new u8[length];\n\n\tframe.encode(id, buff, length);\n\n\tASSERT_EQ(id, 0x10EA2430);\n\tASSERT_EQ(memcmp(raw, buff, length), 0);\n\n\tdelete[] buff;\n\n\tframe.setRequestPGN(0xBA00);\n\n\tASSERT_EQ(frame.getRequestPGN(), 0xBA00);\n\n\tu8 raw2[] = {0x00, 0xBA, 0x00};\n\n\tbuff = new u8[length];\n\n\tframe.encode(id, buff, length);\n\n\tASSERT_EQ(id, 0x10EA2430);\n\tASSERT_EQ(memcmp(raw2, buff, length), 0);\n\n\tdelete[] buff;\n\n}\n\n\nTEST(RequestFrame_test, decode) {\n\n\tRequestFrame frame;\n\tu32 id = 0x10EA5821;\n\n\t{\n\t\tu8 raw[] = {0x05, 0xFE, 0x00};\n\t\tframe.decode(id, raw, 3);\n\n\t\tASSERT_EQ(frame.getSrcAddr(), 0x21);\n\t\tASSERT_EQ(frame.getDstAddr(), 0x58);\n\t\tASSERT_EQ(frame.getPriority(), 4);\n\t\tASSERT_EQ(frame.getRequestPGN(), 0xFE05);\n\t}\n\n\n\t{\n\t\tu8 raw[] = {0x00, 0xBA, 0x00};\n\t\tframe.decode(id, raw, 3);\n\n\t\tASSERT_EQ(frame.getSrcAddr(), 0x21);\n\t\tASSERT_EQ(frame.getDstAddr(), 0x58);\n\t\tASSERT_EQ(frame.getPriority(), 4);\n\t\tASSERT_EQ(frame.getRequestPGN(), 0xBA00);\n\t}\n\n}\n"
  },
  {
    "path": "cmake/FindLibWebSockets.cmake",
    "content": "# This module tries to find libWebsockets library and include files\n#\n# LIBWEBSOCKETS_INCLUDE_DIR, path where to find libwebsockets.h\n# LIBWEBSOCKETS_LIBRARY_DIR, path where to find libwebsockets.so\n# LIBWEBSOCKETS_LIBRARIES, the library to link against\n# LIBWEBSOCKETS_FOUND, If false, do not try to use libWebSockets\n#\n# This currently works probably only for Linux\n\nFIND_PATH ( LIBWEBSOCKETS_INCLUDE_DIR libwebsockets.h\n    /usr/local/include\n    /usr/include\n)\n\nFIND_LIBRARY ( LIBWEBSOCKETS_LIBRARIES websockets\n    /usr/local/lib\n    /usr/lib\n)\n\nGET_FILENAME_COMPONENT( LIBWEBSOCKETS_LIBRARY_DIR ${LIBWEBSOCKETS_LIBRARIES} PATH )\n\nSET ( LIBWEBSOCKETS_FOUND \"NO\" )\nIF ( LIBWEBSOCKETS_INCLUDE_DIR )\n    IF ( LIBWEBSOCKETS_LIBRARIES )\n        SET ( LIBWEBSOCKETS_FOUND \"YES\" )\n    ENDIF ( LIBWEBSOCKETS_LIBRARIES )\nENDIF ( LIBWEBSOCKETS_INCLUDE_DIR )\n\nMARK_AS_ADVANCED(\n    LIBWEBSOCKETS_LIBRARY_DIR\n    LIBWEBSOCKETS_INCLUDE_DIR\n    LIBWEBSOCKETS_LIBRARIES\n)\n"
  },
  {
    "path": "cmake/J1939FrameworkConfig.cmake",
    "content": "include(\"${CMAKE_CURRENT_LIST_DIR}/J1939FrameworkTargets.cmake\")\nset(J1939_Database ${CMAKE_INSTALL_PREFIX}/etc/j1939/frames.json)\n"
  },
  {
    "path": "j1939AddressClaimer/AddressClaimer.cpp",
    "content": "/*\n * AddressClaimer.cpp\n *\n *  Created on: Jan 7, 2019\n *      Author: famez\n */\n\n#include <AddressClaimer.h>\n\n#include <Frames/RequestFrame.h>\n\n#include <Assert.h>\n\n#include <chrono>\n\n\nnamespace J1939 {\n\nAddressClaimer::AddressClaimer(const EcuName& name, const std::queue<u8>& preferred) : mEcuName(name), mPreferred(preferred) {\n\n\tASSERT(!preferred.empty());\n\n\tmThread = std::unique_ptr<std::thread>(new std::thread(&AddressClaimer::exec, this));\n\n}\n\nAddressClaimer::~AddressClaimer() {\n\tmThread->join();\n}\n\n\nbool AddressClaimer::toBeHandled(const J1939Frame& frame) {\n\n\tswitch(frame.getPGN()) {\n\n\tcase REQUEST_PGN: {\n\n\t\tconst RequestFrame &reqFrame = static_cast<const RequestFrame&>(frame);\n\n\t\tif(reqFrame.getRequestPGN() == ADDRESS_CLAIM_PGN)\t\treturn true;\n\n\t}\tbreak;\n\n\t//We could really know if this frame should be treated by this object,\n\t//but it would take more time to check and it is not worth it (check preferred address...)\n\tcase ADDRESS_CLAIM_PGN: {\t\t//The object will check in its own thread whether this frame should be treated.\n\n\t\treturn true;\n\n\t}\tbreak;\n\n\tdefault:\n\t\tbreak;\n\n\t}\n\n\treturn false;\n\n}\n\n\nvoid AddressClaimer::flush() {\n\n\tstd::unique_lock<std::mutex> lk(mMutex);\n\n\tmFrames.clear();\n\n}\n\nFrameSharedPtr AddressClaimer::read(u32 timeout) {\n\n\tstd::unique_lock<std::mutex> lk(mMutex);\n\n\tFrameSharedPtr retVal;\n\n\n\tif(mFrames.empty()) {\n\t\tmCondVar.wait_for(lk, std::chrono::milliseconds(timeout));\n\t}\n\n\tif(!mFrames.empty()) {\n\t\tretVal = mFrames.begin()->second;\n\t\tmFrames.erase(mFrames.begin());\n\t}\n\n\treturn retVal;\n\n}\n\nvoid AddressClaimer::receive(const J1939Frame& frame) {\n\n\tFrameSharedPtr frameSmartPtr(frame.clone());\n\n\tstd::unique_lock<std::mutex> lk(mMutex);\n\n\tmFrames[frame.getIdentifier()] = frameSmartPtr;\n\n\tmCondVar.notify_all();\n\n}\n\n\nbool AddressClaimer::claimAddressStep() {\n\n\n\tmCurrentSrc = J1939_INVALID_ADDRESS;\n\n\t//Notify that we do not have an available address\n\tonSrcAddrChanged(J1939_INVALID_ADDRESS);\n\n\tsize_t pos = 0;\n\n\tflush();\t\t\t//Avoid processing accumulated frames\n\n\twhile(pos++ < mPreferred.size()) {\n\n\t\t//Get the address to try\n\t\tu8 address = mPreferred.front();\n\n\t\t//Introduce again the address at the end of the queue\n\t\tmPreferred.pop();\n\t\tmPreferred.push(address);\n\n\t\tAddressClaimer::ClaimResult result;\n\n\t\t//Retry until result fails or succeeds\n\t\tdo {\n\t\t\tresult = tryObtainAddress(address);\n\n\t\t}\twhile(result == CLAIM_RETRY);\n\n\n\t\tif(result == CLAIM_ADDRESS_OBTAINED) {\t\t//Ok, we do not try anymore\n\t\t\treturn true;\n\t\t}\n\n\t}\n\n\t//We tried all the possible addresses and all of them failed\n\n\t//Send cannot claim address\n\tAddressClaimFrame frame(mEcuName);\n\n\tframe.setSrcAddr(J1939_INVALID_ADDRESS);\n\tframe.setDstAddr(J1939_BROADCAST_ADDRESS);\n\tsendFrame(frame);\n\n\treturn false;\n\n}\n\n\nAddressClaimer::ClaimResult AddressClaimer::tryObtainAddress(u8 address) {\n\n\n\tAddressClaimFrame addrClaim(mEcuName);\n\n\taddrClaim.setSrcAddr(address);\n\taddrClaim.setDstAddr(J1939_BROADCAST_ADDRESS);\n\n\tsendFrame(addrClaim);\n\n\ts32 timeToWait = 250; \t\t//Millis\n\tFrameSharedPtr frame;\n\n\tdo {\n\n\n\t\tauto start = std::chrono::steady_clock::now();\n\n\t\tframe = read(timeToWait);\n\n\n\t\tif(frame && frame->getPGN() == ADDRESS_CLAIM_PGN) {\n\n\t\t\tAddressClaimFrame *rcvFrame = static_cast<AddressClaimFrame*>(frame.get());\n\n\n\t\t\tif(rcvFrame->getSrcAddr() == addrClaim.getSrcAddr()) {\t\t//Contending frame!!\n\n\n\t\t\t\tif(addrClaim.getEcuName() < rcvFrame->getEcuName()) {\t\t//Win\n\n\n\t\t\t\t\treturn CLAIM_RETRY;\n\n\t\t\t\t} else {\t\t\t\t\t\t\t\t\t\t\t\t\t//Lose\n\n\n\t\t\t\t\treturn CLAIM_FAILED;\t\t//Check next preferred address if any\n\t\t\t\t}\n\n\t\t\t} else {\t\t\t\t\t\t\t//No contending frame\n\n\t\t\t\ttimeToWait = 250;\t\t\t\t//Reset time to wait\n\t\t\t\tcontinue;\n\n\t\t\t}\n\n\t\t}\n\n\t\tauto end = std::chrono::steady_clock::now();\n\n\t\tstd::chrono::milliseconds elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);\n\n\t\ttimeToWait -= elapsed.count();\n\n\t} while(timeToWait > 0 && frame);\n\n\n\t//Notify the new address ready to use\n\tmCurrentSrc = address;\t\t\t//Timeout ok\n\tonSrcAddrChanged(address);\n\treturn CLAIM_ADDRESS_OBTAINED;\n\n}\n\nvoid AddressClaimer::exec() {\n\n\n\twhile(true) {\n\n\t\tclaimAddressStep();\n\n\n\t\tbool conflict = false;\n\n\t\twhile(!conflict) {\n\n\t\t\tFrameSharedPtr frame = read(5000);\n\n\t\t\tif(frame) {\n\n\t\t\t\tswitch(frame->getPGN()) {\n\t\t\t\tcase REQUEST_PGN: {\n\t\t\t\t\tRequestFrame *reqFrame = static_cast<RequestFrame*>(frame.get());\n\n\t\t\t\t\tif((reqFrame->getRequestPGN() == ADDRESS_CLAIM_PGN) &&\n\t\t\t\t\t\t\t((reqFrame->getDstAddr() == J1939_BROADCAST_ADDRESS) || (reqFrame->getDstAddr() == mCurrentSrc))) {\n\n\t\t\t\t\t\t//Send claim address\n\t\t\t\t\t\tAddressClaimFrame frame(mEcuName);\n\t\t\t\t\t\tframe.setSrcAddr(mCurrentSrc);\n\t\t\t\t\t\tframe.setDstAddr(J1939_BROADCAST_ADDRESS);\n\t\t\t\t\t\tsendFrame(frame);\n\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase ADDRESS_CLAIM_PGN: {\n\n\t\t\t\t\tAddressClaimFrame *rcvFrame = static_cast<AddressClaimFrame*>(frame.get());\n\n\t\t\t\t\tif(rcvFrame->getSrcAddr() != J1939_INVALID_ADDRESS && rcvFrame->getSrcAddr() == mCurrentSrc) {\t\t//Contending frame!!\n\n\n\t\t\t\t\t\tif(mEcuName < rcvFrame->getEcuName()) {\t\t\t\t\t\t//Win\n\n\t\t\t\t\t\t\t//Send claim address\n\t\t\t\t\t\t\tAddressClaimFrame frame(mEcuName);\n\t\t\t\t\t\t\tframe.setSrcAddr(mCurrentSrc);\n\t\t\t\t\t\t\tframe.setDstAddr(J1939_BROADCAST_ADDRESS);\n\t\t\t\t\t\t\tsendFrame(frame);\n\n\t\t\t\t\t\t} else {\t\t\t\t\t\t\t\t\t\t\t\t\t//Lose\n\t\t\t\t\t\t\t//Come back to claimAddressStep\n\t\t\t\t\t\t\tconflict = true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t}\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\n\t\t}\n\n\n\t}\n\n}\n\n} /* namespace J1939 */\n"
  },
  {
    "path": "j1939AddressClaimer/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.5)\n\nproject(J1939AddressClaimer)\n\nadd_library(J1939AddressClaimer SHARED \n    \t./AddressClaimer.cpp\n)\n\ntarget_include_directories(J1939AddressClaimer\n    PUBLIC \n        include ${J1939_SOURCE_DIR}/include ${Common_SOURCE_DIR}/include\n)\n\ntarget_link_libraries(J1939AddressClaimer\n    PUBLIC\n        J1939 pthread\n)\n\n\ninstall (TARGETS J1939AddressClaimer\n    LIBRARY DESTINATION lib)\n\n\ninstall(DIRECTORY include/ \n    DESTINATION include\n)\n\n"
  },
  {
    "path": "j1939AddressClaimer/include/AddressClaimer.h",
    "content": "/*\n * AddressClaimer.h\n *\n *  Created on: Jan 7, 2019\n *      Author: famez\n */\n\n#ifndef ADDRESSCLAIMER_H_\n#define ADDRESSCLAIMER_H_\n\n#include <map>\n#include <queue>\n\n#include <memory>\n\n//Threading\n#include <thread>\n#include <mutex>\n#include <condition_variable>\n\n#include <Types.h>\n\n#include <J1939Common.h>\n#include <Addressing/AddressClaimFrame.h>\n\n\n\nnamespace J1939 {\n\nclass J1939Frame;\nclass EcuName;\n\ntypedef std::shared_ptr<J1939Frame> FrameSharedPtr;\n\n\nclass AddressClaimer {\nprivate:\n\n\tenum ClaimResult {\n\t\tCLAIM_ADDRESS_OBTAINED,\n\t\tCLAIM_RETRY,\n\t\tCLAIM_FAILED,\n\t};\n\n\n\tstd::map<u32/*id*/, FrameSharedPtr> mFrames;\n\n\tstd::unique_ptr<std::thread> mThread = nullptr;\n\tstd::mutex mMutex;\n\tstd::condition_variable mCondVar;\n\n\tstd::queue<u8> mPreferred;\n\tEcuName mEcuName;\n\n\tu8 mCurrentSrc = J1939_INVALID_ADDRESS;\n\n\tFrameSharedPtr read(u32 timeout);\n\n\tvoid flush();\n\n\tClaimResult tryObtainAddress(u8 address);\n\n\t/*\n\t * Returns true if success, otherwise false.\n\t */\n\tbool claimAddressStep();\n\n\t/**\n\t * Starts the machine state in a thread\n\t */\n\n\tvoid exec();\n\n\t//Methods to override by the inherited class\n\nprotected:\n\tvirtual void onSrcAddrChanged(u8 newAddr) = 0;\n\tvirtual void sendFrame(const J1939Frame&) = 0;\n\npublic:\n\tAddressClaimer(const EcuName& name, const std::queue<u8>& preferred);\n\tvirtual ~AddressClaimer();\n\tbool toBeHandled(const J1939Frame& frame);\n\n\t/**\n\t * This method does not take the ownership of the frame passed as argument.\n\t */\n\tvoid receive(const J1939Frame& frame);\n\n};\n\n} /* namespace J1939 */\n\n#endif /* ADDRESSCLAIMER_H_ */\n"
  },
  {
    "path": "wireshark/dissector/CMakeLists.txt",
    "content": "# CMakeLists.txt\n#\n# Wireshark - Network traffic analyzer\n# By Gerald Combs <gerald@wireshark.org>\n# Copyright 1998 Gerald Combs\n#\n# SPDX-License-Identifier: GPL-2.0-or-later\n#\n\ncmake_minimum_required(VERSION 3.5)\n\ninclude(WiresharkPlugin)\n\nfind_package(J1939Framework REQUIRED)\n\nadd_definitions(-DDATABASE_PATH=\"${J1939_Database}\")\n\n# Plugin name and version info (major minor micro extra)\nset_module_info(j1939 0 0 1 0)\n\nset(DISSECTOR_SRC\n\tpacket-j1939.cpp\n)\n\nset(PLUGIN_FILES\n\tplugin.c\n\t${DISSECTOR_SRC}\n)\n\nset_source_files_properties(\n\t${PLUGIN_FILES}\n\tPROPERTIES\n\tCOMPILE_FLAGS \"${WERROR_COMMON_FLAGS}\"\n)\n\nset (CMAKE_CXX_STANDARD 11)\n\ninclude_directories(${CMAKE_CURRENT_SOURCE_DIR})\n\nregister_plugin_files(plugin.c\n\tplugin\n\t${DISSECTOR_SRC}\n)\n\nadd_plugin_library(j1939 epan)\n\ntarget_link_libraries(j1939 epan J1939 -rdynamic)\n\ninstall_plugin(j1939 epan)\n\nfile(GLOB DISSECTOR_HEADERS RELATIVE \"${CMAKE_CURRENT_SOURCE_DIR}\" \"*.h\")\nCHECKAPI(\n\tNAME\n\t  j1939\n\tSWITCHES\n\t  -g abort -g termoutput -build\n\tSOURCES\n\t  ${DISSECTOR_SRC}\n\t  ${DISSECTOR_HEADERS}\n)\n\n#\n# Editor modelines  -  http://www.wireshark.org/tools/modelines.html\n#\n# Local variables:\n# c-basic-offset: 8\n# tab-width: 8\n# indent-tabs-mode: t\n# End:\n#\n# vi: set shiftwidth=8 tabstop=8 noexpandtab:\n# :indentSize=8:tabSize=8:noTabs=false:\n#\n"
  },
  {
    "path": "wireshark/dissector/Readme.md",
    "content": "### J1939 Dissector for wireshark\n\n#### To install the plugin\n\n```\nsudo apt-get install glib2.0 libgcrypt11-dev qt5-default qttools5-dev qtdeclarative5-dev qtmultimedia5-dev libqt5svg5-dev \n```\n\n- Install the J1939 framework as explained in the README.md at the top level of the repository.\n- Download and extract the source code of wireshark located in https://www.wireshark.org/download/src/. Minimum version 3.0.1.\n- Copy the folder in which this README.md file is located into the following path inside the wireshark source code (creating the folder j1939): **plugins/epan/j1939/**\n- Modify the file CMakeListsCustoms.txt located in the root of the wireshark source code as follows:\n\n```\nset(CUSTOM_PLUGIN_SRC_DIR\nplugins/epan/j1939\n)\n```\n\n\n- Configure (using **CMake**), build and install wireshark from the source code:\n```bash\ncd **wireshark source code**\ncmake .\ncd plugins/epan/j1939/\nmake && sudo make install\n```\n\n\n\n![alt text](https://github.com/famez/J1939-Framework/blob/master/wireshark/dissector/J1939-plugin.png)\n"
  },
  {
    "path": "wireshark/dissector/packet-j1939.cpp",
    "content": "extern \"C\" {\n\n#include \"config.h\"\n\n#include <epan/packet.h>\n#include <epan/address_types.h>\n#include <wsutil/pint.h>\n\n\n\n//For BAM reassemble\n#include <epan/reassemble.h>\n\nvoid proto_register_j1939(void);\nvoid proto_reg_handoff_j1939(void);\n\n}\n\n#include <iostream>\n#include <J1939Factory.h>\n#include <J1939Frame.h>\n#include <J1939DataBase.h>\n#include <GenericFrame.h>\n#include <SPN/SPNNumeric.h>\n#include <SPN/SPNStatus.h>\n#include <SPN/SPNString.h>\n#include <Transport/BAM/BamReassembler.h>\n#include <FMS/TellTale/FMS1Frame.h>\n#include <Diagnosis/Frames/DM1.h>\n\n\n#ifndef DATABASE_PATH\n#define DATABASE_PATH\t\t\"/etc/j1939/frames.json\"\n#endif\n\n\nusing namespace J1939;\n\nint dissect_J1939(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data);\nvoid dissect_generic_frame(tvbuff_t *tvb, proto_tree *j1939_tree, proto_item *ti, GenericFrame *genFrame);\nvoid dissect_fms1_frame(tvbuff_t *tvb, proto_tree *j1939_tree, proto_item *ti, const FMS1Frame *fms1Frame);\nvoid dissect_dm1_frame(tvbuff_t *tvb, proto_tree *j1939_tree, proto_item *ti, const DM1 *dm1Frame);\n\n\nstatic int hf_j1939_frame = -1;\nstatic int hf_j1939_spn = -1;\nstatic int hf_j1939_dtc = -1;\nstatic int hf_j1939_fmi = -1;\nstatic int hf_j1939_oc = -1;\n\nstatic int hf_j1939_blockId = -1;\n\nstatic int proto_j1939 = -1;\nstatic gint ett_j1939 = -1;\nstatic gint ett_j1939_can = -1;\nstatic gint ett_j1939_dtc = -1;\nstatic gint ett_j1939_message = -1;\n\n\nstatic gint ett_bam_fragment = -1;\nstatic gint ett_bam_fragments = -1;\nstatic gint hf_bam_fragments = -1;\nstatic gint hf_bam_fragment = -1;\nstatic gint hf_bam_fragment_overlap = -1;\nstatic gint hf_bam_fragment_overlap_conflict = -1;\nstatic gint hf_bam_fragment_multiple_tails = -1;\nstatic gint hf_bam_fragment_too_long_fragment = -1;\nstatic gint hf_bam_fragment_error = -1;\nstatic gint hf_bam_fragment_count = -1;\nstatic gint hf_bam_reassembled_in = -1;\nstatic gint hf_bam_reassembled_length = -1;\nstatic gint hf_bam_reassembled_data = -1;\n\nstatic dissector_handle_t j1939_handle;\n\nstatic reassembly_table bam_reassembly_table;\n\n\nstatic const fragment_items bam_frag_items = {\n  &ett_bam_fragment,\n  &ett_bam_fragments,\n  &hf_bam_fragments,\n  &hf_bam_fragment,\n  &hf_bam_fragment_overlap,\n  &hf_bam_fragment_overlap_conflict,\n  &hf_bam_fragment_multiple_tails,\n  &hf_bam_fragment_too_long_fragment,\n  &hf_bam_fragment_error,\n  &hf_bam_fragment_count,\n  &hf_bam_reassembled_in,\n  &hf_bam_reassembled_length,\n  &hf_bam_reassembled_data,\n  \"BAM fragments\"\n};\n\n\nstatic const value_string tts_status[] = {\n    { 0, \"Off\" },\n    { 1, \"Red\" },\n    { 2, \"Yellow\" },\n\t{ 3, \"Info\" },\n\t{ 7, \"Not available\" }\n};\n\nBamReassembler bamReassembler;\n\nstd::map<u32/*SPN number*/, int/*header_field_info.id*/> spnNumToHinfoId;\nstd::map<u32/*TTS number*/, int/*header_field_info.id*/> ttsNumToHinfoId;\n\nvoid proto_register_j1939(void) {\n\n\tstatic hf_register_info hf[] = {\n\t\t{ &hf_j1939_frame,\n\t\t\t{\"Frame\", \"j1939.frame\",\n\t\t\t\t\tFT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }\n\t\t},\n\t\t{ &hf_j1939_spn,\n\t\t\t{\"Spn\", \"j1939.spn\",\n\t\t\t\t\tFT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }\n\t\t},\n\t\t{ &hf_j1939_dtc,\n\t\t\t{\"Diagnosis Trouble Code\", \"j1939.dtc\",\n\t\t\t\t\tFT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }\n\t\t},\n\t\t{ &hf_j1939_oc,\n\t\t\t{\"Ocurrence Count\", \"j1939.oc\",\n\t\t\t\t\tFT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }\n\t\t},\n\t\t{ &hf_j1939_fmi,\n\t\t\t{\"Failure Mode Identifier\", \"j1939.fmi\",\n\t\t\t\t\tFT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }\n\t\t},\n\t\t{ &hf_j1939_blockId,\n\t\t\t{\"Block ID\", \"j1939.fms1.blockId\",\n\t\t\t\t\tFT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }\n\t\t},\n\t\t{ &hf_bam_fragment_overlap,\n\t\t\t      { \"Fragment overlap\", \"bam.fragment.overlap\", FT_BOOLEAN, BASE_NONE,\n\t\t\t        NULL, 0x0, \"Fragment overlaps with other fragments\", HFILL }},\n\n\t\t{ &hf_bam_fragment_overlap_conflict,\n\t\t  { \"Conflicting data in fragment overlap\", \"bam.fragment.overlap.conflict\",\n\t\t\tFT_BOOLEAN, BASE_NONE, NULL, 0x0,\n\t\t\t\"Overlapping fragments contained conflicting data\", HFILL }},\n\n\t\t{ &hf_bam_fragment_multiple_tails,\n\t\t  { \"Multiple tail fragments found\", \"bam.fragment.multipletails\",\n\t\t\tFT_BOOLEAN, BASE_NONE, NULL, 0x0,\n\t\t\t\"Several tails were found when defragmenting the packet\", HFILL }},\n\n\t\t{ &hf_bam_fragment_too_long_fragment,\n\t\t  { \"Fragment too long\", \"bam.fragment.toolongfragment\",\n\t\t\tFT_BOOLEAN, BASE_NONE, NULL, 0x0,\n\t\t\t\"Fragment contained data past end of packet\", HFILL }},\n\n\t\t{ &hf_bam_fragment_error,\n\t\t  { \"Defragmentation error\", \"bam.fragment.error\", FT_FRAMENUM, BASE_NONE,\n\t\t\tNULL, 0x0, \"Defragmentation error due to illegal fragments\", HFILL }},\n\n\t\t{ &hf_bam_fragment_count,\n\t\t  { \"Fragment count\", \"bam.fragment.count\", FT_UINT32, BASE_DEC,\n\t\t\tNULL, 0x0, NULL, HFILL }},\n\n\t\t{ &hf_bam_fragment,\n\t\t  { \"BAM Fragment\", \"bam.fragment\", FT_FRAMENUM, BASE_NONE,\n\t\t\tNULL, 0x0, NULL, HFILL }},\n\n\t\t{ &hf_bam_fragments,\n\t\t  { \"BAM Fragments\", \"bam.fragments\", FT_BYTES, BASE_NONE,\n\t\t\tNULL, 0x0, NULL, HFILL }},\n\n\t\t{ &hf_bam_reassembled_in,\n\t\t  { \"Reassembled BAM in frame\", \"bam.reassembled_in\", FT_FRAMENUM, BASE_NONE,\n\t\t  NULL, 0x0, \"This BAM packet is reassembled in this frame\", HFILL }},\n\n\t\t{ &hf_bam_reassembled_length,\n\t\t  { \"Reassembled BAM length\", \"bam.reassembled.length\", FT_UINT32, BASE_DEC,\n\t\t\tNULL, 0x0, \"The total length of the reassembled payload\", HFILL }},\n\n\t\t{ &hf_bam_reassembled_data,\n\t\t  { \"Reassembled BAM data\", \"bam.reassembled.data\", FT_BYTES, BASE_NONE,\n\t\t\tNULL, 0x0, \"The reassembled payload\", HFILL }}\n\t};\n\n\tstatic gint *ett[] = {\n\t\t&ett_j1939,\n\t\t&ett_j1939_can,\n\t\t&ett_j1939_dtc,\n\t\t&ett_j1939_message,\n\t\t&ett_bam_fragment,\n\t\t&ett_bam_fragments\n\t};\n\n\treassembly_table_register(&bam_reassembly_table,\n\t                        &addresses_reassembly_table_functions);\n\n\tproto_j1939 = proto_register_protocol(\"j1939framework Protocol\",\n\t\t\t\t\t\t\t\t\t\t\t\"j1939framework\",\n\t\t\t\t\t\t\t\t\t\t\t\"j1939framework\");\n\n\tproto_register_field_array(proto_j1939, hf, array_length(hf));\n\tproto_register_subtree_array(ett, array_length(ett));\n\n}\n\nvoid proto_reg_handoff_j1939(void) {\n\n\n\tj1939_handle = create_dissector_handle( dissect_J1939, proto_j1939 );\n\n\t//Load database\n\tJ1939DataBase ddbb;\n\tif(!ddbb.parseJsonFile(DATABASE_PATH)) {\t\t//Something went wrong\n\t\treturn;\n\t}\n\n\tconst std::vector<GenericFrame>& ddbbFrames = ddbb.getParsedFrames();\n\n\n\t//Register all the frames listed in the database\n\tfor(auto iter = ddbbFrames.begin(); iter != ddbbFrames.end(); ++iter) {\n\n\t\tJ1939Factory::getInstance().registerFrame(*iter);\n\n\t}\n\n\theader_field_info* info;\n\tstd::string abbrev;\n\tstd::string tts_name;\n\n\tfor(unsigned int tts = 1; tts <= NUMBER_OF_BLOCKS * TTSS_PER_BLOCK; ++tts) {\n\n\t\tinfo = (header_field_info*)g_malloc0(sizeof(header_field_info));\n\n\t\tinfo->id = -1;\n\t\tinfo->ref_type = HF_REF_TYPE_NONE;\n\t\tinfo->same_name_prev_id = -1;\n\n\t\tabbrev = std::string(\"j1939.tts.\") + std::to_string(tts);\n\t\ttts_name = std::string(\"TTS \") + std::to_string(tts) + std::string(\" Status\");\n\n\t\tinfo->name = g_strdup(tts_name.c_str());\n\t\tinfo->abbrev = g_strdup(abbrev.c_str());\n\n\t\tinfo->type = FT_UINT8;\n\t\tinfo->display = BASE_DEC;\n\n\t\tinfo->strings = VALS(tts_status);\n\n\t\tinfo->bitmask = 0x7;\n\n\t\tif((((tts - 1) % TTSS_PER_BLOCK) % 2) == 0) {\t\t\t\t//If TTS number is even, the bitmask corresponds to the 4 most significant bits. Otherwise, it corresponds to the 4 least significant bits.\n\t\t\tinfo->bitmask <<= 4;\n\t\t}\n\n\t\tproto_register_fields_section(proto_j1939, info, 1);\n\n\t\tttsNumToHinfoId[tts] = info->id;\n\n\t}\n\n\tstd::set<u32> pgns = J1939Factory::getInstance().getAllRegisteredPGNs();\n\n\t\n\n\t//Register dissectors for all the known frames\n\tfor(auto pgn = pgns.begin(); pgn != pgns.end(); ++pgn) {\n\n\t\tdissector_add_uint(\"j1939.pgn\", *pgn, j1939_handle);\n\n\t\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(*pgn);\n\n\t\tif(!frame->isGenericFrame()) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tGenericFrame *genFrame = static_cast<GenericFrame *>(frame.get());\n\n\t\t//Also, we have to register SPN specific fields\n\t\tstd::set<u32> spnNumbers = genFrame->getSPNNumbers();\n\n\t\tfor(auto spnNumber = spnNumbers.begin(); spnNumber != spnNumbers.end(); ++spnNumber) {\n\n\t\t\tconst SPN* spn = genFrame->getSPN(*spnNumber);\n\n\t\t\tinfo = (header_field_info*)g_malloc0(sizeof(header_field_info));\n\n\t\t\tinfo->id = -1;\n\t\t\tinfo->ref_type = HF_REF_TYPE_NONE;\n\t\t\tinfo->same_name_prev_id = -1;\n\n\t\t\tabbrev = std::string(\"j1939.spn.\") + std::to_string(*spnNumber);\n\n\t\t\tinfo->name = g_strdup(spn->getName().c_str());\n\t\t\tinfo->abbrev = g_strdup(abbrev.c_str());\n\n\t\t\tswitch(spn->getType()) {\n\n\t\t\tcase SPN::SPN_STATUS: {\n\n\t\t\t\tinfo->type = FT_UINT8;\n\t\t\t\tinfo->display = BASE_DEC;\n\n\t\t\t}\tbreak;\n\n\t\t\tcase SPN::SPN_NUMERIC: {\n\n\t\t\t\tinfo->type = FT_DOUBLE;\n\t\t\t\tinfo->display = BASE_NONE;\n\n\t\t\t}\tbreak;\n\n\t\t\tcase SPN::SPN_STRING: {\n\n\t\t\t\tinfo->type = FT_STRING;\n\t\t\t\tinfo->display = BASE_NONE;\n\n\t\t\t}\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t\tproto_register_fields_section(proto_j1939, info, 1);\n\n\t\t\tspnNumToHinfoId[*spnNumber] = info->id;\n\n\t\t}\n\n\n\n\t}\n\n}\n\n\nint dissect_J1939(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void*) {\n\n\n\tproto_item *ti;\n\tproto_tree *j1939_tree;\n\n\t//Get the buffer from the upper layer so that we can obtain the ID for the Can Frame\n\ttvbuff_t *canIdTvb = tvb_get_ds_tvb(tvb);\n\t\n\t//Obtain the length of the concerning frame\n\tguint32 data_length = tvb_reported_length(tvb);\n\n\t//Allocate a buffer where to store the DLC (payload of the can frame)\n\tguint8* content = (guint8*)wmem_alloc(pinfo->pool, data_length);\n\n\t//Obtain the can id\n\t\n\tguint32 canId;\n\n\tif(tvb_reported_length(canIdTvb) >= 20) {\t\t//Not reassembled frames\n\t\tguint32 leCanId = tvb_get_ntohl(canIdTvb, 0x10);\n\t\tcanId = (leCanId >> 24) | ((leCanId >> 8)&0xFF00) | ((leCanId << 8)&0xFF0000) | ((leCanId << 24) &0xFF000000);\n\t} else if(tvb_reported_length(canIdTvb) >= 4) {\t\t//For reassembled frames\n\t\tcanId = tvb_get_ntohl(canIdTvb, 0);\n\t} else {\n\t\tstd::cout << \"tvb buffer too short\" << std::endl;\n\t\treturn -1;\t\n\t}\n\n\tcanId &= 0x1FFFFFFF;\n\t\n\t\n\t\n\t//Obtain the payload of the Can Frame\n\ttvb_memcpy(tvb, content, 0, data_length);\n\n\t//Generate the frame from the frame factory. As arguments, we pass the ID, the data and the length.\n\tstd::unique_ptr<J1939Frame> frame = J1939Factory::getInstance().getJ1939Frame(canId, content, data_length);\n\n\n\tif(!frame.get()) {\t\t\t//Bad decoding...\n\t\tstd::cout << \"dissect_J1939 error\" << std::endl;\n\t\treturn -1;\n\t}\n\n\tcol_set_str(pinfo->cinfo, COL_PROTOCOL, \"J1939\");\n\tcol_clear(pinfo->cinfo, COL_INFO);\n\n\t//In the info column, publish the name of the frame\n\tcol_add_fstr(pinfo->cinfo, COL_INFO, \"Frame: %s\", frame->getName().c_str());\n\n\t//Add item to the tree with the name of the frame\n\tti = proto_tree_add_string(tree, hf_j1939_frame, canIdTvb, 1, 2, frame->getName().c_str());\n\tj1939_tree = proto_item_add_subtree(ti, ett_j1939);\n\n\tif(frame->getPGN() == DM1_PGN) {\n\t\tDM1 *dm1Frame = static_cast<DM1 *>(frame.get());\n\n\t\tdissect_dm1_frame(tvb, j1939_tree, ti, dm1Frame);\n\t}\n\n\n\tif(frame->isGenericFrame()) {\t\t//If the frame is a generic frame (this means that it contains several defined SPNs), call a proper function to handle it\n\t\tGenericFrame * genFrame = (GenericFrame *)(frame.get());\n\t\tdissect_generic_frame(tvb, j1939_tree, ti, genFrame);\n\n\n\t} else if(bamReassembler.toBeHandled(*frame)) {\t\t//This frame is part of BAM protocol\n\n\n\t\tif(tvb_get_guint8(canIdTvb, 1) == 1) {\n\t\t\treturn 0;\t\t//Broadcast frames are not reassembled\n\t\t}\n\n\t\t//We let our reassembler to handle them\n\t\tguint expected_size = 0;\n\n\t\tfragment_head *bam_head = NULL;\n\n\t\ttvbuff_t *def_tvb = NULL;\n\t\ttvbuff_t *next_tvb;\n\n\t\tguint sq = 0;\n\t\tgboolean update_col_info = TRUE;\n\t\tguint32 frag_data_len = 0;\n\n\t\tif(!pinfo->fd->visited) {\t\t//Only treat the frames if it is the first time we see them!!!\n\n\t\t\ttry {\n\n\t\t\t\texpected_size = bamReassembler.handleFrame(*frame);\n\n\t\t\t} catch(J1939EncodeException &) {\n\n\t\t\t\treturn -1;\n\n\t\t\t}\n\n\n\t\t\tswitch(frame->getPGN()) {\n\n\t\t\tcase TP_CM_PGN: {\n\n\t\t\t\tTPCMFrame *connFrame = (TPCMFrame *)(frame.get());\n\n\t\t\t\tguint8 *canIdTVBData = (guint8 *)g_malloc(sizeof(guint32));\n\n\t\t\t\tguint32 realCanId = (connFrame->getPriority() << J1939_PRIORITY_OFFSET)\n\t\t\t\t\t\t| (connFrame->getDataPgn() << J1939_PGN_OFFSET)\n\t\t\t\t\t\t| (connFrame->getSrcAddr() << J1939_SRC_ADDR_OFFSET);\n\n\n\t\t\t\tfrag_data_len = sizeof(guint32);\n\n\t\t\t\tphton32(canIdTVBData, realCanId);\n\n\t\t\t\tdef_tvb = tvb_new_real_data(canIdTVBData, frag_data_len, frag_data_len);\n\n\t\t\t\ttvb_set_free_cb(def_tvb, g_free);\n\n\t\t\t}\tbreak;\n\n\n\t\t\tcase TP_DT_PGN: {\n\n\t\t\t\tTPDTFrame *dataFrame = (TPDTFrame *)(frame.get());\n\n\t\t\t\tsq = dataFrame->getSq();\n\n\t\t\t\tfrag_data_len = TP_DT_PACKET_SIZE;\n\n\t\t\t\tgint trailing_bytes = TP_DT_PACKET_SIZE * sq - expected_size;\n\n\t\t\t\tif(trailing_bytes >= TP_DT_PACKET_SIZE) {\n\t\t\t\t\treturn -1;\n\t\t\t\t}\n\n\t\t\t\tif(trailing_bytes > 0) {\n\t\t\t\t\tfrag_data_len -= trailing_bytes;\n\t\t\t\t}\n\n\t\t\t\tdef_tvb = tvb_new_subset_remaining(tvb, 1);\n\n\n\t\t\t}\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t}\n\n\n\t\tbam_head = fragment_add_seq_check(&bam_reassembly_table, def_tvb, 0,\n\t\t   pinfo, 0,\n\t\t   NULL, sq,\n\t\t   frag_data_len, !bamReassembler.reassembledFramesPending());\n\n\n\t\tif(bamReassembler.reassembledFramesPending()) {\n\t\t\tbamReassembler.dequeueReassembledFrame();\n\t\t}\n\n\t\tnext_tvb = process_reassembled_data(tvb, 0, pinfo, \"Reassembled BAM\",\n\t\t\t\t\tbam_head, &bam_frag_items, &update_col_info, j1939_tree);\n\n\n\t\tif(next_tvb) {\n\n\t\t\tcall_dissector(j1939_handle, tvb_new_subset_remaining(next_tvb, sizeof(guint32)),\n\t\t\t\t    pinfo, j1939_tree);\n\t\t}\n\n\t} else {\t\t//Another type of frame than the generic ones and the ones that belong to BAM protocol\n\n\t\tswitch(frame->getPGN()) {\n\t\tcase FMS1_PGN:\n\t\t{\n\n\t\t\tFMS1Frame* fms1 = (FMS1Frame *)(frame.get());\n\n\t\t\tdissect_fms1_frame(tvb, j1939_tree, ti, fms1);\n\n\t\t}\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn tvb_captured_length(tvb);\n\n}\n\nvoid dissect_generic_frame(tvbuff_t *tvb, proto_tree *j1939_tree, proto_item *ti, GenericFrame * genFrame) {\n\n\tproto_tree *spn_tree;\n\tstd::set<guint32> spnNumbers = genFrame->getSPNNumbers();\n\n\tfor(auto iter = spnNumbers.begin(); iter != spnNumbers.end(); ++iter) {\n\n\t\tconst SPN *spn = genFrame->getSPN(*iter);\n\n\t\tti = proto_tree_add_uint(j1939_tree, hf_j1939_spn, tvb, spn->getOffset(), spn->getByteSize(), *iter);\n\t\tspn_tree = proto_item_add_subtree(ti, ett_j1939_can);\n\n\t\tswitch(spn->getType()) {\n\t\tcase SPN::SPN_NUMERIC: {\n\t\t\tconst SPNNumeric *spnNum = (SPNNumeric *)(spn);\n\n\t\t\tti = proto_tree_add_double_format(spn_tree, spnNumToHinfoId[*iter], tvb, spn->getOffset(),\n\t\t\t\t\tspnNum->getByteSize(), spnNum->getFormattedValue(), \"%s: %.10g %s\",\n\t\t\t\t\tspn->getName().c_str(), spnNum->getFormattedValue(), spnNum->getUnits().c_str());\n\n\t\t}\tbreak;\n\t\tcase SPN::SPN_STATUS: {\n\n\t\t\tconst SPNStatus *spnStatus = (SPNStatus *)(spn);\n\n\t\t\tti = proto_tree_add_uint_bits_format_value(spn_tree, spnNumToHinfoId[*iter], tvb,\n\t\t\t\t\t(spn->getOffset() << 3) + 8 - spnStatus->getBitOffset() - spnStatus->getBitSize()/* + spnStatus->getBitOffset()*/,\n\t\t\t\t\tspnStatus->getBitSize(), spnStatus->getValue(), \"%s (%u)\"\n\t\t\t\t\t, spnStatus->getValueDescription(spnStatus->getValue()).c_str(),\n\t\t\t\t\tspnStatus->getValue());\n\n\n\t\t}\tbreak;\n\n\t\tcase SPN::SPN_STRING: {\n\n\t\t\tconst SPNString *spnStr = (SPNString *)(spn);\n\n\t\t\tti = proto_tree_add_item(spn_tree, spnNumToHinfoId[*iter], tvb, spn->getOffset(), spnStr->getValue().size(), ENC_NA);\n\n\t\t}\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\n\t}\n\n}\n\n\nvoid dissect_fms1_frame(tvbuff_t *tvb, proto_tree *j1939_tree, proto_item *, const FMS1Frame *fms1Frame) {\n\n\tu8 firstTts = TTSS_PER_BLOCK * fms1Frame->getBlockID() + 1;\n\n\tproto_tree_add_item(j1939_tree, hf_j1939_blockId, tvb, 0, 1, ENC_NA);\n\n\tfor(int tts = firstTts; tts < firstTts + TTSS_PER_BLOCK; ++tts) {\n\n\t\tproto_tree_add_item(j1939_tree, ttsNumToHinfoId[tts], tvb, (((tts - 1) % TTSS_PER_BLOCK) + 1)/ 2, 1, ENC_NA);\n\t}\n\n}\n\n\nvoid dissect_dm1_frame(tvbuff_t *tvb, proto_tree *j1939_tree, proto_item *ti, const DM1 *dm1Frame) {\n\n\tconst std::vector<DTC>& dtcs = dm1Frame->getDTCs();\n\n\tproto_tree *dtc_tree;\n\n\tsize_t offset = 2;\n\n\tfor(auto dtc = dtcs.begin(); dtc != dtcs.end(); ++dtc) {\n\n\t\tti = proto_tree_add_item(j1939_tree, hf_j1939_dtc, tvb, offset, DTC_SIZE, ENC_NA);\n\t\tdtc_tree = proto_item_add_subtree(ti, ett_j1939_dtc);\n\n\t\tti = proto_tree_add_uint_bits_format_value(dtc_tree, hf_j1939_spn, tvb,\n\t\t\t(offset << 3),\n\t\t\tSPN_NUMBER_MAX_BITS, dtc->getSpn(), \"%u\"\n\t\t\t, dtc->getSpn());\n\n\t\tti = proto_tree_add_uint_bits_format_value(dtc_tree, hf_j1939_fmi, tvb,\n\t\t\t\t\t(offset << 3) + SPN_NUMBER_MAX_BITS,\n\t\t\t\t\t5, dtc->getFmi(), \"%u\"\n\t\t\t\t\t, dtc->getFmi());\n\n\t\tti = proto_tree_add_uint_bits_format_value(dtc_tree, hf_j1939_oc, tvb,\n\t\t\t\t\t\t\t(offset << 3) + SPN_NUMBER_MAX_BITS + 5 + 1,\n\t\t\t\t\t\t\t7, dtc->getOc(), \"%u\"\n\t\t\t\t\t\t\t, dtc->getOc());\n\n\n\n\t\toffset += DTC_SIZE;\n\n\t}\n\n}\n"
  },
  {
    "path": "wireshark/dissector/plugin.c",
    "content": "\n\n#include \"config.h\"\n\n#include <gmodule.h>\n\n/* plugins are DLLs */\n#define WS_BUILD_DLL\n#include \"ws_symbol_export.h\"\n\n#include \"epan/proto.h\"\n\nvoid proto_register_j1939(void);\nvoid proto_reg_handoff_j1939(void);\n\nWS_DLL_PUBLIC_DEF const gchar plugin_version[] = \"1.0.0\";\nWS_DLL_PUBLIC_DEF const gchar plugin_release[] = \"1.0.0\";\n\nWS_DLL_PUBLIC void plugin_register(void);\n\nvoid plugin_register(void)\n{\n    static proto_plugin plug_j1939;\n\n    plug_j1939.register_protoinfo = proto_register_j1939;\n    plug_j1939.register_handoff = proto_reg_handoff_j1939;\n    proto_register_plugin(&plug_j1939);\n}\n"
  }
]