OTX-Runtime for DotNet  
Own Diagnostic Runtime System

The following section describes how a user can implement its own DiagRuntimeSystem. The interface of the DiagRuntimeSystem is generic. It only executes a Command and gets a result. Except some special commands, see NoneOtxDiagApi, the structure of the commands and the result is equal to the structure of the related OTX extensions, see OtxDiagApi.

Note: The DiagRuntimeSystem must be implemented in C++.

Requirements

  1. The own diagnostic runtime system must support the functionality of at least the following actions and terms of the DiagCom OTX extension.
    1. GetComChannel
    2. CreateDiagServiceByName
    3. ExecuteDiagService
  2. The own diagnostic runtime system can support the functionality of all other diagnostic relevant OTX extensions:
    1. BusMonitoring
    2. ComInterface
    3. DiagComPlus
    4. DiagConfiguration
    5. DiagDataBrowsing
    6. DiagDataBrowsingPlus
    7. EcuConfiguration
    8. Flash
    9. FlashPlus
    10. Job
    11. VehicleInfo

Note: It is recommended, if an extension is supported, then all commands of that extension should be supported.

Note: If an OTX extension is not supported by the own implementation and inside an OTX procedure a related command will be executed, an Exception will be thrown inside the OTX runtime.

Note: Inside the OTX Development Environment the usage of extensions can be prevent inside the Extension-Manager.

Integration

  1. The own implementation must implement the interface IDiagRuntimeSystem
  2. Implement all relevant OTX and none OTX Commands for vehicle diagnostics, see methods of related OTX extensions in IOtxDiag and INoneOtxDiag
  3. Build the binary of the own implementation
  4. Set the own implementation as the diagnostic runtime system of the CommandProcessor, see SetRuntimeSystem

Sample Implementation

The sections shows a sample implementation of the main Commands:

  1. SelectProject
  2. SelectVehicleInformation
  3. GetComChannel
  4. CreateDiagServiceByName
  5. ExecuteDiagService

Note: A complete example in C++ can be found inside the archive file below.

DiagRuntimeSystemOwnImplementationSample.rar.

Sample Command SelectProject

// Is SelectProject-Command
if (command.GetCommandType() == CommandTypesPb::SelectProject)
{
// Google protobuf data objects inside command
TMessage *_data = command.GetParameter(1)->GetValueAsBytes();
std::string projectName = this->_data->projectname();
DSystemState systemState = this->_vwDiagSystem->GetState();
if (systemState == DSystemState::eINITIALIZED)
{
// Calls a method inside DiagRuntimeSystem to select a project
dproject = this->_vwDiagSystem->SelectProjectByName(projectName);
}
else if (systemState == DSystemState::ePROJECT_SELECTED || systemState == DSystemState::eLOGICALLY_CONNECTED)
{
dproject->DeselectVehicleInformation();
this->_vwDiagSystem->DeselectProject();
// Calls a method inside DiagRuntimeSystem to select a project
this->_vwDiagSystem->SelectProjectByName(projectName);
}
// Returns an empty result
Result *result = new Result(command, 0);
}

Sample Command SelectVehicleInformation

// Is SelectVehicleInformation-Command
if (command.GetCommandType() == CommandTypesPb::SelectVehicleInformation)
{
// Google protobuf data objects inside command
TMessage *_data = command.GetParameter(1)->GetValueAsBytes();
std::string vehicleInfo= this->_data->vehicleinformation();
DSystemState systemState = this->_vwDiagSystem->GetState();
if (systemState == DSystemState::ePROJECT_SELECTED || systemState == DSystemState::eLOGICALLY_CONNECTED)
{
if (this->_vwDiagSystem->GetActiveProject()->GetActiveDbVehicleInformation() != nullptr)
{
this->_vwDiagSystem->GetActiveProject()->DeselectVehicleInformation();
}
// Calls a method inside DiagRuntimeSystem to load the vehicle information
this->_vwDiagSystem->LoadDbVehicleInformation(vehicleInfo);
}
// Returns an empty result
Result *result = new Result(command, 0);
}

Sample Command GetComChannel

