Update the PnP SDK submodule and modify pnpbridge to work with new API changes (#21)

* Update headers

* Pulled latest commit from public-preview-utopia

* Updated pnpbridge to work with latest changes from public-preview-utopia

* Missing linker deps

* add missing files

* remove connection string from config

* update the sample config

* Fix lx build
This commit is contained in:
ajbarb 2019-07-23 13:53:51 -07:00 коммит произвёл GitHub
Родитель 2bc2ab14ef
Коммит 11e5ebe662
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
43 изменённых файлов: 566 добавлений и 709 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -6,3 +6,4 @@
/PnpBridge/src/PnpBridge/Debug
/PnpBridge/src/PnpBridge/x64/Debug
/PnpBridge/src/PnpBridge/PnpBridge.sln
.vscode

3
.gitmodules поставляемый
Просмотреть файл

@ -1,6 +1,3 @@
[submodule "PnpBridge/deps/azure-iot-sdk-c-pnp"]
path = PnpBridge/deps/azure-iot-sdk-c-pnp
url = https://github.com/Azure/azure-iot-sdk-c-pnp
[submodule "pnpbridge/deps/azure-iot-sdk-c-pnp"]
path = pnpbridge/deps/azure-iot-sdk-c-pnp
url = https://github.com/Azure/azure-iot-sdk-c-pnp

Просмотреть файл

@ -6,12 +6,6 @@ if (POLICY CMP0042)
cmake_policy(SET CMP0042 NEW)
endif()
# Include the common build rules for the C SDK
include("${CMAKE_CURRENT_LIST_DIR}/deps/azure-iot-sdk-c-pnp/c-utility/configs/azure_iot_build_rules.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/deps/azure-iot-sdk-c-pnp/c-utility/configs/azure_c_shared_utilityFunctions.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/deps/azure-iot-sdk-c-pnp/configs/azure_iot_sdksFunctions.cmake")
#2
#set(run_e2e_tests OFF CACHE BOOL "skip e2e tests" FORCE)
# TODO: Skip azure c sdk unit tests
@ -24,8 +18,17 @@ set(original_run_unittests ${run_unittests})
set(run_e2e_tests OFF)
set(run_unittests OFF)
# TODO check where this is getting set
set(use_installed_dependencies OFF)
set(compileOption_C "" CACHE STRING "passes a string to the command line of the C compiler")
set(compileOption_CXX "" CACHE STRING "passes a string to the command line of the C++ compiler")
set(linkerOption "" CACHE STRING "passes a string to the shared and exe linker options of the C compiler")
# Include the common build rules for the C SDK
include("${CMAKE_CURRENT_LIST_DIR}/deps/azure-iot-sdk-c-pnp/c-utility/configs/azure_iot_build_rules.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/deps/azure-iot-sdk-c-pnp/c-utility/configs/azure_c_shared_utilityFunctions.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/deps/azure-iot-sdk-c-pnp/configs/azure_iot_sdksFunctions.cmake")
#set(use_installed_dependencies OFF)
if(${original_run_e2e_tests} OR ${original_run_unittests})
set(SHARED_UTIL_REAL_TEST_FOLDER ${CMAKE_CURRENT_LIST_DIR}/deps/azure-iot-sdk-c-pnp/c-utility/tests/real_test_files CACHE INTERNAL "this is what needs to be included when doing test sources" FORCE)
@ -33,19 +36,16 @@ if(${original_run_e2e_tests} OR ${original_run_unittests})
enable_testing()
endif()
# Now add the pnp C sdk with test dir flags disabled
add_subdirectory(deps/azure-iot-sdk-c-pnp)
set(run_e2e_tests ${original_run_e2e_tests})
set(run_unittests ${original_run_unittests})
#2
option(run_e2e_tests "set run_e2e_tests to ON to run e2e tests (default is OFF)" OFF)
option(run_unittests "set run_unittests to ON to run unittests (default is OFF)" OFF)
option(run_int_tests "set run_int_tests to ON to integration tests (default is OFF)." OFF)
# Enable IoT SDK to act as a module for Edge
if(${use_edge_modules})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUSE_EDGE_MODULES")

@ -1 +1 @@
Subproject commit e5f5a95a8ac92ac4e834639d5b41e048ab7d36b6
Subproject commit 8a594e43ff6ff16a32a2ebb788708d6e6e21e4da

Просмотреть файл

@ -271,7 +271,7 @@ echo build.cmd [options]
echo options:
echo -c, --clean delete artifacts from previous build before building
echo --config ^<value^> [Debug] build configuration (e.g. Debug, Release)
echo --platform ^<value^> [x64] build platform (e.g. Win32, x64, arm, ...)
echo --platform ^<value^> [Win32] build platform (e.g. Win32, x64, arm, ...)
echo --winsdkver [10.0.17763.0] windows sdk version
echo --make_nuget ^<value^> [no] generates the binaries to be used for nuget packaging (e.g. yes, no)
echo --run-e2e-tests run end-to-end tests

Просмотреть файл

@ -49,6 +49,8 @@ set(pnp_bridge_INC_FOLDER ${CMAKE_CURRENT_LIST_DIR}/../pnpbridge/inc CACHE INTER
include_directories(inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/deps/parson)
include_directories(../../deps/azure-iot-sdk-c-pnp/c-utility/inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/c-utility/deps/azure-macro-utils-c/inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/c-utility/deps/umock-c/inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/digitaltwin_client/inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/iothub_client/inc)

Просмотреть файл

@ -16,6 +16,7 @@ set(pnpbridge_adaptersample_c_files
./environmental_sensor.c
./environmental_sensor_pnpbridge_discovery.c
./environmental_sensor_pnpbridge.c
./adapter_manifest_pnpbridge.c
)
set(pnpbridge_adaptersample_h_files
@ -30,6 +31,8 @@ set(pnp_bridge_INC_FOLDER ${CMAKE_CURRENT_LIST_DIR}/../pnpbridge/inc CACHE INTER
include_directories(../../deps/azure-iot-sdk-c-pnp/deps/parson)
include_directories(../../deps/azure-iot-sdk-c-pnp/c-utility/inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/c-utility/deps/azure-macro-utils-c/inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/c-utility/deps/umock-c/inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/digitaltwin_client/inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/iothub_client/inc)

Просмотреть файл

@ -30,7 +30,8 @@
"sensor_id": "10"
}
},
"interface_id": "http://contoso.com/EnvironmentalSensor/1.0.0",
"interface_id": "urn:contoso:com:EnvironmentalSensor:1",
"component_name": "MyComponent",
"pnp_parameters": {
"identity": "environment-sensor-sample-pnp-adapter"
},

Просмотреть файл

@ -15,11 +15,12 @@
#include "azure_c_shared_utility/xlogging.h"
#include "azure_c_shared_utility/crt_abstractions.h"
#include "azure_c_shared_utility/const_defines.h"
// DigitalTwin interface name from service perspective.
static const char DigitalTwinSampleEnvironmentalSensor_InterfaceName[] = "http://contoso.com/environmentalsensor/1.0.0";
static const char DigitalTwinSampleEnvironmentalSensor_InterfaceId[] = "urn:contoso:com:EnvironmentalSensor:1";
static const char DigitalTwinSampleEnvironmentalSensor_ComponentName[] = "environmentalSensor";
//
// Telemetry names for this interface.
@ -37,96 +38,43 @@ static const char digitaltwinSample_DeviceStateData[] = "true";
static const int digitaltwinSample_DeviceStateDataLen = sizeof(digitaltwinSample_DeviceStateData) - 1;
//
// Callback function declarations and DigitalTwin synchronous command names for this interface.
// Callback command names for this interface.
//
static void DigitalTwinSampleEnvironmentalSensor_BlinkCallback(const DIGITALTWIN_CLIENT_COMMAND_REQUEST* dtClientCommandContext, DIGITALTWIN_CLIENT_COMMAND_RESPONSE* dtClientCommandResponseContext, void* userContextCallback);
static void DigitalTwinSampleEnvironmentalSensor_TurnOnLightCallback(const DIGITALTWIN_CLIENT_COMMAND_REQUEST* dtClientCommandContext, DIGITALTWIN_CLIENT_COMMAND_RESPONSE* dtClientCommandResponseContext, void* userContextCallback);
static void DigitalTwinSampleEnvironmentalSensor_TurnOffLightCallback(const DIGITALTWIN_CLIENT_COMMAND_REQUEST* dtClientCommandContext, DIGITALTWIN_CLIENT_COMMAND_RESPONSE* dtClientCommandResponseContext, void* userContextCallback);
#define digitaltwinSample_EnvironmentalSensorCommandBlink "blink"
#define digitaltwinSample_EnvironmentalSensorCommandTurnOn "turnon"
#define digitaltwinSample_EnvironmentalSensorCommandTurnOff "turnoff"
static const char* digitaltwinSample_EnvironmentalSensorCommandNames[] = {
digitaltwinSample_EnvironmentalSensorCommandBlink,
digitaltwinSample_EnvironmentalSensorCommandTurnOn,
digitaltwinSample_EnvironmentalSensorCommandTurnOff
};
static const DIGITALTWIN_COMMAND_EXECUTE_CALLBACK digitaltwinSample_EnvironmentalSensorCommandCallbacks[] = {
DigitalTwinSampleEnvironmentalSensor_BlinkCallback,
DigitalTwinSampleEnvironmentalSensor_TurnOnLightCallback,
DigitalTwinSampleEnvironmentalSensor_TurnOffLightCallback
};
static const char digitaltwinSample_EnvironmentalSensorCommandBlink[] = "blink";
static const char digitaltwinSample_EnvironmentalSensorCommandTurnOn[] = "turnon";
static const char digitaltwinSample_EnvironmentalSensorCommandTurnOff[] = "turnoff";
static const char digitaltwinSample_EnvironmentalSensorCommandRunDiagnostics[] = "rundiagnostics";
//
// Callback function declarations and DigitalTwin asynchronous command names for this interface.
// Command status codes
//
static void DigitalTwinSampleEnvironmentalSensor_RunDiagnosticsCallback(const DIGITALTWIN_CLIENT_ASYNC_COMMAND_REQUEST* dtClientAsyncCommandContext, DIGITALTWIN_CLIENT_ASYNC_COMMAND_RESPONSE* dtClientAsyncCommandResponseContext, void* userContextCallback);
#define digitaltwinSample_EnvironmentalSensorCommandRunDiagnostics "rundiagnostics"
static const char* digitaltwinSample_EnvironmentalSensorAsyncCommandNames[] = {
digitaltwinSample_EnvironmentalSensorCommandRunDiagnostics
};
static const DIGITALTWIN_ASYNC_COMMAND_EXECUTE_CALLBACK digitaltwinSample_EnvironmentalSensorAsyncCommandCallbacks[] = {
DigitalTwinSampleEnvironmentalSensor_RunDiagnosticsCallback
};
static const int commandStatusSuccess = 200;
static const int commandStatusPending = 202;
static const int commandStatusFailure = 500;
static const int commandStatusNotPresent = 501;
//
// What we respond to various commands with. Must be valid JSON.
//
static const char digitaltwinSample_EnviromentalSensor_BlinkResponse[] = "{ \"status\": 12, \"description\": \"leds blinking\" }";
static const char digitaltwinSample_EnviromentalSensor_TurnOnLightResponse[] = "{ \"status\": 1, \"description\": \"light on\" }";
static const char digitaltwinSample_EnviromentalSensor_TurnOffLightResponse[] = "{ \"status\": 1, \"description\": \"light off\" }";
static const char digitaltwinSample_EnviromentalSensor_EmptyBody[] = "\" \"";
static const char digitaltwinSample_EnviromentalSensor_RunDiagnosticsStarted[] = "\"Started diagnostics run\"";
static const char digitaltwinSample_EnviromentalSensor_OutOfMemory[] = "\"Out of memory\"";
static const char digitaltwinSample_EnviromentalSensor_NotImplemented[] = "\"Requested command not implemented on this interface\"";
static const char digitaltwinSample_EnviromentalSensor_RunDiagnosticsBusy[] = "\"Running of diagnostics already active. Only one request may be active at a time\"";
static const char digitaltwinSample_EnviromentalSensor_DiagnosticInProgress[] = "\"Diagnostic still in progress\"";
static const char digitaltwinSample_EnviromentalSensor_DiagnosticsComplete[] = "\"Successfully run diagnostics\"";
// DIGITALTWIN_CLIENT_COMMAND_CALLBACK_TABLE provides the environmental sensor with all callbacks
// required to process commands. Note that unlike IoTHub API's - where various callbacks may
// be added and removed dynamically over a handle's lifetime - DIGITALTWIN_INTERFACE_CLIENT_HANDLE's require all callbacks
// for the lifetime of the object be specified at DigitalTwin_InterfaceClient_Create() time.
static const DIGITALTWIN_CLIENT_COMMAND_CALLBACK_TABLE digitaltwinSample_EnvironmentalSensorCommandTable =
{
DIGITALTWIN_CLIENT_COMMAND_CALLBACK_VERSION_1, // version of structure
sizeof(digitaltwinSample_EnvironmentalSensorCommandNames) / sizeof(digitaltwinSample_EnvironmentalSensorCommandNames[0]),
(const char**)digitaltwinSample_EnvironmentalSensorCommandNames,
(const DIGITALTWIN_COMMAND_EXECUTE_CALLBACK*)digitaltwinSample_EnvironmentalSensorCommandCallbacks,
sizeof(digitaltwinSample_EnvironmentalSensorAsyncCommandNames) / sizeof(digitaltwinSample_EnvironmentalSensorAsyncCommandNames[0]),
digitaltwinSample_EnvironmentalSensorAsyncCommandNames,
digitaltwinSample_EnvironmentalSensorAsyncCommandCallbacks,
};
//
// Callback function declarations and DigitalTwin updateable (from service side) properties for this interface
// Property names that are updatebale from the server application/operator.
//
static void DigitalTwinSampleEnvironmentalSensor_BrightnessCallback(const DIGITALTWIN_CLIENT_PROPERTY_UPDATE* dtClientPropertyUpdate, void* userContextCallback);
static void DigitalTwinSampleEnvironmentalSensor_CustomerNameCallback(const DIGITALTWIN_CLIENT_PROPERTY_UPDATE* dtClientPropertyUpdate, void* userContextCallback);
#define digitaltwinSample_EnvironmentalSensorPropertyCustomerName "name"
#define digitaltwinSample_EnvironmentalSensorPropertyBrightness "brightness"
static const char* digitaltwinSample_EnvironmentalSensorPropertyNames[] = {
digitaltwinSample_EnvironmentalSensorPropertyCustomerName,
digitaltwinSample_EnvironmentalSensorPropertyBrightness
};
static const DIGITALTWIN_PROPERTY_UPDATE_CALLBACK digitaltwinSample_EnvironmentalSensorPropertyCallbacks[] = {
DigitalTwinSampleEnvironmentalSensor_CustomerNameCallback,
DigitalTwinSampleEnvironmentalSensor_BrightnessCallback
};
// DIGITALTWIN_CLIENT_PROPERTY_UPDATED_CALLBACK_TABLE provides the environmental sensor with all
// property callbacks required to process commands. Like DIGITALTWIN_CLIENT_COMMAND_CALLBACK_TABLE, all
// these callbacks must be specified during handle creation time.
static const DIGITALTWIN_CLIENT_PROPERTY_UPDATED_CALLBACK_TABLE digitaltwinSample_propertyTable =
{
DIGITALTWIN_CLIENT_PROPERTY_UPDATE_VERSION_1, // version of structure
sizeof(digitaltwinSample_EnvironmentalSensorPropertyNames) / sizeof(digitaltwinSample_EnvironmentalSensorPropertyNames[0]), // number of properties and callbacks to map to
(const char**)digitaltwinSample_EnvironmentalSensorPropertyNames,
(const DIGITALTWIN_PROPERTY_UPDATE_CALLBACK*)digitaltwinSample_EnvironmentalSensorPropertyCallbacks
};
static const char digitaltwinSample_EnvironmentalSensorPropertyCustomerName[] = "name";
static const char digitaltwinSample_EnvironmentalSensorPropertyBrightness[] = "brightness";
// State of simulated diagnostic run.
typedef enum DIGITALTWIN_SAMPLE_DIAGNOSTIC_STATE_TAG
@ -155,97 +103,79 @@ typedef struct DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE_TAG
// callbacks of this interface don't reference it directly but instead use userContextCallback passed to them.
static DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE digitaltwinSample_EnvironmentalSensorState;
static const int commandStatusSuccess = 200;
static const int commandStatusFailure = 500;
// DigitalTwinSampleEnvironmentalSensor_SetCommandResponse is a helper that fills out a DIGITALTWIN_CLIENT_COMMAND_RESPONSE
static void DigitalTwinSampleEnvironmentalSensor_SetCommandResponse(DIGITALTWIN_CLIENT_COMMAND_RESPONSE* dtClientCommandResponseContext, const char* responseData, int status)
static int DigitalTwinSampleEnvironmentalSensor_SetCommandResponse(DIGITALTWIN_CLIENT_COMMAND_RESPONSE* dtCommandResponse, const char* responseData, int status)
{
size_t responseLen = strlen(responseData);
memset(dtClientCommandResponseContext, 0, sizeof(*dtClientCommandResponseContext));
dtClientCommandResponseContext->version = DIGITALTWIN_CLIENT_COMMAND_RESPONSE_VERSION_1;
memset(dtCommandResponse, 0, sizeof(*dtCommandResponse));
dtCommandResponse->version = DIGITALTWIN_CLIENT_COMMAND_RESPONSE_VERSION_1;
int result;
// Allocate a copy of the response data to return to the invoker. The DigitalTwin layer that invoked the application callback
// takes responsibility for freeing this data.
if (mallocAndStrcpy_s((char**)&dtClientCommandResponseContext->responseData, responseData) != 0)
if (mallocAndStrcpy_s((char**)&dtCommandResponse->responseData, responseData) != 0)
{
LogError("ENVIRONMENTAL_SENSOR_INTERFACE: Unable to allocate response data");
dtClientCommandResponseContext->status = commandStatusFailure;
dtCommandResponse->status = commandStatusFailure;
result = MU_FAILURE;
}
else
{
dtClientCommandResponseContext->responseDataLen = responseLen;
dtClientCommandResponseContext->status = status;
dtCommandResponse->responseDataLen = responseLen;
dtCommandResponse->status = status;
result = 0;
}
return result;
}
// Implement the callback to process the command "blink". Information pertaining to the request is specified in DIGITALTWIN_CLIENT_COMMAND_REQUEST,
// and the callback fills out data it wishes to return to the caller on the service in DIGITALTWIN_CLIENT_COMMAND_RESPONSE.
static void DigitalTwinSampleEnvironmentalSensor_BlinkCallback(const DIGITALTWIN_CLIENT_COMMAND_REQUEST* dtClientCommandContext, DIGITALTWIN_CLIENT_COMMAND_RESPONSE* dtClientCommandResponseContext, void* userContextCallback)
static void DigitalTwinSampleEnvironmentalSensor_BlinkCallback(const DIGITALTWIN_CLIENT_COMMAND_REQUEST* dtCommandRequest, DIGITALTWIN_CLIENT_COMMAND_RESPONSE* dtCommandResponse, void* userInterfaceContext)
{
DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE* sensorState = (DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE*)userContextCallback;
DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE* sensorState = (DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE*)userInterfaceContext;
LogInfo("ENVIRONMENTAL_SENSOR_INTERFACE: Blink command invoked. It has been invoked %d times previously", sensorState->numTimesBlinkCommandCalled);
LogInfo("ENVIRONMENTAL_SENSOR_INTERFACE: Blink data=<%.*s>", (int)dtClientCommandContext->requestDataLen, dtClientCommandContext->requestData);
LogInfo("ENVIRONMENTAL_SENSOR_INTERFACE: Blink data=<%.*s>", (int)dtCommandRequest->requestDataLen, dtCommandRequest->requestData);
sensorState->numTimesBlinkCommandCalled++;
DigitalTwinSampleEnvironmentalSensor_SetCommandResponse(dtClientCommandResponseContext, digitaltwinSample_EnviromentalSensor_BlinkResponse, commandStatusSuccess);
(void)DigitalTwinSampleEnvironmentalSensor_SetCommandResponse(dtCommandResponse, digitaltwinSample_EnviromentalSensor_BlinkResponse, commandStatusSuccess);
}
// Implement the callback to process the command "turnon".
static void DigitalTwinSampleEnvironmentalSensor_TurnOnLightCallback(const DIGITALTWIN_CLIENT_COMMAND_REQUEST* dtClientCommandContext, DIGITALTWIN_CLIENT_COMMAND_RESPONSE* dtClientCommandResponseContext, void* userContextCallback)
static void DigitalTwinSampleEnvironmentalSensor_TurnOnLightCallback(const DIGITALTWIN_CLIENT_COMMAND_REQUEST* dtCommandRequest, DIGITALTWIN_CLIENT_COMMAND_RESPONSE* dtCommandResponse, void* userInterfaceContext)
{
DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE* sensorState = (DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE*)userContextCallback;
DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE* sensorState = (DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE*)userInterfaceContext;
(void)sensorState; // Sensor state not used in this sample
LogInfo("ENVIRONMENTAL_SENSOR_INTERFACE: Turn on light command invoked");
LogInfo("ENVIRONMENTAL_SENSOR_INTERFACE: Turn on light data=<%.*s>", (int)dtClientCommandContext->requestDataLen, dtClientCommandContext->requestData);
LogInfo("ENVIRONMENTAL_SENSOR_INTERFACE: Turn on light data=<%.*s>", (int)dtCommandRequest->requestDataLen, dtCommandRequest->requestData);
DigitalTwinSampleEnvironmentalSensor_SetCommandResponse(dtClientCommandResponseContext, digitaltwinSample_EnviromentalSensor_TurnOnLightResponse, commandStatusSuccess);
(void)DigitalTwinSampleEnvironmentalSensor_SetCommandResponse(dtCommandResponse, digitaltwinSample_EnviromentalSensor_TurnOnLightResponse, commandStatusSuccess);
}
// Implement the callback to process the command "turnoff".
static void DigitalTwinSampleEnvironmentalSensor_TurnOffLightCallback(const DIGITALTWIN_CLIENT_COMMAND_REQUEST* dtClientCommandContext, DIGITALTWIN_CLIENT_COMMAND_RESPONSE* dtClientCommandResponseContext, void* userContextCallback)
static void DigitalTwinSampleEnvironmentalSensor_TurnOffLightCallback(const DIGITALTWIN_CLIENT_COMMAND_REQUEST* dtCommandRequest, DIGITALTWIN_CLIENT_COMMAND_RESPONSE* dtCommandResponse, void* userInterfaceContext)
{
DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE* sensorState = (DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE*)userContextCallback;
DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE* sensorState = (DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE*)userInterfaceContext;
(void)sensorState; // Sensor state not used in this sample
LogInfo("ENVIRONMENTAL_SENSOR_INTERFACE: Turn off light command invoked");
LogInfo("ENVIRONMENTAL_SENSOR_INTERFACE: Turn off light data=<%.*s>", (int)dtClientCommandContext->requestDataLen, dtClientCommandContext->requestData);
LogInfo("ENVIRONMENTAL_SENSOR_INTERFACE: Turn off light data=<%.*s>", (int)dtCommandRequest->requestDataLen, dtCommandRequest->requestData);
DigitalTwinSampleEnvironmentalSensor_SetCommandResponse(dtClientCommandResponseContext, digitaltwinSample_EnviromentalSensor_TurnOffLightResponse, commandStatusSuccess);
(void)DigitalTwinSampleEnvironmentalSensor_SetCommandResponse(dtCommandResponse, digitaltwinSample_EnviromentalSensor_TurnOffLightResponse, commandStatusSuccess);
}
// Fills in DIGITALTWIN_CLIENT_ASYNC_COMMAND_RESPONSE with appropriate status code. Note that we do NOT return payload body at this time, but
// instead (on success cases at least) rely on subsequent calls to DigitalTwin_InterfaceClient_UpdateAsyncCommandStatus to send data as modeled.
static void DigitalTwinSampleEnvironmentalSensor_SetAsyncCommandResponse(DIGITALTWIN_CLIENT_ASYNC_COMMAND_RESPONSE* dtClientAsyncCommandResponseContext, int status)
{
memset(dtClientAsyncCommandResponseContext, 0, sizeof(*dtClientAsyncCommandResponseContext));
dtClientAsyncCommandResponseContext->version = DIGITALTWIN_CLIENT_ASYNC_COMMAND_RESPONSE_VERSION_1;
// Allocate a copy of the response data to return to the invoker. The DigitalTwin layer that invoked the application callback
// takes responsibility for freeing this data.
if (mallocAndStrcpy_s((char**)&dtClientAsyncCommandResponseContext->responseData, digitaltwinSample_EnviromentalSensor_EmptyBody) != 0)
{
LogError("ENVIRONMENTAL_SENSOR_INTERFACE: Unable to allocate response data");
dtClientAsyncCommandResponseContext->status = 500;
}
else
{
dtClientAsyncCommandResponseContext->responseDataLen = strlen(digitaltwinSample_EnviromentalSensor_EmptyBody);
dtClientAsyncCommandResponseContext->status = status;
}
}
// Implement the callback to process the command "rundiagnostic". Note that this is an asyncronous command, so all we do in this
// stage is to do some rudimentary checks and to store off the fact we're async for later.
static void DigitalTwinSampleEnvironmentalSensor_RunDiagnosticsCallback(const DIGITALTWIN_CLIENT_ASYNC_COMMAND_REQUEST* dtClientAsyncCommandContext, DIGITALTWIN_CLIENT_ASYNC_COMMAND_RESPONSE* dtClientAsyncCommandResponseContext, void* userContextCallback)
static void DigitalTwinSampleEnvironmentalSensor_RunDiagnosticsCallback(const DIGITALTWIN_CLIENT_COMMAND_REQUEST* dtCommandRequest, DIGITALTWIN_CLIENT_COMMAND_RESPONSE* dtCommandResponse, void* userInterfaceContext)
{
DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE *sensorState = (DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE*)userContextCallback;
DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE *sensorState = (DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE*)userInterfaceContext;
LogInfo("ENVIRONMENTAL_SENSOR_INTERFACE: Run diagnostics command invoked");
LogInfo("ENVIRONMENTAL_SENSOR_INTERFACE: Diagnostics data=<%.*s>, requestId=<%s>", (int)dtClientAsyncCommandContext->requestDataLen, dtClientAsyncCommandContext->requestData, dtClientAsyncCommandContext->requestId);
LogInfo("ENVIRONMENTAL_SENSOR_INTERFACE: Diagnostics data=<%.*s>, requestId=<%s>", (int)dtCommandRequest->requestDataLen, dtCommandRequest->requestData, dtCommandRequest->requestId);
if (sensorState->diagnosticState != DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_DIAGNOSTIC_STATE_INACTIVE)
{
@ -254,26 +184,31 @@ static void DigitalTwinSampleEnvironmentalSensor_RunDiagnosticsCallback(const DI
// The underlying DigitalTwin protocol will allow multiple simultaneous requests to be sent to the client; whether the
// device allows this or not is a decision for the interface & device implementors.
LogError("ENVIRONMENTAL_SENSOR_INTERFACE: Run diagnostics already active. Cannot support multiple in parallel.");
DigitalTwinSampleEnvironmentalSensor_SetAsyncCommandResponse(dtClientAsyncCommandResponseContext, 500);
DigitalTwinSampleEnvironmentalSensor_SetCommandResponse(dtCommandResponse, digitaltwinSample_EnviromentalSensor_RunDiagnosticsBusy, commandStatusFailure);
}
// At this point we need to save the requestId. This is what the server uses to correlate subsequent responses from this operation.
else if (mallocAndStrcpy_s(&sensorState->requestId, dtCommandRequest->requestId) != 0)
{
LogError("ENVIRONMENTAL_SENSOR_INTERFACE: Cannot allocate requestId.");
(void)DigitalTwinSampleEnvironmentalSensor_SetCommandResponse(dtCommandResponse, digitaltwinSample_EnviromentalSensor_OutOfMemory, commandStatusFailure);
}
else if (DigitalTwinSampleEnvironmentalSensor_SetCommandResponse(dtCommandResponse, digitaltwinSample_EnviromentalSensor_RunDiagnosticsStarted, commandStatusPending) != 0)
{
// Because DigitalTwinSampleEnvironmentalSensor_SetCommandResponse failed, it means
// the server will get an error response back. Do NOT change our diagnosticState
// variable in this case or else server and client will be in different states.
LogError("ENVIRONMENTAL_SENSOR_INTERFACE: Failed setting response to server.");
free(sensorState->requestId);
}
else
{
// At this point we need to save the requestId. This is what the server uses to correlate subsequent responses from this operation.
if (mallocAndStrcpy_s(&sensorState->requestId, dtClientAsyncCommandContext->requestId) != 0)
{
LogError("ENVIRONMENTAL_SENSOR_INTERFACE: Cannot allocate requestId.");
DigitalTwinSampleEnvironmentalSensor_SetAsyncCommandResponse(dtClientAsyncCommandResponseContext, 500);
}
else
{
LogInfo("ENVIRONMENTAL_SENSOR_INTERFACE: Successfully set sensorState to run diagnostics. Will run later.");
DigitalTwinSampleEnvironmentalSensor_SetAsyncCommandResponse(dtClientAsyncCommandResponseContext, 202);
// Moving us into DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_DIAGNOSTIC_STATE_PHASE1 will mean our periodic wakeup will process this.
sensorState->diagnosticState = DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_DIAGNOSTIC_STATE_PHASE1;
}
// Moving us into DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_DIAGNOSTIC_STATE_PHASE1 will mean our periodic wakeup will process this.
LogInfo("ENVIRONMENTAL_SENSOR_INTERFACE: Successfully set sensorState to run diagnostics. Will run later.");
sensorState->diagnosticState = DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_DIAGNOSTIC_STATE_PHASE1;
}
}
// DigitalTwinSampleEnvironmentalSensor_SetAsyncUpdateState is a helper to fill in a DIGITALTWIN_CLIENT_ASYNC_COMMAND_UPDATE structure.
static void DigitalTwinSampleEnvironmentalSensor_SetAsyncUpdateState(DIGITALTWIN_CLIENT_ASYNC_COMMAND_UPDATE *asyncCommandUpdate, const char* propertyData, int status)
{
memset(asyncCommandUpdate, 0, sizeof(*asyncCommandUpdate));
@ -284,18 +219,16 @@ static void DigitalTwinSampleEnvironmentalSensor_SetAsyncUpdateState(DIGITALTWIN
asyncCommandUpdate->statusCode = status;
}
// DigitalTwinSampleEnvironmentalSensor_ProcessDiagnosticIfNecessary is periodically invoked in this sample by the main()
// DigitalTwinSampleEnvironmentalSensor_ProcessDiagnosticIfNecessaryAsync is periodically invoked in this sample by the main()
// thread. It will evaluate whether the service has requested diagnostics to be run, which is an async operation. If so,
// it will send the server an update status message depending on the state that we're at.
//
// Threading note: When this interface is invoked on the convenience layer (../digitaltwin_sample_device), this operation can
// THREADING NOTE: When this interface is invoked on the convenience layer (../digitaltwin_sample_device), this operation can
// run on any thread - while processing a callback, on the main() thread itself, or on a new thread spun up by the process.
// When running on the _LL_ layer (../digitaltwin_sample_ll_device) it *must* run on the main() thread because the the _LL_ is not
// thread safe by design.
DIGITALTWIN_CLIENT_RESULT DigitalTwinSampleEnvironmentalSensor_ProcessDiagnosticIfNecessary(DIGITALTWIN_INTERFACE_CLIENT_HANDLE interfaceHandle)
DIGITALTWIN_CLIENT_RESULT DigitalTwinSampleEnvironmentalSensor_ProcessDiagnosticIfNecessaryAsync(DIGITALTWIN_INTERFACE_CLIENT_HANDLE interfaceHandle)
{
(void)interfaceHandle;
DIGITALTWIN_CLIENT_RESULT result = DIGITALTWIN_CLIENT_ERROR;
if (digitaltwinSample_EnvironmentalSensorState.diagnosticState == DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_DIAGNOSTIC_STATE_INACTIVE)
@ -309,11 +242,14 @@ DIGITALTWIN_CLIENT_RESULT DigitalTwinSampleEnvironmentalSensor_ProcessDiagnostic
// In phase1 of the diagnostic, we *only* report that the diagnostic is in progress but not yet complete. We also transition to the next stage.
DIGITALTWIN_CLIENT_ASYNC_COMMAND_UPDATE asyncCommandUpdate;
DigitalTwinSampleEnvironmentalSensor_SetAsyncUpdateState(&asyncCommandUpdate, "\"Diagnostic still in progress\"", 202);
DigitalTwinSampleEnvironmentalSensor_SetAsyncUpdateState(&asyncCommandUpdate, digitaltwinSample_EnviromentalSensor_DiagnosticInProgress, commandStatusPending);
if ((result = DigitalTwin_InterfaceClient_UpdateAsyncCommandStatus(digitaltwinSample_EnvironmentalSensorState.interfaceClientHandle, &asyncCommandUpdate)) != DIGITALTWIN_CLIENT_OK)
if ((result = DigitalTwin_InterfaceClient_UpdateAsyncCommandStatusAsync(interfaceHandle, &asyncCommandUpdate)) != DIGITALTWIN_CLIENT_OK)
{
LogError("ENVIRONMENTAL_SENSOR_INTERFACE: DigitalTwin_InterfaceClient_UpdateAsyncCommandStatus failed, error=<%s>", MU_ENUM_TO_STRING(DIGITALTWIN_CLIENT_RESULT, result));
// We continue processing the diagnostic run even on DigitalTwin_InterfaceClient_UpdateAsyncCommandStatusAsync failure.
// The UpdateAsync command is just a notification to server of state; the underlying diagnostic should not
// be blocked as it has already been initiated.
LogError("ENVIRONMENTAL_SENSOR_INTERFACE: DigitalTwin_InterfaceClient_UpdateAsyncCommandStatusAsync failed, error=<%s>", MU_ENUM_TO_STRING(DIGITALTWIN_CLIENT_RESULT, result));
}
else
{
@ -328,11 +264,12 @@ DIGITALTWIN_CLIENT_RESULT DigitalTwinSampleEnvironmentalSensor_ProcessDiagnostic
// In phase2 of the diagnostic, we're complete. Indicate to service, free resources, and move us to inactive phase so subsequent commands can arrive.
DIGITALTWIN_CLIENT_ASYNC_COMMAND_UPDATE asyncCommandUpdate;
DigitalTwinSampleEnvironmentalSensor_SetAsyncUpdateState(&asyncCommandUpdate, "\"Successfully run diagnostics\"", 200);
DigitalTwinSampleEnvironmentalSensor_SetAsyncUpdateState(&asyncCommandUpdate, digitaltwinSample_EnviromentalSensor_DiagnosticsComplete, commandStatusSuccess);
if ((result = DigitalTwin_InterfaceClient_UpdateAsyncCommandStatus(digitaltwinSample_EnvironmentalSensorState.interfaceClientHandle, &asyncCommandUpdate)) != DIGITALTWIN_CLIENT_OK)
if ((result = DigitalTwin_InterfaceClient_UpdateAsyncCommandStatusAsync(interfaceHandle, &asyncCommandUpdate)) != DIGITALTWIN_CLIENT_OK)
{
LogError("ENVIRONMENTAL_SENSOR_INTERFACE: DigitalTwin_InterfaceClient_UpdateAsyncCommandStatus failed, error=<%s>", MU_ENUM_TO_STRING(DIGITALTWIN_CLIENT_RESULT, result));
// See comments for DigitalTwin_InterfaceClient_UpdateAsyncCommandStatusAsync above for error handling (or lack thereof) motivation.
LogError("ENVIRONMENTAL_SENSOR_INTERFACE: DigitalTwin_InterfaceClient_UpdateAsyncCommandStatusAsync failed, error=<%s>", MU_ENUM_TO_STRING(DIGITALTWIN_CLIENT_RESULT, result));
}
else
{
@ -347,8 +284,6 @@ DIGITALTWIN_CLIENT_RESULT DigitalTwinSampleEnvironmentalSensor_ProcessDiagnostic
return result;
}
// DigitalTwinSampleEnvironmentalSensor_PropertyCallback is invoked when a property is updated (or failed) going to server.
// In this sample, we route ALL property callbacks to this function and just have the userContextCallback set
// to the propertyName. Product code will potentially have context stored in this userContextCallback.
@ -365,9 +300,9 @@ static void DigitalTwinSampleEnvironmentalSensor_PropertyCallback(DIGITALTWIN_CL
}
// Processes a property update, which the server initiated, for customer name.
static void DigitalTwinSampleEnvironmentalSensor_CustomerNameCallback(const DIGITALTWIN_CLIENT_PROPERTY_UPDATE* dtClientPropertyUpdate, void* userContextCallback)
static void DigitalTwinSampleEnvironmentalSensor_CustomerNameCallback(const DIGITALTWIN_CLIENT_PROPERTY_UPDATE* dtClientPropertyUpdate, void* userInterfaceContext)
{
DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE *sensorState = (DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE*)userContextCallback;
DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE *sensorState = (DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE*)userInterfaceContext;
DIGITALTWIN_CLIENT_RESULT result;
LogInfo("ENVIRONMENTAL_SENSOR_INTERFACE: CustomerName property invoked...");
@ -405,7 +340,7 @@ static void DigitalTwinSampleEnvironmentalSensor_CustomerNameCallback(const DIGI
// DigitalTwin_InterfaceClient_ReportPropertyAsync takes the DIGITALTWIN_CLIENT_PROPERTY_RESPONSE and returns information back to service.
//
result = DigitalTwin_InterfaceClient_ReportPropertyAsync(sensorState->interfaceClientHandle, digitaltwinSample_EnvironmentalSensorPropertyCustomerName, (const char*)dtClientPropertyUpdate->propertyDesired,
&propertyResponse, DigitalTwinSampleEnvironmentalSensor_PropertyCallback, digitaltwinSample_EnvironmentalSensorPropertyCustomerName);
&propertyResponse, DigitalTwinSampleEnvironmentalSensor_PropertyCallback, (void*)digitaltwinSample_EnvironmentalSensorPropertyCustomerName);
if (result != DIGITALTWIN_CLIENT_OK)
{
LogError("ENVIRONMENTAL_SENSOR_INTERFACE: DigitalTwin_InterfaceClient_ReportPropertyAsync for CustomerName failed, error=<%s>", MU_ENUM_TO_STRING(DIGITALTWIN_CLIENT_RESULT, result));
@ -437,9 +372,9 @@ static int DigitalTwinSampleEnvironmentalSensor_ParseBrightness(const char* prop
}
// Process a property update for bright level.
static void DigitalTwinSampleEnvironmentalSensor_BrightnessCallback(const DIGITALTWIN_CLIENT_PROPERTY_UPDATE* dtClientPropertyUpdate, void* userContextCallback)
static void DigitalTwinSampleEnvironmentalSensor_BrightnessCallback(const DIGITALTWIN_CLIENT_PROPERTY_UPDATE* dtClientPropertyUpdate, void* userInterfaceContext)
{
DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE *sensorState = (DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE*)userContextCallback;
DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE *sensorState = (DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE*)userInterfaceContext;
DIGITALTWIN_CLIENT_RESULT result;
LogInfo("ENVIRONMENTAL_SENSOR_INTERFACE: Brightness property invoked...");
@ -476,7 +411,7 @@ static void DigitalTwinSampleEnvironmentalSensor_BrightnessCallback(const DIGITA
// DigitalTwin_InterfaceClient_ReportPropertyAsync takes the DIGITALTWIN_CLIENT_PROPERTY_RESPONSE and returns information back to service.
//
result = DigitalTwin_InterfaceClient_ReportPropertyAsync(sensorState->interfaceClientHandle, digitaltwinSample_EnvironmentalSensorPropertyBrightness, (const char*)dtClientPropertyUpdate->propertyDesired, &propertyResponse,
DigitalTwinSampleEnvironmentalSensor_PropertyCallback, digitaltwinSample_EnvironmentalSensorPropertyBrightness);
DigitalTwinSampleEnvironmentalSensor_PropertyCallback, (void*)digitaltwinSample_EnvironmentalSensorPropertyBrightness);
if (result != DIGITALTWIN_CLIENT_OK)
{
LogError("ENVIRONMENTAL_SENSOR_INTERFACE: DigitalTwin_InterfaceClient_ReportPropertyAsync for Brightness failed, error=<%s>", MU_ENUM_TO_STRING(DIGITALTWIN_CLIENT_RESULT, result));
@ -488,7 +423,7 @@ static void DigitalTwinSampleEnvironmentalSensor_BrightnessCallback(const DIGITA
}
// Sends a reported property for device state of this simulated device.
static DIGITALTWIN_CLIENT_RESULT DigitalTwinSampleEnvironmentalSensor_ReportDeviceState(DIGITALTWIN_INTERFACE_CLIENT_HANDLE interfaceHandle)
static DIGITALTWIN_CLIENT_RESULT DigitalTwinSampleEnvironmentalSensor_ReportDeviceStateAsync(DIGITALTWIN_INTERFACE_CLIENT_HANDLE interfaceHandle)
{
DIGITALTWIN_CLIENT_RESULT result;
@ -509,16 +444,16 @@ static DIGITALTWIN_CLIENT_RESULT DigitalTwinSampleEnvironmentalSensor_ReportDevi
// DigitalTwinSampleEnvironmentalSensor_InterfaceRegisteredCallback is invoked when this interface
// is successfully or unsuccessfully registered with the service, and also when the interface is deleted.
static void DigitalTwinSampleEnvironmentalSensor_InterfaceRegisteredCallback(DIGITALTWIN_CLIENT_RESULT dtInterfaceStatus, void* userContextCallback)
static void DigitalTwinSampleEnvironmentalSensor_InterfaceRegisteredCallback(DIGITALTWIN_CLIENT_RESULT dtInterfaceStatus, void* userInterfaceContext)
{
DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE *sensorState = (DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE*)userContextCallback;
DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE *sensorState = (DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_STATE*)userInterfaceContext;
if (dtInterfaceStatus == DIGITALTWIN_CLIENT_OK)
{
// Once the interface is registered, send our reported properties to the service.
// It *IS* safe to invoke most DigitalTwin API calls from a callback thread like this, though it
// is NOT safe to create/destroy/register interfaces now.
LogInfo("ENVIRONMENTAL_SENSOR_INTERFACE: Interface successfully registered.");
DigitalTwinSampleEnvironmentalSensor_ReportDeviceState(sensorState->interfaceClientHandle);
DigitalTwinSampleEnvironmentalSensor_ReportDeviceStateAsync(sensorState->interfaceClientHandle);
}
else if (dtInterfaceStatus == DIGITALTWIN_CLIENT_ERROR_INTERFACE_UNREGISTERING)
{
@ -531,6 +466,55 @@ static void DigitalTwinSampleEnvironmentalSensor_InterfaceRegisteredCallback(DIG
}
}
// DigitalTwinSample_ProcessCommandUpdate receives commands from the server. This implementation acts as a simple dispatcher
// to the functions to perform the actual processing.
void DigitalTwinSample_ProcessCommandUpdate(const DIGITALTWIN_CLIENT_COMMAND_REQUEST* dtCommandRequest, DIGITALTWIN_CLIENT_COMMAND_RESPONSE* dtCommandResponse, void* userInterfaceContext)
{
if (strcmp(dtCommandRequest->commandName, digitaltwinSample_EnvironmentalSensorCommandBlink) == 0)
{
DigitalTwinSampleEnvironmentalSensor_BlinkCallback(dtCommandRequest, dtCommandResponse, userInterfaceContext);
}
else if (strcmp(dtCommandRequest->commandName, digitaltwinSample_EnvironmentalSensorCommandTurnOn) == 0)
{
DigitalTwinSampleEnvironmentalSensor_TurnOnLightCallback(dtCommandRequest, dtCommandResponse, userInterfaceContext);
}
else if (strcmp(dtCommandRequest->commandName, digitaltwinSample_EnvironmentalSensorCommandTurnOff) == 0)
{
DigitalTwinSampleEnvironmentalSensor_TurnOffLightCallback(dtCommandRequest, dtCommandResponse, userInterfaceContext);
}
else if (strcmp(dtCommandRequest->commandName, digitaltwinSample_EnvironmentalSensorCommandRunDiagnostics) == 0)
{
DigitalTwinSampleEnvironmentalSensor_RunDiagnosticsCallback(dtCommandRequest, dtCommandResponse, userInterfaceContext);
}
else
{
// If the command is not implemented by this interface, by convention we return a 501 error to server.
LogError("ENVIRONMENTAL_SENSOR_INTERFACE: Command name <%s> is not associated with this interface", dtCommandRequest->commandName);
(void)DigitalTwinSampleEnvironmentalSensor_SetCommandResponse(dtCommandResponse, digitaltwinSample_EnviromentalSensor_NotImplemented, commandStatusNotPresent);
}
}
// DigitalTwinSampleEnvironmentalSensor_ProcessPropertyUpdate receives updated properties from the server. This implementation
// acts as a simple dispatcher to the functions to perform the actual processing.
static void DigitalTwinSampleEnvironmentalSensor_ProcessPropertyUpdate(const DIGITALTWIN_CLIENT_PROPERTY_UPDATE* dtClientPropertyUpdate, void* userInterfaceContext)
{
if (strcmp(dtClientPropertyUpdate->propertyName, digitaltwinSample_EnvironmentalSensorPropertyCustomerName) == 0)
{
DigitalTwinSampleEnvironmentalSensor_CustomerNameCallback(dtClientPropertyUpdate, userInterfaceContext);
}
else if (strcmp(dtClientPropertyUpdate->propertyName, digitaltwinSample_EnvironmentalSensorPropertyBrightness) == 0)
{
DigitalTwinSampleEnvironmentalSensor_BrightnessCallback(dtClientPropertyUpdate, userInterfaceContext);
}
else
{
// If the property is not implemented by this interface, presently we only record a log message but do not have a mechanism to report back to the service
LogError("ENVIRONMENTAL_SENSOR_INTERFACE: Property name <%s> is not associated with this interface", dtClientPropertyUpdate->propertyName);
}
}
//
// DigitalTwinSampleEnvironmentalSensor_CreateInterface is the initial entry point into the DigitalTwin Sample Environmental Sensor interface.
// It simply creates a DIGITALTWIN_INTERFACE_CLIENT_HANDLE that is mapped to the environmental sensor interface name.
@ -539,7 +523,7 @@ static void DigitalTwinSampleEnvironmentalSensor_InterfaceRegisteredCallback(DIG
// NOTE: The actual registration of this interface is left to the caller, which may register
// multiple interfaces on one DIGITALTWIN_DEVICE_CLIENT_HANDLE.
//
DIGITALTWIN_INTERFACE_CLIENT_HANDLE DigitalTwinSampleEnvironmentalSensor_CreateInterface(char* interfaceId)
DIGITALTWIN_INTERFACE_CLIENT_HANDLE DigitalTwinSampleEnvironmentalSensor_CreateInterface(char* InterfaceId, char* ComponentName)
{
DIGITALTWIN_INTERFACE_CLIENT_HANDLE interfaceHandle;
DIGITALTWIN_CLIENT_RESULT result;
@ -547,26 +531,26 @@ DIGITALTWIN_INTERFACE_CLIENT_HANDLE DigitalTwinSampleEnvironmentalSensor_CreateI
memset(&digitaltwinSample_EnvironmentalSensorState, 0, sizeof(digitaltwinSample_EnvironmentalSensorState));
digitaltwinSample_EnvironmentalSensorState.diagnosticState = DIGITALTWIN_SAMPLE_ENVIRONMENTAL_SENSOR_DIAGNOSTIC_STATE_INACTIVE;
if ((result = DigitalTwin_InterfaceClient_Create(interfaceId, DigitalTwinSampleEnvironmentalSensor_InterfaceRegisteredCallback, (void*)&digitaltwinSample_EnvironmentalSensorState, &interfaceHandle)) != DIGITALTWIN_CLIENT_OK)
if ((result = DigitalTwin_InterfaceClient_Create(InterfaceId, ComponentName, DigitalTwinSampleEnvironmentalSensor_InterfaceRegisteredCallback, (void*)&digitaltwinSample_EnvironmentalSensorState, &interfaceHandle)) != DIGITALTWIN_CLIENT_OK)
{
LogError("ENVIRONMENTAL_SENSOR_INTERFACE: Unable to allocate interface client handle for <%s>, error=<%s>", DigitalTwinSampleEnvironmentalSensor_InterfaceName, MU_ENUM_TO_STRING(DIGITALTWIN_CLIENT_RESULT, result));
LogError("ENVIRONMENTAL_SENSOR_INTERFACE: Unable to allocate interface client handle for interfaceId=<%s>, componentName=<%s>, error=<%s>", DigitalTwinSampleEnvironmentalSensor_InterfaceId, DigitalTwinSampleEnvironmentalSensor_ComponentName, MU_ENUM_TO_STRING(DIGITALTWIN_CLIENT_RESULT, result));
interfaceHandle = NULL;
}
else if ((result = DigitalTwin_InterfaceClient_SetPropertiesUpdatedCallbacks(interfaceHandle, &digitaltwinSample_propertyTable)) != DIGITALTWIN_CLIENT_OK)
else if ((result = DigitalTwin_InterfaceClient_SetPropertiesUpdatedCallback(interfaceHandle, DigitalTwinSampleEnvironmentalSensor_ProcessPropertyUpdate)) != DIGITALTWIN_CLIENT_OK)
{
LogError("ENVIRONMENTAL_SENSOR_INTERFACE: DigitalTwin_InterfaceClient_SetPropertiesUpdatedCallbacks failed. error=<%s>", MU_ENUM_TO_STRING(DIGITALTWIN_CLIENT_RESULT, result));
LogError("ENVIRONMENTAL_SENSOR_INTERFACE: DigitalTwin_InterfaceClient_SetPropertiesUpdatedCallback failed. error=<%s>", MU_ENUM_TO_STRING(DIGITALTWIN_CLIENT_RESULT, result));
DigitalTwinSampleEnvironmentalSensor_Close(interfaceHandle);
interfaceHandle = NULL;
}
else if ((result = DigitalTwin_InterfaceClient_SetCommandsCallbacks(interfaceHandle, &digitaltwinSample_EnvironmentalSensorCommandTable)) != DIGITALTWIN_CLIENT_OK)
else if ((result = DigitalTwin_InterfaceClient_SetCommandsCallback(interfaceHandle, DigitalTwinSample_ProcessCommandUpdate)) != DIGITALTWIN_CLIENT_OK)
{
LogError("ENVIRONMENTAL_SENSOR_INTERFACE: DigitalTwin_InterfaceClient_SetCommandsCallbacks failed. error=<%s>", MU_ENUM_TO_STRING(DIGITALTWIN_CLIENT_RESULT, result));
LogError("ENVIRONMENTAL_SENSOR_INTERFACE: DigitalTwin_InterfaceClient_SetCommandsCallback failed. error=<%s>", MU_ENUM_TO_STRING(DIGITALTWIN_CLIENT_RESULT, result));
DigitalTwinSampleEnvironmentalSensor_Close(interfaceHandle);
interfaceHandle = NULL;
}
else
{
LogInfo("ENVIRONMENTAL_SENSOR_INTERFACE: Created DIGITALTWIN_INTERFACE_CLIENT_HANDLE. InterfaceName=<%s>, handle=<%p>", DigitalTwinSampleEnvironmentalSensor_InterfaceName, interfaceHandle);
LogInfo("ENVIRONMENTAL_SENSOR_INTERFACE: Created DIGITALTWIN_INTERFACE_CLIENT_HANDLE. interfaceId=<%s>, componentName=<%s>, handle=<%p>", DigitalTwinSampleEnvironmentalSensor_InterfaceId, DigitalTwinSampleEnvironmentalSensor_ComponentName, interfaceHandle);
digitaltwinSample_EnvironmentalSensorState.interfaceClientHandle = interfaceHandle;
}
@ -592,11 +576,11 @@ static void DigitalTwinSampleEnvironmentalSensor_TelemetryCallback(DIGITALTWIN_C
}
//
// DigitalTwinSampleEnvironmentalSensor_SendTelemetryMessages is periodically invoked by the caller to
// DigitalTwinSampleEnvironmentalSensor_SendTelemetryMessagesAsync is periodically invoked by the caller to
// send telemetry containing the current temperature and humidity (in both cases random numbers
// so this sample will work on platforms without these sensors).
//
DIGITALTWIN_CLIENT_RESULT DigitalTwinSampleEnvironmentalSensor_SendTelemetryMessages(DIGITALTWIN_INTERFACE_CLIENT_HANDLE interfaceHandle)
DIGITALTWIN_CLIENT_RESULT DigitalTwinSampleEnvironmentalSensor_SendTelemetryMessagesAsync(DIGITALTWIN_INTERFACE_CLIENT_HANDLE interfaceHandle)
{
DIGITALTWIN_CLIENT_RESULT result;
@ -644,4 +628,3 @@ void DigitalTwinSampleEnvironmentalSensor_Close(DIGITALTWIN_INTERFACE_CLIENT_HAN
free(digitaltwinSample_EnvironmentalSensorState.requestId);
digitaltwinSample_EnvironmentalSensorState.requestId = NULL;
}

Просмотреть файл

@ -14,13 +14,12 @@ extern "C"
#endif
// Creates a new DIGITALTWIN_INTERFACE_CLIENT_HANDLE for this interface.
DIGITALTWIN_INTERFACE_CLIENT_HANDLE DigitalTwinSampleEnvironmentalSensor_CreateInterface(char* interfaceId);
DIGITALTWIN_INTERFACE_CLIENT_HANDLE DigitalTwinSampleEnvironmentalSensor_CreateInterface(char* interfaceId, char* ComponentName);
// Sends DigitalTwin telemetry messages about current environment
DIGITALTWIN_CLIENT_RESULT DigitalTwinSampleEnvironmentalSensor_SendTelemetryMessages(DIGITALTWIN_INTERFACE_CLIENT_HANDLE interfaceHandle);
DIGITALTWIN_CLIENT_RESULT DigitalTwinSampleEnvironmentalSensor_SendTelemetryMessagesAsync(DIGITALTWIN_INTERFACE_CLIENT_HANDLE interfaceHandle);
// Periodically checks to see if an asychronous command for running diagnostics has been queued, and process it if so.
DIGITALTWIN_CLIENT_RESULT DigitalTwinSampleEnvironmentalSensor_ProcessDiagnosticIfNecessary(DIGITALTWIN_INTERFACE_CLIENT_HANDLE interfaceHandle);
DIGITALTWIN_CLIENT_RESULT DigitalTwinSampleEnvironmentalSensor_ProcessDiagnosticIfNecessaryAsync(DIGITALTWIN_INTERFACE_CLIENT_HANDLE interfaceHandle);
// Closes down resources associated with device info interface.
void DigitalTwinSampleEnvironmentalSensor_Close(DIGITALTWIN_INTERFACE_CLIENT_HANDLE interfaceHandle);

Просмотреть файл

@ -3,7 +3,7 @@
#include <pnpbridge.h>
#include "azure_c_shared_utility/base32.h"
#include "azure_c_shared_utility/azure_base32.h"
#include "azure_c_shared_utility/gballoc.h"
#include "azure_c_shared_utility/xlogging.h"
#include "azure_c_shared_utility/threadapi.h"
@ -32,7 +32,7 @@ int EnvironmentSensor_TelemetryWorker(void* context) {
return 0;
}
DigitalTwinSampleEnvironmentalSensor_SendTelemetryMessages(device->pnpinterfaceHandle);
DigitalTwinSampleEnvironmentalSensor_SendTelemetryMessagesAsync(device->pnpinterfaceHandle);
// Sleep for 5 sec
ThreadAPI_Sleep(5000);
@ -77,8 +77,10 @@ EnvironmentSensor_CreatePnpInterface(
PNPADPATER_INTERFACE_PARAMS interfaceParams = { 0 };
PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface;
int res = 0;
PNPMESSAGE_PROPERTIES* props = NULL;
interfaceId = PnpMessage_GetInterfaceId(Message);
props = PnpMessage_AccessProperties(Message);
device = calloc(1, sizeof(ENVIRONMENT_SENSOR));
if (NULL == device) {
@ -89,7 +91,7 @@ EnvironmentSensor_CreatePnpInterface(
device->ShuttingDown = false;
// Create PNP interface using PNP device SDK
pnpInterfaceClient = DigitalTwinSampleEnvironmentalSensor_CreateInterface((char*)interfaceId);
pnpInterfaceClient = DigitalTwinSampleEnvironmentalSensor_CreateInterface((char*)interfaceId, props->ComponentName);
if (NULL == pnpInterfaceClient) {
res = -1;
goto end;

Просмотреть файл

@ -3,7 +3,7 @@
#include <pnpbridge.h>
#include "azure_c_shared_utility/base32.h"
#include "azure_c_shared_utility/azure_base32.h"
#include "azure_c_shared_utility/gballoc.h"
#include "azure_c_shared_utility/xlogging.h"
#include "azure_c_shared_utility/threadapi.h"

Просмотреть файл

@ -40,6 +40,8 @@ set(pnpbridge_INC_FOLDER ${CMAKE_CURRENT_LIST_DIR}/../../pnpbridge/inc CACHE INT
include_directories(../inc)
include_directories(../../../deps/azure-iot-sdk-c-pnp/deps/parson)
include_directories(../../../deps/azure-iot-sdk-c-pnp/c-utility/inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/c-utility/deps/azure-macro-utils-c/inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/c-utility/deps/umock-c/inc)
include_directories(../../../deps/azure-iot-sdk-c-pnp/digitaltwin_client/inc)
include_directories(${pnpbridge_INC_FOLDER})

Просмотреть файл

@ -14,6 +14,21 @@ PNP_ADAPTER CameraPnpInterface = {
CameraPnpInterfaceShutdown
};
void
CameraPnpCallback_ProcessCommandUpdate(
const DIGITALTWIN_CLIENT_COMMAND_REQUEST* dtCommandRequest,
DIGITALTWIN_CLIENT_COMMAND_RESPONSE* dtCommandResponse,
void* userInterfaceContext
)
{
if (strcmp(dtCommandRequest->commandName, "takephoto") == 0) {
CameraPnpCallback_TakePhoto(dtCommandRequest, dtCommandResponse, userInterfaceContext);
}
else {
LogError("Unknown command request");
}
}
// Forward decls for callback functions:
void
CameraPnpCallback_TakePhoto(
@ -42,23 +57,6 @@ CameraPnpCallback_TakePhoto(
}
}
static const char* s_CameraPnpCommandNames[] = {
"takephoto"
};
static const DIGITALTWIN_COMMAND_EXECUTE_CALLBACK s_CameraPnpCommandCallbacks[] = {
CameraPnpCallback_TakePhoto
};
static const DIGITALTWIN_CLIENT_COMMAND_CALLBACK_TABLE s_CameraPnpCommandTable =
{
DIGITALTWIN_CLIENT_COMMAND_CALLBACK_VERSION_1, // version of structure
sizeof(s_CameraPnpCommandNames) / sizeof(s_CameraPnpCommandNames[0]),
(const char**)s_CameraPnpCommandNames,
(const DIGITALTWIN_COMMAND_EXECUTE_CALLBACK*)s_CameraPnpCommandCallbacks
};
// Camera discovery API entry points.
CameraPnpDiscovery* g_pPnpDiscovery = nullptr;
@ -133,6 +131,7 @@ CameraPnpInterfaceBind(
PNPADAPTER_INTERFACE_HANDLE adapterInterface = nullptr;
PNPMESSAGE_PROPERTIES* pnpMsgProps = nullptr;
DIGITALTWIN_CLIENT_RESULT dtRes;
PNPMESSAGE_PROPERTIES* props;
pnpMsgProps = PnpMessage_AccessProperties(payload);
@ -151,13 +150,14 @@ CameraPnpInterfaceBind(
jmsg = json_parse_string(PnpMessage_GetMessage(payload));
jobj = json_value_get_object(jmsg);
interfaceId = PnpMessage_GetInterfaceId(payload);
props = PnpMessage_AccessProperties(payload);
//s_CameraPnpCommandTable
dtRes = DigitalTwin_InterfaceClient_Create(interfaceId,
dtRes = DigitalTwin_InterfaceClient_Create(interfaceId, props->ComponentName,
nullptr, pIotPnp.get(), &pnpInterfaceClient);
RETURN_HR_IF(E_UNEXPECTED, DIGITALTWIN_CLIENT_OK != dtRes);
dtRes = DigitalTwin_InterfaceClient_SetCommandsCallbacks(pnpInterfaceClient, &s_CameraPnpCommandTable);
dtRes = DigitalTwin_InterfaceClient_SetCommandsCallback(pnpInterfaceClient, CameraPnpCallback_ProcessCommandUpdate);
RETURN_HR_IF(E_UNEXPECTED, DIGITALTWIN_CLIENT_OK != dtRes);
// Create PnpAdapter Interface

Просмотреть файл

@ -28,6 +28,8 @@ set(pnpbridge_INC_FOLDER ${CMAKE_CURRENT_LIST_DIR}/../../pnpbridge/inc CACHE INT
include_directories(../inc)
include_directories(../../../deps/azure-iot-sdk-c-pnp/deps/parson)
include_directories(../../../deps/azure-iot-sdk-c-pnp/c-utility/inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/c-utility/deps/azure-macro-utils-c/inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/c-utility/deps/umock-c/inc)
include_directories(../../../deps/azure-iot-sdk-c-pnp/digitaltwin_client/inc)
include_directories(${pnpbridge_INC_FOLDER})

Просмотреть файл

@ -7,7 +7,7 @@
#include <initguid.h>
#include <devpkey.h>
#include "azure_c_shared_utility/base32.h"
#include "azure_c_shared_utility/azure_base32.h"
#include "azure_c_shared_utility/gballoc.h"
#include "azure_c_shared_utility/xlogging.h"
#include "azure_c_shared_utility/threadapi.h"
@ -191,8 +191,8 @@ CoreDeviceDiscovery_Enumerate(
int
CoreDevice_StartDiscovery(
const PNPMEMORY DeviceArgs,
const PNPMEMORY AdapterArgs
_In_ const PNPMEMORY DeviceArgs,
_In_ const PNPMEMORY AdapterArgs
)
{
DWORD cmRet;

Просмотреть файл

@ -3,7 +3,7 @@
#include <PnpBridge.h>
#include "azure_c_shared_utility/base32.h"
#include "azure_c_shared_utility/azure_base32.h"
#include "azure_c_shared_utility/gballoc.h"
#include "azure_c_shared_utility/xlogging.h"
#include "azure_c_shared_utility/threadapi.h"
@ -146,6 +146,7 @@ CoreDevice_CreatePnpInterface(
const char* interfaceId = PnpMessage_GetInterfaceId(param);
const char* symbolicLink = json_object_get_string(args, "symbolic_link");
const char* publishMode = json_object_get_string(args, "PublishMode");
PNPMESSAGE_PROPERTIES* props = PnpMessage_AccessProperties(param);
device = calloc(1, sizeof(CORE_DEVICE_TAG));
if (NULL == device) {
@ -153,7 +154,7 @@ CoreDevice_CreatePnpInterface(
goto exit;
}
dtres = DigitalTwin_InterfaceClient_Create(interfaceId,
dtres = DigitalTwin_InterfaceClient_Create(interfaceId, props->ComponentName,
NULL, NULL, &pnpInterfaceClient);
if (DIGITALTWIN_CLIENT_OK != dtres) {
result = -1;

Просмотреть файл

@ -38,6 +38,8 @@ set(pnpbridge_INC_FOLDER ${CMAKE_CURRENT_LIST_DIR}/../../pnpbridge/inc CACHE INT
include_directories(../inc)
include_directories(../../../deps/azure-iot-sdk-c-pnp/deps/parson)
include_directories(../../../deps/azure-iot-sdk-c-pnp/c-utility/inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/c-utility/deps/azure-macro-utils-c/inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/c-utility/deps/umock-c/inc)
include_directories(../../../deps/azure-iot-sdk-c-pnp/digitaltwin_client/inc)
include_directories(${pnpbridge_INC_FOLDER})

Просмотреть файл

@ -62,8 +62,12 @@ const ModbusCommand* ModbusPnp_LookupCommand(SINGLYLINKEDLIST_HANDLE interfaceDe
return NULL;
}
void ModbusPnp_CommandHandler(const DIGITALTWIN_CLIENT_COMMAND_REQUEST* dtClientCommandContext, DIGITALTWIN_CLIENT_COMMAND_RESPONSE* dtClientCommandResponseContext, void* userContextCallback)
//PMODBUS_DEVICE_CONTEXT modbusDevice, const char* commandName, char* data, char** response)
void
ModbusPnp_CommandHandler(
const DIGITALTWIN_CLIENT_COMMAND_REQUEST* dtClientCommandContext,
DIGITALTWIN_CLIENT_COMMAND_RESPONSE* dtClientCommandResponseContext,
void* userContextCallback
)
{
PMODBUS_DEVICE_CONTEXT modbusDevice = (PMODBUS_DEVICE_CONTEXT) userContextCallback;
const ModbusCommand* command = ModbusPnp_LookupCommand(modbusDevice->InterfaceDefinitions, dtClientCommandContext->commandName, 0);

Просмотреть файл

@ -1,6 +1,6 @@
#include <PnpBridge.h>
#include "azure_c_shared_utility/base32.h"
#include "azure_c_shared_utility/azure_base32.h"
#include "azure_c_shared_utility/gballoc.h"
#include "azure_c_shared_utility/xlogging.h"
#include "azure_c_shared_utility/threadapi.h"
@ -14,7 +14,7 @@
const char* modbusDeviceChangeMessageformat = "{ \
\"Identity\": \"modbus-pnp-discovery\" \
\"identity\": \"modbus-pnp-discovery\" \
}";
#pragma region PnpDiscovery
@ -678,17 +678,26 @@ cleanup:
#pragma region PnpDiscovery
int ModbusPnp_StartDiscovery(const char* deviceArgs, const char* adapterArgs) {
if (deviceArgs == NULL) {
int
ModbusPnp_StartDiscovery(
_In_ PNPMEMORY DeviceArgs,
_In_ PNPMEMORY AdapterArgs
)
{
if (DeviceArgs == NULL) {
return -1;
}
UNREFERENCED_PARAMETER(adapterArgs);
UNREFERENCED_PARAMETER(AdapterArgs);
LogInfo("Starting modbus discovery adapter");
// Parse Modbus DeviceConfig
ModbusDeviceConfig* deviceConfig = calloc(1, sizeof(ModbusDeviceConfig));
deviceConfig->ConnectionType = UNKOWN;
JSON_Value* jvalue = json_parse_string(deviceArgs);
PDEVICE_ADAPTER_PARMAETERS deviceParams = (PDEVICE_ADAPTER_PARMAETERS) PnpMemory_GetBuffer(DeviceArgs, NULL);
JSON_Value* jvalue = json_parse_string(deviceParams->AdapterParameters[0]);
JSON_Object* args = json_value_get_object(jvalue);
JSON_Object* deviceConfigObj = json_object_dotget_object(args, "deviceConfig");
@ -707,9 +716,8 @@ int ModbusPnp_StartDiscovery(const char* deviceArgs, const char* adapterArgs) {
return -1;
}
if (UNKOWN == deviceConfig->ConnectionType)
{
LogError("Mssing Modbus connection settings.");
if (UNKOWN == deviceConfig->ConnectionType) {
LogError("Missing Modbus connection settings.");
return -1;
}
@ -864,11 +872,9 @@ ModbusPnp_CreatePnpInterface(
char** propertyNames = NULL;
int propertyCount = 0;
DIGITALTWIN_PROPERTY_UPDATE_CALLBACK* propertyUpdateTable = NULL;
DIGITALTWIN_CLIENT_PROPERTY_UPDATED_CALLBACK_TABLE modbusPropertyTable = { 0 };
char** commandNames = NULL;
int commandCount = 0;
DIGITALTWIN_COMMAND_EXECUTE_CALLBACK* commandUpdateTable = NULL;
DIGITALTWIN_CLIENT_COMMAND_CALLBACK_TABLE modbusCommandTable = { 0 };
const ModbusInterfaceConfig* interfaceConfig = singlylinkedlist_item_get_value(interfaceDefHandle);
DIGITALTWIN_CLIENT_RESULT dtRes;
@ -934,10 +940,10 @@ ModbusPnp_CreatePnpInterface(
propertyUpdateTable[i] = ModbusPnp_PropertyHandler;
}
modbusPropertyTable.numCallbacks = readWritePropertyCount;
/* modbusPropertyTable.numCallbacks = readWritePropertyCount;
modbusPropertyTable.propertyNames = propertyNames;
modbusPropertyTable.callbacks = propertyUpdateTable;
modbusPropertyTable.version = 1;
modbusPropertyTable.version = 1;*/
}
}
@ -979,14 +985,15 @@ ModbusPnp_CreatePnpInterface(
}
}
modbusCommandTable.numCommandCallbacks = commandCount;
/*modbusCommandTable.numCommandCallbacks = commandCount;
modbusCommandTable.commandNames = commandNames;
modbusCommandTable.commandCallbacks = commandUpdateTable;
modbusCommandTable.version = 1;
modbusCommandTable.version = 1;*/
}
}
dtRes = DigitalTwin_InterfaceClient_Create(interfaceId,
"modbus",
NULL,
deviceContext,
&pnpInterfaceClient);
@ -996,7 +1003,7 @@ ModbusPnp_CreatePnpInterface(
}
if (propertyCount > 0) {
dtRes = DigitalTwin_InterfaceClient_SetPropertiesUpdatedCallbacks(pnpInterfaceClient, &modbusPropertyTable);
dtRes = DigitalTwin_InterfaceClient_SetPropertiesUpdatedCallback(pnpInterfaceClient, ModbusPnp_PropertyHandler);
if (DIGITALTWIN_CLIENT_OK != dtRes) {
result = -1;
goto exit;
@ -1004,7 +1011,7 @@ ModbusPnp_CreatePnpInterface(
}
if (commandCount > 0) {
dtRes = DigitalTwin_InterfaceClient_SetCommandsCallbacks(pnpInterfaceClient, &modbusCommandTable);
dtRes = DigitalTwin_InterfaceClient_SetCommandsCallback(pnpInterfaceClient, ModbusPnp_CommandHandler);
if (DIGITALTWIN_CLIENT_OK != dtRes) {
result = -1;
goto exit;

Просмотреть файл

@ -27,6 +27,8 @@ set(pnpbridge_INC_FOLDER ${CMAKE_CURRENT_LIST_DIR}/../../pnpbridge/inc CACHE INT
include_directories(../inc)
include_directories(../../../deps/azure-iot-sdk-c-pnp/deps/parson)
include_directories(../../../deps/azure-iot-sdk-c-pnp/c-utility/inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/c-utility/deps/azure-macro-utils-c/inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/c-utility/deps/umock-c/inc)
include_directories(../../../deps/azure-iot-sdk-c-pnp/pnp_client/inc)
include_directories(${pnpbridge_INC_FOLDER})

Просмотреть файл

@ -3,7 +3,7 @@
#include <pnpbridge.h>
#include "azure_c_shared_utility/base32.h"
#include "azure_c_shared_utility/azure_base32.h"
#include "azure_c_shared_utility/gballoc.h"
#include "azure_c_shared_utility/xlogging.h"
#include "azure_c_shared_utility/threadapi.h"
@ -38,15 +38,6 @@ typedef uint16_t UINT16;
#include "serial_pnp.h"
// BEGIN - PNPCSDK#20
// https://github.com/Azure/azure-iot-sdk-c-pnp/issues/20
// Temporary redirection for property and command handling since PnP C SDK property change
// callback doesn't provide the command name.
//#define CMD_PROP_HANDLER_ADAPTER_NAME SerialPnp
//#include <cmdandprophandler.h>
// END - PNPCSDK#20
int SerialPnp_UartReceiver(void* context)
{
int result = 0;
@ -877,7 +868,12 @@ void SerialPnp_DeviceDescriptorRequest(PSERIAL_DEVICE_CONTEXT serialDevice, byte
LogInfo("Receieved descriptor response, of length %d", *length);
}
int SerialPnp_StartDiscovery(PNPMEMORY deviceArgs, PNPMEMORY adapterArgs) {
int
SerialPnp_StartDiscovery(
_In_ PNPMEMORY deviceArgs,
_In_ PNPMEMORY adapterArgs
)
{
if (deviceArgs == NULL) {
return -1;
}
@ -1017,7 +1013,13 @@ static void SerialPnp_SetCommandResponse(DIGITALTWIN_CLIENT_COMMAND_RESPONSE* pn
}
void SerialPnp_CommandUpdateHandler(const DIGITALTWIN_CLIENT_COMMAND_REQUEST* dtClientCommandContext, DIGITALTWIN_CLIENT_COMMAND_RESPONSE* dtClientCommandResponseContext, void* userContextCallback) {
void
SerialPnp_CommandUpdateHandler(
const DIGITALTWIN_CLIENT_COMMAND_REQUEST* dtClientCommandContext,
DIGITALTWIN_CLIENT_COMMAND_RESPONSE* dtClientCommandResponseContext,
void* userContextCallback
)
{
PSERIAL_DEVICE_CONTEXT deviceContext;
// LogInfo("Processed command frequency property updated. propertyUpdated = %.*s", (int)propertyDataUpdatedLen, propertyDataUpdated);
@ -1077,94 +1079,17 @@ int SerialPnp_CreatePnpInterface(PNPADAPTER_CONTEXT AdapterHandle, PNPMESSAGE ms
while (interfaceDefHandle != NULL) {
PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface = NULL;
DIGITALTWIN_INTERFACE_CLIENT_HANDLE pnpInterfaceClient = NULL;
char** propertyNames = NULL;
int propertyCount = 0;
DIGITALTWIN_PROPERTY_UPDATE_CALLBACK* propertyUpdateTable = NULL;
DIGITALTWIN_CLIENT_PROPERTY_UPDATED_CALLBACK_TABLE serialPropertyTable = { 0 };
char** commandNames = NULL;
int commandCount = 0;
DIGITALTWIN_COMMAND_EXECUTE_CALLBACK* commandUpdateTable = NULL;
DIGITALTWIN_CLIENT_COMMAND_CALLBACK_TABLE serialCommandTable = { 0 };
const InterfaceDefinition* interfaceDef = singlylinkedlist_item_get_value(interfaceDefHandle);
// Construct property table
{
SINGLYLINKEDLIST_HANDLE property = interfaceDef->Properties;
propertyCount = SerialPnp_GetListCount(interfaceDef->Properties);
if (propertyCount > 0) {
LIST_ITEM_HANDLE eventDef = singlylinkedlist_get_head_item(property);
const PropertyDefinition* ev;
propertyNames = malloc(sizeof(char*)*propertyCount);
if (NULL == propertyNames) {
result = -1;
goto exit;
}
propertyUpdateTable = malloc(sizeof(DIGITALTWIN_PROPERTY_UPDATE_CALLBACK*)*propertyCount);
if (NULL == propertyUpdateTable) {
result = -1;
goto exit;
}
eventDef = singlylinkedlist_get_head_item(property);
int x = 0;
while (eventDef != NULL) {
ev = singlylinkedlist_item_get_value(eventDef);
propertyNames[x] = ev->defintion.Name;
propertyUpdateTable[x] = SerialPnp_PropertyUpdateHandler;
x++;
eventDef = singlylinkedlist_get_next_item(eventDef);
}
serialPropertyTable.numCallbacks = propertyCount;
serialPropertyTable.propertyNames = (const char **)propertyNames;
serialPropertyTable.callbacks = propertyUpdateTable;
serialPropertyTable.version = 1;
}
}
// Construct command table
{
SINGLYLINKEDLIST_HANDLE command = interfaceDef->Commands;
commandCount = SerialPnp_GetListCount(command);
if (commandCount > 0) {
LIST_ITEM_HANDLE cmdDef;
int x = 0;
const CommandDefinition* cv;
commandNames = malloc(sizeof(char*)*commandCount);
if (NULL == commandNames) {
result = -1;
goto exit;
}
commandUpdateTable = malloc(sizeof(DIGITALTWIN_COMMAND_EXECUTE_CALLBACK*)*commandCount);
if (NULL == commandUpdateTable) {
result = -1;
goto exit;
}
cmdDef = singlylinkedlist_get_head_item(command);
while (cmdDef != NULL) {
cv = singlylinkedlist_item_get_value(cmdDef);
commandNames[x] = cv->defintion.Name;
commandUpdateTable[x] = SerialPnp_CommandUpdateHandler;
x++;
cmdDef = singlylinkedlist_get_next_item(cmdDef);
}
serialCommandTable.numCommandCallbacks = commandCount;
serialCommandTable.commandNames = (const char **)commandNames;
serialCommandTable.commandCallbacks = commandUpdateTable;
serialCommandTable.version = 1;
}
}
propertyCount = SerialPnp_GetListCount(interfaceDef->Properties);
commandCount = SerialPnp_GetListCount(interfaceDef->Commands);
DIGITALTWIN_CLIENT_RESULT dtRes;
PNPMESSAGE_PROPERTIES* props = PnpMessage_AccessProperties(msg);
dtRes = DigitalTwin_InterfaceClient_Create(interfaceId,
props->ComponentName,
NULL,
deviceContext,
&pnpInterfaceClient);
@ -1174,7 +1099,8 @@ int SerialPnp_CreatePnpInterface(PNPADAPTER_CONTEXT AdapterHandle, PNPMESSAGE ms
}
if (propertyCount > 0) {
dtRes = DigitalTwin_InterfaceClient_SetPropertiesUpdatedCallbacks(pnpInterfaceClient, &serialPropertyTable);
dtRes = DigitalTwin_InterfaceClient_SetPropertiesUpdatedCallback(pnpInterfaceClient,
SerialPnp_PropertyUpdateHandler);
if (DIGITALTWIN_CLIENT_OK != dtRes) {
result = -1;
goto exit;
@ -1182,7 +1108,8 @@ int SerialPnp_CreatePnpInterface(PNPADAPTER_CONTEXT AdapterHandle, PNPMESSAGE ms
}
if (commandCount > 0) {
dtRes = DigitalTwin_InterfaceClient_SetCommandsCallbacks(pnpInterfaceClient, &serialCommandTable);
dtRes = DigitalTwin_InterfaceClient_SetCommandsCallback(pnpInterfaceClient,
SerialPnp_CommandUpdateHandler);
if (DIGITALTWIN_CLIENT_OK != dtRes) {
result = -1;
goto exit;
@ -1203,20 +1130,6 @@ int SerialPnp_CreatePnpInterface(PNPADAPTER_CONTEXT AdapterHandle, PNPMESSAGE ms
}
}
if (NULL != propertyUpdateTable) {
free(propertyUpdateTable);
}
if (NULL != propertyNames) {
free(propertyNames);
}
if (NULL != commandUpdateTable) {
free(commandUpdateTable);
}
if (NULL != commandNames) {
free(commandNames);
}
// Save the PnpAdapterInterface in device context
deviceContext->pnpAdapterInterface = pnpAdapterInterface;

Просмотреть файл

@ -62,6 +62,8 @@ set(pnp_bridge_INC_FOLDER ${CMAKE_CURRENT_LIST_DIR} CACHE INTERNAL "this is what
include_directories(inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/deps/parson)
include_directories(../../deps/azure-iot-sdk-c-pnp/c-utility/inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/c-utility/deps/azure-macro-utils-c/inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/c-utility/deps/umock-c/inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/digitaltwin_client/inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/iothub_client/inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/provisioning_client/inc)
@ -87,17 +89,11 @@ set(pnp_bridge_common_libs
prov_device_client
prov_mqtt_transport
utpm
pnpbridge_adapters
pnpbridge_serial
digitaltwin_client
)
if(WIN32)
set(pnp_bridge_common_libs
${pnp_bridge_common_libs}
pnpbridge_modbus
pnpbridge_camera
pnpbridge_coredevicehealth
)
endif()

Просмотреть файл

@ -8,6 +8,9 @@ extern "C"
{
#endif
#include "azure_macro_utils/macro_utils.h"
#include "umock_c/umock_c_prod.h"
// AUTH mechanisms for connecting to IOT device
typedef enum AUTH_TYPE {
AUTH_TYPE_TPM,
@ -125,21 +128,53 @@ PCONNECTION_PARAMETERS PnpBridgeConfig_GetConnectionDetails(JSON_Object* Connect
*
* @returns PNPBRIDGE_OK on success and other PNPBRIDGE_RESULT values on failure.
*/
PNPBRIDGE_RESULT PnpBridgeConfig_RetrieveConfiguration(JSON_Value* ConfigJson, PNPBRIDGE_CONFIGURATION* BridgeConfig);
MOCKABLE_FUNCTION(,
PNPBRIDGE_RESULT,
PnpBridgeConfig_RetrieveConfiguration,
JSON_Value*, ConfigJson,
PNPBRIDGE_CONFIGURATION*, BridgeConfig
);
JSON_Object* Configuration_GetMatchParametersForDevice(JSON_Object* device);
MOCKABLE_FUNCTION(,
JSON_Object*,
Configuration_GetMatchParametersForDevice,
JSON_Object*, device
);
JSON_Object* Configuration_GetDiscoveryParametersForDevice(JSON_Object* device);
MOCKABLE_FUNCTION(,
JSON_Object*,
Configuration_GetDiscoveryParametersForDevice,
_In_ JSON_Object*, device
);
JSON_Object* Configuration_GetPnpParametersForDevice(JSON_Object* device);
MOCKABLE_FUNCTION(,
JSON_Object*,
Configuration_GetPnpParametersForDevice,
JSON_Object*, device
);
JSON_Object* Configuration_GetPnpParameters(JSON_Value* config, const char* identity);
MOCKABLE_FUNCTION(,
JSON_Object*,
Configuration_GetPnpParameters,
JSON_Value*, config, const char*, identity
);
JSON_Object* Configuration_GetDiscoveryParameters(JSON_Value* config, const char *identity);
MOCKABLE_FUNCTION(,
JSON_Object*,
Configuration_GetDiscoveryParameters,
JSON_Value*, config, const char, *identity
);
JSON_Array* Configuration_GetConfiguredDevices(JSON_Value* config);
MOCKABLE_FUNCTION(,
JSON_Array*,
Configuration_GetConfiguredDevices, JSON_Value*, config
);
PNPBRIDGE_RESULT Configuration_IsDeviceConfigured(JSON_Value* config, JSON_Object* Message, JSON_Object** Device);
MOCKABLE_FUNCTION(,
PNPBRIDGE_RESULT,
Configuration_IsDeviceConfigured,
JSON_Value*, config, JSON_Object*, Message, JSON_Object**, Device
);
#ifdef __cplusplus
}

Просмотреть файл

@ -13,6 +13,9 @@ TODOC: PROVIDE DETAILS OF PNPMESSAGE
#ifndef PNPBRIDGE_DISCOVERY_ADAPTER_INTERFACE_H
#define PNPBRIDGE_DISCOVERY_ADAPTER_INTERFACE_H
#include "azure_macro_utils/macro_utils.h"
#include "umock_c/umock_c_prod.h"
#ifdef __cplusplus
extern "C"
{
@ -78,9 +81,11 @@ typedef int
* @returns integer greater than zero on success and other values on failure.
*/
int
DiscoveryAdapter_ReportDevice(
_In_ PNPMESSAGE Message
MOCKABLE_FUNCTION(,
int,
DiscoveryAdapter_ReportDevice,
_In_ PNPMESSAGE, Message
);
typedef struct _DISCOVERY_ADAPTER {

Просмотреть файл

@ -1,6 +1,9 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#ifndef PNPBRIDGE_NOSAL_H
#define PNPBRIDGE_NOSAL_H
#ifdef __cplusplus
extern "C"
{
@ -34,4 +37,6 @@ extern "C"
#ifdef __cplusplus
}
#endif
#endif
#endif //PNPBRIDGE_NOSAL_H

Просмотреть файл

@ -4,6 +4,9 @@
#ifndef PNPBRIDGE_PNP_ADAPTER_INTERFACE_H
#define PNPBRIDGE_PNP_ADAPTER_INTERFACE_H
#include "azure_macro_utils/macro_utils.h"
#include "umock_c/umock_c_prod.h"
#ifdef __cplusplus
extern "C"
{
@ -121,10 +124,11 @@ PNPADPATER_INTERFACE_PARAMS_INIT(
*
* @returns Result indicating status of pnp adapter interface creation
*/
int
PnpAdapterInterface_Create(
PPNPADPATER_INTERFACE_PARAMS params,
PPNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface
MOCKABLE_FUNCTION(,
int,
PnpAdapterInterface_Create,
PPNPADPATER_INTERFACE_PARAMS, params,
PPNPADAPTER_INTERFACE_HANDLE, pnpAdapterInterface
);
/**
@ -133,7 +137,11 @@ PnpAdapterInterface_Create(
* @param pnpAdapterInterface Handle to pnp adapter interface
*
*/
void PnpAdapterInterface_Destroy(PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface);
MOCKABLE_FUNCTION(,
void,
PnpAdapterInterface_Destroy,
PNPADAPTER_INTERFACE_HANDLE, pnpAdapterInterface
);
/**
* @brief PnpAdapter_GetPnpInterfaceClient gets the Azure iot pnp interface client handle
@ -142,7 +150,11 @@ void PnpAdapterInterface_Destroy(PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface
*
* @returns Handle to Azure Pnp Interface client
*/
DIGITALTWIN_INTERFACE_CLIENT_HANDLE PnpAdapterInterface_GetPnpInterfaceClient(PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface);
MOCKABLE_FUNCTION(,
DIGITALTWIN_INTERFACE_CLIENT_HANDLE,
PnpAdapterInterface_GetPnpInterfaceClient,
PNPADAPTER_INTERFACE_HANDLE, pnpAdapterInterface
);
/**
* @brief PnpAdapter_SetContext sets a context for pnp adapter interface handle
@ -153,7 +165,12 @@ DIGITALTWIN_INTERFACE_CLIENT_HANDLE PnpAdapterInterface_GetPnpInterfaceClient(PN
*
* @returns integer greater than zero on success and other values on failure.
*/
int PnpAdapterInterface_SetContext(PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface, void* context);
MOCKABLE_FUNCTION(,
int,
PnpAdapterInterface_SetContext,
PNPADAPTER_INTERFACE_HANDLE, pnpAdapterInterface,
void*, context
);
/**
* @brief PnpAdapter_GetContext gets context set by pnp adapter.
@ -164,7 +181,11 @@ int PnpAdapterInterface_SetContext(PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterfa
*
* @returns void* context
*/
void* PnpAdapterInterface_GetContext(PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface);
MOCKABLE_FUNCTION(,
void*,
PnpAdapterInterface_GetContext,
PNPADAPTER_INTERFACE_HANDLE, pnpAdapterInterface
);
/*
PnpAdapter Binding info

Просмотреть файл

@ -12,41 +12,47 @@
#ifndef PNPBRIDGE_H
#define PNPBRIDGE_H
#if !defined(_MSC_VER)
#include <nosal.h>
#endif
#include "azure_macro_utils/macro_utils.h"
#include "umock_c/umock_c_prod.h"
#include <digitaltwin_interface_client.h>
#include <pnpbridge_memory.h>
#include <pnpmessage_api.h>
#include <discoveryadapter_api.h>
#include <pnpadapter_api.h>
#ifdef __cplusplus
extern "C"
{
#endif
#if !defined(_MSC_VER)
#include <nosal.h>
#endif
#include <pnpbridge_memory.h>
typedef void* MX_IOT_HANDLE;
DIGITALTWIN_DEVICE_CLIENT_HANDLE IotHandle_GetPnpDeviceClient(MX_IOT_HANDLE IotHandle);
// Getter method for DigitalTwin client handle from a device/module
MOCKABLE_FUNCTION(,
DIGITALTWIN_DEVICE_CLIENT_HANDLE,
IotHandle_GetPnpDeviceClient,
_In_ MX_IOT_HANDLE, IotHandle
);
#include <pnpmessage_api.h>
#include <discoveryadapter_api.h>
#include <pnpadapter_api.h>
MOCKABLE_FUNCTION(, int, PnpBridge_Main);
int
PnpBridge_Main();
MOCKABLE_FUNCTION(, void, PnpBridge_Stop);
void
PnpBridge_Stop();
int
PnpBridge_UploadToBlobAsync(
const char* pszDestination,
const unsigned char* pbData,
size_t cbData,
IOTHUB_CLIENT_FILE_UPLOAD_CALLBACK iotHubClientFileUploadCallback,
void* context
);
MOCKABLE_FUNCTION(,
int,
PnpBridge_UploadToBlobAsync,
const char*, pszDestination,
const unsigned char*, pbData,
size_t, cbData,
IOTHUB_CLIENT_FILE_UPLOAD_CALLBACK, iotHubClientFileUploadCallback,
void*, context
);
#ifdef __cplusplus
}

Просмотреть файл

@ -13,11 +13,15 @@ extern "C"
#include <stdio.h>
#if !defined(_MSC_VER)
#include <nosal.h>
#endif
#include "azure_c_shared_utility/gballoc.h"
#include "azure_c_shared_utility/xlogging.h"
#include "azure_c_shared_utility/macro_utils.h"
#include "azure_c_shared_utility/umock_c_prod.h"
#include "azure_macro_utils/macro_utils.h"
#include "umock_c/umock_c_prod.h"
#include "iothub_transport_ll.h"
#include "iothub_message.h"
@ -38,13 +42,14 @@ extern "C"
#include <iothubtransportmqtt.h>
#include <digitaltwin_device_client.h>
#include <digitaltwin_module_client.h>
#include <digitaltwin_interface_client.h>
#include "parson.h"
#include <assert.h>
#define DIGITALTWIN_MODULE_CLIENT_HANDLE void*
#define TRY
#define LEAVE goto __tryLabel;
#define FINALLY goto __tryLabel; __tryLabel:
@ -55,6 +60,7 @@ extern "C"
PNPBRIDGE_OK, \
PNPBRIDGE_INSUFFICIENT_MEMORY, \
PNPBRIDGE_FILE_NOT_FOUND, \
PNPBRIDGE_NOT_SUPPORTED, \
PNPBRIDGE_INVALID_ARGS, \
PNPBRIDGE_CONFIG_READ_FAILED, \
PNPBRIDGE_DUPLICATE_ENTRY, \
@ -99,6 +105,7 @@ int Map_GetIndexValueFromKey(MAP_HANDLE handle, const char* key);
#define PNP_CONFIG_DEVICES "devices"
#define PNP_CONFIG_IDENTITY "identity"
#define PNP_CONFIG_INTERFACE_ID "interface_id"
#define PNP_CONFIG_COMPONENT_NAME "component_name"
#define PNP_CONFIG_PUBLISH_MODE "publish_mode"
#define PNP_CONFIG_MATCH_FILTERS "match_filters"
#define PNP_CONFIG_MATCH_TYPE "match_type"
@ -159,7 +166,9 @@ typedef struct _MESSAGE_QUEUE {
LOCK_HANDLE QueueLock;
int PublishCount;
volatile int PublishCount;
volatile int InCount;
THREAD_HANDLE Worker;
@ -177,6 +186,11 @@ PnpMessageQueue_Create(
PMESSAGE_QUEUE* PnpMessageQueue
);
void
PnpMessageQueue_Release(
PMESSAGE_QUEUE Queue
);
// Thread entry callback
int
PnpMessageQueue_Worker(
@ -195,22 +209,12 @@ PnpMesssageQueue_Remove(
PNPMESSAGE* PnpMessage
);
PDLIST_ENTRY
PnpMesssageQueue_GetPublishQ(
PMESSAGE_QUEUE Queue
);
PNPBRIDGE_RESULT
PnpMesssageQueue_AddToPublishQ(
PMESSAGE_QUEUE Queue,
PNPMESSAGE PnpMessage
);
void
PnpMessageQueue_Release(
PMESSAGE_QUEUE Queue
);
int PnpBridge_ProcessPnpMessage(PNPMESSAGE PnpMessage);
int

Просмотреть файл

@ -35,8 +35,6 @@ typedef struct _PNP_BRIDGE {
void PnpBridge_Release(PPNP_BRIDGE pnpBridge);
int PnpMessage_SetInterfaceId(PNPMESSAGE Message, const char* InterfaceId);
#ifdef __cplusplus
}
#endif

Просмотреть файл

@ -20,10 +20,22 @@ typedef enum _PNPMESSAGE_CHANGE_TYPE {
typedef struct _PNPMESSAGE_CHANGE_PROPERTIES {
void* Context;
PNPMESSAGE_CHANGE_TYPE ChangeType;
char* ComponentName;
} PNPMESSAGE_PROPERTIES;
typedef void* PNPMESSAGE;
const char*
PnpMessage_GetInterfaceId(
_In_ PNPMESSAGE Message
);
int
PnpMessage_SetInterfaceId(
PNPMESSAGE Message,
const char* InterfaceId
);
int
PnpMessage_CreateMessage(
_Out_ PNPMESSAGE* Message
@ -35,18 +47,7 @@ PnpMessage_SetMessage(
const char* Payload
);
int
PnpMessage_SetInterfaceId(
_In_ PNPMESSAGE Message,
_In_ const char* InterfaceId
);
char*
PnpMessage_GetInterfaceId(
_In_ PNPMESSAGE Message
);
char*
const char*
PnpMessage_GetMessage(
_In_ PNPMESSAGE Message
);

Просмотреть файл

@ -43,6 +43,8 @@ set(pnp_bridge_INC_FOLDER ${CMAKE_CURRENT_LIST_DIR} CACHE INTERNAL "this is what
include_directories(inc)
include_directories(../../../../deps/azure-iot-sdk-c-pnp/deps/parson)
include_directories(../../../../deps/azure-iot-sdk-c-pnp/c-utility/inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/c-utility/deps/azure-macro-utils-c/inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/c-utility/deps/umock-c/inc)
include_directories(../../../../deps/azure-iot-sdk-c-pnp/digitaltwin_client/inc)
include_directories(../../../../deps/azure-iot-sdk-c-pnp/iothub_client/inc)
include_directories(../../../../deps/azure-iot-sdk-c-pnp/provisioning_client/inc)
@ -70,8 +72,8 @@ set(pnp_bridge_common_libs
utpm
pnpbridge
pnpbridge_adapters
pnpbridge_serial
digitaltwin_client
pnpbridge_serial
)
if(WIN32)

Просмотреть файл

@ -30,7 +30,8 @@
"hardware_id": "USB\\VID_06CB&PID_00B3"
}
},
"interface_id": "http://windows.com/coredevicehealth/1.0.0",
"interface_id": "urn:contoso:com:coredevicehealth:1",
"component_name": "MyComponent1",
"pnp_parameters": {
"identity": "core-device-health"
}
@ -41,6 +42,7 @@
"match_type": "exact"
},
"self_describing": "true",
"component_name": "MyComponent2",
"pnp_parameters": {
"identity": "modbus-pnp-interface"
},
@ -56,7 +58,7 @@
}
},
"interfaceConfig": {
"interfaceId": "http://contoso.com/Co2Detector/1.0.0",
"interfaceId": "urn:contoso:com:Co2Detector:1",
"telemetry": {
"co2": {
"startAddress": "40001",
@ -124,6 +126,7 @@
"match_type": "exact"
},
"self_describing": "true",
"component_name": "MyComponent3",
"pnp_parameters": {
"identity": "serial-pnp-interface"
},
@ -143,7 +146,8 @@
"hardware_id": "UVC_Webcam_00"
}
},
"interface_id": "http://windows.com/camera_health_monitor/1.0.0",
"interface_id": "urn:contoso:com:camera_health_monitor:1",
"component_name": "MyComponent4",
"pnp_parameters": {
"identity": "camera-health-monitor"
}

Просмотреть файл

@ -15,6 +15,7 @@ BOOL WINAPI CtrlHandler(DWORD fdwCtrlType)
default:
return FALSE;
//
}
}
#else

Просмотреть файл

@ -49,6 +49,8 @@ set(pnp_bridge_INC_FOLDER ${CMAKE_CURRENT_LIST_DIR} CACHE INTERNAL "this is what
include_directories(inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/deps/parson)
include_directories(../../deps/azure-iot-sdk-c-pnp/c-utility/inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/c-utility/deps/azure-macro-utils-c/inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/c-utility/deps/umock-c/inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/digitaltwin_client/inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/iothub_client/inc)
include_directories(../../deps/azure-iot-sdk-c-pnp/provisioning_client/inc)

Просмотреть файл

@ -382,7 +382,10 @@ JSON_Object* Configuration_GetMatchParametersForDevice(JSON_Object* device)
return matchParams;
}
JSON_Object* Configuration_GetDiscoveryParametersForDevice(JSON_Object* device)
JSON_Object*
Configuration_GetDiscoveryParametersForDevice(
_In_ JSON_Object* device
)
{
if (device == NULL) {
return NULL;

Просмотреть файл

@ -59,8 +59,15 @@ PNPBRIDGE_RESULT DiscoveryAdapterManager_Create(PDISCOVERY_MANAGER* discoveryMan
return PNPBRIDGE_OK;
}
PNPBRIDGE_RESULT DiscoveryManager_StarDiscoveryAdapter(PDISCOVERY_MANAGER discoveryManager, PDISCOVERY_ADAPTER discoveryInterface,
SINGLYLINKEDLIST_HANDLE DeviceAdapterParamsList, int DeviceAdapterParamsCount, JSON_Object* adapterParams, int key)
PNPBRIDGE_RESULT
DiscoveryManager_StarDiscoveryAdapter(
PDISCOVERY_MANAGER discoveryManager,
PDISCOVERY_ADAPTER discoveryInterface,
SINGLYLINKEDLIST_HANDLE DeviceAdapterParamsList,
int DeviceAdapterParamsCount,
JSON_Object* adapterParams,
int key
)
{
PNPBRIDGE_RESULT result = PNPBRIDGE_OK;
char* adapterParamString = NULL;

Просмотреть файл

@ -248,7 +248,9 @@ IotComms_PnPInterfaceRegisteredCallback(
{
PPNP_REGISTRATION_CONTEXT registrationContext = (PPNP_REGISTRATION_CONTEXT)userContextCallback;
registrationContext->RegistrationStatus = (pnpInterfaceStatus == DIGITALTWIN_CLIENT_OK) ? APP_PNP_REGISTRATION_SUCCEEDED : APP_PNP_REGISTRATION_FAILED;
Lock(registrationContext->Lock);
Condition_Post(registrationContext->Condition);
Unlock(registrationContext->Lock);
}
#define DIGITALTWIN_SAMPLE_DEVICE_CAPABILITY_MODEL_URI "http://azureiot.com/TestDeviceCapabilityModule/1.0.0"
@ -270,7 +272,6 @@ IotComms_RegisterPnPInterfaces(
callbackContext.RegistrationStatus = APP_PNP_REGISTRATION_PENDING;
callbackContext.Condition = Condition_Init();
callbackContext.Lock = Lock_Init();
Lock(callbackContext.Lock);
// DigitalTwinClient doesn't support incremental publishing of PnP Interface
// Inorder to workaround this we will destroy the DigitalTwinClient and recreate it
@ -283,9 +284,8 @@ IotComms_RegisterPnPInterfaces(
InterfaceCount, IotComms_PnPInterfaceRegisteredCallback, &callbackContext);
}
else {
pnpResult = DigitalTwin_ModuleClient_RegisterInterfacesAsync(
IotHandle->u1.IotModule.pnpModuleClientHandle, DIGITALTWIN_SAMPLE_DEVICE_CAPABILITY_MODEL_URI, Interfaces,
InterfaceCount, IotComms_PnPInterfaceRegisteredCallback, &callbackContext);
LogError("Module support is not present in public preview");
pnpResult = PNPBRIDGE_NOT_SUPPORTED;
}
if (DIGITALTWIN_CLIENT_OK != pnpResult) {
@ -293,7 +293,9 @@ IotComms_RegisterPnPInterfaces(
goto end;
}
Lock(callbackContext.Lock);
Condition_Wait(callbackContext.Condition, callbackContext.Lock, 0);
Unlock(callbackContext.Lock);
if (callbackContext.RegistrationStatus != APP_PNP_REGISTRATION_SUCCEEDED) {
LogError("PnP has failed to register.\n");
@ -385,44 +387,6 @@ IOTHUB_DEVICE_HANDLE IotComms_InitializeIotDevice(bool TraceOn, PCONNECTION_PARA
return NULL;
}
PNPBRIDGE_RESULT IotComms_InitializeIotModuleHandle(MX_IOT_HANDLE_TAG* IotHandle, bool TraceOn, PCONNECTION_PARAMETERS ConnectionParams)
{
PNPBRIDGE_RESULT result = PNPBRIDGE_OK;
TRY {
// Mark this handle as module
IotHandle->IsModule = true;
AZURE_UNREFERENCED_PARAMETER(TraceOn);
AZURE_UNREFERENCED_PARAMETER(ConnectionParams);
// Connect to Iot Hub Module
IotHandle->u1.IotModule.moduleHandle = IoTHubModuleClient_CreateFromEnvironment(MQTT_Protocol);
if (NULL == IotHandle->u1.IotModule.moduleHandle) {
LogError("IoTHubModuleClient_CreateFromEnvironment failed\n");
result = PNPBRIDGE_FAILED;
LEAVE;
}
// Create PnpModuleClient
if (DIGITALTWIN_CLIENT_OK != DigitalTwin_ModuleClient_CreateFromModuleHandle(
IotHandle->u1.IotModule.moduleHandle, &IotHandle->u1.IotModule.pnpModuleClientHandle))
{
LogError("PnP_ModuleClient_CreateFromModuleHandle failed\n");
result = PNPBRIDGE_FAILED;
LEAVE;
}
// We have completed initializing the pnp client
IotHandle->DeviceClientInitialized = true;
} FINALLY {
}
return result;
}
PNPBRIDGE_RESULT
IotComms_InitializeIotDeviceHandle(
MX_IOT_HANDLE_TAG* IotHandle,
@ -470,12 +434,7 @@ IotComms_DigitalTwinClient_Initalize(
}
}
else {
if (DIGITALTWIN_CLIENT_OK != DigitalTwin_ModuleClient_CreateFromModuleHandle(
IotHandle->u1.IotDevice.deviceHandle, &IotHandle->u1.IotModule.pnpModuleClientHandle))
{
LogError("DigitalTwin_ModuleClient_CreateFromModuleHandle failed\n");
result = PNPBRIDGE_FAILED;
}
result = PNPBRIDGE_NOT_SUPPORTED;
}
IotHandle->DigitalTwinClientInitialized = (PNPBRIDGE_OK == result);
@ -493,7 +452,7 @@ IotComms_DigitalTwinClient_Destroy(
DigitalTwin_DeviceClient_Destroy(IotHandle->u1.IotDevice.PnpDeviceClientHandle);
}
else {
DigitalTwin_ModuleClient_Destroy(IotHandle->u1.IotModule.moduleHandle);
LogError("Module support is not present in public preview");
}
}
@ -503,7 +462,7 @@ IotComms_DigitalTwinClient_Destroy(
PNPBRIDGE_RESULT IotComms_InitializeIotHandle(MX_IOT_HANDLE_TAG* IotHandle, bool TraceOn, PCONNECTION_PARAMETERS ConnectionParams)
{
if (ConnectionParams->ConnectionType == CONNECTION_TYPE_EDGE_MODULE) {
return IotComms_InitializeIotModuleHandle(IotHandle, TraceOn, ConnectionParams);
return PNPBRIDGE_NOT_SUPPORTED;
}
else {
return IotComms_InitializeIotDeviceHandle(IotHandle, TraceOn, ConnectionParams);

Просмотреть файл

@ -126,7 +126,11 @@ void* PnpAdapterInterface_GetContext(PNPADAPTER_INTERFACE_HANDLE pnpAdapterInter
return adapterInterface->context;
}
DIGITALTWIN_DEVICE_CLIENT_HANDLE IotHandle_GetPnpDeviceClient(MX_IOT_HANDLE IotHandle) {
DIGITALTWIN_DEVICE_CLIENT_HANDLE
IotHandle_GetPnpDeviceClient(
MX_IOT_HANDLE IotHandle
)
{
MX_IOT_HANDLE_TAG* iotHandle = (MX_IOT_HANDLE_TAG*)IotHandle;
return iotHandle->u1.IotDevice.PnpDeviceClientHandle;

Просмотреть файл

@ -251,9 +251,10 @@ PnpBridge_ProcessPnpMessage(
// Create an Pnp interface
char* interfaceId = NULL;
char* componentName = NULL;
char* selfDescribing = (char*)json_object_get_string(jdevice, PNP_CONFIG_SELF_DESCRIBING);
if (NULL != selfDescribing && 0 == strcmp(selfDescribing, "true")) {
interfaceId = (char*)json_object_get_string(jobj, "InterfaceId");
interfaceId = msg->InterfaceId;
if (NULL == interfaceId) {
LogError("Interface id is missing for self descrbing device");
result = PNPBRIDGE_INVALID_ARGS;
@ -268,8 +269,18 @@ PnpBridge_ProcessPnpMessage(
LEAVE;
}
componentName = (char*)json_object_get_string(jdevice, PNP_CONFIG_COMPONENT_NAME);
if (NULL == interfaceId) {
LogError("Interface Id is missing in config for the device");
result = PNPBRIDGE_INVALID_ARGS;
LEAVE;
}
// Add interfaceId to the message
PnpMessage_SetInterfaceId(PnpMessage, interfaceId);
// Add the component name
mallocAndStrcpy_s(&PnpMessage_AccessProperties(PnpMessage)->ComponentName, componentName);
}
if (PnpAdapterManager_IsInterfaceIdPublished(pnpBridge->PnpMgr, interfaceId)) {
@ -355,10 +366,9 @@ DiscoveryAdapter_ReportDevice(
PnpMesssageQueue_Add(queue, PnpMessage);
// Notify the worker
Lock(queue->WaitConditionLock);
Condition_Post(queue->WaitCondition);
Lock(queue->WaitCondition);
Condition_Post(queue->WaitCondition);
Unlock(queue->WaitCondition);
Unlock(queue->WaitConditionLock);
return 0;
}
@ -404,7 +414,9 @@ PnpBridge_Main()
// Prevent main thread from returning by waiting for the
// exit condition to be set. This condition will be set when
// the bridge has received a stop signal
Lock(pnpBridge->ExitLock);
Condition_Wait(pnpBridge->ExitCondition, pnpBridge->ExitLock, 0);
Unlock(pnpBridge->ExitLock);
} FINALLY {
g_PnpBridge = NULL;
@ -424,7 +436,9 @@ PnpBridge_Stop()
if (PNP_BRIDGE_TEARING_DOWN != g_PnpBridgeState) {
g_PnpBridgeState = PNP_BRIDGE_TEARING_DOWN;
Lock(g_PnpBridge->ExitLock);
Condition_Post(g_PnpBridge->ExitCondition);
Unlock(g_PnpBridge->ExitLock);
}
}

Просмотреть файл

@ -3,7 +3,7 @@
// Custom destroy method for PNPMESSAGE's PNPMEMORY
void
PnpMessage_Destroy(
PNPMEMORY Message
_In_ PNPMEMORY Message
)
{
PPNPBRIDGE_CHANGE_PAYLOAD msg = (PPNPBRIDGE_CHANGE_PAYLOAD)PnpMemory_GetBuffer(Message, NULL);
@ -15,10 +15,21 @@ PnpMessage_Destroy(
if (msg->InterfaceId) {
free((void*)msg->InterfaceId);
}
if (msg->Properties.ComponentName) {
free(msg->Properties.ComponentName);
}
}
const char* PnpMessage_GetMessageBuffer(PNPMESSAGE Message, int *Length) {
PPNPBRIDGE_CHANGE_PAYLOAD msg = (PPNPBRIDGE_CHANGE_PAYLOAD) PnpMemory_GetBuffer(Message, NULL);
const char*
PnpMessage_GetMessageBuffer(
_In_ PNPMESSAGE Message,
_Out_opt_ int *Length
)
{
PPNPBRIDGE_CHANGE_PAYLOAD msg;
msg = (PPNPBRIDGE_CHANGE_PAYLOAD) PnpMemory_GetBuffer(Message, NULL);
if (Length) {
*Length = msg->MessageLength;
@ -26,7 +37,11 @@ const char* PnpMessage_GetMessageBuffer(PNPMESSAGE Message, int *Length) {
return msg->Message;
}
int PnpMessage_CreateMessage(PNPMESSAGE* Message) {
int
PnpMessage_CreateMessage(
_In_ PNPMESSAGE* Message
)
{
PNPMEMORY_ATTRIBUTES attrib = { 0 };
PNPMESSAGE* message = NULL;
attrib.destroyCallback = PnpMessage_Destroy;
@ -44,8 +59,17 @@ int PnpMessage_CreateMessage(PNPMESSAGE* Message) {
return 0;
}
int PnpMessage_SetMessage(PNPMESSAGE Message, const char* payload) {
PPNPBRIDGE_CHANGE_PAYLOAD msg = (PPNPBRIDGE_CHANGE_PAYLOAD)PnpMemory_GetBuffer(Message, NULL);
int
PnpMessage_SetMessage(
_In_ PNPMESSAGE Message,
_In_ const char* payload
)
{
PPNPBRIDGE_CHANGE_PAYLOAD msg;
assert(NULL != Message);
msg = (PPNPBRIDGE_CHANGE_PAYLOAD)PnpMemory_GetBuffer(Message, NULL);
// Allocate memory for the payload
int length = (int) strlen(payload);
@ -60,9 +84,16 @@ int PnpMessage_SetMessage(PNPMESSAGE Message, const char* payload) {
return 0;
}
char* PnpMessage_GetMessage(PNPMESSAGE Message)
const char*
PnpMessage_GetMessage(
_In_ PNPMESSAGE Message
)
{
PPNPBRIDGE_CHANGE_PAYLOAD msg = (PPNPBRIDGE_CHANGE_PAYLOAD)PnpMemory_GetBuffer(Message, NULL);
PPNPBRIDGE_CHANGE_PAYLOAD msg;
assert(NULL != Message);
msg = (PPNPBRIDGE_CHANGE_PAYLOAD)PnpMemory_GetBuffer(Message, NULL);
return (char*) msg->Message;
}
@ -73,7 +104,11 @@ PnpMessage_SetInterfaceId(
const char* InterfaceId
)
{
PPNPBRIDGE_CHANGE_PAYLOAD msg = (PPNPBRIDGE_CHANGE_PAYLOAD)PnpMemory_GetBuffer(Message, NULL);
PPNPBRIDGE_CHANGE_PAYLOAD msg;
assert(NULL != Message);
msg = (PPNPBRIDGE_CHANGE_PAYLOAD)PnpMemory_GetBuffer(Message, NULL);
// Allocate memory for the payload
int length = (int) strlen(InterfaceId);
@ -87,9 +122,9 @@ PnpMessage_SetInterfaceId(
return 0;
}
char*
const char*
PnpMessage_GetInterfaceId(
PNPMESSAGE Message
_In_ PNPMESSAGE Message
)
{
PPNPBRIDGE_CHANGE_PAYLOAD msg = NULL;
@ -102,7 +137,7 @@ PnpMessage_GetInterfaceId(
PNPMESSAGE_PROPERTIES*
PnpMessage_AccessProperties(
PNPMESSAGE Message
_In_ PNPMESSAGE Message
)
{
PPNPBRIDGE_CHANGE_PAYLOAD msg = NULL;
@ -115,15 +150,15 @@ PnpMessage_AccessProperties(
void
PnpMessage_AddReference(
PNPMESSAGE Message
)
_In_ PNPMESSAGE Message
)
{
PnpMemory_AddReference(Message);
}
void
PnpMessage_ReleaseReference(
PNPMESSAGE Message
_In_ PNPMESSAGE Message
)
{
PnpMemory_ReleaseReference(Message);
@ -131,7 +166,7 @@ PnpMessage_ReleaseReference(
int
PnpMessageQueue_Worker(
void* threadArgument
_In_ void* threadArgument
)
{
PMESSAGE_QUEUE queue = NULL;
@ -143,11 +178,19 @@ PnpMessageQueue_Worker(
PNPMESSAGE message = NULL;
// TODO: check status
Condition_Wait(queue->WaitCondition, queue->WaitConditionLock, 0);
Lock(queue->WaitConditionLock);
if (queue->TearDown) {
Unlock(queue->WaitConditionLock);
ThreadAPI_Exit(0);
}
if (0 == queue->InCount) {
Condition_Wait(queue->WaitCondition, queue->WaitConditionLock, 0);
}
Unlock(queue->WaitConditionLock);
// Due to SDK limitation of not being able to incrementally publish
// interface unload all Pnp adapters and re-init the interface
// Steps for this:
@ -169,7 +212,7 @@ PnpMessageQueue_Worker(
PnpMesssageQueue_AddToPublishQ(queue, message);
}
PDLIST_ENTRY head = PnpMesssageQueue_GetPublishQ(queue);
PDLIST_ENTRY head = &queue->PublishQueue;
PDLIST_ENTRY current = head->Flink;
while (current->Blink != head->Blink) {
PDLIST_ENTRY next = current->Flink;
@ -196,7 +239,7 @@ PnpMessageQueue_Worker(
PNPBRIDGE_RESULT
PnpMessageQueue_Create(
PMESSAGE_QUEUE* PnpMessageQueue
_In_ PMESSAGE_QUEUE* PnpMessageQueue
)
{
PMESSAGE_QUEUE queue = NULL;
@ -227,8 +270,6 @@ PnpMessageQueue_Create(
LEAVE;
}
Lock(queue->WaitConditionLock);
queue->WaitCondition = Condition_Init();
if (NULL == queue->WaitCondition) {
LogError("Failed to queue WaitCondition");
@ -278,6 +319,8 @@ PnpMesssageQueue_Add(
DList_AppendTailList(&Queue->IngressQueue, &msg->Entry);
Queue->InCount++;
// Release the queue lock
Unlock(Queue->QueueLock);
@ -286,11 +329,13 @@ PnpMesssageQueue_Add(
PNPBRIDGE_RESULT
PnpMesssageQueue_AddToPublishQ(
PMESSAGE_QUEUE Queue,
PNPMESSAGE PnpMessage
_In_ PMESSAGE_QUEUE Queue,
_In_ PNPMESSAGE PnpMessage
)
{
PPNPBRIDGE_CHANGE_PAYLOAD msg = (PPNPBRIDGE_CHANGE_PAYLOAD)PnpMemory_GetBuffer(PnpMessage, NULL);
PPNPBRIDGE_CHANGE_PAYLOAD msg;
msg = (PPNPBRIDGE_CHANGE_PAYLOAD) PnpMemory_GetBuffer(PnpMessage, NULL);
DList_InitializeListHead(&msg->Entry);
@ -301,18 +346,10 @@ PnpMesssageQueue_AddToPublishQ(
return PNPBRIDGE_OK;
}
PDLIST_ENTRY
PnpMesssageQueue_GetPublishQ(
PMESSAGE_QUEUE Queue
)
{
return &Queue->PublishQueue;
}
PNPBRIDGE_RESULT
PnpMesssageQueue_Remove(
PMESSAGE_QUEUE Queue,
PNPMESSAGE* PnpMessage
_In_ PMESSAGE_QUEUE Queue,
_Out_ PNPMESSAGE* PnpMessage
)
{
*PnpMessage = NULL;
@ -327,6 +364,7 @@ PnpMesssageQueue_Remove(
if (NULL != currentEntry) {
msg = containingRecord(currentEntry, PNPBRIDGE_CHANGE_PAYLOAD, Entry);
*PnpMessage = msg->Self;
Queue->InCount--;
}
}
@ -337,13 +375,16 @@ PnpMesssageQueue_Remove(
void
PnpMessageQueue_Release(
PMESSAGE_QUEUE Queue
_In_ PMESSAGE_QUEUE Queue
)
{
assert(NULL != Queue);
Queue->TearDown = true;
Lock(Queue->WaitConditionLock);
Condition_Post(Queue->WaitCondition);
Lock(Queue->WaitConditionLock);
// Wait for message queue worker to complete
if (NULL != Queue->Worker) {

Просмотреть файл

@ -3,14 +3,25 @@
#include "pnpbridge_common.h"
MAP_RESULT Map_Add_Index(MAP_HANDLE handle, const char* key, int value) {
MAP_RESULT
Map_Add_Index(
MAP_HANDLE handle,
const char* key,
int value
)
{
char str[12];
sprintf(str, "%d", value);
return Map_Add(handle, key, str);
}
int Map_GetIndexValueFromKey(MAP_HANDLE handle, const char* key) {
int
Map_GetIndexValueFromKey(
MAP_HANDLE handle,
const char* key
)
{
const char* index = Map_GetValueFromKey(handle, key);
return atoi(index);
}

Просмотреть файл

@ -37,15 +37,13 @@ static void my_gballoc_free(void* ptr)
#include "azure_c_shared_utility/crt_abstractions.h"
#include "azure_c_shared_utility/strings.h"
#include "iothub_module_client.h"
#include "internal/pnp_client_core.h"
#include "internal/lock_thread_binding_impl.h"
//#include "pnp_module_client.h"
#include "pnpbridge.h"
#include "pnpbridge_common.h"
#include "discovery_manager.h"
#include "discoveryadapter_manager.h"
#undef ENABLE_MOCKS
DISCOVERY_ADAPTER EnvironmentSensorDiscovery = {
@ -60,66 +58,19 @@ PDISCOVERY_ADAPTER DISCOVERY_ADAPTER_MANIFEST[] = {
const int DiscoveryAdapterCount = sizeof(DISCOVERY_ADAPTER_MANIFEST) / sizeof(PDISCOVERY_ADAPTER);
TEST_DEFINE_ENUM_TYPE(PNP_CLIENT_RESULT, PNP_CLIENT_RESULT_VALUES);
IMPLEMENT_UMOCK_C_ENUM_TYPE(PNP_CLIENT_RESULT, PNP_CLIENT_RESULT_VALUES);
#define PNP_TEST_INTERFACE_HANDLE1 ((PNP_INTERFACE_CLIENT_HANDLE)0x1001)
#define PNP_TEST_INTERFACE_HANDLE2 ((PNP_INTERFACE_CLIENT_HANDLE)0x1002)
#define PNP_TEST_INTERFACE_HANDLE3 ((PNP_INTERFACE_CLIENT_HANDLE)0x1003)
static PNP_INTERFACE_CLIENT_HANDLE testPnPInterfacesToRegister[] = {PNP_TEST_INTERFACE_HANDLE1, PNP_TEST_INTERFACE_HANDLE2, PNP_TEST_INTERFACE_HANDLE3 };
static const int testPnPInterfacesToRegisterLen = sizeof(testPnPInterfacesToRegister) / sizeof(testPnPInterfacesToRegister[0]);
static void* pnpTestModuleRegisterInterfaceCallbackContext = (void*)0x1236;
static const IOTHUB_MODULE_CLIENT_HANDLE testIotHubModuleHandle = (IOTHUB_MODULE_CLIENT_HANDLE)0x1236;
static void on_umock_c_error(UMOCK_C_ERROR_CODE error_code)
{
char temp_str[256];
(void)snprintf(temp_str, sizeof(temp_str), "umock_c reported error :%s", ENUM_TO_STRING(UMOCK_C_ERROR_CODE, error_code));
(void)snprintf(temp_str, sizeof(temp_str), "umock_c reported error :%s", MU_ENUM_TO_STRING(UMOCK_C_ERROR_CODE, error_code));
ASSERT_FAIL(temp_str);
}
DEFINE_ENUM_STRINGS(UMOCK_C_ERROR_CODE, UMOCK_C_ERROR_CODE_VALUES)
// Create a custom mock function to allocate a single byte (with a corresponding free mock function).
// This will make sure when Valgrind runs, it would catch handle leaks (which it wouldn't if this was the default mock)
static PNP_CLIENT_CORE_HANDLE test_PnP_ClientCore_Create(PNP_IOTHUB_BINDING* iotHubBinding)
{
(void)iotHubBinding;
return (PNP_CLIENT_CORE_HANDLE)my_gballoc_malloc(1);
}
static void test_PnP_ClientCore_Destroy(PNP_CLIENT_CORE_HANDLE pnpClientCoreHandle)
{
(void)pnpClientCoreHandle;
my_gballoc_free(pnpClientCoreHandle);
}
MU_DEFINE_ENUM_STRINGS(UMOCK_C_ERROR_CODE, UMOCK_C_ERROR_CODE_VALUES)
BEGIN_TEST_SUITE(pnpbridge_discovery_manager_ut)
TEST_SUITE_INITIALIZE(suite_init)
{
int result;
result = umock_c_init(on_umock_c_error);
ASSERT_ARE_EQUAL(int, 0, result);
REGISTER_UMOCK_ALIAS_TYPE(PNP_CLIENT_CORE_HANDLE, void*);
REGISTER_UMOCK_ALIAS_TYPE(PNP_INTERFACE_REGISTERED_CALLBACK, void*);
REGISTER_GLOBAL_MOCK_HOOK(gballoc_malloc, my_gballoc_malloc);
REGISTER_GLOBAL_MOCK_FAIL_RETURN(gballoc_malloc, NULL);
REGISTER_GLOBAL_MOCK_HOOK(gballoc_calloc, my_gballoc_calloc);
REGISTER_GLOBAL_MOCK_FAIL_RETURN(gballoc_calloc, NULL);
REGISTER_GLOBAL_MOCK_HOOK(gballoc_free, my_gballoc_free);
REGISTER_GLOBAL_MOCK_HOOK(PnP_ClientCore_Create, test_PnP_ClientCore_Create);
REGISTER_GLOBAL_MOCK_FAIL_RETURN(PnP_ClientCore_Create, NULL);
REGISTER_GLOBAL_MOCK_HOOK(PnP_ClientCore_Destroy, test_PnP_ClientCore_Destroy);
REGISTER_GLOBAL_MOCK_RETURN(PnP_ClientCore_RegisterInterfacesAsync, PNP_CLIENT_OK);
REGISTER_GLOBAL_MOCK_FAIL_RETURN(PnP_ClientCore_RegisterInterfacesAsync, PNP_CLIENT_ERROR);
}
TEST_FUNCTION_INITIALIZE(TestMethodInit)
@ -161,139 +112,5 @@ TEST_FUNCTION(PnpAdapterManager_InitializeAdapter_ok)
DiscoveryAdapterManager_Release(discoveryMgr);
}
// TEST_FUNCTION(PnP_ModuleClient_CreateFromModuleHandle_NULL_handle_fails)
// {
// // arrange
// PNP_MODULE_CLIENT_HANDLE h;
// //act
// h = PnP_ModuleClient_CreateFromModuleHandle(NULL);
// //assert
// ASSERT_IS_NULL(h);
// }
// TEST_FUNCTION(PnP_ModuleClient_CreateFromModuleHandle_fail)
// {
// // arrange
// int negativeTestsInitResult = umock_c_negative_tests_init();
// ASSERT_ARE_EQUAL(int, 0, negativeTestsInitResult);
// PNP_MODULE_CLIENT_HANDLE h;
// set_expected_calls_for_PnP_ModuleClient_CreateFromModuleHandle();
// umock_c_negative_tests_snapshot();
// size_t count = umock_c_negative_tests_call_count();
// for (size_t i = 0; i < count; i++)
// {
// char message[256];
// sprintf(message, "PnP_ModuleClient_CreateFromModuleHandle failure in test %lu", (unsigned long)i);
// umock_c_negative_tests_reset();
// umock_c_negative_tests_fail_call(i);
// h = PnP_ModuleClient_CreateFromModuleHandle(testIotHubModuleHandle);
// //assert
// ASSERT_IS_NULL(h);
// }
// //cleanup
// umock_c_negative_tests_deinit();
// }
// static PNP_MODULE_CLIENT_HANDLE allocate_PNP_MODULE_CLIENT_HANDLE_for_test()
// {
// PNP_MODULE_CLIENT_HANDLE h = PnP_ModuleClient_CreateFromModuleHandle(testIotHubModuleHandle);
// ASSERT_IS_NOT_NULL(h);
// umock_c_reset_all_calls();
// return h;
// }
// ///////////////////////////////////////////////////////////////////////////////
// // PnP_ModuleClient_Destroy
// ///////////////////////////////////////////////////////////////////////////////
// static void set_expected_calls_for_PnP_ModuleClient_Destroy()
// {
// STRICT_EXPECTED_CALL(PnP_ClientCore_Destroy(IGNORED_PTR_ARG));
// }
// TEST_FUNCTION(PnP_ModuleClient_Destroy_ok)
// {
// //arrange
// PNP_MODULE_CLIENT_HANDLE h = allocate_PNP_MODULE_CLIENT_HANDLE_for_test();
// set_expected_calls_for_PnP_ModuleClient_Destroy();
// //act
// PnP_ModuleClient_Destroy(h);
// //assert
// ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
// }
// ///////////////////////////////////////////////////////////////////////////////
// // PnP_ModuleClient_RegisterInterfacesAsync
// ///////////////////////////////////////////////////////////////////////////////
// static void pnpTestModuleRegisterInterfaceCallback(PNP_REPORTED_INTERFACES_STATUS pnpInterfaceStatus, void* userContextCallback)
// {
// (void)pnpInterfaceStatus;
// (void)userContextCallback;
// }
// static void set_expected_calls_for_PnP_ModuleClient_RegisterInterfacesAsync()
// {
// STRICT_EXPECTED_CALL(PnP_ClientCore_RegisterInterfacesAsync(IGNORED_PTR_ARG, testPnPInterfacesToRegister, testPnPInterfacesToRegisterLen, pnpTestModuleRegisterInterfaceCallback, pnpTestModuleRegisterInterfaceCallbackContext));
// }
// TEST_FUNCTION(PnP_ModuleClient_RegisterInterfacesAsync_ok)
// {
// // arrange
// PNP_MODULE_CLIENT_HANDLE h = allocate_PNP_MODULE_CLIENT_HANDLE_for_test();
// PNP_CLIENT_RESULT result;
// //act
// set_expected_calls_for_PnP_ModuleClient_RegisterInterfacesAsync();
// result = PnP_ModuleClient_RegisterInterfacesAsync(h, testPnPInterfacesToRegister, testPnPInterfacesToRegisterLen, pnpTestModuleRegisterInterfaceCallback, pnpTestModuleRegisterInterfaceCallbackContext);
// //assert
// ASSERT_ARE_EQUAL(PNP_CLIENT_RESULT, result, PNP_CLIENT_OK);
// ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
// //cleanup
// PnP_ModuleClient_Destroy(h);
// }
// TEST_FUNCTION(PnP_ModuleClient_RegisterInterfacesAsync_fail)
// {
// // arrange
// int negativeTestsInitResult = umock_c_negative_tests_init();
// ASSERT_ARE_EQUAL(int, 0, negativeTestsInitResult);
// PNP_MODULE_CLIENT_HANDLE h = allocate_PNP_MODULE_CLIENT_HANDLE_for_test();
// PNP_CLIENT_RESULT result;
// set_expected_calls_for_PnP_ModuleClient_RegisterInterfacesAsync();
// umock_c_negative_tests_snapshot();
// size_t count = umock_c_negative_tests_call_count();
// for (size_t i = 0; i < count; i++)
// {
// umock_c_negative_tests_reset();
// umock_c_negative_tests_fail_call(i);
// //act
// result = PnP_ModuleClient_RegisterInterfacesAsync(h, testPnPInterfacesToRegister, testPnPInterfacesToRegisterLen, pnpTestModuleRegisterInterfaceCallback, pnpTestModuleRegisterInterfaceCallbackContext);
// //assert
// ASSERT_ARE_NOT_EQUAL(PNP_CLIENT_RESULT, result, PNP_CLIENT_OK, "PnP_ModuleClient_RegisterInterfacesAsync failure in test %lu", (unsigned long)i);
// }
// //cleanup
// umock_c_negative_tests_deinit();
// PnP_ModuleClient_Destroy(h);
// }
END_TEST_SUITE(pnpbridge_discovery_manager_ut)