// Is GetComChannel-Command
if (command.GetCommandType() == CommandTypesPb::GetComChannel)
{
// Google protobuf data objects inside command
TMessage *_data = command.GetParameter(1)->GetValueAsBytes();
// Gets the ComChannel data from protobuf object
string identifier = this->_data->identifier();
string ecuvariantname = this->_data->ecuvariantname();
bool performvariantselection = this->_data->performvariantselection();
// Calls a method inside DiagRuntimeSystem
shared_ptr<DLogicalLinkEx> logicalLink = this->_vwDiagSystem->CreateLogicalLink(identifier, ecuvariantname, performvariantselection);
// Creates ComChannel protobuf object
DComChannelPb comChannelPb;
comChannelPb.set_identifier(identifier);
comChannelPb.set_ecuvariantname(ecuvariantname);
Util::ConvertMcd2Pb(logicalLink, &comChannelPb);
// Serialize ComChannel protobuf object into String
string data;
comChannelPb.SerializeToString(&data);
shared_ptr<Common::Parameter> pHandle = make_shared<Common::Parameter>();
pHandle->SetBytesValue(data);
result.AddParameter(1, pHandle);
return result;
}

Sample Command CreateDiagServiceByName

// Is CreateDiagServiceByName-Command
if (command.GetCommandType() == CommandTypesPb::CreateDiagServiceByName)
{
// Google protobuf data objects inside command
TMessage *_data = command.GetParameter(1)->GetValueAsBytes();
std::string name = _data->name();
// Calls a method inside DiagRuntimeSystem
shared_ptr<DDataPrimitiveEx> diagComPrimitive = logicalLink->CreateDiagServiceByName(name);
DDiagServicePb diagServicePb;
diagServicePb.mutable_comchannel()->CopyFrom(this->_data->comchannel());
// Copy data of runtime object to protobuf
Util::ConvertMcd2Pb(diagComPrimitive, &diagServicePb);
// Serialize DiagService protobuf object into String
string data;
diagServicePb.SerializeToString(&data);
shared_ptr<Common::Parameter> pHandle = make_shared<Common::Parameter>();
pHandle->SetBytesValue(data);
result.AddParameter(1, pHandle);
return result;
}

Sample Command ExecuteDiagService

Synchronous execution with OTX Inline-Mapping and processing of the request and response parameters.

// Is ExecuteDiagService-Command
if (command.GetCommandType() == CommandTypesPb::ExecuteDiagService)
{
// Google protobuf data objects inside command
TMessage *_data = command.GetParameter(1)->GetValueAsBytes();
bool async = command.GetParameter(2)->GetValueAsBool();
if (!this->_data->has_requestparamters())
{
this->_data->set_allocated_requestparamters(new DParameterCollectionPb());
}
// Gets DiagService from protobuf
DDiagServicePb *diagService = this->_data->mutable_diagservice();
// Get RequestParameters from protobuf
RepeatedPtrField<DParameterPb> *requestparameters = this->_data->mutable_requestparamters()->mutable_items();
// Get ResponseParameters from protobuf
RepeatedPtrField<DParameterPb> *responseparameters = responseparameters = this->_data->mutable_responseparamters()->mutable_items();
if (this->async)
{
// Calls a method inside DiagRuntimeSystem
dataPrimitive->ExecuteAsync(requestparameters, this->_data->suppresspositiveresponse());
result.SetResultCode(ResultCodesPb::Pending);
}
else
{
// Calls a method inside DiagRuntimeSystem
shared_ptr<DResultEx> dResult = dataPrimitive->DDiagComPrimitiveEx::ExecuteSync(requestparameters, responseparameters, this->_data->suppresspositiveresponse());
DiagLoggingUtil::WriteResponses(this->_clientId, this->_clientName, *dataPrimitive, *dResult);
DResultPb resultPb;
resultPb.mutable_diagservice()->mutable_comchannel()->set_handle(diagService->mutable_comchannel()->handle());
resultPb.mutable_diagservice()->set_handle(diagService->handle());
std::shared_ptr<DDbDiagComPrimitive> dbObject = dataPrimitive->DDiagComPrimitiveEx::GetDbObject();
resultPb.mutable_diagservice()->set_shortname(dbObject->GetShortName());
resultPb.mutable_diagservice()->set_longname(Util::UnicodeToString(dbObject->GetLongName()));
Util::ConvertMcd2Pb(dResult, &resultPb);
// Serialize Result protobuf object into String
string data;
resultPb.SerializeToString(&data);
shared_ptr<Parameter> parameter1 = make_shared<Parameter>();
parameter1->SetBytesValue(data);
result.AddParameter(1, parameter1);
// Set DResponseParamters
this->_data->mutable_responseparamters()->SerializeToString(&data);
shared_ptr<Parameter> parameter2 = make_shared<Parameter>();
parameter2->SetBytesValue(data);
result.AddParameter(2, parameter2);
}
return result;
}