merge changes
This commit is contained in:
Коммит
a32409deed
|
@ -0,0 +1,44 @@
|
|||
cmake_minimum_required(VERSION 2.8.11)
|
||||
project(azure_iot_pnp_bridge)
|
||||
|
||||
if (POLICY CMP0042)
|
||||
cmake_policy(SET CMP0042 NEW)
|
||||
endif()
|
||||
|
||||
#
|
||||
#making a global variable to know if we are on linux, windows, or macosx.
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
set(WINDOWS TRUE)
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
set(LINUX TRUE)
|
||||
# on Linux, enable valgrind
|
||||
# these commands (MEMORYCHECK...) need to apear BEFORE include(CTest) or they will not have any effect
|
||||
find_program(MEMORYCHECK_COMMAND valgrind)
|
||||
set(MEMORYCHECK_COMMAND_OPTIONS "--leak-check=full --error-exitcode=1")
|
||||
elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||
set(MACOSX TRUE)
|
||||
add_definitions(-DMACOSX)
|
||||
endif()
|
||||
|
||||
|
||||
if (MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /wd4232")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4 /wd4232")
|
||||
# Make warning as error
|
||||
# add_definitions(/WX)
|
||||
else()
|
||||
# Make warning as error
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
|
||||
endif()
|
||||
|
||||
|
||||
IF(WIN32)
|
||||
# windows needs this define
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
set(skip_samples ON)
|
||||
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(deps/azure-iot-sdk-c-pnp)
|
|
@ -0,0 +1,86 @@
|
|||
@echo off
|
||||
|
||||
goto START
|
||||
|
||||
:Usage
|
||||
echo Usage: build.prereq.cmd x86^|ARM^|x64 Debug^|Release [WindowsSDKVersion]
|
||||
echo WinSDKVer............... Default is 10.0.14393.0, specify another version if necessary
|
||||
echo [/?].................... Displays this usage string.
|
||||
echo Example:
|
||||
echo build.pnpbridge.cmd x64 Debug 10.0.17763.0
|
||||
endlocal
|
||||
exit /b 1
|
||||
|
||||
:START
|
||||
setlocal ENABLEDELAYEDEXPANSION
|
||||
|
||||
if [%1] == [/?] goto Usage
|
||||
if [%1] == [-?] goto Usage
|
||||
|
||||
if [%1] == [] (
|
||||
set TARGETARCH=x64
|
||||
) else (
|
||||
set TARGETARCH=%1
|
||||
)
|
||||
|
||||
if /I [%TARGETARCH%] == [x86] (
|
||||
set TARGETPLATFORM=Win32
|
||||
) else (
|
||||
set TARGETPLATFORM=%TARGETARCH%
|
||||
)
|
||||
|
||||
if [%2] == [] (
|
||||
set TARGETCONFIG=Debug
|
||||
) else (
|
||||
set TARGETCONFIG=%2
|
||||
)
|
||||
|
||||
if [%3] == [] (
|
||||
set TARGETPLATVER=10.0.17763.0
|
||||
) else (
|
||||
set TARGETPLATVER=%3
|
||||
)
|
||||
|
||||
pushd %~dp0..
|
||||
|
||||
echo .
|
||||
echo "Using CMAKE to set up Azure PnpBridge projects"
|
||||
echo.
|
||||
|
||||
set OUTPUTDIR=%TARGETPLATFORM%_%TARGETCONFIG%
|
||||
|
||||
md %OUTPUTDIR%
|
||||
pushd %OUTPUTDIR%
|
||||
if /I [%TARGETARCH%] == [x86] (
|
||||
cmake -G "Visual Studio 15 2017" .. -Dskip_samples=ON ..
|
||||
)
|
||||
|
||||
if /I [%TARGETARCH%] == [arm] (
|
||||
cmake -G "Visual Studio 15 2017 ARM" .. -Duse_prov_client:BOOL=ON -Duse_tpm_simulator:BOOL=OFF -Dbuild_provisioning_service_client=ON -Duse_prov_client_core=ON -Dskip_samples=ON ..
|
||||
)
|
||||
|
||||
if /I [%TARGETARCH%] == [x64] (
|
||||
cmake -G "Visual Studio 15 2017 Win64" .. -Dskip_samples=ON ..
|
||||
)
|
||||
popd
|
||||
|
||||
|
||||
echo .
|
||||
echo "Building Azure SDK libraries"
|
||||
echo .
|
||||
|
||||
pushd %OUTPUTDIR%
|
||||
msbuild %~dp0..\%OUTPUTDIR%\azure_iot_pnp_bridge.sln /p:Configuration=%TARGETCONFIG% /p:Platform=%TARGETPLATFORM% /p:TargetPlatformVersion=%TARGETPLATVER%
|
||||
if errorlevel 1 goto BuildError
|
||||
|
||||
popd
|
||||
|
||||
goto Success
|
||||
|
||||
:BuildError
|
||||
popd
|
||||
@echo Error building project...
|
||||
exit /b 1
|
||||
|
||||
:Success
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
cmake_minimum_required(VERSION 2.8.11)
|
||||
|
||||
add_subdirectory(PnpBridge)
|
|
@ -228,7 +228,7 @@ CameraCaptureEngine::GetDefaultCamera(
|
|||
}
|
||||
|
||||
pwzInterfaceList = std::make_unique<WCHAR[]>(cchInterfaceList);
|
||||
cr = CM_Get_Device_Interface_List((GUID*)&guidCategory, nullptr, pwzInterfaceList.get(), cchInterfaceList, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
|
||||
cr = CM_Get_Device_Interface_ListW((GUID*)&guidCategory, nullptr, pwzInterfaceList.get(), cchInterfaceList, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
|
||||
if (cr != CR_SUCCESS)
|
||||
{
|
||||
pwzInterfaceList = nullptr;
|
||||
|
|
|
@ -11,7 +11,6 @@ PNP_ADAPTER CameraPnpInterface = {
|
|||
"camera-health-monitor",
|
||||
CameraPnpInterfaceInitialize,
|
||||
CameraPnpInterfaceBind,
|
||||
CameraPnpInterfaceRelease,
|
||||
CameraPnpInterfaceShutdown
|
||||
};
|
||||
|
||||
|
@ -107,6 +106,7 @@ CameraPnpInterfaceInitialize(
|
|||
_In_ const char* adapterArgs
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(adapterArgs);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -119,7 +119,7 @@ CameraPnpInterfaceShutdown(
|
|||
|
||||
int
|
||||
CameraPnpInterfaceBind(
|
||||
_In_ PNPADAPTER_INTERFACE_HANDLE Interface,
|
||||
_In_ PNPADAPTER_CONTEXT adapterHandle,
|
||||
_In_ PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle,
|
||||
_In_ PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD payload
|
||||
)
|
||||
|
@ -132,8 +132,9 @@ CameraPnpInterfaceBind(
|
|||
JSON_Value* jmsg;
|
||||
JSON_Object* jobj;
|
||||
|
||||
PNPADAPTER_INTERFACE_HANDLE adapterInterface = nullptr;
|
||||
|
||||
if (nullptr == Interface || nullptr == payload || nullptr == payload->Context)
|
||||
if (nullptr == payload || nullptr == payload->Context)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
@ -152,12 +153,17 @@ CameraPnpInterfaceBind(
|
|||
pnpInterfaceClient = PnP_InterfaceClient_Create(pnpDeviceClientHandle, interfaceId, nullptr, &s_CameraPnpCommandTable, pIotPnp.get());
|
||||
RETURN_HR_IF_NULL (E_UNEXPECTED, pnpInterfaceClient);
|
||||
|
||||
PnpAdapter_SetPnpInterfaceClient(Interface, pnpInterfaceClient);
|
||||
// Create PnpAdapter Interface
|
||||
PNPADPATER_INTERFACE_INIT_PARAMS interfaceParams = { 0 };
|
||||
interfaceParams.releaseInterface = CameraPnpInterfaceRelease;
|
||||
|
||||
RETURN_IF_FAILED (pIotPnp->Initialize(PnpAdapter_GetPnpInterfaceClient(Interface), pnpDeviceClientHandle, nullptr /* cameraName.c_str() */));
|
||||
RETURN_HR_IF (E_UNEXPECTED, 0 != PnpAdapterInterface_Create(adapterHandle, interfaceId, pnpInterfaceClient, &adapterInterface, &interfaceParams))
|
||||
|
||||
pIotPnp = std::make_unique<CameraIotPnpDevice>();
|
||||
RETURN_IF_FAILED (pIotPnp->Initialize(PnpAdapterInterface_GetPnpInterfaceClient(adapterInterface), nullptr /* cameraName.c_str() */));
|
||||
RETURN_IF_FAILED (pIotPnp->StartTelemetryWorker());
|
||||
|
||||
RETURN_HR_IF (E_UNEXPECTED, 0 != PnpAdapter_SetContext(Interface, (void*)pIotPnp.get()));
|
||||
RETURN_HR_IF (E_UNEXPECTED, 0 != PnpAdapterInterface_SetContext(adapterInterface, (void*)pIotPnp.get()));
|
||||
|
||||
// Our interface context now owns the object.
|
||||
pIotPnp.release();
|
||||
|
@ -170,7 +176,7 @@ CameraPnpInterfaceRelease(
|
|||
_In_ PNPADAPTER_INTERFACE_HANDLE Interface
|
||||
)
|
||||
{
|
||||
CameraIotPnpDevice* p = (CameraIotPnpDevice*)PnpAdapter_GetContext(Interface);
|
||||
CameraIotPnpDevice* p = (CameraIotPnpDevice*)PnpAdapterInterface_GetContext(Interface);
|
||||
|
||||
if (p != nullptr)
|
||||
{
|
||||
|
@ -183,7 +189,9 @@ CameraPnpInterfaceRelease(
|
|||
|
||||
// Clear our context to make sure we don't keep a stale
|
||||
// object around.
|
||||
(void) PnpAdapter_SetContext(Interface, nullptr);
|
||||
(void) PnpAdapterInterface_SetContext(Interface, nullptr);
|
||||
|
||||
PnpAdapterInterface_Destroy(Interface);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ CameraPnpInterfaceShutdown(
|
|||
|
||||
int
|
||||
CameraPnpInterfaceBind(
|
||||
_In_ PNPADAPTER_INTERFACE_HANDLE Interface,
|
||||
_In_ PNPADAPTER_CONTEXT adapterHandle,
|
||||
_In_ PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle,
|
||||
_In_ PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD payload
|
||||
);
|
||||
|
|
|
@ -82,11 +82,13 @@ CameraPnpDiscovery::InitializePnpDiscovery(
|
|||
{
|
||||
PNPBRIDGE_DEVICE_CHANGE_PAYLOAD payload = { };
|
||||
std::unique_ptr<JsonWrapper> pjson = std::make_unique<JsonWrapper>();
|
||||
std::unique_ptr<JsonWrapper> pmatchjson = std::make_unique<JsonWrapper>();
|
||||
|
||||
RETURN_IF_FAILED (pjson->Initialize());
|
||||
RETURN_IF_FAILED (pjson->AddFormatString("Identity", "camera-health-monitor"));
|
||||
RETURN_IF_FAILED (pjson->AddFormatString("HardwareId", "UVC_Webcam_00"));
|
||||
RETURN_IF_FAILED (pjson->AddFormatString("InterfaceId", "http://windows.com/camera_health_monitor/1.0.0"));
|
||||
RETURN_IF_FAILED (pmatchjson->Initialize());
|
||||
RETURN_IF_FAILED (pmatchjson->AddFormatString("HardwareId", "UVC_Webcam_00"));
|
||||
RETURN_IF_FAILED (pjson->AddObject("MatchParameters", pmatchjson->GetMessageW()));
|
||||
|
||||
payload.Message = pjson->GetMessageW();
|
||||
payload.MessageLength = static_cast<int>(pjson->GetSize());
|
||||
|
@ -97,6 +99,7 @@ CameraPnpDiscovery::InitializePnpDiscovery(
|
|||
pfnCallback(&payload);
|
||||
|
||||
// $$LEAKLEAK!!!
|
||||
pmatchjson->Detach();
|
||||
pjson->Detach();
|
||||
}
|
||||
|
||||
|
|
|
@ -54,33 +54,33 @@ JsonWrapper::AddValueAsString(
|
|||
char sz[MAX_32BIT_DECIMAL_DIGIT] = { };
|
||||
|
||||
RETURN_HR_IF_NULL (E_INVALIDARG, m_object);
|
||||
RETURN_HR_IF_NULL (E_INVALIDARG, name);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, name);
|
||||
|
||||
RETURN_IF_FAILED (StringCchPrintfA(sz, _countof(sz), "%u", val));
|
||||
RETURN_IF_FAILED(StringCchPrintfA(sz, _countof(sz), "%u", val));
|
||||
|
||||
// json_object_set_string returns 0 on success and -1 on
|
||||
// failure. Failure for this can be either via invalid
|
||||
// arg (i.e., JSON_Object is invalid) or we ran out of
|
||||
// memory. We'll assume, since this is only called by our
|
||||
// object and the methods are protected, that the parameters
|
||||
// are valid. So only failure would be E_OUTOFMEMORY.
|
||||
RETURN_HR_IF (E_OUTOFMEMORY, JSONFailure == json_object_set_string(m_object, name, sz));
|
||||
// json_object_set_string returns 0 on success and -1 on
|
||||
// failure. Failure for this can be either via invalid
|
||||
// arg (i.e., JSON_Object is invalid) or we ran out of
|
||||
// memory. We'll assume, since this is only called by our
|
||||
// object and the methods are protected, that the parameters
|
||||
// are valid. So only failure would be E_OUTOFMEMORY.
|
||||
RETURN_HR_IF(E_OUTOFMEMORY, JSONFailure == json_object_set_string(m_object, name, sz));
|
||||
|
||||
return S_OK;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
JsonWrapper::AddValueAsString(
|
||||
_In_z_ LPCSTR name,
|
||||
_In_ LONGLONG val
|
||||
)
|
||||
)
|
||||
{
|
||||
char sz[MAX_64BIT_DECIMAL_DIGIT] = { };
|
||||
|
||||
RETURN_HR_IF_NULL (E_INVALIDARG, m_object);
|
||||
RETURN_HR_IF_NULL (E_INVALIDARG, name);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, m_object);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, name);
|
||||
|
||||
RETURN_IF_FAILED (StringCchPrintfA(sz, _countof(sz), "%I64d", val));
|
||||
RETURN_IF_FAILED(StringCchPrintfA(sz, _countof(sz), "%I64d", val));
|
||||
|
||||
// json_object_set_string returns 0 on success and -1 on
|
||||
// failure. Failure for this can be either via invalid
|
||||
|
@ -88,7 +88,7 @@ JsonWrapper::AddValueAsString(
|
|||
// memory. We'll assume, since this is only called by our
|
||||
// object and the methods are protected, that the parameters
|
||||
// are valid. So only failure would be E_OUTOFMEMORY.
|
||||
RETURN_HR_IF (E_OUTOFMEMORY, JSONFailure == json_object_set_string(m_object, name, sz));
|
||||
RETURN_HR_IF(E_OUTOFMEMORY, JSONFailure == json_object_set_string(m_object, name, sz));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -97,13 +97,13 @@ HRESULT
|
|||
JsonWrapper::AddValueAsString(
|
||||
_In_z_ LPCSTR name,
|
||||
_In_ double val
|
||||
)
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
char sz[MAX_64BIT_DECIMAL_DIGIT] = { };
|
||||
|
||||
RETURN_HR_IF_NULL (E_INVALIDARG, m_object);
|
||||
RETURN_HR_IF_NULL (E_INVALIDARG, name);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, m_object);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, name);
|
||||
|
||||
hr = StringCchPrintfA(sz, _countof(sz), "%.3f", val);
|
||||
if (hr == S_OK || hr == STRSAFE_E_INSUFFICIENT_BUFFER)
|
||||
|
@ -112,7 +112,7 @@ JsonWrapper::AddValueAsString(
|
|||
// we truncated the string, assume we're fine.
|
||||
hr = S_OK;
|
||||
}
|
||||
RETURN_IF_FAILED (hr);
|
||||
RETURN_IF_FAILED(hr);
|
||||
|
||||
// json_object_set_string returns 0 on success and -1 on
|
||||
// failure. Failure for this can be either via invalid
|
||||
|
@ -120,7 +120,7 @@ JsonWrapper::AddValueAsString(
|
|||
// memory. We'll assume, since this is only called by our
|
||||
// object and the methods are protected, that the parameters
|
||||
// are valid. So only failure would be E_OUTOFMEMORY.
|
||||
RETURN_HR_IF (E_OUTOFMEMORY, JSONFailure == json_object_set_string(m_object, name, sz));
|
||||
RETURN_HR_IF(E_OUTOFMEMORY, JSONFailure == json_object_set_string(m_object, name, sz));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -129,14 +129,14 @@ HRESULT
|
|||
JsonWrapper::AddHresultAsString(
|
||||
_In_z_ LPCSTR name,
|
||||
_In_ HRESULT hr
|
||||
)
|
||||
)
|
||||
{
|
||||
char sz[MAX_32BIT_HEX_DIGIT] = { };
|
||||
|
||||
RETURN_HR_IF_NULL (E_INVALIDARG, m_object);
|
||||
RETURN_HR_IF_NULL (E_INVALIDARG, name);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, m_object);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, name);
|
||||
|
||||
RETURN_IF_FAILED (StringCchPrintfA(sz, _countof(sz), "0x%08X", hr));
|
||||
RETURN_IF_FAILED(StringCchPrintfA(sz, _countof(sz), "0x%08X", hr));
|
||||
|
||||
// json_object_set_string returns 0 on success and -1 on
|
||||
// failure. Failure for this can be either via invalid
|
||||
|
@ -144,7 +144,23 @@ JsonWrapper::AddHresultAsString(
|
|||
// memory. We'll assume, since this is only called by our
|
||||
// object and the methods are protected, that the parameters
|
||||
// are valid. So only failure would be E_OUTOFMEMORY.
|
||||
RETURN_HR_IF (E_OUTOFMEMORY, JSONFailure == json_object_set_string(m_object, name, sz));
|
||||
RETURN_HR_IF(E_OUTOFMEMORY, JSONFailure == json_object_set_string(m_object, name, sz));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
JsonWrapper::AddObject(
|
||||
_In_z_ LPCSTR name,
|
||||
_In_z_ LPCSTR object
|
||||
)
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, m_object);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, name);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, object);
|
||||
|
||||
JSON_Value* value = json_parse_string(object);
|
||||
RETURN_HR_IF(E_OUTOFMEMORY, JSONFailure == json_object_set_value(m_object, name, value));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
|
|
@ -19,8 +19,7 @@ public:
|
|||
HRESULT AddValueAsString(_In_z_ LPCSTR name, _In_ LONGLONG val);
|
||||
HRESULT AddValueAsString(_In_z_ LPCSTR name, _In_ double val);
|
||||
HRESULT AddHresultAsString(_In_z_ LPCSTR name, _In_ HRESULT hr);
|
||||
HRESULT AddValue(_In_z_ LPCSTR name, _In_z_ LPCWSTR val);
|
||||
HRESULT AddValue(_In_z_ LPCSTR name, _In_z_ LPCSTR val);
|
||||
HRESULT AddObject(_In_z_ LPCSTR name, _In_z_ LPCSTR object);
|
||||
HRESULT AddFormatString(_In_z_ LPCSTR name, _In_z_ LPCSTR format, ...);
|
||||
size_t GetSize();
|
||||
const char* GetMessage();
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
#define CONC(A, B) CONC_(A, B)
|
||||
#define CONC_(A, B) A##B
|
||||
|
||||
static void SerialPnp_PropertyUpdateHandler(const char* propertyName, unsigned const char* propertyInitial, size_t propertyInitialLen, unsigned const char* propertyDataUpdated, size_t propertyDataUpdatedLen, int desiredVersion, void* userContextCallback);
|
||||
|
||||
#define PROP_HANDLER(index) void CONC(SerialPnp_PropertyUpdateHandler, CONC(CMD_PROP_HANDLER_ADAPTER_NAME, index))(unsigned const char* propertyInitial, \
|
||||
#define PROP_HANDLER(index) void CONC(PnpBridge_PropertyUpdateHandler, CONC(CMD_PROP_HANDLER_ADAPTER_NAME, index))(unsigned const char* propertyInitial, \
|
||||
size_t propertyInitialLen, unsigned const char* propertyDataUpdated, size_t propertyDataUpdatedLen, int desiredVersion, void* userContextCallback) \
|
||||
{PROP_HANDLER_ADAPTER_METHOD(index, propertyInitial, propertyInitialLen, propertyDataUpdated, propertyDataUpdatedLen, \
|
||||
desiredVersion, userContextCallback);};
|
||||
|
@ -29,9 +27,13 @@ PROP_HANDLER(17);
|
|||
PROP_HANDLER(18);
|
||||
PROP_HANDLER(19);
|
||||
|
||||
#define PROP_HANDLER_METHOD(index) &CONC(SerialPnp_PropertyUpdateHandler, CONC(CMD_PROP_HANDLER_ADAPTER_NAME, index))
|
||||
#define PROP_HANDLER_METHOD(index) &CONC(PnpBridge_PropertyUpdateHandler, CONC(CMD_PROP_HANDLER_ADAPTER_NAME, index))
|
||||
|
||||
void* PredefinedPropertyHandlerTables[] = {
|
||||
|
||||
typedef void(*PropertyHandlersFunction)(unsigned const char* propertyInitial,
|
||||
size_t propertyInitialLen, unsigned const char* propertyDataUpdated, size_t propertyDataUpdatedLen, int desiredVersion, void* userContextCallback);
|
||||
|
||||
PropertyHandlersFunction PredefinedPropertyHandlerTables[] = {
|
||||
PROP_HANDLER_METHOD(0),
|
||||
PROP_HANDLER_METHOD(1),
|
||||
PROP_HANDLER_METHOD(2),
|
||||
|
@ -54,7 +56,7 @@ void* PredefinedPropertyHandlerTables[] = {
|
|||
PROP_HANDLER_METHOD(19)
|
||||
};
|
||||
|
||||
#define CMD_HANDLER(index) void CONC(SerialPnp_CommandUpdateHandler, CONC(CMD_PROP_HANDLER_ADAPTER_NAME, index))( \
|
||||
#define CMD_HANDLER(index) void CONC(PnpBridge_CommandUpdateHandler, CONC(CMD_PROP_HANDLER_ADAPTER_NAME, index))( \
|
||||
const PNP_CLIENT_COMMAND_REQUEST* pnpClientCommandContext, PNP_CLIENT_COMMAND_RESPONSE* pnpClientCommandResponseContext, void* userContextCallback) \
|
||||
{CMD_HANDLER_ADAPTER_METHOD(index, pnpClientCommandContext, pnpClientCommandResponseContext, userContextCallback);};
|
||||
|
||||
|
@ -79,9 +81,11 @@ CMD_HANDLER(17);
|
|||
CMD_HANDLER(18);
|
||||
CMD_HANDLER(19);
|
||||
|
||||
#define CMD_HANDLER_METHOD(index) &CONC(SerialPnp_CommandUpdateHandler, CONC(CMD_PROP_HANDLER_ADAPTER_NAME, index))
|
||||
#define CMD_HANDLER_METHOD(index) &CONC(PnpBridge_CommandUpdateHandler, CONC(CMD_PROP_HANDLER_ADAPTER_NAME, index))
|
||||
|
||||
void* PredefinedCommandHandlerTables[] = {
|
||||
typedef void(*CommandHandlersFunction)(const PNP_CLIENT_COMMAND_REQUEST* pnpClientCommandContext, PNP_CLIENT_COMMAND_RESPONSE* pnpClientCommandResponseContext, void* userContextCallback);
|
||||
|
||||
CommandHandlersFunction PredefinedCommandHandlerTables[] = {
|
||||
CMD_HANDLER_METHOD(0),
|
||||
CMD_HANDLER_METHOD(1),
|
||||
CMD_HANDLER_METHOD(2),
|
|
@ -17,14 +17,14 @@
|
|||
|
||||
#include "parson.h"
|
||||
|
||||
PNP_INTERFACE_CLIENT_HANDLE pnpinterfaceHandle = NULL;
|
||||
#include "adapters/CoreDeviceHealth/CoreDeviceHealth.h"
|
||||
|
||||
void WindowsPnpSendEventCallback(PNP_SEND_TELEMETRY_STATUS pnpSendEventStatus, void* userContextCallback)
|
||||
{
|
||||
LogInfo("WindowsPnpSendEventCallback called, result=%d, userContextCallback=%p", pnpSendEventStatus, userContextCallback);
|
||||
}
|
||||
|
||||
int Sample_SendEventAsync(char* eventName, char* data)
|
||||
int Sample_SendEventAsync(PNP_INTERFACE_CLIENT_HANDLE pnpinterfaceHandle, char* eventName, char* data)
|
||||
{
|
||||
int result;
|
||||
PNP_CLIENT_RESULT pnpClientResult;
|
||||
|
@ -49,9 +49,6 @@ int Sample_SendEventAsync(char* eventName, char* data)
|
|||
return result;
|
||||
}
|
||||
|
||||
volatile bool state = false;
|
||||
SINGLYLINKEDLIST_HANDLE g_coreDeviceWatchers = NULL;
|
||||
|
||||
DWORD
|
||||
__stdcall
|
||||
CoreDevice_OnDeviceNotification(
|
||||
|
@ -61,51 +58,94 @@ CoreDevice_OnDeviceNotification(
|
|||
_In_reads_bytes_(eventDataSize) PCM_NOTIFY_EVENT_DATA eventData,
|
||||
_In_ DWORD eventDataSize)
|
||||
{
|
||||
char* deviceSymbolicLink = context;
|
||||
PCORE_DEVICE_TAG device = context;
|
||||
|
||||
UNREFERENCED_PARAMETER(hNotify);
|
||||
UNREFERENCED_PARAMETER(eventDataSize);
|
||||
|
||||
char buff[512];
|
||||
sprintf_s(buff, 512, "%S", eventData->u.DeviceInterface.SymbolicLink);
|
||||
|
||||
if (action == CM_NOTIFY_ACTION_DEVICEINTERFACEREMOVAL) {
|
||||
if (state && strcmp(buff, deviceSymbolicLink) == 0) {
|
||||
state = false;
|
||||
if (device->state && strcmp(buff, device->symbolicLink) == 0) {
|
||||
device->state = false;
|
||||
LogInfo("device removed %S", eventData->u.DeviceInterface.SymbolicLink);
|
||||
Sample_SendEventAsync("DeviceStatus", "Disconnected");
|
||||
Sample_SendEventAsync(device->pnpinterfaceHandle, "DeviceStatus", "Disconnected");
|
||||
}
|
||||
}
|
||||
else if (action == CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL) {
|
||||
if (!state && strcmp(buff, deviceSymbolicLink) == 0) {
|
||||
state = true;
|
||||
if (!device->state && strcmp(buff, device->symbolicLink) == 0) {
|
||||
device->state = true;
|
||||
LogInfo("device connected %S", eventData->u.DeviceInterface.SymbolicLink);
|
||||
Sample_SendEventAsync("DeviceStatus", "Connected");
|
||||
Sample_SendEventAsync(device->pnpinterfaceHandle, "DeviceStatus", "Connected");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
HCMNOTIFICATION CoreDevice_hNotifyCtx = NULL;
|
||||
|
||||
int CoreDevice_CreatePnpInterface(PNPADAPTER_INTERFACE_HANDLE Interface, PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD param) {
|
||||
int CoreDevice_ReleaseInterface(PNPADAPTER_INTERFACE_HANDLE pnpInterface) {
|
||||
PCORE_DEVICE_TAG device = PnpAdapterInterface_GetContext(pnpInterface);
|
||||
|
||||
if (NULL != device) {
|
||||
if (NULL != device->hNotifyCtx) {
|
||||
CM_Unregister_Notification(device->hNotifyCtx);
|
||||
}
|
||||
if (NULL != device->symbolicLink) {
|
||||
free(device->symbolicLink);
|
||||
}
|
||||
free(device);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CoreDevice_CreatePnpInterface(PNPADAPTER_CONTEXT adapterHandle, PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD param) {
|
||||
DWORD cmRet;
|
||||
CM_NOTIFY_FILTER cmFilter;
|
||||
PNP_INTERFACE_CLIENT_HANDLE pnpInterfaceClient;
|
||||
JSON_Value* jvalue = json_parse_string(param->Message);
|
||||
JSON_Object* jmsg = json_value_get_object(jvalue);
|
||||
JSON_Object* args = jmsg;
|
||||
PCORE_DEVICE_TAG device = NULL;
|
||||
const char* interfaceId = json_object_get_string(args, "InterfaceId");
|
||||
const char* hardwareId = json_object_get_string(args, "HardwareId");
|
||||
//const char* hardwareId = json_object_get_string(args, "HardwareId");
|
||||
const char* symbolicLink = json_object_get_string(args, "SymbolicLink");
|
||||
const char* publishMode = json_object_get_string(args, "PublishMode");
|
||||
int result = 0;
|
||||
|
||||
if (Interface == NULL) {
|
||||
return -1;
|
||||
device = calloc(1, sizeof(CORE_DEVICE_TAG));
|
||||
if (NULL != device) {
|
||||
result = -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
pnpInterfaceClient = PnP_InterfaceClient_Create(pnpDeviceClientHandle, interfaceId, NULL, NULL, NULL);
|
||||
if (NULL == pnpInterfaceClient) {
|
||||
return -1;
|
||||
result = -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
PnpAdapter_SetPnpInterfaceClient(Interface, pnpInterfaceClient);
|
||||
// Create PnpAdapter Interface
|
||||
{
|
||||
PNPADPATER_INTERFACE_INIT_PARAMS interfaceParams = { 0 };
|
||||
interfaceParams.releaseInterface = CoreDevice_ReleaseInterface;
|
||||
PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface;
|
||||
|
||||
result = PnpAdapterInterface_Create(adapterHandle, interfaceId, pnpInterfaceClient, &pnpAdapterInterface, &interfaceParams);
|
||||
if (result < 0) {
|
||||
goto end;
|
||||
}
|
||||
PnpAdapterInterface_SetContext(pnpAdapterInterface, device);
|
||||
}
|
||||
|
||||
// Don't bind the interface for publishMode always. There will be a device
|
||||
// arrived notification from the discovery adapter.
|
||||
if (NULL != publishMode && stricmp(publishMode, "always") == 0) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
device->symbolicLink = malloc(strlen(symbolicLink)+1);
|
||||
strcpy_s(device->symbolicLink, strlen(symbolicLink) + 1, symbolicLink);
|
||||
|
||||
ZeroMemory(&cmFilter, sizeof(cmFilter));
|
||||
cmFilter.cbSize = sizeof(cmFilter);
|
||||
|
@ -115,20 +155,29 @@ int CoreDevice_CreatePnpInterface(PNPADAPTER_INTERFACE_HANDLE Interface, PNP_DEV
|
|||
|
||||
cmRet = CM_Register_Notification(
|
||||
&cmFilter,
|
||||
(void*)symbolicLink,
|
||||
(void*)device,
|
||||
CoreDevice_OnDeviceNotification,
|
||||
&CoreDevice_hNotifyCtx
|
||||
&device->hNotifyCtx
|
||||
);
|
||||
|
||||
if (cmRet != CR_SUCCESS) {
|
||||
return -1;
|
||||
result = -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
pnpinterfaceHandle = pnpInterfaceClient;
|
||||
state = true;
|
||||
|
||||
Sample_SendEventAsync("DeviceStatus", "Connected");
|
||||
device->pnpinterfaceHandle = pnpInterfaceClient;
|
||||
device->state = true;
|
||||
|
||||
Sample_SendEventAsync(device->pnpinterfaceHandle, "DeviceStatus", "Connected");
|
||||
end:
|
||||
if (result < 0) {
|
||||
if (NULL != device) {
|
||||
if (NULL != device->symbolicLink) {
|
||||
free(device->symbolicLink);
|
||||
}
|
||||
free(device);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -181,30 +230,18 @@ int SendDeviceDisconnectedEventAsync(PNP_INTERFACE_CLIENT_HANDLE pnpInterfaceCor
|
|||
return result;
|
||||
}
|
||||
|
||||
int CoreDevice_ReleaseInterface(PNPADAPTER_INTERFACE_HANDLE pnpInterface) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CoreDevice_Initialize(const char* adapterArgs) {
|
||||
g_coreDeviceWatchers = singlylinkedlist_create();
|
||||
if (NULL == g_coreDeviceWatchers) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
UNREFERENCED_PARAMETER(adapterArgs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CoreDevice_Shutdown() {
|
||||
if (NULL != g_coreDeviceWatchers) {
|
||||
singlylinkedlist_destroy(g_coreDeviceWatchers);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
PNP_ADAPTER CoreDeviceHealthInterface = {
|
||||
.Identity = "core-device-health",
|
||||
.Initialize = CoreDevice_Initialize,
|
||||
.Shutdown = CoreDevice_Shutdown,
|
||||
.CreatePnpInterface = CoreDevice_CreatePnpInterface,
|
||||
.ReleaseInterface = CoreDevice_ReleaseInterface,
|
||||
.identity = "core-device-health",
|
||||
.initialize = CoreDevice_Initialize,
|
||||
.shutdown = CoreDevice_Shutdown,
|
||||
.createPnpInterface = CoreDevice_CreatePnpInterface,
|
||||
};
|
|
@ -8,6 +8,12 @@ extern "C"
|
|||
{
|
||||
#endif
|
||||
|
||||
typedef struct _CORE_DEVICE_TAG {
|
||||
PNP_INTERFACE_CLIENT_HANDLE pnpinterfaceHandle;
|
||||
HCMNOTIFICATION hNotifyCtx;
|
||||
char* symbolicLink;
|
||||
volatile bool state;
|
||||
} CORE_DEVICE_TAG, *PCORE_DEVICE_TAG;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -35,6 +35,9 @@ OnDeviceNotification(
|
|||
_In_reads_bytes_(eventDataSize) PCM_NOTIFY_EVENT_DATA eventData,
|
||||
_In_ DWORD eventDataSize)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(hNotify);
|
||||
UNREFERENCED_PARAMETER(eventDataSize);
|
||||
UNREFERENCED_PARAMETER(context);
|
||||
|
||||
if (action == CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL) {
|
||||
if (DeviceChangeHandler != NULL) {
|
||||
|
@ -52,14 +55,12 @@ OnDeviceNotification(
|
|||
LPWSTR SingleDeviceId;
|
||||
int msgLen = 512;
|
||||
STRING_HANDLE asJson;
|
||||
// JSON_Value* json;
|
||||
// JSON_Object* jsonObject;
|
||||
|
||||
payload.ChangeType = PNPBRIDGE_INTERFACE_CHANGE_ARRIVAL;
|
||||
|
||||
// Find the hardware Id
|
||||
DevPropSize = MAX_DEVICE_ID_LEN * sizeof(WCHAR);
|
||||
status = CM_Get_Device_Interface_Property(
|
||||
status = CM_Get_Device_Interface_PropertyW(
|
||||
eventData->u.DeviceInterface.SymbolicLink,
|
||||
&DEVPKEY_Device_InstanceId,
|
||||
&DevPropType,
|
||||
|
@ -68,19 +69,19 @@ OnDeviceNotification(
|
|||
0);
|
||||
|
||||
if (status != CR_SUCCESS) {
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
status = CM_Locate_DevNode(
|
||||
status = CM_Locate_DevNodeW(
|
||||
&Devinst,
|
||||
deviceInstance,
|
||||
CM_LOCATE_DEVNODE_NORMAL);
|
||||
|
||||
if (status != CR_SUCCESS) {
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
status = CM_Get_DevNode_Property(
|
||||
status = CM_Get_DevNode_PropertyW(
|
||||
Devinst,
|
||||
&DEVPKEY_Device_HardwareIds,
|
||||
&PropType,
|
||||
|
@ -111,9 +112,6 @@ OnDeviceNotification(
|
|||
STRING_HANDLE asJson1 = STRING_new_JSON(msg1);
|
||||
sprintf_s(msg, msgLen, deviceChangeMessageformat, STRING_c_str(asJson), STRING_c_str(asJson1));
|
||||
|
||||
// json = json_parse_string(msg);
|
||||
// jsonObject = json_value_get_object(json);
|
||||
|
||||
payload.Message = msg;
|
||||
|
||||
payload.Context = malloc(sizeof(eventData->u.DeviceInterface.ClassGuid));
|
||||
|
@ -124,6 +122,7 @@ OnDeviceNotification(
|
|||
STRING_delete(asJson);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -131,22 +130,26 @@ int WindowsPnp_StartDiscovery(PNPBRIDGE_NOTIFY_DEVICE_CHANGE DeviceChangeCallbac
|
|||
DWORD cmRet;
|
||||
CM_NOTIFY_FILTER cmFilter;
|
||||
HCMNOTIFICATION hNotifyCtx = NULL;
|
||||
JSON_Value* jmsg;
|
||||
JSON_Object* jobj;
|
||||
|
||||
UNREFERENCED_PARAMETER(deviceArgs);
|
||||
|
||||
g_deviceWatchers = singlylinkedlist_create();
|
||||
if (NULL == g_deviceWatchers) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
JSON_Value* jmsg;
|
||||
JSON_Object* jobj;
|
||||
jmsg = json_parse_string(adapterArgs);
|
||||
jobj = json_value_get_object(jmsg);
|
||||
JSON_Array* interfaceClasses = json_object_dotget_array(jobj, "DeviceInterfaceClasses");
|
||||
|
||||
DeviceChangeHandler = DeviceChangeCallback;
|
||||
|
||||
for (int j = 0; j < (int)json_array_get_count(interfaceClasses); j++) {
|
||||
GUID guid = { 0 };
|
||||
const char *interfaceClass = json_array_get_string(interfaceClasses, j);
|
||||
GUID guid;
|
||||
if (UuidFromStringA((char *)interfaceClass, &guid) != RPC_S_OK) {
|
||||
if (UuidFromStringA((RPC_CSTR)interfaceClass, &guid) != RPC_S_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -156,10 +159,10 @@ int WindowsPnp_StartDiscovery(PNPBRIDGE_NOTIFY_DEVICE_CHANGE DeviceChangeCallbac
|
|||
cmFilter.FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE;
|
||||
cmFilter.u.DeviceInterface.ClassGuid = guid;
|
||||
cmRet = CM_Register_Notification(
|
||||
&cmFilter, // PCM_NOTIFY_FILTER pFilter,
|
||||
NULL, // PVOID pContext,
|
||||
(PCM_NOTIFY_CALLBACK)OnDeviceNotification, // PCM_NOTIFY_CALLBACK pCallback,
|
||||
&hNotifyCtx // PHCMNOTIFICATION pNotifyContext
|
||||
&cmFilter,
|
||||
NULL,
|
||||
(PCM_NOTIFY_CALLBACK)OnDeviceNotification,
|
||||
&hNotifyCtx
|
||||
);
|
||||
|
||||
if (cmRet != CR_SUCCESS) {
|
||||
|
@ -168,10 +171,6 @@ int WindowsPnp_StartDiscovery(PNPBRIDGE_NOTIFY_DEVICE_CHANGE DeviceChangeCallbac
|
|||
singlylinkedlist_add(g_deviceWatchers, hNotifyCtx);
|
||||
}
|
||||
|
||||
DeviceChangeHandler = DeviceChangeCallback;
|
||||
|
||||
//EnumerateDevices()
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,18 +35,13 @@ void SerialPnp_CommandUpdateHandlerRedirect(int index,
|
|||
#define PROP_HANDLER_ADAPTER_METHOD SerialPnp_PropertyUpdateHandlerRedirect
|
||||
#define CMD_HANDLER_ADAPTER_METHOD SerialPnp_CommandUpdateHandlerRedirect
|
||||
|
||||
#include <CmdAndPropHandler.h>
|
||||
#include "adapters/CmdAndPropHandler.h"
|
||||
// END - PNPCSDK#20
|
||||
|
||||
SINGLYLINKEDLIST_HANDLE g_InterfaceDefinitions = NULL;
|
||||
|
||||
int SerialPnp_UartReceiver(void* context)
|
||||
{
|
||||
BYTE msgBuffer[2048];
|
||||
PBYTE p = msgBuffer;
|
||||
UINT16 SizeToRead = 0;
|
||||
int result = 0;
|
||||
PSERIAL_DEVICE_CONTEXT deviceContext = (PSERIAL_DEVICE_CONTEXT) context;
|
||||
PSERIAL_DEVICE_CONTEXT deviceContext = (PSERIAL_DEVICE_CONTEXT)context;
|
||||
|
||||
while (result >= 0) {
|
||||
byte* desc = NULL;
|
||||
|
@ -68,7 +63,7 @@ void SerialPnp_TxPacket(PSERIAL_DEVICE_CONTEXT serialDevice, byte* OutPacket, in
|
|||
{
|
||||
int txLength = 1 + Length;
|
||||
// First iterate through and find out our new length
|
||||
for (int i = 0; i<Length; i++)
|
||||
for (int i = 0; i < Length; i++)
|
||||
{
|
||||
if ((OutPacket[i] == 0x5A) || (OutPacket[i] == 0xEF))
|
||||
{
|
||||
|
@ -81,7 +76,7 @@ void SerialPnp_TxPacket(PSERIAL_DEVICE_CONTEXT serialDevice, byte* OutPacket, in
|
|||
|
||||
txLength = 1;
|
||||
SerialPnp_TxPacket[0] = 0x5A; // Start of frame
|
||||
for (int i = 0; i<Length; i++)
|
||||
for (int i = 0; i < Length; i++)
|
||||
{
|
||||
// Escape these bytes where necessary
|
||||
if ((OutPacket[i] == 0x5A) || (OutPacket[i] == 0xEF))
|
||||
|
@ -104,12 +99,12 @@ void SerialPnp_TxPacket(PSERIAL_DEVICE_CONTEXT serialDevice, byte* OutPacket, in
|
|||
free(SerialPnp_TxPacket);
|
||||
}
|
||||
|
||||
const EventDefinition* SerialPnp_LookupEvent(char* EventName, int InterfaceId)
|
||||
const EventDefinition* SerialPnp_LookupEvent(SINGLYLINKEDLIST_HANDLE interfaceDefinitions, char* EventName, int InterfaceId)
|
||||
{
|
||||
const InterfaceDefinition* interfaceDef;
|
||||
LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(g_InterfaceDefinitions);
|
||||
LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(interfaceDefinitions);
|
||||
|
||||
for(int i=0; i<InterfaceId-1; i++)
|
||||
for (int i = 0; i < InterfaceId - 1; i++)
|
||||
{
|
||||
interfaceDefHandle = singlylinkedlist_get_next_item(interfaceDefHandle);
|
||||
}
|
||||
|
@ -129,19 +124,20 @@ const EventDefinition* SerialPnp_LookupEvent(char* EventName, int InterfaceId)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
byte* SerialPnp_StringSchemaToBinary(Schema Schema, byte* data, int* length)
|
||||
byte* SerialPnp_StringSchemaToBinary(Schema Schema, byte* buffer, int* length)
|
||||
{
|
||||
byte* bd = NULL;
|
||||
char* data = (char*) buffer;
|
||||
|
||||
if ((Schema == Float) || (Schema == Int))
|
||||
{
|
||||
bd = malloc(sizeof(byte)*4);
|
||||
bd = malloc(sizeof(byte) * 4);
|
||||
*length = 4;
|
||||
|
||||
if (Schema == Float)
|
||||
{
|
||||
float x = 0;
|
||||
x = (float) atof(data);
|
||||
x = (float)atof(data);
|
||||
memcpy(bd, &x, sizeof(float));
|
||||
}
|
||||
else if (Schema == Int)
|
||||
|
@ -204,15 +200,15 @@ void SerialPnp_UnsolicitedPacket(PSERIAL_DEVICE_CONTEXT device, byte* packet, DW
|
|||
memcpy(event_name, packet + 6, rxNameLength);
|
||||
event_name[rxNameLength] = '\0';
|
||||
|
||||
const EventDefinition* ev = SerialPnp_LookupEvent(event_name, rxInterfaceId);
|
||||
const EventDefinition* ev = SerialPnp_LookupEvent(device->InterfaceDefinitions, event_name, rxInterfaceId);
|
||||
|
||||
byte* rxData = malloc(sizeof(byte)*rxDataSize);
|
||||
memcpy(rxData, packet + 6 + rxNameLength, rxDataSize);
|
||||
|
||||
char* rxstrdata = SerialPnp_BinarySchemaToString(ev->DataSchema, rxData, (byte) rxDataSize);
|
||||
char* rxstrdata = SerialPnp_BinarySchemaToString(ev->DataSchema, rxData, (byte)rxDataSize);
|
||||
LogInfo("%s: %s", ev->defintion.Name, rxstrdata);
|
||||
|
||||
SerialPnp_SendEventAsync(device->InterfaceHandle, ev->defintion.Name, rxstrdata);
|
||||
SerialPnp_SendEventAsync(PnpAdapterInterface_GetPnpInterfaceClient(device->pnpAdapterInterface), ev->defintion.Name, rxstrdata);
|
||||
|
||||
free(event_name);
|
||||
free(rxData);
|
||||
|
@ -227,12 +223,12 @@ void SerialPnp_UnsolicitedPacket(PSERIAL_DEVICE_CONTEXT device, byte* packet, DW
|
|||
}
|
||||
}
|
||||
|
||||
const PropertyDefinition* SerialPnp_LookupProperty(const char* propertyName, int InterfaceId)
|
||||
const PropertyDefinition* SerialPnp_LookupProperty(SINGLYLINKEDLIST_HANDLE interfaceDefinitions, const char* propertyName, int InterfaceId)
|
||||
{
|
||||
LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(g_InterfaceDefinitions);
|
||||
LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(interfaceDefinitions);
|
||||
const InterfaceDefinition* interfaceDef;
|
||||
|
||||
for (int i = 0; i<InterfaceId - 1; i++)
|
||||
for (int i = 0; i < InterfaceId - 1; i++)
|
||||
{
|
||||
interfaceDefHandle = singlylinkedlist_get_next_item(interfaceDefHandle);
|
||||
}
|
||||
|
@ -252,12 +248,12 @@ const PropertyDefinition* SerialPnp_LookupProperty(const char* propertyName, int
|
|||
return NULL;
|
||||
}
|
||||
|
||||
const CommandDefinition* SerialPnp_LookupCommand(const char* commandName, int InterfaceId)
|
||||
const CommandDefinition* SerialPnp_LookupCommand(SINGLYLINKEDLIST_HANDLE interfaceDefinitions, const char* commandName, int InterfaceId)
|
||||
{
|
||||
LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(g_InterfaceDefinitions);
|
||||
LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(interfaceDefinitions);
|
||||
const InterfaceDefinition* interfaceDef;
|
||||
|
||||
for (int i = 0; i<InterfaceId - 1; i++)
|
||||
for (int i = 0; i < InterfaceId - 1; i++)
|
||||
{
|
||||
interfaceDefHandle = singlylinkedlist_get_next_item(interfaceDefHandle);
|
||||
}
|
||||
|
@ -277,12 +273,12 @@ const CommandDefinition* SerialPnp_LookupCommand(const char* commandName, int In
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int SerialPnp_PropertyHandler(PSERIAL_DEVICE_CONTEXT serialDevice, const char* property, char* input)
|
||||
int SerialPnp_PropertyHandler(PSERIAL_DEVICE_CONTEXT serialDevice, const char* property, char* data)
|
||||
{
|
||||
const PropertyDefinition* prop = SerialPnp_LookupProperty(property, 0);
|
||||
const PropertyDefinition* prop = SerialPnp_LookupProperty(serialDevice->InterfaceDefinitions, property, 0);
|
||||
byte* input = (byte*)data;
|
||||
|
||||
if (prop == NULL)
|
||||
{
|
||||
if (prop == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -298,10 +294,10 @@ int SerialPnp_PropertyHandler(PSERIAL_DEVICE_CONTEXT serialDevice, const char* p
|
|||
txPacket[1] = (byte)(txlength >> 8);
|
||||
txPacket[2] = 0x07; // command request
|
||||
// [3] is reserved
|
||||
txPacket[4] = (byte) 0;
|
||||
txPacket[5] = (byte) nameLength;
|
||||
txPacket[4] = (byte)0;
|
||||
txPacket[5] = (byte)nameLength;
|
||||
|
||||
memcpy(txPacket+6, property, nameLength);
|
||||
memcpy(txPacket + 6, property, nameLength);
|
||||
if (inputPayload != NULL) {
|
||||
memcpy(txPacket + 6 + nameLength, inputPayload, length);
|
||||
}
|
||||
|
@ -322,9 +318,10 @@ int SerialPnp_PropertyHandler(PSERIAL_DEVICE_CONTEXT serialDevice, const char* p
|
|||
}
|
||||
|
||||
|
||||
int SerialPnp_CommandHandler(PSERIAL_DEVICE_CONTEXT serialDevice, const char* command, char* input, char** response)
|
||||
int SerialPnp_CommandHandler(PSERIAL_DEVICE_CONTEXT serialDevice, const char* command, char* data, char** response)
|
||||
{
|
||||
const CommandDefinition* cmd = SerialPnp_LookupCommand(command, 0);
|
||||
const CommandDefinition* cmd = SerialPnp_LookupCommand(serialDevice->InterfaceDefinitions, command, 0);
|
||||
byte* input = (byte*)data;
|
||||
|
||||
if (cmd == NULL)
|
||||
{
|
||||
|
@ -356,10 +353,10 @@ int SerialPnp_CommandHandler(PSERIAL_DEVICE_CONTEXT serialDevice, const char* co
|
|||
SerialPnp_TxPacket(serialDevice, txPacket, txlength);
|
||||
|
||||
byte* responsePacket;
|
||||
SerialPnp_RxPacket(serialDevice, &responsePacket, &length, 0x02);
|
||||
SerialPnp_RxPacket(serialDevice, &responsePacket, (DWORD*)&length, 0x02);
|
||||
|
||||
char* stval = SerialPnp_BinarySchemaToString(cmd->ResponseSchema, responsePacket, length);
|
||||
*response = responsePacket;
|
||||
char* stval = SerialPnp_BinarySchemaToString(cmd->ResponseSchema, responsePacket, (byte)length);
|
||||
*response = stval;
|
||||
|
||||
if (inputPayload != NULL) {
|
||||
free(inputPayload);
|
||||
|
@ -371,7 +368,7 @@ int SerialPnp_CommandHandler(PSERIAL_DEVICE_CONTEXT serialDevice, const char* co
|
|||
}
|
||||
|
||||
|
||||
void SerialPnp_ParseDescriptor(byte* descriptor, DWORD length)
|
||||
void SerialPnp_ParseDescriptor(SINGLYLINKEDLIST_HANDLE interfaceDefinitions, byte* descriptor, DWORD length)
|
||||
{
|
||||
int c = 4;
|
||||
|
||||
|
@ -379,15 +376,12 @@ void SerialPnp_ParseDescriptor(byte* descriptor, DWORD length)
|
|||
byte display_name_length = descriptor[c++];
|
||||
|
||||
char display_name[128];
|
||||
memcpy(display_name, descriptor+c, display_name_length);
|
||||
memcpy(display_name, descriptor + c, display_name_length);
|
||||
display_name[display_name_length] = '\0';
|
||||
|
||||
LogInfo("Device Version : %d", version);
|
||||
LogInfo("Device Name : %s", display_name);
|
||||
|
||||
|
||||
g_InterfaceDefinitions = singlylinkedlist_create();
|
||||
|
||||
c += display_name_length;
|
||||
|
||||
while (c < (int)length)
|
||||
|
@ -401,10 +395,10 @@ void SerialPnp_ParseDescriptor(byte* descriptor, DWORD length)
|
|||
indef->Commands = singlylinkedlist_create();
|
||||
|
||||
// parse ID5
|
||||
UINT16 interface_id_length = descriptor[c] | (descriptor[c+1] << 8);
|
||||
UINT16 interface_id_length = descriptor[c] | (descriptor[c + 1] << 8);
|
||||
c += 2;
|
||||
|
||||
char* interface_id = malloc(sizeof(char)*(interface_id_length+1));
|
||||
char* interface_id = malloc(sizeof(char)*(interface_id_length + 1));
|
||||
memcpy(interface_id, descriptor + c, interface_id_length);
|
||||
interface_id[interface_id_length] = '\0';
|
||||
LogInfo("Interface ID : %s", interface_id);
|
||||
|
@ -454,9 +448,9 @@ void SerialPnp_ParseDescriptor(byte* descriptor, DWORD length)
|
|||
CommandDefinition* tfdef = calloc(1, sizeof(CommandDefinition));
|
||||
tfdef->defintion = fielddef;
|
||||
|
||||
UINT16 prequest_schema = (UINT16)(descriptor[c] | (descriptor[c+1] << 8));
|
||||
UINT16 prequest_schema = (UINT16)(descriptor[c] | (descriptor[c + 1] << 8));
|
||||
c += 2;
|
||||
UINT16 presponse_schema = (UINT16)(descriptor[c] | (descriptor[c+1] << 8));
|
||||
UINT16 presponse_schema = (UINT16)(descriptor[c] | (descriptor[c + 1] << 8));
|
||||
c += 2;
|
||||
|
||||
tfdef->RequestSchema = prequest_schema;
|
||||
|
@ -477,7 +471,7 @@ void SerialPnp_ParseDescriptor(byte* descriptor, DWORD length)
|
|||
|
||||
LogInfo("\tUnit : %s", punit);
|
||||
|
||||
UINT16 schema = descriptor[c] | (descriptor[c+1] << 8);
|
||||
UINT16 schema = descriptor[c] | (descriptor[c + 1] << 8);
|
||||
c += 2;
|
||||
tfdef->DataSchema = schema;
|
||||
|
||||
|
@ -505,7 +499,7 @@ void SerialPnp_ParseDescriptor(byte* descriptor, DWORD length)
|
|||
|
||||
LogInfo("\tUnit : %s", punit);
|
||||
|
||||
UINT16 schema = (UINT16)(descriptor[c] | (descriptor[c+1] << 8));
|
||||
UINT16 schema = (UINT16)(descriptor[c] | (descriptor[c + 1] << 8));
|
||||
c += 2;
|
||||
tfdef->DataSchema = schema;
|
||||
|
||||
|
@ -515,7 +509,7 @@ void SerialPnp_ParseDescriptor(byte* descriptor, DWORD length)
|
|||
}
|
||||
}
|
||||
|
||||
singlylinkedlist_add(g_InterfaceDefinitions, indef);
|
||||
singlylinkedlist_add(interfaceDefinitions, indef);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -540,22 +534,22 @@ int SerialPnp_FindSerialDevices()
|
|||
SerialDeviceList = singlylinkedlist_create();
|
||||
|
||||
cmResult = CM_Get_Device_Interface_List_Size(
|
||||
&bufferSize,
|
||||
(LPGUID) &GUID_DEVINTERFACE_COMPORT,
|
||||
NULL,
|
||||
CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
|
||||
&bufferSize,
|
||||
(LPGUID)&GUID_DEVINTERFACE_COMPORT,
|
||||
NULL,
|
||||
CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
|
||||
if (CR_SUCCESS != cmResult) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
deviceInterfaceList = malloc(bufferSize*sizeof(char));
|
||||
deviceInterfaceList = malloc(bufferSize * sizeof(char));
|
||||
|
||||
cmResult = CM_Get_Device_Interface_ListA(
|
||||
(LPGUID) &GUID_DEVINTERFACE_COMPORT,
|
||||
NULL,
|
||||
deviceInterfaceList,
|
||||
bufferSize,
|
||||
CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
|
||||
(LPGUID)&GUID_DEVINTERFACE_COMPORT,
|
||||
NULL,
|
||||
deviceInterfaceList,
|
||||
bufferSize,
|
||||
CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
|
||||
if (CR_SUCCESS != cmResult) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -565,8 +559,8 @@ int SerialPnp_FindSerialDevices()
|
|||
currentDeviceInterface += strlen(currentDeviceInterface) + 1)
|
||||
{
|
||||
PSERIAL_DEVICE serialDevs = malloc(sizeof(SERIAL_DEVICE));
|
||||
serialDevs->InterfaceName = malloc((strlen(currentDeviceInterface)+1)*sizeof(char));
|
||||
strcpy_s(serialDevs->InterfaceName, strlen(currentDeviceInterface)+1, currentDeviceInterface);
|
||||
serialDevs->InterfaceName = malloc((strlen(currentDeviceInterface) + 1) * sizeof(char));
|
||||
strcpy_s(serialDevs->InterfaceName, strlen(currentDeviceInterface) + 1, currentDeviceInterface);
|
||||
singlylinkedlist_add(SerialDeviceList, serialDevs);
|
||||
SerialDeviceCount++;
|
||||
}
|
||||
|
@ -581,20 +575,18 @@ const char* serialDeviceChangeMessageformat = "{ \
|
|||
int SerialPnp_OpenDeviceWorker(void* context) {
|
||||
byte* desc;
|
||||
DWORD length;
|
||||
PNPBRIDGE_DEVICE_CHANGE_PAYLOAD payload = {0};
|
||||
PNPBRIDGE_DEVICE_CHANGE_PAYLOAD payload = { 0 };
|
||||
PSERIAL_DEVICE_CONTEXT deviceContext = context;
|
||||
|
||||
SerialPnp_ResetDevice(deviceContext);
|
||||
SerialPnp_DeviceDescriptorRequest(deviceContext, &desc, &length);
|
||||
|
||||
SerialPnp_ParseDescriptor(desc, length);
|
||||
SerialPnp_PropertyHandler(deviceContext, "sample_rate", "5000");
|
||||
SerialPnp_ParseDescriptor(deviceContext->InterfaceDefinitions, desc, length);
|
||||
|
||||
STRING_HANDLE asJson = STRING_new_JSON(serialDeviceChangeMessageformat);
|
||||
JSON_Value* json = json_parse_string(serialDeviceChangeMessageformat);
|
||||
JSON_Object* jsonObject = json_value_get_object(json);
|
||||
|
||||
LIST_ITEM_HANDLE interfaceItem = singlylinkedlist_get_head_item(g_InterfaceDefinitions);
|
||||
LIST_ITEM_HANDLE interfaceItem = singlylinkedlist_get_head_item(deviceContext->InterfaceDefinitions);
|
||||
while (interfaceItem != NULL) {
|
||||
const InterfaceDefinition* def = (const InterfaceDefinition*)singlylinkedlist_item_get_value(interfaceItem);
|
||||
json_object_set_string(jsonObject, "InterfaceId", def->Id);
|
||||
|
@ -611,7 +603,6 @@ int SerialPnp_OpenDeviceWorker(void* context) {
|
|||
}
|
||||
|
||||
int SerialPnp_OpenDevice(const char* port, DWORD baudRate, PNPBRIDGE_NOTIFY_DEVICE_CHANGE DeviceChangeCallback) {
|
||||
BOOL status = FALSE;
|
||||
HANDLE hSerial = CreateFileA(port,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0, // must be opened with exclusive-access
|
||||
|
@ -647,8 +638,14 @@ int SerialPnp_OpenDevice(const char* port, DWORD baudRate, PNPBRIDGE_NOTIFY_DEVI
|
|||
|
||||
PSERIAL_DEVICE_CONTEXT deviceContext = malloc(sizeof(SERIAL_DEVICE_CONTEXT));
|
||||
deviceContext->hSerial = hSerial;
|
||||
deviceContext->InterfaceHandle = NULL;
|
||||
deviceContext->pnpAdapterInterface = NULL;
|
||||
deviceContext->SerialDeviceChangeCallback = DeviceChangeCallback;
|
||||
deviceContext->InterfaceDefinitions = singlylinkedlist_create();
|
||||
|
||||
//deviceContext->osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
// TODO error handling
|
||||
// https://docs.microsoft.com/en-us/previous-versions/ff802693(v=msdn.10)
|
||||
|
||||
if (ThreadAPI_Create(&deviceContext->SerialDeviceWorker, SerialPnp_OpenDeviceWorker, deviceContext) != THREADAPI_OK) {
|
||||
LogError("ThreadAPI_Create failed");
|
||||
|
@ -662,6 +659,7 @@ void SerialPnp_RxPacket(PSERIAL_DEVICE_CONTEXT serialDevice, byte** receivedPack
|
|||
BYTE inb = 0;
|
||||
DWORD dwRead = 0;
|
||||
*receivedPacket = NULL;
|
||||
*length = 0;
|
||||
|
||||
while (ReadFile(serialDevice->hSerial, &inb, 1, &dwRead, NULL)) {
|
||||
// Check for a start of packet byte
|
||||
|
@ -700,7 +698,7 @@ void SerialPnp_RxPacket(PSERIAL_DEVICE_CONTEXT serialDevice, byte** receivedPack
|
|||
{
|
||||
int PacketLength = (int)((serialDevice->RxBuffer[0]) | (serialDevice->RxBuffer[1] << 8)); // LSB first, L-endian
|
||||
|
||||
if (serialDevice->RxBufferIndex == PacketLength && (packetType == 0x00 || packetType == serialDevice->RxBuffer[2]))
|
||||
if (((int)serialDevice->RxBufferIndex == PacketLength) && (packetType == 0x00 || packetType == serialDevice->RxBuffer[2]))
|
||||
{
|
||||
*receivedPacket = malloc(serialDevice->RxBufferIndex * sizeof(byte));
|
||||
*length = serialDevice->RxBufferIndex;
|
||||
|
@ -776,6 +774,8 @@ int SerialPnp_StartDiscovery(PNPBRIDGE_NOTIFY_DEVICE_CHANGE DeviceChangeCallback
|
|||
return -1;
|
||||
}
|
||||
|
||||
UNREFERENCED_PARAMETER(adapterArgs);
|
||||
|
||||
const char* port = NULL;
|
||||
const char* useComDevInterfaceStr;
|
||||
const char* baudRateParam;
|
||||
|
@ -796,9 +796,7 @@ int SerialPnp_StartDiscovery(PNPBRIDGE_NOTIFY_DEVICE_CHANGE DeviceChangeCallback
|
|||
}
|
||||
}
|
||||
|
||||
JSON_Object* SerialDeviceInterfaceInfo = args;
|
||||
|
||||
baudRateParam = (const char*) json_object_dotget_string(args, "BaudRate");
|
||||
baudRateParam = (const char*)json_object_dotget_string(args, "BaudRate");
|
||||
if (NULL == baudRateParam) {
|
||||
LogError("BaudRate parameter is missing in configuration");
|
||||
return -1;
|
||||
|
@ -845,10 +843,7 @@ int SerialPnp_SendEventAsync(PNP_INTERFACE_CLIENT_HANDLE pnpInterface, char* eve
|
|||
return 0;
|
||||
}
|
||||
|
||||
char msg[512];
|
||||
sprintf_s(msg, 512, "{\"%s\":\"%s\"}", eventName, data);
|
||||
|
||||
if ((pnpClientResult = PnP_InterfaceClient_SendTelemetryAsync(pnpInterface, "temp", (const unsigned char*)msg, strlen(msg), SerialPnp_SendEventCallback, NULL)) != PNP_CLIENT_OK)
|
||||
if ((pnpClientResult = PnP_InterfaceClient_SendTelemetryAsync(pnpInterface, eventName, (const unsigned char*)data, strlen(data), SerialPnp_SendEventCallback, NULL)) != PNP_CLIENT_OK)
|
||||
{
|
||||
LogError("PnP_InterfaceClient_SendEventAsync failed, result=%d\n", pnpClientResult);
|
||||
result = __FAILURE__;
|
||||
|
@ -867,6 +862,9 @@ static void SerialPnp_PropertyUpdateHandler(const char* propertyName, unsigned c
|
|||
PNP_CLIENT_READWRITE_PROPERTY_RESPONSE propertyResponse;
|
||||
PSERIAL_DEVICE_CONTEXT deviceContext;
|
||||
|
||||
UNREFERENCED_PARAMETER(propertyInitial);
|
||||
UNREFERENCED_PARAMETER(propertyInitialLen);
|
||||
|
||||
LogInfo("Processed property. propertyUpdated = %.*s", (int)propertyDataUpdatedLen, propertyDataUpdated);
|
||||
|
||||
deviceContext = (PSERIAL_DEVICE_CONTEXT)userContextCallback;
|
||||
|
@ -881,7 +879,7 @@ static void SerialPnp_PropertyUpdateHandler(const char* propertyName, unsigned c
|
|||
propertyResponse.statusCode = 200;
|
||||
propertyResponse.statusDescription = "Property Updated Successfully";
|
||||
|
||||
pnpClientResult = PnP_InterfaceClient_ReportReadWritePropertyStatusAsync(deviceContext->InterfaceHandle, propertyName, &propertyResponse, NULL, NULL);
|
||||
pnpClientResult = PnP_InterfaceClient_ReportReadWritePropertyStatusAsync(deviceContext->pnpAdapterInterface, propertyName, &propertyResponse, NULL, NULL);
|
||||
}
|
||||
|
||||
// PnPSampleEnvironmentalSensor_SetCommandResponse is a helper that fills out a PNP_CLIENT_COMMAND_RESPONSE
|
||||
|
@ -911,7 +909,7 @@ static void SerialPnp_SetCommandResponse(PNP_CLIENT_COMMAND_RESPONSE* pnpClientC
|
|||
void SerialPnp_CommandUpdateHandler(const char* commandName, const PNP_CLIENT_COMMAND_REQUEST* pnpClientCommandContext, PNP_CLIENT_COMMAND_RESPONSE* pnpClientCommandResponseContext, void* userContextCallback) {
|
||||
PSERIAL_DEVICE_CONTEXT deviceContext;
|
||||
|
||||
// LogInfo("Processed command frequency property updated. propertyUpdated = %.*s", (int)propertyDataUpdatedLen, propertyDataUpdated);
|
||||
// LogInfo("Processed command frequency property updated. propertyUpdated = %.*s", (int)propertyDataUpdatedLen, propertyDataUpdated);
|
||||
|
||||
deviceContext = (PSERIAL_DEVICE_CONTEXT)userContextCallback;
|
||||
|
||||
|
@ -925,10 +923,11 @@ void SerialPnp_PropertyUpdateHandlerRedirect(int index, unsigned const char* pro
|
|||
size_t propertyInitialLen, unsigned const char* propertyDataUpdated,
|
||||
size_t propertyDataUpdatedLen, int desiredVersion, void* userContextCallback)
|
||||
{
|
||||
LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(g_InterfaceDefinitions);
|
||||
PSERIAL_DEVICE_CONTEXT deviceContext = userContextCallback;
|
||||
LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(deviceContext->InterfaceDefinitions);
|
||||
const InterfaceDefinition* interfaceDef;
|
||||
|
||||
for (int i = 0; i<0 - 1; i++)
|
||||
for (int i = 0; i < 0 - 1; i++)
|
||||
{
|
||||
interfaceDefHandle = singlylinkedlist_get_next_item(interfaceDefHandle);
|
||||
}
|
||||
|
@ -953,10 +952,11 @@ void SerialPnp_CommandUpdateHandlerRedirect(int index,
|
|||
PNP_CLIENT_COMMAND_RESPONSE* pnpClientCommandResponseContext,
|
||||
void* userContextCallback)
|
||||
{
|
||||
LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(g_InterfaceDefinitions);
|
||||
PSERIAL_DEVICE_CONTEXT deviceContext = userContextCallback;
|
||||
LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(deviceContext->InterfaceDefinitions);
|
||||
const InterfaceDefinition* interfaceDef;
|
||||
|
||||
for (int i = 0; i<0 - 1; i++)
|
||||
for (int i = 0; i < 0 - 1; i++)
|
||||
{
|
||||
interfaceDefHandle = singlylinkedlist_get_next_item(interfaceDefHandle);
|
||||
}
|
||||
|
@ -975,8 +975,8 @@ void SerialPnp_CommandUpdateHandlerRedirect(int index,
|
|||
}
|
||||
}
|
||||
|
||||
const InterfaceDefinition* SerialPnp_GetInterface(const char* interfaceId) {
|
||||
LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(g_InterfaceDefinitions);
|
||||
const InterfaceDefinition* SerialPnp_GetInterface(PSERIAL_DEVICE_CONTEXT deviceContext, const char* interfaceId) {
|
||||
LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(deviceContext->InterfaceDefinitions);
|
||||
while (interfaceDefHandle != NULL) {
|
||||
const InterfaceDefinition* interfaceDef = singlylinkedlist_item_get_value(interfaceDefHandle);
|
||||
if (stricmp(interfaceDef->Id, interfaceId) == 0) {
|
||||
|
@ -1001,125 +1001,252 @@ int SerialPnp_GetListCount(SINGLYLINKEDLIST_HANDLE list) {
|
|||
return count;
|
||||
}
|
||||
|
||||
int SerialPnp_CreatePnpInterface(PNPADAPTER_INTERFACE_HANDLE Interface, PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD args) {
|
||||
PSERIAL_DEVICE_CONTEXT deviceContext = (PSERIAL_DEVICE_CONTEXT) args->Context;
|
||||
int SerialPnp_CreatePnpInterface(PNPADAPTER_CONTEXT adapterHandle, PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD args) {
|
||||
PSERIAL_DEVICE_CONTEXT deviceContext = (PSERIAL_DEVICE_CONTEXT)args->Context;
|
||||
JSON_Value* jvalue = json_parse_string(args->Message);
|
||||
JSON_Object* jmsg = json_value_get_object(jvalue);
|
||||
PNP_INTERFACE_CLIENT_HANDLE pnpInterfaceClient;
|
||||
|
||||
const char* interfaceId = json_object_get_string(jmsg, "InterfaceId");
|
||||
const InterfaceDefinition* interfaceDef = SerialPnp_GetInterface(interfaceId);
|
||||
PNP_CLIENT_READWRITE_PROPERTY_UPDATED_CALLBACK_TABLE serialPropertyTable = { 0 };
|
||||
PNP_CLIENT_COMMAND_CALLBACK_TABLE serialCommandTable = { 0 };
|
||||
PNP_COMMAND_EXECUTE_CALLBACK* commandUpdateTable = NULL;
|
||||
char** propertyNames = NULL;
|
||||
PNP_READWRITE_PROPERTY_UPDATE_CALLBACK* propertyUpdateTable = NULL;
|
||||
char** commandNames = NULL;
|
||||
int propertyCount = 0;
|
||||
int commandCount = 0;
|
||||
int result = 0;
|
||||
|
||||
if (NULL == interfaceDef) {
|
||||
return -1;
|
||||
}
|
||||
// Create an Azure Pnp interface for each interface in the SerialPnp descriptor
|
||||
LIST_ITEM_HANDLE interfaceDefHandle = singlylinkedlist_get_head_item(deviceContext->InterfaceDefinitions);
|
||||
while (interfaceDefHandle != NULL) {
|
||||
PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface = NULL;
|
||||
PNP_INTERFACE_CLIENT_HANDLE pnpInterfaceClient = NULL;
|
||||
char** propertyNames = NULL;
|
||||
int propertyCount = 0;
|
||||
PNP_READWRITE_PROPERTY_UPDATE_CALLBACK* propertyUpdateTable = NULL;
|
||||
PNP_CLIENT_READWRITE_PROPERTY_UPDATED_CALLBACK_TABLE serialPropertyTable = { 0 };
|
||||
char** commandNames = NULL;
|
||||
int commandCount = 0;
|
||||
PNP_COMMAND_EXECUTE_CALLBACK* commandUpdateTable = NULL;
|
||||
PNP_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);
|
||||
// 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;
|
||||
if (propertyCount > 0) {
|
||||
LIST_ITEM_HANDLE eventDef = singlylinkedlist_get_head_item(property);
|
||||
const PropertyDefinition* ev;
|
||||
|
||||
propertyNames = malloc(sizeof(char*)*propertyCount);
|
||||
propertyUpdateTable = malloc(sizeof(PNP_READWRITE_PROPERTY_UPDATE_CALLBACK*)*propertyCount);
|
||||
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] = PredefinedPropertyHandlerTables[x];
|
||||
x++;
|
||||
eventDef = singlylinkedlist_get_next_item(eventDef);
|
||||
propertyNames = malloc(sizeof(char*)*propertyCount);
|
||||
if (NULL == propertyNames) {
|
||||
result = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
propertyUpdateTable = malloc(sizeof(PNP_READWRITE_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] = PredefinedPropertyHandlerTables[x];
|
||||
x++;
|
||||
eventDef = singlylinkedlist_get_next_item(eventDef);
|
||||
}
|
||||
|
||||
serialPropertyTable.numCallbacks = propertyCount;
|
||||
serialPropertyTable.propertyNames = propertyNames;
|
||||
serialPropertyTable.callbacks = propertyUpdateTable;
|
||||
serialPropertyTable.version = 1;
|
||||
}
|
||||
|
||||
serialPropertyTable.numCallbacks = propertyCount;
|
||||
serialPropertyTable.propertyNames = propertyNames;
|
||||
serialPropertyTable.callbacks = propertyUpdateTable;
|
||||
serialPropertyTable.version = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Construct command table
|
||||
{
|
||||
SINGLYLINKEDLIST_HANDLE command = interfaceDef->Commands;
|
||||
int commandCount = SerialPnp_GetListCount(command);
|
||||
|
||||
if (commandCount > 0) {
|
||||
LIST_ITEM_HANDLE cmdDef;
|
||||
int x = 0;
|
||||
const CommandDefinition* cv;
|
||||
// Construct command table
|
||||
{
|
||||
SINGLYLINKEDLIST_HANDLE command = interfaceDef->Commands;
|
||||
commandCount = SerialPnp_GetListCount(command);
|
||||
|
||||
commandNames = malloc(sizeof(char*)*commandCount);
|
||||
commandUpdateTable = malloc(sizeof(PNP_COMMAND_EXECUTE_CALLBACK*)*commandCount);
|
||||
cmdDef = singlylinkedlist_get_head_item(command);
|
||||
while (cmdDef != NULL) {
|
||||
cv = singlylinkedlist_item_get_value(cmdDef);
|
||||
commandNames[x] = cv->defintion.Name;
|
||||
commandUpdateTable[x] = PredefinedCommandHandlerTables[x];
|
||||
x++;
|
||||
cmdDef = singlylinkedlist_get_next_item(cmdDef);
|
||||
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(PNP_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] = PredefinedCommandHandlerTables[x];
|
||||
x++;
|
||||
cmdDef = singlylinkedlist_get_next_item(cmdDef);
|
||||
}
|
||||
|
||||
serialCommandTable.numCommandCallbacks = commandCount;
|
||||
serialCommandTable.commandNames = commandNames;
|
||||
serialCommandTable.commandCallbacks = commandUpdateTable;
|
||||
serialCommandTable.version = 1;
|
||||
}
|
||||
|
||||
serialCommandTable.numCommandCallbacks = commandCount;
|
||||
serialCommandTable.commandNames = commandNames;
|
||||
serialCommandTable.commandCallbacks = commandUpdateTable;
|
||||
serialCommandTable.version = 1;
|
||||
}
|
||||
|
||||
pnpInterfaceClient = PnP_InterfaceClient_Create(pnpDeviceClientHandle, interfaceId,
|
||||
propertyCount > 0 ? &serialPropertyTable : NULL,
|
||||
commandCount > 0 ? &serialCommandTable : NULL,
|
||||
deviceContext);
|
||||
if (NULL == pnpInterfaceClient) {
|
||||
result = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// Create PnpAdapter Interface
|
||||
{
|
||||
PNPADPATER_INTERFACE_INIT_PARAMS interfaceParams = { 0 };
|
||||
interfaceParams.releaseInterface = SerialPnp_ReleasePnpInterface;
|
||||
//interfaceParams.pnpInterface = pnpInterfaceClient;
|
||||
|
||||
result = PnpAdapterInterface_Create(adapterHandle, interfaceId, pnpInterfaceClient, &pnpAdapterInterface, &interfaceParams);
|
||||
if (result < 0) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
interfaceDefHandle = singlylinkedlist_get_next_item(interfaceDefHandle);
|
||||
}
|
||||
|
||||
pnpInterfaceClient = PnP_InterfaceClient_Create(pnpDeviceClientHandle, interfaceId, propertyCount > 0 ? &serialPropertyTable : NULL, commandCount > 0 ? &serialCommandTable : NULL, deviceContext);
|
||||
if (NULL == pnpInterfaceClient) {
|
||||
return -1;
|
||||
}
|
||||
exit:
|
||||
|
||||
if (NULL != propertyUpdateTable) {
|
||||
free(propertyUpdateTable);
|
||||
// Cleanup incase of failure
|
||||
if (result < 0) {
|
||||
// Destroy PnpInterfaceClient
|
||||
//if (NULL != pnpInterfaceClient) {
|
||||
// PnP_InterfaceClient_Destroy(pnpInterfaceClient);
|
||||
//}
|
||||
}
|
||||
if (NULL != propertyNames) {
|
||||
free(propertyNames);
|
||||
}
|
||||
|
||||
if (NULL != commandUpdateTable) {
|
||||
free(commandUpdateTable);
|
||||
}
|
||||
if (NULL != commandNames) {
|
||||
free(commandNames);
|
||||
}
|
||||
|
||||
PnpAdapter_SetPnpInterfaceClient(Interface, pnpInterfaceClient);
|
||||
deviceContext->InterfaceHandle = PnpAdapter_GetPnpInterfaceClient(Interface);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SerialPnp_ReleasePnpInterface(PNPADAPTER_INTERFACE_HANDLE pnpInterface) {
|
||||
PSERIAL_DEVICE_CONTEXT deviceContext = PnpAdapter_GetContext(pnpInterface);
|
||||
void SerialPnp_FreeFieldDefinition(FieldDefinition* fdef) {
|
||||
if (NULL != fdef->Description) {
|
||||
free(fdef->Description);
|
||||
}
|
||||
|
||||
if (NULL != deviceContext) {
|
||||
if (NULL != fdef->DisplayName) {
|
||||
free(fdef->DisplayName);
|
||||
}
|
||||
|
||||
if (NULL != fdef->Name) {
|
||||
free(fdef->Name);
|
||||
}
|
||||
}
|
||||
|
||||
void SerialPnp_FreeEventDefinition(SINGLYLINKEDLIST_HANDLE events) {
|
||||
if (NULL == events) {
|
||||
return;
|
||||
}
|
||||
|
||||
LIST_ITEM_HANDLE eventItem = singlylinkedlist_get_head_item(events);
|
||||
while (NULL != eventItem) {
|
||||
EventDefinition* e = (EventDefinition*)singlylinkedlist_item_get_value(eventItem);
|
||||
SerialPnp_FreeFieldDefinition(&e->defintion);
|
||||
if (NULL != e->Units) {
|
||||
free(e->Units);
|
||||
}
|
||||
free(e);
|
||||
eventItem = singlylinkedlist_get_next_item(eventItem);
|
||||
}
|
||||
}
|
||||
|
||||
void SerialPnp_FreeCommandDefinition(SINGLYLINKEDLIST_HANDLE cmds) {
|
||||
if (NULL == cmds) {
|
||||
return;
|
||||
}
|
||||
|
||||
LIST_ITEM_HANDLE cmdItem = singlylinkedlist_get_head_item(cmds);
|
||||
while (NULL != cmdItem) {
|
||||
CommandDefinition* c = (CommandDefinition*)singlylinkedlist_item_get_value(cmdItem);
|
||||
free(c);
|
||||
cmdItem = singlylinkedlist_get_next_item(cmdItem);
|
||||
}
|
||||
}
|
||||
|
||||
void SerialPnp_FreePropertiesDefinition(SINGLYLINKEDLIST_HANDLE props) {
|
||||
if (NULL == props) {
|
||||
return;
|
||||
}
|
||||
|
||||
LIST_ITEM_HANDLE propItem = singlylinkedlist_get_head_item(props);
|
||||
while (NULL != propItem) {
|
||||
PropertyDefinition* p = (PropertyDefinition*)singlylinkedlist_item_get_value(propItem);
|
||||
SerialPnp_FreeFieldDefinition(&p->defintion);
|
||||
if (NULL != p->Units) {
|
||||
free(p->Units);
|
||||
}
|
||||
free(p);
|
||||
propItem = singlylinkedlist_get_next_item(propItem);
|
||||
}
|
||||
}
|
||||
|
||||
int SerialPnp_ReleasePnpInterface(PNPADAPTER_INTERFACE_HANDLE pnpInterface) {
|
||||
PSERIAL_DEVICE_CONTEXT deviceContext = PnpAdapterInterface_GetContext(pnpInterface);
|
||||
|
||||
if (NULL == deviceContext) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// BUG: If a serial device has multiple interface, this wont work
|
||||
if (deviceContext->hSerial) {
|
||||
if (NULL != deviceContext->hSerial) {
|
||||
CloseHandle(deviceContext->hSerial);
|
||||
}
|
||||
|
||||
if (deviceContext->InterfaceDefinitions) {
|
||||
LIST_ITEM_HANDLE interfaceItem = singlylinkedlist_get_head_item(deviceContext->InterfaceDefinitions);
|
||||
while (interfaceItem != NULL) {
|
||||
InterfaceDefinition* def = (InterfaceDefinition*)singlylinkedlist_item_get_value(interfaceItem);
|
||||
SerialPnp_FreeEventDefinition(def->Events);
|
||||
SerialPnp_FreeCommandDefinition(def->Commands);
|
||||
SerialPnp_FreePropertiesDefinition(def->Properties);
|
||||
|
||||
free(def);
|
||||
interfaceItem = singlylinkedlist_get_next_item(interfaceItem);
|
||||
}
|
||||
singlylinkedlist_destroy(deviceContext->InterfaceDefinitions);
|
||||
}
|
||||
|
||||
free(deviceContext);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SerialPnp_Initialize(const char* adapterArgs) {
|
||||
UNREFERENCED_PARAMETER(adapterArgs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1134,9 +1261,8 @@ DISCOVERY_ADAPTER SerialPnpDiscovery = {
|
|||
};
|
||||
|
||||
PNP_ADAPTER SerialPnpInterface = {
|
||||
.Identity = "serial-pnp-interface",
|
||||
.Initialize = SerialPnp_Initialize,
|
||||
.Shutdown = SerialPnp_Shutdown,
|
||||
.CreatePnpInterface = SerialPnp_CreatePnpInterface,
|
||||
.ReleaseInterface = SerialPnp_ReleasePnpInterface
|
||||
.identity = "serial-pnp-interface",
|
||||
.initialize = SerialPnp_Initialize,
|
||||
.shutdown = SerialPnp_Shutdown,
|
||||
.createPnpInterface = SerialPnp_CreatePnpInterface
|
||||
};
|
||||
|
|
|
@ -5,94 +5,101 @@ extern "C"
|
|||
{
|
||||
#endif
|
||||
|
||||
typedef struct SerialPnPPacketHeader
|
||||
{
|
||||
byte StartOfFrame;
|
||||
USHORT Length;
|
||||
byte PacketType;
|
||||
} SerialPnPPacketHeader;
|
||||
typedef struct SerialPnPPacketHeader
|
||||
{
|
||||
byte StartOfFrame;
|
||||
USHORT Length;
|
||||
byte PacketType;
|
||||
} SerialPnPPacketHeader;
|
||||
|
||||
typedef enum Schema
|
||||
{
|
||||
Invalid = 0,
|
||||
Byte,
|
||||
Float,
|
||||
Double,
|
||||
Int,
|
||||
Long,
|
||||
Boolean,
|
||||
String
|
||||
} Schema;
|
||||
typedef enum Schema
|
||||
{
|
||||
Invalid = 0,
|
||||
Byte,
|
||||
Float,
|
||||
Double,
|
||||
Int,
|
||||
Long,
|
||||
Boolean,
|
||||
String
|
||||
} Schema;
|
||||
|
||||
typedef struct FieldDefinition
|
||||
{
|
||||
char* Name;
|
||||
char* DisplayName;
|
||||
char* Description;
|
||||
} FieldDefinition;
|
||||
typedef struct FieldDefinition
|
||||
{
|
||||
char* Name;
|
||||
char* DisplayName;
|
||||
char* Description;
|
||||
} FieldDefinition;
|
||||
|
||||
|
||||
typedef struct EventDefinition
|
||||
{
|
||||
FieldDefinition defintion;
|
||||
Schema DataSchema;
|
||||
char* Units;
|
||||
} EventDefinition;
|
||||
typedef struct EventDefinition
|
||||
{
|
||||
FieldDefinition defintion;
|
||||
Schema DataSchema;
|
||||
char* Units;
|
||||
} EventDefinition;
|
||||
|
||||
typedef struct PropertyDefinition
|
||||
{
|
||||
FieldDefinition defintion;
|
||||
char* Units;
|
||||
bool Required;
|
||||
bool Writeable;
|
||||
Schema DataSchema;
|
||||
} PropertyDefinition;
|
||||
typedef struct PropertyDefinition
|
||||
{
|
||||
FieldDefinition defintion;
|
||||
char* Units;
|
||||
bool Required;
|
||||
bool Writeable;
|
||||
Schema DataSchema;
|
||||
} PropertyDefinition;
|
||||
|
||||
typedef struct CommandDefinition
|
||||
{
|
||||
FieldDefinition defintion;
|
||||
Schema RequestSchema;
|
||||
Schema ResponseSchema;
|
||||
} CommandDefinition;
|
||||
typedef struct CommandDefinition
|
||||
{
|
||||
FieldDefinition defintion;
|
||||
Schema RequestSchema;
|
||||
Schema ResponseSchema;
|
||||
} CommandDefinition;
|
||||
|
||||
typedef struct InterfaceDefinition
|
||||
{
|
||||
char* Id;
|
||||
int Index;
|
||||
SINGLYLINKEDLIST_HANDLE Events;
|
||||
SINGLYLINKEDLIST_HANDLE Properties;
|
||||
SINGLYLINKEDLIST_HANDLE Commands;
|
||||
} InterfaceDefinition;
|
||||
typedef struct InterfaceDefinition
|
||||
{
|
||||
char* Id;
|
||||
int Index;
|
||||
SINGLYLINKEDLIST_HANDLE Events;
|
||||
SINGLYLINKEDLIST_HANDLE Properties;
|
||||
SINGLYLINKEDLIST_HANDLE Commands;
|
||||
} InterfaceDefinition;
|
||||
|
||||
typedef enum DefinitionType {
|
||||
Telemetry,
|
||||
Property,
|
||||
Command
|
||||
} DefinitionType;
|
||||
typedef enum DefinitionType {
|
||||
Telemetry,
|
||||
Property,
|
||||
Command
|
||||
} DefinitionType;
|
||||
|
||||
typedef struct _SERIAL_DEVICE_CONTEXT {
|
||||
HANDLE hSerial;
|
||||
PNP_INTERFACE_CLIENT_HANDLE* InterfaceHandle;
|
||||
byte RxBuffer[4096]; // Todo: maximum buffer size
|
||||
unsigned int RxBufferIndex;
|
||||
bool RxEscaped;
|
||||
THREAD_HANDLE SerialDeviceWorker;
|
||||
PNPBRIDGE_NOTIFY_DEVICE_CHANGE SerialDeviceChangeCallback;
|
||||
} SERIAL_DEVICE_CONTEXT, *PSERIAL_DEVICE_CONTEXT;
|
||||
typedef struct _SERIAL_DEVICE_CONTEXT {
|
||||
HANDLE hSerial;
|
||||
PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface;
|
||||
|
||||
void SerialPnp_RxPacket(PSERIAL_DEVICE_CONTEXT serialDevice, byte** receivedPacket, DWORD* length, char packetType);
|
||||
byte RxBuffer[4096]; // Todo: maximum buffer size
|
||||
unsigned int RxBufferIndex;
|
||||
bool RxEscaped;
|
||||
//OVERLAPPED osReader;
|
||||
THREAD_HANDLE SerialDeviceWorker;
|
||||
PNPBRIDGE_NOTIFY_DEVICE_CHANGE SerialDeviceChangeCallback;
|
||||
|
||||
// list of interface definitions on this serial device
|
||||
SINGLYLINKEDLIST_HANDLE InterfaceDefinitions;
|
||||
} SERIAL_DEVICE_CONTEXT, *PSERIAL_DEVICE_CONTEXT;
|
||||
|
||||
void SerialPnp_TxPacket(PSERIAL_DEVICE_CONTEXT serialDevice, byte* OutPacket, int Length);
|
||||
void SerialPnp_RxPacket(PSERIAL_DEVICE_CONTEXT serialDevice, byte** receivedPacket, DWORD* length, char packetType);
|
||||
|
||||
void SerialPnp_UnsolicitedPacket(PSERIAL_DEVICE_CONTEXT device, byte* packet, DWORD length);
|
||||
void SerialPnp_TxPacket(PSERIAL_DEVICE_CONTEXT serialDevice, byte* OutPacket, int Length);
|
||||
|
||||
void SerialPnp_ResetDevice(PSERIAL_DEVICE_CONTEXT serialDevice);
|
||||
void SerialPnp_UnsolicitedPacket(PSERIAL_DEVICE_CONTEXT device, byte* packet, DWORD length);
|
||||
|
||||
void SerialPnp_DeviceDescriptorRequest(PSERIAL_DEVICE_CONTEXT serialDevice, byte** desc, DWORD* length);
|
||||
void SerialPnp_ResetDevice(PSERIAL_DEVICE_CONTEXT serialDevice);
|
||||
|
||||
byte* SerialPnp_StringSchemaToBinary(Schema Schema, byte* data, int* length);
|
||||
void SerialPnp_DeviceDescriptorRequest(PSERIAL_DEVICE_CONTEXT serialDevice, byte** desc, DWORD* length);
|
||||
|
||||
int SerialPnp_SendEventAsync(PNP_INTERFACE_CLIENT_HANDLE pnpInterface, char* eventName, char* data);
|
||||
byte* SerialPnp_StringSchemaToBinary(Schema Schema, byte* data, int* length);
|
||||
|
||||
int SerialPnp_SendEventAsync(PNP_INTERFACE_CLIENT_HANDLE pnpInterface, char* eventName, char* data);
|
||||
|
||||
int SerialPnp_ReleasePnpInterface(PNPADAPTER_INTERFACE_HANDLE pnpInterface);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
#Copyright (c) Microsoft. All rights reserved.
|
||||
#Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
cmake_minimum_required(VERSION 2.8.11)
|
||||
#this is CMakeLists for pnp_bridge
|
||||
|
||||
set(PROJECT_NAME PnpBridge)
|
||||
|
||||
if(POLICY CMP0042)
|
||||
cmake_policy(SET CMP0042 NEW)
|
||||
endif()
|
||||
|
||||
# compileAsC99()
|
||||
|
||||
set(pnp_bridge_c_files
|
||||
./ConfigurationParser.c
|
||||
./DiscoveryManager.c
|
||||
./IotHubComms.c
|
||||
./PnpAdapterManger.c
|
||||
./PnpBridge.c
|
||||
./utility.c
|
||||
./Core/PnpAdapterInterface.c
|
||||
./Core/PnpBridgeMemory.c
|
||||
./Adapters/AdapterManifest.c
|
||||
./Adapters/Camera/CameraIotPnpAPIs.cpp
|
||||
./Adapters/Camera/CameraCaptureEngineCallbacks.cpp
|
||||
./Adapters/Camera/CameraCaptureEngine.cpp
|
||||
./Adapters/Camera/CameraPnpDiscovery.cpp
|
||||
./Adapters/Camera/CameraIotPnpDevice.cpp
|
||||
./Adapters/Camera/JsonWrapper.cpp
|
||||
./Adapters/Camera/CameraStatConsumer.cpp
|
||||
./Adapters/CoreDeviceHealth/CoreDeviceHealth.c
|
||||
./Adapters/CoreDeviceHealth/WindowsPnPDeviceDiscovery.c
|
||||
./Adapters/SerialPnp/SerialPnp.c
|
||||
)
|
||||
|
||||
set(pnp_bridge_h_files
|
||||
./common.h
|
||||
./ConfigurationParser.h
|
||||
./DiscoveryAdapterInterface.h
|
||||
./DiscoveryManager.h
|
||||
./IotHubComms.h
|
||||
./PnpAdapterInterface.h
|
||||
./PnpAdapterManager.h
|
||||
./PnpBridge.h
|
||||
./PnpBridgeCommon.h
|
||||
./PnpBridgeh.h
|
||||
./Core/PnpBridgeMemory.h
|
||||
./Adapters/PnpAdapterManifest.h
|
||||
./Adapters/DiscoveryAdapterManifest.h
|
||||
./Adapters/CmdAndPropHandler.h
|
||||
./Adapters/Camera/CameraCaptureEngine.h
|
||||
./Adapters/Camera/CameraCaptureEngineCallbacks.h
|
||||
./Adapters/Camera/CameraIotPnpAPIs.h
|
||||
./Adapters/Camera/CameraIotPnpDevice.h
|
||||
./Adapters/Camera/CameraPnpDiscovery.h
|
||||
./Adapters/Camera/CameraStatConsumer.h
|
||||
./Adapters/Camera/JsonWrapper.h
|
||||
./Adapters/Camera/pch.h
|
||||
./Adapters/CoreDeviceHealth/CoreDeviceHealth.h
|
||||
./Adapters/CoreDeviceHealth/WindowsPnpDeviceDiscovery.h
|
||||
./Adapters/SerialPnp/SerialPnp.h
|
||||
)
|
||||
|
||||
add_definitions("-D_UNICODE")
|
||||
|
||||
set(pnp_bridge_libs)
|
||||
|
||||
set(install_staticlibs
|
||||
${PROJECT_NAME}
|
||||
)
|
||||
|
||||
set(pnp_bridge_h_install_files
|
||||
${pnp_bridge_h_files}
|
||||
)
|
||||
|
||||
set(pnp_bridge_INC_FOLDER ${CMAKE_CURRENT_LIST_DIR} CACHE INTERNAL "this is what needs to be included if using pnp_bridge lib" FORCE)
|
||||
|
||||
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/pnp_client/inc)
|
||||
include_directories(../../deps/azure-iot-sdk-c-pnp/iothub_client/inc)
|
||||
include_directories(${pnp_bridge_INC_FOLDER})
|
||||
|
||||
IF(WIN32)
|
||||
#windows needs this define
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
add_definitions(-DGB_MEASURE_MEMORY_FOR_THIS -DGB_DEBUG_ALLOC)
|
||||
ENDIF(WIN32)
|
||||
|
||||
add_definitions(-DPNP_LOGGING_ENABLED)
|
||||
|
||||
|
||||
add_executable(${PROJECT_NAME}
|
||||
${pnp_bridge_c_files}
|
||||
${pnp_bridge_h_files}
|
||||
)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} ${pnp_bridge_libs} iothub_client parson pnp_client iothub_client_http_transport iothub_client_amqp_transport iothub_client_amqp_ws_transport iothub_client_mqtt_transport iothub_client_mqtt_ws_transport umqtt aziotsharedutil cfgmgr32 mfplat mfsensorgroup)
|
||||
|
||||
set(pnp_bridge_libs
|
||||
${PROJECT_NAME}
|
||||
${pnp_bridge_libs}
|
||||
)
|
||||
|
||||
# install(FILES ${pnp_bridge_h_install_files}
|
||||
# DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/azureiot/pnp)
|
||||
# install(TARGETS ${install_staticlibs}
|
||||
# ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
# LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
|
@ -1,176 +1,251 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
#include "PnpBridgeCommon.h"
|
||||
|
||||
PNPBRIDGE_RESULT PnpBridgeConfig_ReadConfigurationFromFile(const char *filename, JSON_Value** config) {
|
||||
if (NULL == filename || NULL == config) {
|
||||
return PNPBRIDGE_INVALID_ARGS;
|
||||
}
|
||||
|
||||
*config = json_parse_file(filename);
|
||||
if (*config == NULL) {
|
||||
return PNPBRIDGE_CONFIG_READ_FAILED;
|
||||
}
|
||||
|
||||
return PNPBRIDGE_OK;
|
||||
}
|
||||
|
||||
PNPBRIDGE_RESULT PnpBridgeConfig_ReadConfigurationFromString(const char *configString, JSON_Value** config) {
|
||||
if (NULL == configString || NULL == config) {
|
||||
return PNPBRIDGE_INVALID_ARGS;
|
||||
}
|
||||
|
||||
*config = json_parse_string(configString);
|
||||
if (*config == NULL) {
|
||||
return PNPBRIDGE_CONFIG_READ_FAILED;
|
||||
}
|
||||
|
||||
return PNPBRIDGE_OK;
|
||||
}
|
||||
|
||||
JSON_Array* Configuration_GetConfiguredDevices(JSON_Value* config) {
|
||||
JSON_Object* jsonObject = json_value_get_object(config);
|
||||
JSON_Array *devices = json_object_dotget_array(jsonObject, "Devices");
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
JSON_Object* Configuration_GetPnpParametersForDevice(JSON_Object* device) {
|
||||
if (device == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSON_Object* discoveryParams = json_object_dotget_object(device, "PnpParameters");
|
||||
return discoveryParams;
|
||||
}
|
||||
|
||||
|
||||
JSON_Object* Configuration_GetDiscoveryParametersForDevice(JSON_Object* device) {
|
||||
if (device == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSON_Object* discoveryParams = json_object_dotget_object(device, "DiscoveryParameters");
|
||||
return discoveryParams;
|
||||
}
|
||||
|
||||
const char* Configuration_GetConnectionString(JSON_Value* config) {
|
||||
JSON_Object* jsonObject = json_value_get_object(config);
|
||||
JSON_Object *pnpBridgeParams = json_object_dotget_object(jsonObject, "PnpBridgeParameters");
|
||||
if (NULL == pnpBridgeParams) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return json_object_dotget_string(pnpBridgeParams, "ConnectionString");
|
||||
}
|
||||
|
||||
JSON_Object* Configuration_GetAdapterParameters(JSON_Value* config, const char* identity, const char* adapterType) {
|
||||
JSON_Object* jsonObject = json_value_get_object(config);
|
||||
JSON_Object *adapter = json_object_dotget_object(jsonObject, adapterType);
|
||||
if (NULL == adapter) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSON_Array* params = json_object_dotget_array(adapter, "Parameters");
|
||||
if (NULL == params) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (int j = 0; j < (int)json_array_get_count(params); j++) {
|
||||
JSON_Object *param = json_array_get_object(params, j);
|
||||
const char* id = json_object_dotget_string(param, "Identity");
|
||||
if (NULL != id) {
|
||||
if (strcmp(id, identity) == 0) {
|
||||
return param;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSON_Object* Configuration_GetPnpParameters(JSON_Value* config, const char* identity) {
|
||||
return Configuration_GetAdapterParameters(config, identity, "PnpAdapters");
|
||||
}
|
||||
|
||||
JSON_Object* Configuration_GetDiscoveryParameters(JSON_Value* config,const char* identity) {
|
||||
return Configuration_GetAdapterParameters(config, identity, "DiscoveryAdapters");
|
||||
}
|
||||
|
||||
PNPBRIDGE_RESULT Configuration_IsDeviceConfigured(JSON_Value* config, JSON_Object* Message, JSON_Object** Device) {
|
||||
JSON_Array *devices = Configuration_GetConfiguredDevices(config);
|
||||
JSON_Object* discMatchParams;
|
||||
int res = -1;
|
||||
bool foundMatch = false;
|
||||
|
||||
const char* formatId = json_object_dotget_string(Message, "Identity");
|
||||
discMatchParams = json_object_get_object(Message, "MatchParameters");
|
||||
|
||||
// There needs to be only one match at the end.
|
||||
for (int i = 0; i < (int)json_array_get_count(devices); i++) {
|
||||
JSON_Object *device = json_array_get_object(devices, i);
|
||||
JSON_Object* moduleParams = Configuration_GetPnpParametersForDevice(device);
|
||||
if (NULL == moduleParams) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const char* deviceFormatId = json_object_dotget_string(moduleParams, "Identity");
|
||||
if (strcmp(deviceFormatId, formatId) == 0) {
|
||||
JSON_Object* matchCriteria = json_object_dotget_object(device, "MatchFilters");
|
||||
const char* matchType = json_object_get_string(matchCriteria, "MatchType");
|
||||
if (strcmp(matchType, "*") == 0) {
|
||||
if (true == foundMatch) {
|
||||
LogError("Found multiple devices in the config that match the filter");
|
||||
res = -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
foundMatch = true;
|
||||
res = 0;
|
||||
*Device = device;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NULL == discMatchParams) {
|
||||
continue;
|
||||
}
|
||||
|
||||
JSON_Object* matchParameters = json_object_dotget_object(matchCriteria, "MatchParameters");
|
||||
const size_t matchParameterCount = json_object_get_count(matchParameters);
|
||||
for (int i = 0; i < (int)matchParameterCount; i++) {
|
||||
const char* name = json_object_get_name(matchParameters, i);
|
||||
const char* value = json_object_get_string(matchParameters, name);
|
||||
|
||||
if (!json_object_dothas_value(discMatchParams, name)) {
|
||||
res = -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
const char* value2 = json_object_get_string(discMatchParams, name);
|
||||
if (strstr(value2, value) == 0) {
|
||||
res = -1;
|
||||
goto end;
|
||||
}
|
||||
else {
|
||||
if (true == foundMatch) {
|
||||
LogError("Found multiple devices in the config that match the filter");
|
||||
res = -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
const char* interfaceId = json_object_dotget_string(device, "InterfaceId");
|
||||
json_object_set_string(Message, "InterfaceId", interfaceId);
|
||||
foundMatch = true;
|
||||
*Device = device;
|
||||
res = 0;
|
||||
}
|
||||
}
|
||||
res = 0;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
return res;
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
#include "PnpBridgeCommon.h"
|
||||
|
||||
PNPBRIDGE_RESULT PnpBridgeConfig_ReadConfigurationFromFile(const char *filename, JSON_Value** config) {
|
||||
if (NULL == filename || NULL == config) {
|
||||
return PNPBRIDGE_INVALID_ARGS;
|
||||
}
|
||||
|
||||
*config = json_parse_file(filename);
|
||||
if (*config == NULL) {
|
||||
return PNPBRIDGE_CONFIG_READ_FAILED;
|
||||
}
|
||||
|
||||
return PNPBRIDGE_OK;
|
||||
}
|
||||
|
||||
PNPBRIDGE_RESULT PnpBridgeConfig_ValidateConfiguration(JSON_Value* config) {
|
||||
PNPBRIDGE_RESULT result = PNPBRIDGE_OK;
|
||||
|
||||
// Check for mandatory parameters
|
||||
TRY
|
||||
{
|
||||
// Devices
|
||||
{
|
||||
JSON_Array* devices = Configuration_GetConfiguredDevices(config);
|
||||
for (int i = 0; i < (int)json_array_get_count(devices); i++) {
|
||||
JSON_Object *device = json_array_get_object(devices, i);
|
||||
|
||||
// InterfaceId or SelfDescribing
|
||||
{
|
||||
const char* selfDescribing = json_object_dotget_string(device, PNP_CONFIG_NAME_SELF_DESCRIBING);
|
||||
const char* interfaceId = json_object_dotget_string(device, PNP_CONFIG_NAME_INTERFACE_ID);
|
||||
if (NULL == selfDescribing) {
|
||||
if (NULL == interfaceId) {
|
||||
LogError("A device is missing InterfaceId");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (NULL != interfaceId) {
|
||||
LogError("A self describing device shouldn't have interface id");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PnpParameters
|
||||
{
|
||||
JSON_Object* pnpParams = Configuration_GetPnpParametersForDevice(device);
|
||||
if (NULL == pnpParams) {
|
||||
LogError("A device is missing PnpParameters");
|
||||
result = PNPBRIDGE_INVALID_ARGS;
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
// PnpParameters -> Idenitity
|
||||
const char* identity = json_object_dotget_string(pnpParams, PNP_CONFIG_IDENTITY_NAME);
|
||||
if (NULL == identity) {
|
||||
LogError("PnpParameter is missing Adapter identity");
|
||||
result = PNPBRIDGE_INVALID_ARGS;
|
||||
LEAVE;
|
||||
}
|
||||
}
|
||||
|
||||
// DiscoveryParameters
|
||||
{
|
||||
JSON_Object* discParams = Configuration_GetDiscoveryParametersForDevice(device);
|
||||
if (discParams) {
|
||||
// DiscoveryParameters -> Idenitity
|
||||
const char* identity = json_object_dotget_string(discParams, PNP_CONFIG_IDENTITY_NAME);
|
||||
if (NULL == identity) {
|
||||
LogError("DiscoveryParameters is missing Adapter identity");
|
||||
result = PNPBRIDGE_INVALID_ARGS;
|
||||
LEAVE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
FINALLY
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PNPBRIDGE_RESULT PnpBridgeConfig_ReadConfigurationFromString(const char *configString, JSON_Value** config) {
|
||||
if (NULL == configString || NULL == config) {
|
||||
return PNPBRIDGE_INVALID_ARGS;
|
||||
}
|
||||
|
||||
*config = json_parse_string(configString);
|
||||
if (*config == NULL) {
|
||||
return PNPBRIDGE_CONFIG_READ_FAILED;
|
||||
}
|
||||
|
||||
return PNPBRIDGE_OK;
|
||||
}
|
||||
|
||||
JSON_Array* Configuration_GetConfiguredDevices(JSON_Value* config) {
|
||||
JSON_Object* jsonObject = json_value_get_object(config);
|
||||
JSON_Array *devices = json_object_dotget_array(jsonObject, "Devices");
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
JSON_Object* Configuration_GetPnpParametersForDevice(JSON_Object* device) {
|
||||
if (device == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSON_Object* pnpParams = json_object_dotget_object(device, "PnpParameters");
|
||||
return pnpParams;
|
||||
}
|
||||
|
||||
JSON_Object* Configuration_GetMatchParametersForDevice(JSON_Object* device) {
|
||||
if (device == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSON_Object* filterParams = json_object_dotget_object(device, "MatchFilters");
|
||||
JSON_Object* matchParams = json_object_dotget_object(filterParams, "MatchParameters");
|
||||
return matchParams;
|
||||
}
|
||||
|
||||
JSON_Object* Configuration_GetDiscoveryParametersForDevice(JSON_Object* device) {
|
||||
if (device == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSON_Object* discoveryParams = json_object_dotget_object(device, "DiscoveryParameters");
|
||||
return discoveryParams;
|
||||
}
|
||||
|
||||
const char* Configuration_GetConnectionString(JSON_Value* config) {
|
||||
JSON_Object* jsonObject = json_value_get_object(config);
|
||||
JSON_Object *pnpBridgeParams = json_object_dotget_object(jsonObject, "PnpBridgeParameters");
|
||||
if (NULL == pnpBridgeParams) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return json_object_dotget_string(pnpBridgeParams, "ConnectionString");
|
||||
}
|
||||
|
||||
JSON_Object* Configuration_GetAdapterParameters(JSON_Value* config, const char* identity, const char* adapterType) {
|
||||
JSON_Object* jsonObject = json_value_get_object(config);
|
||||
JSON_Object *adapter = json_object_dotget_object(jsonObject, adapterType);
|
||||
if (NULL == adapter) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSON_Array* params = json_object_dotget_array(adapter, "Parameters");
|
||||
if (NULL == params) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (int j = 0; j < (int)json_array_get_count(params); j++) {
|
||||
JSON_Object *param = json_array_get_object(params, j);
|
||||
const char* id = json_object_dotget_string(param, PNP_CONFIG_IDENTITY_NAME);
|
||||
if (NULL != id) {
|
||||
if (strcmp(id, identity) == 0) {
|
||||
return param;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSON_Object* Configuration_GetPnpParameters(JSON_Value* config, const char* identity) {
|
||||
return Configuration_GetAdapterParameters(config, identity, PNP_CONFIG_NAME_PNP_ADAPTERS);
|
||||
}
|
||||
|
||||
JSON_Object* Configuration_GetDiscoveryParameters(JSON_Value* config,const char* identity) {
|
||||
return Configuration_GetAdapterParameters(config, identity, PNP_CONFIG_NAME_DISCOVERY_ADAPTERS);
|
||||
}
|
||||
|
||||
PNPBRIDGE_RESULT Configuration_IsDeviceConfigured(JSON_Value* config, JSON_Object* Message, JSON_Object** Device) {
|
||||
JSON_Array *devices = Configuration_GetConfiguredDevices(config);
|
||||
JSON_Object* discMatchParams;
|
||||
char* pnpAdapterIdentity = NULL;
|
||||
PNPBRIDGE_RESULT result = PNPBRIDGE_OK;
|
||||
|
||||
*Device = NULL;
|
||||
|
||||
TRY
|
||||
{
|
||||
discMatchParams = json_object_get_object(Message, PNP_CONFIG_NAME_MATCH_PARAMETERS);
|
||||
for (int i = 0; i < (int)json_array_get_count(devices); i++) {
|
||||
JSON_Object* device = json_array_get_object(devices, i);
|
||||
JSON_Object* pnpParams = Configuration_GetPnpParametersForDevice(device);
|
||||
if (NULL == pnpParams) {
|
||||
continue;
|
||||
}
|
||||
|
||||
JSON_Object* matchCriteria = json_object_dotget_object(device, PNP_CONFIG_MATCH_FILTERS_NAME);
|
||||
const char* matchType = json_object_get_string(matchCriteria, PNP_CONFIG_MATCH_TYPE_NAME);
|
||||
const char* currPnpAdapterId = json_object_get_string(pnpParams, PNP_CONFIG_IDENTITY_NAME);
|
||||
bool exactMatch = stricmp(matchType, "exact") == 0;
|
||||
|
||||
if (NULL == discMatchParams) {
|
||||
continue;
|
||||
}
|
||||
|
||||
JSON_Object* matchParameters = json_object_dotget_object(matchCriteria, PNP_CONFIG_NAME_MATCH_PARAMETERS);
|
||||
const size_t matchParameterCount = json_object_get_count(matchParameters);
|
||||
bool foundMatch = false;
|
||||
for (int j = 0; j < (int)matchParameterCount; j++) {
|
||||
const char* name = json_object_get_name(matchParameters, j);
|
||||
const char* value1 = json_object_get_string(matchParameters, name);
|
||||
|
||||
if (!json_object_dothas_value(discMatchParams, name)) {
|
||||
break;
|
||||
}
|
||||
|
||||
const char* value2 = json_object_get_string(discMatchParams, name);
|
||||
bool match;
|
||||
if (exactMatch) {
|
||||
match = 0 != strstr(value2, value1);
|
||||
}
|
||||
else {
|
||||
match = 0 == stricmp(value2, value1);
|
||||
}
|
||||
if (false == match) {
|
||||
foundMatch = false;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
foundMatch = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundMatch) {
|
||||
pnpAdapterIdentity = (char*)currPnpAdapterId;
|
||||
*Device = device;
|
||||
result = PNPBRIDGE_OK;
|
||||
LEAVE;
|
||||
}
|
||||
}
|
||||
}
|
||||
FINALLY
|
||||
{
|
||||
if (NULL == *Device) {
|
||||
result = PNPBRIDGE_INVALID_ARGS;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
|
@ -26,6 +26,8 @@ PNPBRIDGE_RESULT PnpBridgeConfig_ReadConfigurationFromFile(const char *filename,
|
|||
*/
|
||||
PNPBRIDGE_RESULT PnpBridgeConfig_ReadConfigurationFromString(const char *configString, JSON_Value** config);
|
||||
|
||||
JSON_Object* Configuration_GetMatchParametersForDevice(JSON_Object* device);
|
||||
|
||||
JSON_Object* Configuration_GetDiscoveryParametersForDevice(JSON_Object* device);
|
||||
|
||||
JSON_Object* Configuration_GetPnpParametersForDevice(JSON_Object* device);
|
||||
|
@ -40,6 +42,8 @@ PNPBRIDGE_RESULT Configuration_IsDeviceConfigured(JSON_Value* config, JSON_Objec
|
|||
|
||||
const char* Configuration_GetConnectionString(JSON_Value* config);
|
||||
|
||||
PNPBRIDGE_RESULT PnpBridgeConfig_ValidateConfiguration(JSON_Value* config);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -8,8 +8,6 @@
|
|||
extern PDISCOVERY_ADAPTER DISCOVERY_ADAPTER_MANIFEST[];
|
||||
extern const int DiscoveryAdapterCount;
|
||||
|
||||
DISCOVERY_ADAPTER discoveryInterface = { 0 };
|
||||
|
||||
void DiscoveryAdapterChangeHandler(PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD DeviceChangePayload);
|
||||
PNPBRIDGE_RESULT DiscoveryManager_StarDiscoveryAdapter(PDISCOVERY_MANAGER discoveryManager, PDISCOVERY_ADAPTER discoveryInterface, JSON_Object* deviceParams, JSON_Object* adapterParams, int key);
|
||||
|
||||
|
@ -106,63 +104,88 @@ PNPBRIDGE_RESULT DiscoveryManager_StarDiscoveryAdapter(PDISCOVERY_MANAGER discov
|
|||
return PNPBRIDGE_OK;
|
||||
}
|
||||
|
||||
PNPBRIDGE_RESULT DiscoveryAdapterManager_Start(PDISCOVERY_MANAGER discoveryManager, JSON_Value* config) {
|
||||
const char* PnpBridge_DeviceChangeMessageformat = "{ \
|
||||
\"Identity\": \"pnpbridge-core\", \
|
||||
\"InterfaceId\": \"%s\", \
|
||||
\"PublishMode\": \"true\", \
|
||||
\"MatchParameters\": %s \
|
||||
}";
|
||||
|
||||
PNPBRIDGE_RESULT DiscoveryAdapterManager_PublishAlwaysInterfaces(PDISCOVERY_MANAGER discoveryManager, JSON_Value* config) {
|
||||
AZURE_UNREFERENCED_PARAMETER(discoveryManager);
|
||||
JSON_Array *devices = Configuration_GetConfiguredDevices(config);
|
||||
|
||||
if (NULL == devices) {
|
||||
return PNPBRIDGE_INVALID_ARGS;
|
||||
}
|
||||
for (int i = 0; i < (int)json_array_get_count(devices); i++) {
|
||||
JSON_Object* device = json_array_get_object(devices, i);
|
||||
const char* publishModeString = json_object_get_string(device, PNP_CONFIG_NAME_PUBLISH_MODE);
|
||||
if (NULL != publishModeString && stricmp(publishModeString, "always") == 0) {
|
||||
PNPBRIDGE_DEVICE_CHANGE_PAYLOAD payload = { 0 };
|
||||
payload.ChangeType = PNPBRIDGE_INTERFACE_CHANGE_PERSIST;
|
||||
|
||||
for (int i = 0; i < DiscoveryAdapterCount; i++) {
|
||||
PDISCOVERY_ADAPTER discoveryInterface = DISCOVERY_ADAPTER_MANIFEST[i];
|
||||
JSON_Object* deviceParams = NULL;
|
||||
// Get the match filters and post a device change message
|
||||
JSON_Object* matchParams = Configuration_GetMatchParametersForDevice(device);
|
||||
const char* interfaceId = json_object_dotget_string(device, PNP_CONFIG_NAME_INTERFACE_ID);
|
||||
if (NULL != interfaceId && NULL != matchParams) {
|
||||
char msg[512] = { 0 };
|
||||
sprintf_s(msg, 512, PnpBridge_DeviceChangeMessageformat, interfaceId, json_serialize_to_string(json_object_get_wrapping_value(matchParams)));
|
||||
|
||||
payload.Message = msg;
|
||||
payload.MessageLength = (int)strlen(msg);
|
||||
|
||||
for (int j = 0; j < (int)json_array_get_count(devices); j++) {
|
||||
JSON_Object *device = json_array_get_object(devices, j);
|
||||
|
||||
// For this Identity check if there is any device
|
||||
// TODO: Create an array of device
|
||||
JSON_Object* params = Configuration_GetDiscoveryParametersForDevice(device);
|
||||
if (NULL != params) {
|
||||
const char* deviceFormatId = json_object_get_string(params, "Identity");
|
||||
if (strcmp(deviceFormatId, discoveryInterface->Identity) == 0) {
|
||||
deviceParams = params;
|
||||
break;
|
||||
}
|
||||
DiscoveryAdapterChangeHandler(&payload);
|
||||
}
|
||||
}
|
||||
|
||||
JSON_Object* adapterParams = NULL;
|
||||
adapterParams = Configuration_GetDiscoveryParameters(config, discoveryInterface->Identity);
|
||||
|
||||
//PSTART_DISCOVERY_PARAMS threadContext;
|
||||
|
||||
//// threadContext memory will be freed during cleanup.
|
||||
//threadContext = malloc(sizeof(START_DISCOVERY_PARAMS));
|
||||
//if (NULL == threadContext) {
|
||||
// return PNPBRIDGE_INSUFFICIENT_MEMORY;
|
||||
//}
|
||||
|
||||
//threadContext->adapterParams = adapterParams;
|
||||
//threadContext->deviceParams = deviceParams;
|
||||
//threadContext->discoveryInterface = discoveryInterface;
|
||||
//threadContext->key = i;
|
||||
//threadContext->discoveryManager = discoveryManager;
|
||||
|
||||
//if (THREADAPI_OK != ThreadAPI_Create(&threadContext->workerThreadHandle, DiscoveryManager_StarDiscovery_Worker_Thread, threadContext)) {
|
||||
// LogError("Failed to create PnpBridge_Worker_Thread \n");
|
||||
// threadContext->workerThreadHandle = NULL;
|
||||
// return PNPBRIDGE_FAILED;
|
||||
//}
|
||||
int result = DiscoveryManager_StarDiscoveryAdapter(discoveryManager, discoveryInterface, deviceParams, adapterParams, i);
|
||||
if (PNPBRIDGE_OK != result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//singlylinkedlist_add(discoveryManager->startDiscoveryThreadHandles, threadContext);
|
||||
}
|
||||
|
||||
return PNPBRIDGE_OK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
PNPBRIDGE_RESULT DiscoveryAdapterManager_Start(PDISCOVERY_MANAGER discoveryManager, JSON_Value* config) {
|
||||
JSON_Array *devices = Configuration_GetConfiguredDevices(config);
|
||||
PNPBRIDGE_RESULT result = PNPBRIDGE_OK;
|
||||
|
||||
TRY
|
||||
{
|
||||
if (NULL == devices) {
|
||||
result = PNPBRIDGE_INVALID_ARGS;
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
for (int i = 0; i < DiscoveryAdapterCount; i++) {
|
||||
PDISCOVERY_ADAPTER discoveryInterface = DISCOVERY_ADAPTER_MANIFEST[i];
|
||||
JSON_Object* deviceParams = NULL;
|
||||
|
||||
for (int j = 0; j < (int)json_array_get_count(devices); j++) {
|
||||
JSON_Object *device = json_array_get_object(devices, j);
|
||||
|
||||
// For this Identity check if there is any device
|
||||
// TODO: Create an array of device
|
||||
JSON_Object* params = Configuration_GetDiscoveryParametersForDevice(device);
|
||||
if (NULL != params) {
|
||||
const char* discoveryIdentity = json_object_get_string(params, PNP_CONFIG_IDENTITY_NAME);
|
||||
if (NULL != discoveryIdentity) {
|
||||
if (stricmp(discoveryIdentity, discoveryInterface->Identity) == 0) {
|
||||
deviceParams = params;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JSON_Object* adapterParams = NULL;
|
||||
adapterParams = Configuration_GetDiscoveryParameters(config, discoveryInterface->Identity);
|
||||
|
||||
result = DiscoveryManager_StarDiscoveryAdapter(discoveryManager, discoveryInterface, deviceParams, adapterParams, i);
|
||||
if (PNPBRIDGE_OK != result) {
|
||||
LEAVE;
|
||||
}
|
||||
}
|
||||
}
|
||||
FINALLY
|
||||
{
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void DiscoveryAdapterManager_Stop(PDISCOVERY_MANAGER discoveryManager) {
|
||||
|
|
|
@ -27,6 +27,8 @@ PNPBRIDGE_RESULT DiscoveryAdapterManager_Create(PDISCOVERY_MANAGER* discoveryMan
|
|||
*/
|
||||
PNPBRIDGE_RESULT DiscoveryAdapterManager_Start(PDISCOVERY_MANAGER discoveryManager, JSON_Value* config);
|
||||
|
||||
PNPBRIDGE_RESULT DiscoveryAdapterManager_PublishAlwaysInterfaces(PDISCOVERY_MANAGER discoveryManager, JSON_Value* config);
|
||||
|
||||
void DiscoveryAdapterManager_Stop(PDISCOVERY_MANAGER discoveryManager);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
// DeviceAggregator.cpp : Defines the entry point for the console application.
|
||||
|
||||
#include "PnpBridgeCommon.h"
|
||||
#include "ConfigurationParser.h"
|
||||
#include "DiscoveryManager.h"
|
||||
#include "PnpAdapterInterface.h"
|
||||
#include "PnpAdapterManager.h"
|
||||
|
||||
#include "PnpBridgeh.h"
|
||||
|
||||
// State of PnP registration process. We cannot proceed with PnP until we get into the state APP_PNP_REGISTRATION_SUCCEEDED.
|
||||
typedef enum APP_PNP_REGISTRATION_STATUS_TAG
|
||||
{
|
||||
APP_PNP_REGISTRATION_PENDING,
|
||||
APP_PNP_REGISTRATION_SUCCEEDED,
|
||||
APP_PNP_REGISTRATION_FAILED
|
||||
} APP_PNP_REGISTRATION_STATUS;
|
||||
|
||||
// appPnpInterfacesRegistered is invoked when the interfaces have been registered or failed.
|
||||
void appPnpInterfacesRegistered(PNP_REPORTED_INTERFACES_STATUS pnpInterfaceStatus, void *userContextCallback)
|
||||
{
|
||||
APP_PNP_REGISTRATION_STATUS* appPnpRegistrationStatus = (APP_PNP_REGISTRATION_STATUS*)userContextCallback;
|
||||
*appPnpRegistrationStatus = (pnpInterfaceStatus == PNP_REPORTED_INTERFACES_OK) ? APP_PNP_REGISTRATION_SUCCEEDED : APP_PNP_REGISTRATION_FAILED;
|
||||
}
|
||||
|
||||
// Invokes PnP_DeviceClient_RegisterInterfacesAsync, which indicates to Azure IoT which PnP interfaces this device supports.
|
||||
// The PnP Handle *is not valid* until this operation has completed (as indicated by the callback appPnpInterfacesRegistered being invoked).
|
||||
// In this sample, we block indefinitely but production code should include a timeout.
|
||||
int AppRegisterPnPInterfacesAndWait(PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, PNP_INTERFACE_CLIENT_HANDLE* interfaces, int count)
|
||||
{
|
||||
APP_PNP_REGISTRATION_STATUS appPnpRegistrationStatus = APP_PNP_REGISTRATION_PENDING;
|
||||
PNPBRIDGE_RESULT result;
|
||||
PNP_CLIENT_RESULT pnpResult;
|
||||
|
||||
pnpResult = PnP_DeviceClient_RegisterInterfacesAsync(pnpDeviceClientHandle, interfaces, count, appPnpInterfacesRegistered, &appPnpRegistrationStatus);
|
||||
if (PNP_CLIENT_OK != pnpResult) {
|
||||
result = PNPBRIDGE_FAILED;
|
||||
goto end;
|
||||
}
|
||||
|
||||
while (appPnpRegistrationStatus == APP_PNP_REGISTRATION_PENDING) {
|
||||
ThreadAPI_Sleep(100);
|
||||
}
|
||||
|
||||
if (appPnpRegistrationStatus != APP_PNP_REGISTRATION_SUCCEEDED) {
|
||||
LogError("PnP has failed to register.\n");
|
||||
result = __FAILURE__;
|
||||
}
|
||||
else {
|
||||
result = 0;
|
||||
}
|
||||
|
||||
end:
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// InitializeIotHubDeviceHandle initializes underlying IoTHub client, creates a device handle with the specified connection string,
|
||||
// and sets some options on this handle prior to beginning.
|
||||
IOTHUB_DEVICE_HANDLE InitializeIotHubDeviceHandle(const char* connectionString)
|
||||
{
|
||||
IOTHUB_DEVICE_HANDLE deviceHandle = NULL;
|
||||
IOTHUB_CLIENT_RESULT iothubClientResult;
|
||||
bool traceOn = false;
|
||||
bool urlEncodeOn = true;
|
||||
|
||||
// TODO: PnP SDK should auto-set OPTION_AUTO_URL_ENCODE_DECODE for MQTT as its strictly required. Need way for IoTHub handle to communicate this back.
|
||||
if (IoTHub_Init() != 0)
|
||||
{
|
||||
LogError("IoTHub_Init failed\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get connection string from config
|
||||
if ((deviceHandle = IoTHubDeviceClient_CreateFromConnectionString(connectionString, MQTT_Protocol)) == NULL)
|
||||
{
|
||||
LogError("Failed to create device handle\n");
|
||||
}
|
||||
else if ((iothubClientResult = IoTHubDeviceClient_SetOption(deviceHandle, OPTION_LOG_TRACE, &traceOn)) != IOTHUB_CLIENT_OK)
|
||||
{
|
||||
LogError("Failed to set option %s, error=%d\n", OPTION_LOG_TRACE, iothubClientResult);
|
||||
IoTHubDeviceClient_Destroy(deviceHandle);
|
||||
deviceHandle = NULL;
|
||||
}
|
||||
else if ((iothubClientResult = IoTHubDeviceClient_SetOption(deviceHandle, OPTION_AUTO_URL_ENCODE_DECODE, &urlEncodeOn)) != IOTHUB_CLIENT_OK)
|
||||
{
|
||||
LogError("Failed to set option %s, error=%d\n", OPTION_AUTO_URL_ENCODE_DECODE, iothubClientResult);
|
||||
IoTHubDeviceClient_Destroy(deviceHandle);
|
||||
deviceHandle = NULL;
|
||||
}
|
||||
|
||||
if (deviceHandle == NULL)
|
||||
{
|
||||
IoTHub_Deinit();
|
||||
}
|
||||
}
|
||||
|
||||
return deviceHandle;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
IOTHUB_DEVICE_HANDLE InitializeIotHubDeviceHandle(const char* connectionString);
|
||||
|
||||
int AppRegisterPnPInterfacesAndWait(PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, PNP_INTERFACE_CLIENT_HANDLE* interfaces, int count);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -9,14 +9,10 @@ extern "C"
|
|||
{
|
||||
#endif
|
||||
|
||||
typedef struct _PNPADAPTER_INTERFACE {
|
||||
PNP_INTERFACE_CLIENT_HANDLE Interface;
|
||||
void* Context;
|
||||
int key;
|
||||
} PNPADAPTER_INTERFACE, *PPNPADAPTER_INTERFACE;
|
||||
|
||||
// Pnp adapter interface handle
|
||||
typedef void* PNPADAPTER_INTERFACE_HANDLE;
|
||||
|
||||
typedef PNPADAPTER_INTERFACE_HANDLE* PPNPADAPTER_INTERFACE_HANDLE;
|
||||
typedef void* PNPADAPTER_CONTEXT;
|
||||
|
||||
/**
|
||||
* @brief PNPADAPTER_PNP_INTERFACE_INITIALIZE callback uses to initialize a pnp adapter.
|
||||
|
@ -50,7 +46,11 @@ typedef int(*PNPADAPTER_PNP_INTERFACE_SHUTDOWN)();
|
|||
*
|
||||
* @returns integer greater than zero on success and other values on failure.
|
||||
*/
|
||||
typedef int(*PNPADAPTER_BIND_PNP_INTERFACE)(PNPADAPTER_INTERFACE_HANDLE pnpInterface, PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD payload);
|
||||
//typedef int(*PNPADAPTER_BIND_PNP_INTERFACE)(PNPADAPTER_INTERFACE_HANDLE pnpInterface, PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD payload);
|
||||
|
||||
typedef int(*PNPADAPTER_BIND_PNP_INTERFACE)(PNPADAPTER_CONTEXT adapterHandle,
|
||||
PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle,
|
||||
PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD payload);
|
||||
|
||||
/**
|
||||
* @brief PNPADAPTER_RELEASE_PNP_INTERFACE uninitializes the pnp interface.
|
||||
|
@ -61,9 +61,41 @@ typedef int(*PNPADAPTER_BIND_PNP_INTERFACE)(PNPADAPTER_INTERFACE_HANDLE pnpInter
|
|||
*
|
||||
* @returns integer greater than zero on success and other values on failure.
|
||||
*/
|
||||
typedef int(*PNPADAPTER_RELEASE_PNP_INTERFACE)(PNPADAPTER_INTERFACE_HANDLE pnpInterface);
|
||||
typedef int(*PNPADAPTER_INTERFACE_RELEASE)(PNPADAPTER_INTERFACE_HANDLE pnpInterface);
|
||||
|
||||
|
||||
typedef int(*PNPADAPTER_DEVICE_ARRIVED)(PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD payload);
|
||||
|
||||
/**
|
||||
PnpAdapterInterface Methods
|
||||
**/
|
||||
|
||||
// Pnp adapter interface creation parameters
|
||||
typedef struct _PNPADPATER_INTERFACE_INIT_PARAMS {
|
||||
PNPADAPTER_DEVICE_ARRIVED deviceArrived;
|
||||
PNPADAPTER_INTERFACE_RELEASE releaseInterface;
|
||||
} PNPADPATER_INTERFACE_INIT_PARAMS, *PPNPADPATER_INTERFACE_INIT_PARAMS;
|
||||
|
||||
/**
|
||||
* @brief PnpAdapter_CreatePnpInterface creates a PnP Bridge adapter interface
|
||||
|
||||
* @param pnpAdapterInterface Handle to pnp adapter interface
|
||||
*
|
||||
* @returns Result indicating status of pnp adapter interface creation
|
||||
*/
|
||||
int PnpAdapterInterface_Create(PNPADAPTER_CONTEXT adapterHandle, const char* interfaceName,
|
||||
PNP_INTERFACE_CLIENT_HANDLE Interface,
|
||||
PPNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface,
|
||||
PPNPADPATER_INTERFACE_INIT_PARAMS params);
|
||||
|
||||
/**
|
||||
* @brief PnpAdapter_DestroyPnpInterface destroys a PnP Bridge adapter interface
|
||||
|
||||
* @param pnpAdapterInterface Handle to pnp adapter interface
|
||||
*
|
||||
*/
|
||||
void PnpAdapterInterface_Destroy(PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface);
|
||||
|
||||
/**
|
||||
* @brief PnpAdapter_GetPnpInterfaceClient gets the Azure iot pnp interface client handle
|
||||
|
||||
|
@ -71,23 +103,7 @@ typedef int(*PNPADAPTER_RELEASE_PNP_INTERFACE)(PNPADAPTER_INTERFACE_HANDLE pnpIn
|
|||
*
|
||||
* @returns Handle to Azure Pnp Interface client
|
||||
*/
|
||||
PNP_INTERFACE_CLIENT_HANDLE PnpAdapter_GetPnpInterfaceClient(PNPADAPTER_INTERFACE_HANDLE pnpInterface);
|
||||
|
||||
/**
|
||||
* @brief PnpAdapter_SetPnpInterfaceClient seta the Azure iot pnp interface client handle
|
||||
*
|
||||
* @remarks This API is for private preview only. When PnpBridge calls CreatePnpInterface
|
||||
callback on a pnp adapter, the adapter should create the Azure PnpInterfaceClient
|
||||
using PnP_InterfaceClient_Create and then call PnpAdapter_SetPnpInterfaceClient with
|
||||
the PnpInterfaceClient
|
||||
|
||||
* @param pnpInterface Handle to pnp adapter interface
|
||||
*
|
||||
** @param pnpInterfaceClient Handle to Azure pnp interface client
|
||||
*
|
||||
* @returns VOID
|
||||
*/
|
||||
void PnpAdapter_SetPnpInterfaceClient(PNPADAPTER_INTERFACE_HANDLE pnpInterface, PNP_INTERFACE_CLIENT_HANDLE pnpInterfaceClient);
|
||||
PNP_INTERFACE_CLIENT_HANDLE PnpAdapterInterface_GetPnpInterfaceClient(PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface);
|
||||
|
||||
/**
|
||||
* @brief PnpAdapter_SetContext sets a context for pnp adapter interface handle
|
||||
|
@ -98,7 +114,7 @@ void PnpAdapter_SetPnpInterfaceClient(PNPADAPTER_INTERFACE_HANDLE pnpInterface,
|
|||
*
|
||||
* @returns integer greater than zero on success and other values on failure.
|
||||
*/
|
||||
int PnpAdapter_SetContext(PNPADAPTER_INTERFACE_HANDLE pnpInterface, void* context);
|
||||
int PnpAdapterInterface_SetContext(PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface, void* context);
|
||||
|
||||
/**
|
||||
* @brief PnpAdapter_GetContext gets context set by pnp adapter.
|
||||
|
@ -109,16 +125,23 @@ int PnpAdapter_SetContext(PNPADAPTER_INTERFACE_HANDLE pnpInterface, void* contex
|
|||
*
|
||||
* @returns void* context
|
||||
*/
|
||||
void* PnpAdapter_GetContext(PNPADAPTER_INTERFACE_HANDLE pnpInterface);
|
||||
void* PnpAdapterInterface_GetContext(PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface);
|
||||
|
||||
/*
|
||||
PnpAdapter Binding info
|
||||
*/
|
||||
typedef struct _PNP_ADAPTER {
|
||||
// Identity of the Pnp Adapter that will be used in the config
|
||||
// of a device under PnpParameters
|
||||
const char* Identity;
|
||||
PNPADAPTER_PNP_INTERFACE_INITIALIZE Initialize;
|
||||
PNPADAPTER_BIND_PNP_INTERFACE CreatePnpInterface;
|
||||
PNPADAPTER_RELEASE_PNP_INTERFACE ReleaseInterface;
|
||||
PNPADAPTER_PNP_INTERFACE_SHUTDOWN Shutdown;
|
||||
const char* identity;
|
||||
|
||||
PNPADAPTER_PNP_INTERFACE_INITIALIZE initialize;
|
||||
|
||||
PNPADAPTER_BIND_PNP_INTERFACE createPnpInterface;
|
||||
|
||||
//PNPADAPTER_RELEASE_PNP_INTERFACE releaseInterface;
|
||||
|
||||
PNPADAPTER_PNP_INTERFACE_SHUTDOWN shutdown;
|
||||
} PNP_ADAPTER, *PPNP_ADAPTER;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -8,11 +8,46 @@ extern "C"
|
|||
{
|
||||
#endif
|
||||
|
||||
// Represents a PNPADPTER and its configuration in PnpAdapterManger
|
||||
typedef struct _PNP_ADAPTER_TAG {
|
||||
PPNP_ADAPTER adapter;
|
||||
|
||||
// List of pnp interfaces created under this adapter
|
||||
SINGLYLINKEDLIST_HANDLE pnpInterfaceList;
|
||||
|
||||
// Lock to protect pnpInterfaceList modification
|
||||
LOCK_HANDLE pnpInterfaceListLock;
|
||||
} PNP_ADAPTER_TAG, *PPNP_ADAPTER_TAG;
|
||||
|
||||
// Structure uses to share context between adapter manager and adapter interface
|
||||
typedef struct _PNP_ADAPTER_CONTEXT_TAG {
|
||||
PPNP_ADAPTER_TAG adapter;
|
||||
JSON_Object* deviceConfig;
|
||||
} PNP_ADAPTER_CONTEXT_TAG, *PPNP_ADAPTER_CONTEXT_TAG;
|
||||
|
||||
// Structure used for an instance of Pnp Adapter Manager
|
||||
typedef struct _PNP_ADAPTER_MANAGER {
|
||||
SINGLYLINKEDLIST_HANDLE AdapterList;
|
||||
MAP_HANDLE PnpAdapterMap;
|
||||
MAP_HANDLE pnpAdapterMap;
|
||||
PPNP_ADAPTER_TAG* pnpAdapters;
|
||||
} PNP_ADAPTER_MANAGER, *PPNP_ADAPTER_MANAGER;
|
||||
|
||||
typedef enum {
|
||||
PublishInvalid,
|
||||
PublishAlways,
|
||||
PublishOnDeviceFound
|
||||
} PublishMode;
|
||||
|
||||
// Pnp adapter interface structure
|
||||
typedef struct _PNPADAPTER_INTERFACE_TAG {
|
||||
void* context;
|
||||
int key;
|
||||
PublishMode publishMode;
|
||||
char* interfaceId;
|
||||
PNP_INTERFACE_CLIENT_HANDLE pnpInterfaceClient;
|
||||
PNPADPATER_INTERFACE_INIT_PARAMS params;
|
||||
PNPADAPTER_CONTEXT adapterContext;
|
||||
LIST_ITEM_HANDLE adapterEntry;
|
||||
} PNPADAPTER_INTERFACE_TAG, *PPNPADAPTER_INTERFACE_TAG;
|
||||
|
||||
/**
|
||||
* @brief PnpAdapterManager_Create creates the Azure Pnp Interface adapter manager.
|
||||
|
@ -39,10 +74,15 @@ PNPBRIDGE_RESULT PnpAdapterManager_Create(PPNP_ADAPTER_MANAGER* adapter, JSON_Va
|
|||
*/
|
||||
void PnpAdapterManager_Release(PPNP_ADAPTER_MANAGER adapter);
|
||||
|
||||
|
||||
PNPBRIDGE_RESULT PnpAdapterManager_SupportsIdentity(PPNP_ADAPTER_MANAGER adapter, JSON_Object* Message, bool* supported, int* key);
|
||||
PNPBRIDGE_RESULT PnpAdapterManager_CreatePnpInterface(PPNP_ADAPTER_MANAGER adapter, PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, int key, PNP_INTERFACE_CLIENT_HANDLE* InterfaceClient, PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD DeviceChangePayload);
|
||||
PNPBRIDGE_RESULT PnpAdapterManager_ReleasePnpInterface(PPNP_ADAPTER_MANAGER adapter, PNPADAPTER_INTERFACE_HANDLE Interface);
|
||||
PNPBRIDGE_RESULT PnpAdapterManager_CreatePnpInterface(PPNP_ADAPTER_MANAGER adapter, PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, int key, JSON_Object* deviceConfig, PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD DeviceChangePayload);
|
||||
|
||||
PNPBRIDGE_RESULT PnpAdapterManager_GetAllInterfaces(PPNP_ADAPTER_MANAGER adapterMgr, PNP_INTERFACE_CLIENT_HANDLE** interfaces, int* count);
|
||||
bool PnpAdapterManager_IsInterfaceIdPublished(PPNP_ADAPTER_MANAGER adapterMgr, const char* interfaceId);
|
||||
void PnpAdapterManager_ReleaseAdapter(PPNP_ADAPTER_TAG adapterTag);
|
||||
|
||||
void PnpAdapterManager_AddInterface(PPNP_ADAPTER_TAG adapter, PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface);
|
||||
void PnpAdapterManager_RemoveInterface(PPNP_ADAPTER_TAG adapter, PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -10,19 +10,19 @@ extern const int PnpAdapterCount;
|
|||
|
||||
PNPBRIDGE_RESULT PnpAdapterManager_ValidatePnpAdapter(PPNP_ADAPTER pnpAdapter, MAP_HANDLE pnpAdapterMap) {
|
||||
bool containsKey = false;
|
||||
if (NULL == pnpAdapter->Identity) {
|
||||
if (NULL == pnpAdapter->identity) {
|
||||
LogError("PnpAdapter's Identity filed is not initialized");
|
||||
return PNPBRIDGE_INVALID_ARGS;
|
||||
}
|
||||
if (MAP_OK != Map_ContainsKey(pnpAdapterMap, pnpAdapter->Identity, &containsKey)) {
|
||||
if (MAP_OK != Map_ContainsKey(pnpAdapterMap, pnpAdapter->identity, &containsKey)) {
|
||||
LogError("Map_ContainsKey failed");
|
||||
return PNPBRIDGE_FAILED;
|
||||
}
|
||||
if (containsKey) {
|
||||
LogError("Found duplicate pnp adapter identity %s", pnpAdapter->Identity);
|
||||
LogError("Found duplicate pnp adapter identity %s", pnpAdapter->identity);
|
||||
return PNPBRIDGE_DUPLICATE_ENTRY;
|
||||
}
|
||||
if (NULL == pnpAdapter->Initialize || NULL == pnpAdapter->Shutdown || NULL == pnpAdapter->CreatePnpInterface || NULL == pnpAdapter->ReleaseInterface) {
|
||||
if (NULL == pnpAdapter->initialize || NULL == pnpAdapter->shutdown || NULL == pnpAdapter->createPnpInterface) {
|
||||
LogError("PnpAdapter's callbacks are not initialized");
|
||||
return PNPBRIDGE_INVALID_ARGS;
|
||||
}
|
||||
|
@ -30,6 +30,66 @@ PNPBRIDGE_RESULT PnpAdapterManager_ValidatePnpAdapter(PPNP_ADAPTER pnpAdapter,
|
|||
return PNPBRIDGE_OK;
|
||||
}
|
||||
|
||||
PNPBRIDGE_RESULT PnpAdapterManager_InitializeAdapter(PPNP_ADAPTER_TAG* adapterTag, PPNP_ADAPTER adapter) {
|
||||
PNPBRIDGE_RESULT result = PNPBRIDGE_OK;
|
||||
PPNP_ADAPTER_TAG adapterT = NULL;
|
||||
TRY
|
||||
{
|
||||
adapterT = calloc(1, sizeof(PNP_ADAPTER_TAG));
|
||||
if (NULL == adapterT) {
|
||||
result = PNPBRIDGE_INSUFFICIENT_MEMORY;
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
adapterT->adapter = adapter;
|
||||
adapterT->pnpInterfaceListLock = Lock_Init();
|
||||
adapterT->pnpInterfaceList = singlylinkedlist_create();
|
||||
if (NULL == adapterT->pnpInterfaceListLock) {
|
||||
result = PNPBRIDGE_INSUFFICIENT_MEMORY;
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
*adapterTag = adapterT;
|
||||
}
|
||||
FINALLY
|
||||
{
|
||||
if (!PNPBRIDGE_SUCCESS(result)) {
|
||||
PnpAdapterManager_ReleaseAdapter(adapterT);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void PnpAdapterManager_ReleaseAdapter(PPNP_ADAPTER_TAG adapterTag) {
|
||||
if (NULL == adapterTag) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (NULL != adapterTag->pnpInterfaceList) {
|
||||
SINGLYLINKEDLIST_HANDLE pnpInterfaces = adapterTag->pnpInterfaceList;
|
||||
Lock(adapterTag->pnpInterfaceListLock);
|
||||
LIST_ITEM_HANDLE handle = singlylinkedlist_get_head_item(pnpInterfaces);
|
||||
while (NULL != handle) {
|
||||
PPNPADAPTER_INTERFACE_TAG adapterInterface = (PPNPADAPTER_INTERFACE_TAG)singlylinkedlist_item_get_value(handle);
|
||||
// Disconnect the adapter interface from the list. The cleanup of adapte interface
|
||||
// will be done when destroy API is called
|
||||
if (NULL != adapterInterface->adapterEntry) {
|
||||
adapterInterface->adapterEntry = NULL;
|
||||
}
|
||||
adapterInterface->params.releaseInterface(adapterInterface);
|
||||
|
||||
handle = singlylinkedlist_get_next_item(handle);
|
||||
}
|
||||
Unlock(adapterTag->pnpInterfaceListLock);
|
||||
|
||||
singlylinkedlist_destroy(adapterTag->pnpInterfaceList);
|
||||
Lock_Deinit(adapterTag->pnpInterfaceListLock);
|
||||
}
|
||||
|
||||
free(adapterTag);
|
||||
}
|
||||
|
||||
PNPBRIDGE_RESULT PnpAdapterManager_Create(PPNP_ADAPTER_MANAGER* adapterMgr, JSON_Value* config) {
|
||||
PNPBRIDGE_RESULT result = PNPBRIDGE_OK;
|
||||
PPNP_ADAPTER_MANAGER adapter = NULL;
|
||||
|
@ -45,8 +105,15 @@ PNPBRIDGE_RESULT PnpAdapterManager_Create(PPNP_ADAPTER_MANAGER* adapterMgr, JSON
|
|||
goto exit;
|
||||
}
|
||||
|
||||
adapter->PnpAdapterMap = Map_Create(NULL);
|
||||
if (NULL == adapter->PnpAdapterMap) {
|
||||
adapter->pnpAdapterMap = Map_Create(NULL);
|
||||
if (NULL == adapter->pnpAdapterMap) {
|
||||
result = PNPBRIDGE_FAILED;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// Create PNP_ADAPTER_HANDLE's
|
||||
adapter->pnpAdapters = calloc(PnpAdapterCount, sizeof(PPNP_ADAPTER_TAG));
|
||||
if (NULL == adapter->pnpAdapters) {
|
||||
result = PNPBRIDGE_FAILED;
|
||||
goto exit;
|
||||
}
|
||||
|
@ -54,79 +121,102 @@ PNPBRIDGE_RESULT PnpAdapterManager_Create(PPNP_ADAPTER_MANAGER* adapterMgr, JSON
|
|||
// Load a list of static modules and build an interface map
|
||||
for (int i = 0; i < PnpAdapterCount; i++) {
|
||||
PPNP_ADAPTER pnpAdapter = PNP_ADAPTER_MANIFEST[i];
|
||||
|
||||
result = PnpAdapterManager_InitializeAdapter(&adapter->pnpAdapters[i], pnpAdapter);
|
||||
if (!PNPBRIDGE_SUCCESS(result)) {
|
||||
LogError("Failed to initialize PnpAdapter %s", pnpAdapter->identity);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NULL == pnpAdapter->Identity) {
|
||||
if (NULL == pnpAdapter->identity) {
|
||||
LogError("Invalid Identity specified for a PnpAdapter");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Validate Pnp Adapter Methods
|
||||
result = PnpAdapterManager_ValidatePnpAdapter(pnpAdapter, adapter->PnpAdapterMap);
|
||||
result = PnpAdapterManager_ValidatePnpAdapter(pnpAdapter, adapter->pnpAdapterMap);
|
||||
if (PNPBRIDGE_OK != result) {
|
||||
LogError("PnpAdapter structure is not initialized properly");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
JSON_Object* initParams = Configuration_GetPnpParameters(config, pnpAdapter->Identity);
|
||||
JSON_Object* initParams = Configuration_GetPnpParameters(config, pnpAdapter->identity);
|
||||
const char* initParamstring = NULL;
|
||||
if (initParams != NULL) {
|
||||
initParamstring = json_serialize_to_string(json_object_get_wrapping_value(initParams));
|
||||
}
|
||||
result = pnpAdapter->Initialize(initParamstring);
|
||||
result = pnpAdapter->initialize(initParamstring);
|
||||
if (PNPBRIDGE_OK != result) {
|
||||
LogError("Failed to initialze a PnpAdapter");
|
||||
continue;
|
||||
}
|
||||
|
||||
Map_Add_Index(adapter->PnpAdapterMap, pnpAdapter->Identity, i);
|
||||
Map_Add_Index(adapter->pnpAdapterMap, pnpAdapter->identity, i);
|
||||
}
|
||||
|
||||
*adapterMgr = adapter;
|
||||
|
||||
exit:
|
||||
if (!PNPBRIDGE_SUCCESS(result)) {
|
||||
if (NULL != adapter) {
|
||||
PnpAdapterManager_Release(adapter);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void PnpAdapterManager_Release(PPNP_ADAPTER_MANAGER adapter) {
|
||||
void PnpAdapterManager_Release(PPNP_ADAPTER_MANAGER adapterMgr) {
|
||||
const char* const* keys;
|
||||
const char* const* values;
|
||||
size_t count;
|
||||
|
||||
// Call shutdown on all interfaces
|
||||
if (Map_GetInternals(adapter->PnpAdapterMap, &keys, &values, &count) != MAP_OK) {
|
||||
LogError("Map_GetInternals failed to get all pnp adapters");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < (int)count; i++) {
|
||||
int index = values[i][0];
|
||||
PPNP_ADAPTER pnpAdapter = PNP_ADAPTER_MANIFEST[index];
|
||||
if (NULL != pnpAdapter->Shutdown) {
|
||||
pnpAdapter->Shutdown();
|
||||
if (NULL != adapterMgr->pnpAdapterMap) {
|
||||
// Call shutdown on all interfaces
|
||||
if (Map_GetInternals(adapterMgr->pnpAdapterMap, &keys, &values, &count) != MAP_OK) {
|
||||
LogError("Map_GetInternals failed to get all pnp adapters");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < (int)count; i++) {
|
||||
int index = values[i][0];
|
||||
PPNP_ADAPTER_TAG adapterT = adapterMgr->pnpAdapters[index];
|
||||
if (NULL != adapterT) {
|
||||
// Release all interfaces
|
||||
PnpAdapterManager_ReleaseAdapter(adapterT);
|
||||
|
||||
PPNP_ADAPTER adapter = PNP_ADAPTER_MANIFEST[index];
|
||||
if (NULL != adapter->shutdown) {
|
||||
adapter->shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Map_Destroy(adapter->PnpAdapterMap);
|
||||
free(adapter);
|
||||
if (NULL != adapterMgr->pnpAdapters) {
|
||||
free(adapterMgr->pnpAdapters);
|
||||
}
|
||||
|
||||
Map_Destroy(adapterMgr->pnpAdapterMap);
|
||||
free(adapterMgr);
|
||||
}
|
||||
|
||||
PNPBRIDGE_RESULT PnpAdapterManager_SupportsIdentity(PPNP_ADAPTER_MANAGER adapter, JSON_Object* Message, bool* supported, int* key) {
|
||||
bool containsMessageKey = false;
|
||||
char* interfaceId = NULL;
|
||||
JSON_Object* pnpParams = json_object_get_object(Message, "PnpParameters");
|
||||
char* getIdentity = (char*) json_object_get_string(pnpParams, "Identity");
|
||||
JSON_Object* pnpParams = json_object_get_object(Message, PNP_CONFIG_NAME_PNP_PARAMETERS);
|
||||
char* getIdentity = (char*) json_object_get_string(pnpParams, PNP_CONFIG_IDENTITY_NAME);
|
||||
MAP_RESULT mapResult;
|
||||
|
||||
*supported = false;
|
||||
|
||||
mapResult = Map_ContainsKey(adapter->PnpAdapterMap, getIdentity, &containsMessageKey);
|
||||
mapResult = Map_ContainsKey(adapter->pnpAdapterMap, getIdentity, &containsMessageKey);
|
||||
if (MAP_OK != mapResult || !containsMessageKey) {
|
||||
LogError("PnpAdapter %s is not present in AdapterManifest", getIdentity);
|
||||
return PNPBRIDGE_FAILED;
|
||||
}
|
||||
|
||||
// Get the interface ID
|
||||
int index = Map_GetIndexValueFromKey(adapter->PnpAdapterMap, getIdentity);
|
||||
int index = Map_GetIndexValueFromKey(adapter->pnpAdapterMap, getIdentity);
|
||||
|
||||
*supported = true;
|
||||
*key = index;
|
||||
|
@ -139,75 +229,109 @@ PNPBRIDGE_RESULT PnpAdapterManager_SupportsIdentity(PPNP_ADAPTER_MANAGER adapter
|
|||
method will take care of binding it to a module implementing
|
||||
PnP primitives
|
||||
*/
|
||||
PNPBRIDGE_RESULT PnpAdapterManager_CreatePnpInterface(PPNP_ADAPTER_MANAGER adapter, PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle, int key, PNP_INTERFACE_CLIENT_HANDLE* InterfaceClient, PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD DeviceChangePayload) {
|
||||
PNPBRIDGE_RESULT PnpAdapterManager_CreatePnpInterface(PPNP_ADAPTER_MANAGER adapterMgr, PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle,
|
||||
int key, JSON_Object* deviceConfig,
|
||||
PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD DeviceChangePayload)
|
||||
{
|
||||
// Get the module using the key as index
|
||||
PPNP_ADAPTER pnpAdapter = PNP_ADAPTER_MANIFEST[key];
|
||||
PPNP_ADAPTER_TAG adapterT = adapterMgr->pnpAdapters[key];
|
||||
PNP_ADAPTER_CONTEXT_TAG context = { 0 };
|
||||
|
||||
PPNPADAPTER_INTERFACE pnpInterface = malloc(sizeof(PNPADAPTER_INTERFACE));
|
||||
|
||||
//pnpInterface->Interface = InterfaceClient;
|
||||
pnpInterface->key = key;
|
||||
context.adapter = adapterT;
|
||||
context.deviceConfig = deviceConfig;
|
||||
|
||||
// Invoke interface binding method
|
||||
int ret = pnpAdapter->CreatePnpInterface(pnpInterface, pnpDeviceClientHandle, DeviceChangePayload);
|
||||
int ret = adapterT->adapter->createPnpInterface(&context, pnpDeviceClientHandle, DeviceChangePayload);
|
||||
if (ret < 0) {
|
||||
return PNPBRIDGE_FAILED;
|
||||
}
|
||||
|
||||
*InterfaceClient = pnpInterface->Interface;
|
||||
|
||||
return PNPBRIDGE_OK;
|
||||
}
|
||||
|
||||
PNPBRIDGE_RESULT PnpAdapterManager_ReleasePnpInterface(PPNP_ADAPTER_MANAGER adapter, PNPADAPTER_INTERFACE_HANDLE interfaceClient) {
|
||||
if (NULL == interfaceClient) {
|
||||
return PNPBRIDGE_INVALID_ARGS;
|
||||
PNPBRIDGE_RESULT PnpAdapterManager_GetAllInterfaces(PPNP_ADAPTER_MANAGER adapterMgr, PNP_INTERFACE_CLIENT_HANDLE** interfaces , int* count) {
|
||||
int n = 0;
|
||||
|
||||
// Get the number of created interfaces
|
||||
for (int i = 0; i < PnpAdapterCount; i++) {
|
||||
PPNP_ADAPTER_TAG pnpAdapter = adapterMgr->pnpAdapters[i];
|
||||
|
||||
SINGLYLINKEDLIST_HANDLE pnpInterfaces = pnpAdapter->pnpInterfaceList;
|
||||
LIST_ITEM_HANDLE handle = singlylinkedlist_get_head_item(pnpInterfaces);
|
||||
while (NULL != handle) {
|
||||
handle = singlylinkedlist_get_next_item(handle);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
PPNPADAPTER_INTERFACE pnpInterface = (PPNPADAPTER_INTERFACE)interfaceClient;
|
||||
// create an array of interface handles
|
||||
PNP_INTERFACE_CLIENT_HANDLE* pnpClientHandles = NULL;
|
||||
{
|
||||
pnpClientHandles = calloc(n, sizeof(PNP_INTERFACE_CLIENT_HANDLE));
|
||||
int x = 0;
|
||||
for (int i = 0; i < PnpAdapterCount; i++) {
|
||||
PPNP_ADAPTER_TAG pnpAdapter = adapterMgr->pnpAdapters[i];
|
||||
|
||||
// Get the module index
|
||||
PPNP_ADAPTER pnpAdapter = PNP_ADAPTER_MANIFEST[pnpInterface->key];
|
||||
pnpAdapter->ReleaseInterface(interfaceClient);
|
||||
|
||||
return PNPBRIDGE_OK;
|
||||
}
|
||||
|
||||
PNP_INTERFACE_CLIENT_HANDLE PnpAdapter_GetPnpInterfaceClient(PNPADAPTER_INTERFACE_HANDLE pnpInterfaceClient) {
|
||||
if (pnpInterfaceClient == NULL) {
|
||||
return NULL;
|
||||
SINGLYLINKEDLIST_HANDLE pnpInterfaces = pnpAdapter->pnpInterfaceList;
|
||||
Lock(pnpAdapter->pnpInterfaceListLock);
|
||||
LIST_ITEM_HANDLE handle = singlylinkedlist_get_head_item(pnpInterfaces);
|
||||
while (NULL != handle) {
|
||||
PPNPADAPTER_INTERFACE_TAG adapterInterface = (PNP_INTERFACE_CLIENT_HANDLE) singlylinkedlist_item_get_value(handle);
|
||||
pnpClientHandles[x] = PnpAdapterInterface_GetPnpInterfaceClient(adapterInterface);
|
||||
handle = singlylinkedlist_get_next_item(handle);
|
||||
x++;
|
||||
}
|
||||
Unlock(pnpAdapter->pnpInterfaceListLock);
|
||||
}
|
||||
}
|
||||
|
||||
PPNPADAPTER_INTERFACE interfaceClient = (PPNPADAPTER_INTERFACE)pnpInterfaceClient;
|
||||
return interfaceClient->Interface;
|
||||
*count = n;
|
||||
*interfaces = pnpClientHandles;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PnpAdapter_SetPnpInterfaceClient(PNPADAPTER_INTERFACE_HANDLE pnpInterface, PNP_INTERFACE_CLIENT_HANDLE pnpInterfaceClient) {
|
||||
if (pnpInterfaceClient == NULL) {
|
||||
LogError("pnpInterface argument is NULL");
|
||||
bool PnpAdapterManager_IsInterfaceIdPublished(PPNP_ADAPTER_MANAGER adapterMgr, const char* interfaceId) {
|
||||
for (int i = 0; i < PnpAdapterCount; i++) {
|
||||
PPNP_ADAPTER_TAG pnpAdapter = adapterMgr->pnpAdapters[i];
|
||||
|
||||
SINGLYLINKEDLIST_HANDLE pnpInterfaces = pnpAdapter->pnpInterfaceList;
|
||||
Lock(pnpAdapter->pnpInterfaceListLock);
|
||||
LIST_ITEM_HANDLE handle = singlylinkedlist_get_head_item(pnpInterfaces);
|
||||
while (NULL != handle) {
|
||||
PPNPADAPTER_INTERFACE_TAG adapterInterface = (PNP_INTERFACE_CLIENT_HANDLE)singlylinkedlist_item_get_value(handle);
|
||||
if (stricmp(adapterInterface->interfaceId, interfaceId)) {
|
||||
return true;
|
||||
}
|
||||
handle = singlylinkedlist_get_next_item(handle);
|
||||
}
|
||||
Unlock(pnpAdapter->pnpInterfaceListLock);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void PnpAdapterManager_AddInterface(PPNP_ADAPTER_TAG adapter, PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface) {
|
||||
LIST_ITEM_HANDLE handle = NULL;
|
||||
Lock(adapter->pnpInterfaceListLock);
|
||||
|
||||
handle = singlylinkedlist_add(adapter->pnpInterfaceList, pnpAdapterInterface);
|
||||
Unlock(adapter->pnpInterfaceListLock);
|
||||
|
||||
if (NULL != handle) {
|
||||
PPNPADAPTER_INTERFACE_TAG interface = (PPNPADAPTER_INTERFACE_TAG)pnpAdapterInterface;
|
||||
interface->adapterEntry = handle;
|
||||
}
|
||||
// Handle failure case when singlylinkedlist_add returns NULL
|
||||
}
|
||||
|
||||
void PnpAdapterManager_RemoveInterface(PPNP_ADAPTER_TAG adapter, PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface) {
|
||||
PPNPADAPTER_INTERFACE_TAG interface = (PPNPADAPTER_INTERFACE_TAG)pnpAdapterInterface;
|
||||
if (NULL == interface->adapterEntry) {
|
||||
return;
|
||||
}
|
||||
|
||||
PPNPADAPTER_INTERFACE interfaceClient = (PPNPADAPTER_INTERFACE)pnpInterface;
|
||||
interfaceClient->Interface = pnpInterfaceClient;
|
||||
}
|
||||
|
||||
PNPBRIDGE_RESULT PnpAdapter_SetContext(PNPADAPTER_INTERFACE_HANDLE pnpInterfaceClient, void* Context) {
|
||||
if (NULL == pnpInterfaceClient) {
|
||||
return PNPBRIDGE_INVALID_ARGS;
|
||||
}
|
||||
|
||||
PPNPADAPTER_INTERFACE interfaceClient = (PPNPADAPTER_INTERFACE)pnpInterfaceClient;
|
||||
interfaceClient->Context = Context;
|
||||
|
||||
return PNPBRIDGE_OK;
|
||||
}
|
||||
|
||||
void* PnpAdapter_GetContext(PNPADAPTER_INTERFACE_HANDLE PnpInterfaceClient) {
|
||||
if (NULL == PnpInterfaceClient) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PPNPADAPTER_INTERFACE pnpInterfaceClient = (PPNPADAPTER_INTERFACE)PnpInterfaceClient;
|
||||
return pnpInterfaceClient->Context;
|
||||
Lock(adapter->pnpInterfaceListLock);
|
||||
singlylinkedlist_remove(adapter->pnpInterfaceList, interface->adapterEntry);
|
||||
Unlock(adapter->pnpInterfaceListLock);
|
||||
}
|
|
@ -1,484 +1,365 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
// DeviceAggregator.cpp : Defines the entry point for the console application.
|
||||
|
||||
#include "PnpBridgeCommon.h"
|
||||
#include "ConfigurationParser.h"
|
||||
#include "DiscoveryManager.h"
|
||||
#include "PnpAdapterInterface.h"
|
||||
#include "PnpAdapterManager.h"
|
||||
|
||||
#include "PnpBridgeh.h"
|
||||
#include <iothub_client.h>
|
||||
|
||||
//////////////////////////// GLOBALS ///////////////////////////////////
|
||||
PPNP_BRIDGE g_PnpBridge = NULL;
|
||||
bool g_Shutdown = false;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//const char* connectionString = "HostName=iot-pnp-hub1.azure-devices.net;DeviceId=win-gateway;SharedAccessKey=GfbYy7e2PikTf2qHyabvEDBaJB5S4T+H+b9TbLsXfns=";
|
||||
//const char* connectionString = "HostName=saas-iothub-1529564b-8f58-4871-b721-fe9459308cb1.azure-devices.net;DeviceId=956da476-8b3c-41ce-b405-d2d32bcf5e79;SharedAccessKey=sQcfPeDCZGEJWPI3M3SyB8pD60TNdOw10oFKuv5FBio=";
|
||||
|
||||
typedef struct _PNPBRIDGE_INTERFACE_TAG {
|
||||
PNP_INTERFACE_CLIENT_HANDLE Interface;
|
||||
char* InterfaceName;
|
||||
} PNPBRIDGE_INTERFACE_TAG, *PPNPBRIDGE_INTERFACE_TAG;
|
||||
|
||||
// InitializeIotHubDeviceHandle initializes underlying IoTHub client, creates a device handle with the specified connection string,
|
||||
// and sets some options on this handle prior to beginning.
|
||||
IOTHUB_DEVICE_HANDLE InitializeIotHubDeviceHandle(const char* connectionString)
|
||||
{
|
||||
IOTHUB_DEVICE_HANDLE deviceHandle = NULL;
|
||||
IOTHUB_CLIENT_RESULT iothubClientResult;
|
||||
bool traceOn = true;
|
||||
bool urlEncodeOn = true;
|
||||
|
||||
// TODO: PnP SDK should auto-set OPTION_AUTO_URL_ENCODE_DECODE for MQTT as its strictly required. Need way for IoTHub handle to communicate this back.
|
||||
if (IoTHub_Init() != 0)
|
||||
{
|
||||
LogError("IoTHub_Init failed\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get connection string from config
|
||||
if ((deviceHandle = IoTHubDeviceClient_CreateFromConnectionString(connectionString, MQTT_Protocol)) == NULL)
|
||||
{
|
||||
LogError("Failed to create device handle\n");
|
||||
}
|
||||
else if ((iothubClientResult = IoTHubDeviceClient_SetOption(deviceHandle, OPTION_LOG_TRACE, &traceOn)) != IOTHUB_CLIENT_OK)
|
||||
{
|
||||
LogError("Failed to set option %s, error=%d\n", OPTION_LOG_TRACE, iothubClientResult);
|
||||
IoTHubDeviceClient_Destroy(deviceHandle);
|
||||
deviceHandle = NULL;
|
||||
}
|
||||
else if ((iothubClientResult = IoTHubDeviceClient_SetOption(deviceHandle, OPTION_AUTO_URL_ENCODE_DECODE, &urlEncodeOn)) != IOTHUB_CLIENT_OK)
|
||||
{
|
||||
LogError("Failed to set option %s, error=%d\n", OPTION_AUTO_URL_ENCODE_DECODE, iothubClientResult);
|
||||
IoTHubDeviceClient_Destroy(deviceHandle);
|
||||
deviceHandle = NULL;
|
||||
}
|
||||
|
||||
if (deviceHandle == NULL)
|
||||
{
|
||||
IoTHub_Deinit();
|
||||
}
|
||||
}
|
||||
|
||||
return deviceHandle;
|
||||
}
|
||||
|
||||
void PnpBridge_CoreCleanup() {
|
||||
if (g_PnpBridge->publishedInterfaces) {
|
||||
LIST_ITEM_HANDLE interfaceItem = singlylinkedlist_get_head_item(g_PnpBridge->publishedInterfaces);
|
||||
while (interfaceItem != NULL) {
|
||||
PPNPBRIDGE_INTERFACE_TAG interface = (PPNPBRIDGE_INTERFACE_TAG)singlylinkedlist_item_get_value(interfaceItem);
|
||||
free(interface->Interface);
|
||||
interfaceItem = singlylinkedlist_get_next_item(interfaceItem);
|
||||
}
|
||||
singlylinkedlist_destroy(g_PnpBridge->publishedInterfaces);
|
||||
}
|
||||
if (g_PnpBridge->dispatchLock) {
|
||||
Lock_Deinit(g_PnpBridge->dispatchLock);
|
||||
}
|
||||
}
|
||||
|
||||
PNPBRIDGE_RESULT PnpBridge_Initialize(JSON_Value* config) {
|
||||
const char* connectionString;
|
||||
|
||||
connectionString = Configuration_GetConnectionString(config);
|
||||
|
||||
if (NULL == connectionString) {
|
||||
LogError("Connection string not specified in the config\n");
|
||||
return PNPBRIDGE_FAILED;
|
||||
}
|
||||
|
||||
g_PnpBridge = (PPNP_BRIDGE) calloc(1, sizeof(PNP_BRIDGE));
|
||||
|
||||
if (!g_PnpBridge) {
|
||||
LogError("Failed to allocate memory for PnpBridge global");
|
||||
PnpBridge_CoreCleanup();
|
||||
return PNPBRIDGE_INSUFFICIENT_MEMORY;
|
||||
}
|
||||
|
||||
g_PnpBridge->configuration = config;
|
||||
|
||||
g_PnpBridge->publishedInterfaces = singlylinkedlist_create();
|
||||
if (NULL == g_PnpBridge->publishedInterfaces) {
|
||||
LogError("Failed to allocate memory publish interface list");
|
||||
PnpBridge_CoreCleanup();
|
||||
return PNPBRIDGE_INSUFFICIENT_MEMORY;
|
||||
}
|
||||
|
||||
g_PnpBridge->publishedInterfaceCount = 0;
|
||||
|
||||
g_PnpBridge->dispatchLock = Lock_Init();
|
||||
if (NULL == g_PnpBridge->dispatchLock) {
|
||||
LogError("Failed to init PnpBridge lock");
|
||||
PnpBridge_CoreCleanup();
|
||||
return PNPBRIDGE_INSUFFICIENT_MEMORY;
|
||||
}
|
||||
|
||||
g_Shutdown = false;
|
||||
|
||||
// Connect to Iot Hub and create a PnP device client handle
|
||||
if ((g_PnpBridge->deviceHandle = InitializeIotHubDeviceHandle(connectionString)) == NULL)
|
||||
{
|
||||
LogError("Could not allocate IoTHub Device handle\n");
|
||||
PnpBridge_CoreCleanup();
|
||||
return PNPBRIDGE_FAILED;
|
||||
}
|
||||
else if ((g_PnpBridge->pnpDeviceClientHandle = PnP_DeviceClient_CreateFromDeviceHandle(g_PnpBridge->deviceHandle)) == NULL)
|
||||
{
|
||||
LogError("PnP_DeviceClient_CreateFromDeviceHandle failed\n");
|
||||
PnpBridge_CoreCleanup();
|
||||
return PNPBRIDGE_FAILED;
|
||||
}
|
||||
|
||||
return PNPBRIDGE_OK;
|
||||
}
|
||||
|
||||
void PnpBridge_Release() {
|
||||
|
||||
LogInfo("Cleaning DeviceAggregator resources");
|
||||
|
||||
Lock(g_PnpBridge->dispatchLock);
|
||||
|
||||
// Stop Disovery Modules
|
||||
if (g_PnpBridge->discoveryMgr) {
|
||||
DiscoveryAdapterManager_Stop(g_PnpBridge->discoveryMgr);
|
||||
g_PnpBridge->discoveryMgr = NULL;
|
||||
}
|
||||
|
||||
// Stop Pnp Modules
|
||||
if (g_PnpBridge->interfaceMgr) {
|
||||
PnpAdapterManager_Release(g_PnpBridge->interfaceMgr);
|
||||
g_PnpBridge->interfaceMgr = NULL;
|
||||
}
|
||||
|
||||
Unlock(g_PnpBridge->dispatchLock);
|
||||
|
||||
PnpBridge_CoreCleanup();
|
||||
|
||||
if (g_PnpBridge) {
|
||||
free(g_PnpBridge);
|
||||
}
|
||||
}
|
||||
|
||||
int PnpBridge_Worker_Thread(void* threadArgument)
|
||||
{
|
||||
PNPBRIDGE_RESULT result = PNPBRIDGE_OK;
|
||||
|
||||
// Start Device Discovery
|
||||
result = DiscoveryAdapterManager_Start(g_PnpBridge->discoveryMgr, g_PnpBridge->configuration);
|
||||
if (PNPBRIDGE_OK != result) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// TODO: Change this to an event
|
||||
while (true)
|
||||
{
|
||||
ThreadAPI_Sleep(1 * 1000);
|
||||
if (g_Shutdown) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return result;
|
||||
}
|
||||
|
||||
// State of PnP registration process. We cannot proceed with PnP until we get into the state APP_PNP_REGISTRATION_SUCCEEDED.
|
||||
typedef enum APP_PNP_REGISTRATION_STATUS_TAG
|
||||
{
|
||||
APP_PNP_REGISTRATION_PENDING,
|
||||
APP_PNP_REGISTRATION_SUCCEEDED,
|
||||
APP_PNP_REGISTRATION_FAILED
|
||||
} APP_PNP_REGISTRATION_STATUS;
|
||||
|
||||
// appPnpInterfacesRegistered is invoked when the interfaces have been registered or failed.
|
||||
void appPnpInterfacesRegistered(PNP_REPORTED_INTERFACES_STATUS pnpInterfaceStatus, void *userContextCallback)
|
||||
{
|
||||
APP_PNP_REGISTRATION_STATUS* appPnpRegistrationStatus = (APP_PNP_REGISTRATION_STATUS*)userContextCallback;
|
||||
*appPnpRegistrationStatus = (pnpInterfaceStatus == PNP_REPORTED_INTERFACES_OK) ? APP_PNP_REGISTRATION_SUCCEEDED : APP_PNP_REGISTRATION_FAILED;
|
||||
}
|
||||
|
||||
// Invokes PnP_DeviceClient_RegisterInterfacesAsync, which indicates to Azure IoT which PnP interfaces this device supports.
|
||||
// The PnP Handle *is not valid* until this operation has completed (as indicated by the callback appPnpInterfacesRegistered being invoked).
|
||||
// In this sample, we block indefinitely but production code should include a timeout.
|
||||
int AppRegisterPnPInterfacesAndWait(PNP_DEVICE_CLIENT_HANDLE pnpDeviceClientHandle)
|
||||
{
|
||||
APP_PNP_REGISTRATION_STATUS appPnpRegistrationStatus = APP_PNP_REGISTRATION_PENDING;
|
||||
PNPBRIDGE_RESULT result;
|
||||
PNP_CLIENT_RESULT pnpResult;
|
||||
PPNPBRIDGE_INTERFACE_TAG* interfaceTags = malloc(sizeof(PPNPBRIDGE_INTERFACE_TAG)*g_PnpBridge->publishedInterfaceCount);
|
||||
PNP_INTERFACE_CLIENT_HANDLE* interfaceClients = malloc(sizeof(PNP_INTERFACE_CLIENT_HANDLE)*g_PnpBridge->publishedInterfaceCount);
|
||||
LIST_ITEM_HANDLE interfaceItem = singlylinkedlist_get_head_item(g_PnpBridge->publishedInterfaces);
|
||||
int i = 0;
|
||||
|
||||
while (interfaceItem != NULL) {
|
||||
PNP_INTERFACE_CLIENT_HANDLE interface = ((PPNPBRIDGE_INTERFACE_TAG) singlylinkedlist_item_get_value(interfaceItem))->Interface;
|
||||
interfaceClients[i++] = interface;
|
||||
interfaceItem = singlylinkedlist_get_next_item(interfaceItem);
|
||||
}
|
||||
|
||||
pnpResult = PnP_DeviceClient_RegisterInterfacesAsync(pnpDeviceClientHandle, interfaceClients, g_PnpBridge->publishedInterfaceCount, appPnpInterfacesRegistered, &appPnpRegistrationStatus);
|
||||
if (PNP_CLIENT_OK != pnpResult) {
|
||||
result = PNPBRIDGE_FAILED;
|
||||
goto end;
|
||||
}
|
||||
|
||||
while (appPnpRegistrationStatus == APP_PNP_REGISTRATION_PENDING) {
|
||||
ThreadAPI_Sleep(100);
|
||||
}
|
||||
|
||||
if (appPnpRegistrationStatus != APP_PNP_REGISTRATION_SUCCEEDED) {
|
||||
LogError("PnP has failed to register.\n");
|
||||
result = __FAILURE__;
|
||||
}
|
||||
else {
|
||||
result = 0;
|
||||
}
|
||||
|
||||
end:
|
||||
free(interfaceClients);
|
||||
free(interfaceTags);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PNPBRIDGE_RESULT PnpBridge_ValidateDeviceChangePayload(PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD DeviceChangePayload) {
|
||||
if (NULL == DeviceChangePayload) {
|
||||
return PNPBRIDGE_INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (NULL == DeviceChangePayload->Message) {
|
||||
return PNPBRIDGE_INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (0 == DeviceChangePayload->MessageLength) {
|
||||
return PNPBRIDGE_INVALID_ARGS;
|
||||
}
|
||||
|
||||
//if (PNPBRIDGE_INTERFACE_CHANGE_INVALID == DeviceChangePayload->ChangeType) {
|
||||
// return PNPBRIDGE_INVALID_ARGS;
|
||||
//}
|
||||
|
||||
return PNPBRIDGE_OK;
|
||||
}
|
||||
|
||||
PNPBRIDGE_RESULT PnpBridge_DeviceChangeCallback(PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD DeviceChangePayload) {
|
||||
PNPBRIDGE_RESULT result;
|
||||
bool containsFilter = false;
|
||||
int key = 0;
|
||||
|
||||
Lock(g_PnpBridge->dispatchLock);
|
||||
|
||||
if (g_Shutdown) {
|
||||
LogInfo("PnpBridge is shutting down. Dropping the change notification");
|
||||
goto end;
|
||||
}
|
||||
|
||||
result = PnpBridge_ValidateDeviceChangePayload(DeviceChangePayload);
|
||||
if (PNPBRIDGE_OK != result) {
|
||||
LogInfo("Change payload is invalid");
|
||||
goto end;
|
||||
}
|
||||
|
||||
JSON_Value* jmsg;
|
||||
JSON_Object* jobj;
|
||||
JSON_Object* jdevice;
|
||||
|
||||
jmsg = json_parse_string(DeviceChangePayload->Message);
|
||||
jobj = json_value_get_object(jmsg);
|
||||
if (Configuration_IsDeviceConfigured(g_PnpBridge->configuration, jobj, &jdevice) < 0) {
|
||||
LogInfo("Device is not configured. Dropping the change notification");
|
||||
goto end;
|
||||
}
|
||||
|
||||
result = PnpAdapterManager_SupportsIdentity(g_PnpBridge->interfaceMgr, jdevice, &containsFilter, &key);
|
||||
if (PNPBRIDGE_OK != result) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (containsFilter) {
|
||||
// Create an Azure IoT PNP interface
|
||||
PPNPBRIDGE_INTERFACE_TAG pInt = malloc(sizeof(PNPBRIDGE_INTERFACE_TAG));
|
||||
char* interfaceId = (char*) json_object_get_string(jobj, "InterfaceId");
|
||||
|
||||
if (interfaceId != NULL) {
|
||||
int idSize = (int) strlen(interfaceId) + 1;
|
||||
char* id = malloc(idSize*sizeof(char));
|
||||
strcpy_s(id, idSize, interfaceId);
|
||||
id[idSize - 1] = '\0';
|
||||
|
||||
// check if interface is already published
|
||||
PPNPBRIDGE_INTERFACE_TAG* interfaceTags = malloc(sizeof(PPNPBRIDGE_INTERFACE_TAG)*g_PnpBridge->publishedInterfaceCount);
|
||||
LIST_ITEM_HANDLE interfaceItem = singlylinkedlist_get_head_item(g_PnpBridge->publishedInterfaces);
|
||||
while (interfaceItem != NULL) {
|
||||
PPNPBRIDGE_INTERFACE_TAG interface = (PPNPBRIDGE_INTERFACE_TAG) singlylinkedlist_item_get_value(interfaceItem);
|
||||
if (strcmp(interface->InterfaceName, id) == 0) {
|
||||
LogError("PnP Interface has already been published. Dropping the change notification. \n");
|
||||
result = PNPBRIDGE_FAILED;
|
||||
goto end;
|
||||
}
|
||||
interfaceItem = singlylinkedlist_get_next_item(interfaceItem);
|
||||
}
|
||||
|
||||
pInt->InterfaceName = id;
|
||||
|
||||
result = PnpAdapterManager_CreatePnpInterface(g_PnpBridge->interfaceMgr, g_PnpBridge->pnpDeviceClientHandle, key, &pInt->Interface, DeviceChangePayload);
|
||||
if (PNPBRIDGE_OK != result) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
g_PnpBridge->publishedInterfaceCount++;
|
||||
singlylinkedlist_add(g_PnpBridge->publishedInterfaces, pInt);
|
||||
|
||||
LogInfo("Publishing Azure Pnp Interface %s\n", interfaceId);
|
||||
AppRegisterPnPInterfacesAndWait(g_PnpBridge->pnpDeviceClientHandle);
|
||||
|
||||
goto end;
|
||||
}
|
||||
else {
|
||||
LogError("Interface id not set for the device change callback\n");
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
Unlock(g_PnpBridge->dispatchLock);
|
||||
|
||||
return PNPBRIDGE_OK;
|
||||
}
|
||||
|
||||
PNPBRIDGE_RESULT PnpBridge_Main() {
|
||||
PNPBRIDGE_RESULT result = PNPBRIDGE_OK;
|
||||
JSON_Value* config = NULL;
|
||||
|
||||
LogInfo("Starting Azure PnpBridge\n");
|
||||
|
||||
//#define CONFIG_FILE "c:\\data\\test\\dag\\config.json"
|
||||
result = PnpBridgeConfig_ReadConfigurationFromFile("config.json", &config);
|
||||
if (PNPBRIDGE_OK != result) {
|
||||
LogError("Failed to parse configuration. Check if config file is present and ensure its formatted correctly.\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
result = PnpBridge_Initialize(config);
|
||||
if (PNPBRIDGE_OK != result) {
|
||||
LogError("PnpBridge_Initialize failed: %d\n", result);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
LogInfo("Connected to Azure IoT Hub\n");
|
||||
|
||||
// Load all the adapters in interface manifest that implement Azure IoT PnP Interface
|
||||
// PnpBridge will call into corresponding adapter when a device is reported by
|
||||
// DiscoveryExtension
|
||||
result = PnpAdapterManager_Create(&g_PnpBridge->interfaceMgr, g_PnpBridge->configuration);
|
||||
if (PNPBRIDGE_OK != result) {
|
||||
LogError("PnpAdapterManager_Create failed: %d\n", result);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// Load all the extensions that are capable of discovering devices
|
||||
// and reporting back to PnpBridge
|
||||
result = DiscoveryAdapterManager_Create(&g_PnpBridge->discoveryMgr);
|
||||
if (PNPBRIDGE_OK != result) {
|
||||
LogError("DiscoveryAdapterManager_Create failed: %d\n", result);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
THREAD_HANDLE workerThreadHandle = NULL;
|
||||
if (THREADAPI_OK != ThreadAPI_Create(&workerThreadHandle, PnpBridge_Worker_Thread, NULL)) {
|
||||
LogError("Failed to create PnpBridge_Worker_Thread \n");
|
||||
workerThreadHandle = NULL;
|
||||
}
|
||||
else {
|
||||
ThreadAPI_Join(workerThreadHandle, NULL);
|
||||
}
|
||||
|
||||
exit:
|
||||
PnpBridge_Release();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void PnpBridge_Stop() {
|
||||
Lock(g_PnpBridge->dispatchLock);
|
||||
g_Shutdown = true;
|
||||
Unlock(g_PnpBridge->dispatchLock);
|
||||
}
|
||||
|
||||
int
|
||||
PnpBridge_UploadToBlobAsync(
|
||||
_In_z_ const char* pszDestination,
|
||||
_In_reads_bytes_(cbData) const unsigned char* pbData,
|
||||
_In_ size_t cbData,
|
||||
_In_ IOTHUB_CLIENT_FILE_UPLOAD_CALLBACK iotHubClientFileUploadCallback,
|
||||
_In_opt_ void* context
|
||||
)
|
||||
{
|
||||
IOTHUB_CLIENT_RESULT iotResult = IOTHUB_CLIENT_OK;
|
||||
|
||||
if (NULL == g_PnpBridge->deviceHandle)
|
||||
{
|
||||
return PNPBRIDGE_FAILED;
|
||||
}
|
||||
|
||||
if (NULL == pszDestination || (NULL == pbData && cbData > 0) ||
|
||||
(NULL != pbData && cbData == 0) ||
|
||||
NULL == iotHubClientFileUploadCallback)
|
||||
{
|
||||
return PNPBRIDGE_INVALID_ARGS;
|
||||
}
|
||||
|
||||
iotResult = IoTHubClient_UploadToBlobAsync(g_PnpBridge->deviceHandle,
|
||||
pszDestination,
|
||||
pbData,
|
||||
cbData,
|
||||
iotHubClientFileUploadCallback,
|
||||
context);
|
||||
switch(iotResult)
|
||||
{
|
||||
case IOTHUB_CLIENT_OK:
|
||||
return PNPBRIDGE_OK;
|
||||
break;
|
||||
case IOTHUB_CLIENT_INVALID_ARG:
|
||||
case IOTHUB_CLIENT_INVALID_SIZE:
|
||||
return PNPBRIDGE_INVALID_ARGS;
|
||||
break;
|
||||
case IOTHUB_CLIENT_INDEFINITE_TIME:
|
||||
case IOTHUB_CLIENT_ERROR:
|
||||
default:
|
||||
return PNPBRIDGE_FAILED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
BOOL WINAPI CtrlHandler(DWORD fdwCtrlType)
|
||||
{
|
||||
switch (fdwCtrlType)
|
||||
{
|
||||
// Handle the CTRL-C signal.
|
||||
case CTRL_C_EVENT:
|
||||
PnpBridge_Stop();
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
if (SetConsoleCtrlHandler(CtrlHandler, TRUE))
|
||||
{
|
||||
printf("\n -- Press Ctrl+C to stop PnpBridge\n");
|
||||
}
|
||||
|
||||
PnpBridge_Main();
|
||||
}
|
||||
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
#include "PnpBridgeCommon.h"
|
||||
#include "ConfigurationParser.h"
|
||||
#include "DiscoveryManager.h"
|
||||
#include "PnpAdapterInterface.h"
|
||||
#include "PnpAdapterManager.h"
|
||||
#include "IotHubComms.h"
|
||||
|
||||
#include "PnpBridgeh.h"
|
||||
|
||||
// Global instance of PnpBridge
|
||||
PPNP_BRIDGE g_PnpBridge = NULL;
|
||||
|
||||
PNPBRIDGE_RESULT PnpBridge_Initialize(PPNP_BRIDGE* pnpBridge, JSON_Value* config) {
|
||||
const char* connectionString;
|
||||
PNPBRIDGE_RESULT result = PNPBRIDGE_OK;
|
||||
PPNP_BRIDGE pbridge = NULL;
|
||||
|
||||
connectionString = Configuration_GetConnectionString(config);
|
||||
|
||||
TRY
|
||||
{
|
||||
if (NULL == connectionString) {
|
||||
LogError("Connection string not specified in the config\n");
|
||||
result = PNPBRIDGE_FAILED;
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
pbridge = (PPNP_BRIDGE)calloc(1, sizeof(PNP_BRIDGE));
|
||||
|
||||
if (NULL == pbridge) {
|
||||
LogError("Failed to allocate memory for PnpBridge global");
|
||||
result = PNPBRIDGE_INSUFFICIENT_MEMORY;
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
pbridge->configuration = config;
|
||||
|
||||
pbridge->dispatchLock = Lock_Init();
|
||||
if (NULL == pbridge->dispatchLock) {
|
||||
LogError("Failed to init PnpBridge lock");
|
||||
result = PNPBRIDGE_INSUFFICIENT_MEMORY;
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
pbridge->shutdown = false;
|
||||
|
||||
// Connect to Iot Hub and create a PnP device client handle
|
||||
if ((pbridge->deviceHandle = InitializeIotHubDeviceHandle(connectionString)) == NULL)
|
||||
{
|
||||
LogError("Could not allocate IoTHub Device handle\n");
|
||||
result = PNPBRIDGE_FAILED;
|
||||
LEAVE;
|
||||
}
|
||||
else if ((pbridge->pnpDeviceClientHandle = PnP_DeviceClient_CreateFromDeviceHandle(pbridge->deviceHandle)) == NULL)
|
||||
{
|
||||
LogError("PnP_DeviceClient_CreateFromDeviceHandle failed\n");
|
||||
result = PNPBRIDGE_FAILED;
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
*pnpBridge = pbridge;
|
||||
}
|
||||
FINALLY
|
||||
{
|
||||
if (PNPBRIDGE_OK != result) {
|
||||
PnpBridge_Release(pbridge);
|
||||
*pnpBridge = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void PnpBridge_Release(PPNP_BRIDGE pnpBridge) {
|
||||
if (NULL == pnpBridge) {
|
||||
return;
|
||||
}
|
||||
|
||||
LogInfo("Cleaning DeviceAggregator resources");
|
||||
|
||||
if (pnpBridge->dispatchLock) {
|
||||
Lock(pnpBridge->dispatchLock);
|
||||
}
|
||||
|
||||
// Stop Disovery Modules
|
||||
if (pnpBridge->discoveryMgr) {
|
||||
DiscoveryAdapterManager_Stop(pnpBridge->discoveryMgr);
|
||||
pnpBridge->discoveryMgr = NULL;
|
||||
}
|
||||
|
||||
// Stop Pnp Modules
|
||||
if (pnpBridge->adapterMgr) {
|
||||
PnpAdapterManager_Release(pnpBridge->adapterMgr);
|
||||
pnpBridge->adapterMgr = NULL;
|
||||
}
|
||||
|
||||
if (pnpBridge->dispatchLock) {
|
||||
Unlock(pnpBridge->dispatchLock);
|
||||
Lock_Deinit(pnpBridge->dispatchLock);
|
||||
}
|
||||
|
||||
if (pnpBridge) {
|
||||
free(pnpBridge);
|
||||
}
|
||||
}
|
||||
|
||||
int PnpBridge_Worker_Thread(void* threadArgument)
|
||||
{
|
||||
AZURE_UNREFERENCED_PARAMETER(threadArgument);
|
||||
|
||||
PPNP_BRIDGE pnpBridge = (PPNP_BRIDGE)threadArgument;
|
||||
|
||||
PNPBRIDGE_RESULT result = PNPBRIDGE_OK;
|
||||
|
||||
// Publish persistent Pnp Interfaces
|
||||
result = DiscoveryAdapterManager_PublishAlwaysInterfaces(pnpBridge->discoveryMgr, pnpBridge->configuration);
|
||||
if (!PNPBRIDGE_SUCCESS(result)) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// Start Device Discovery
|
||||
result = DiscoveryAdapterManager_Start(pnpBridge->discoveryMgr, pnpBridge->configuration);
|
||||
if (PNPBRIDGE_OK != result) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// TODO: Change this to an event
|
||||
while (true)
|
||||
{
|
||||
ThreadAPI_Sleep(1 * 1000);
|
||||
if (pnpBridge->shutdown) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return result;
|
||||
}
|
||||
|
||||
PNPBRIDGE_RESULT PnpBridge_ValidateDeviceChangePayload(PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD DeviceChangePayload) {
|
||||
if (NULL == DeviceChangePayload) {
|
||||
return PNPBRIDGE_INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (NULL == DeviceChangePayload->Message) {
|
||||
return PNPBRIDGE_INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (0 == DeviceChangePayload->MessageLength) {
|
||||
return PNPBRIDGE_INVALID_ARGS;
|
||||
}
|
||||
|
||||
return PNPBRIDGE_OK;
|
||||
}
|
||||
|
||||
PNPBRIDGE_RESULT PnpBridge_DeviceChangeCallback(PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD DeviceChangePayload) {
|
||||
PPNP_BRIDGE pnpBridge = g_PnpBridge;
|
||||
PNPBRIDGE_RESULT result = PNPBRIDGE_OK;
|
||||
bool containsFilter = false;
|
||||
int key = 0;
|
||||
JSON_Value* jmsg = NULL;
|
||||
|
||||
TRY
|
||||
{
|
||||
Lock(pnpBridge->dispatchLock);
|
||||
|
||||
if (pnpBridge->shutdown) {
|
||||
LogInfo("PnpBridge is shutting down. Dropping the change notification");
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
result = PnpBridge_ValidateDeviceChangePayload(DeviceChangePayload);
|
||||
if (PNPBRIDGE_OK != result) {
|
||||
LogInfo("Change payload is invalid");
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
JSON_Object* jobj;
|
||||
JSON_Object* jdevice;
|
||||
|
||||
jmsg = json_parse_string(DeviceChangePayload->Message);
|
||||
if (NULL == jmsg) {
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
jobj = json_value_get_object(jmsg);
|
||||
if (Configuration_IsDeviceConfigured(pnpBridge->configuration, jobj, &jdevice) < 0) {
|
||||
LogInfo("Device is not configured. Dropping the change notification");
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
result = PnpAdapterManager_SupportsIdentity(pnpBridge->adapterMgr, jdevice, &containsFilter, &key);
|
||||
if (PNPBRIDGE_OK != result) {
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
if (!containsFilter) {
|
||||
LogError("Dropping device change callback");
|
||||
result = PNPBRIDGE_INVALID_ARGS;
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
// Create an Pnp interface
|
||||
char* interfaceId = NULL;
|
||||
char* selfDescribing = (char*)json_object_get_string(jdevice, PNP_CONFIG_NAME_SELF_DESCRIBING);;
|
||||
if (NULL != selfDescribing && 0 == stricmp(selfDescribing, "true")) {
|
||||
interfaceId = (char*)json_object_get_string(jobj, "InterfaceId");
|
||||
if (NULL == interfaceId) {
|
||||
LogError("Interface id is missing for self descrbing device");
|
||||
result = PNPBRIDGE_INVALID_ARGS;
|
||||
LEAVE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
interfaceId = (char*)json_object_get_string(jdevice, "InterfaceId");
|
||||
if (NULL == interfaceId) {
|
||||
LogError("Interface Id is missing in config for the device");
|
||||
result = PNPBRIDGE_INVALID_ARGS;
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
// Add interfaceId to the message
|
||||
json_object_set_string(jobj, PNP_CONFIG_NAME_INTERFACE_ID, interfaceId);
|
||||
}
|
||||
|
||||
if (PnpAdapterManager_IsInterfaceIdPublished(pnpBridge->adapterMgr, interfaceId)) {
|
||||
LogError("PnP Interface has already been published. Dropping the change notification. \n");
|
||||
result = PNPBRIDGE_FAILED;
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
result = PnpAdapterManager_CreatePnpInterface(pnpBridge->adapterMgr, pnpBridge->pnpDeviceClientHandle, key, jdevice, DeviceChangePayload);
|
||||
if (!PNPBRIDGE_SUCCESS(result)) {
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
// Query all the pnp interface clients and publish them
|
||||
{
|
||||
PNP_INTERFACE_CLIENT_HANDLE* interfaces = NULL;
|
||||
int count = 0;
|
||||
PnpAdapterManager_GetAllInterfaces(pnpBridge->adapterMgr, &interfaces, &count);
|
||||
|
||||
LogInfo("Publishing Azure Pnp Interface %s", interfaceId);
|
||||
AppRegisterPnPInterfacesAndWait(pnpBridge->pnpDeviceClientHandle, interfaces, count);
|
||||
free(interfaces);
|
||||
}
|
||||
}
|
||||
FINALLY
|
||||
{
|
||||
Unlock(pnpBridge->dispatchLock);
|
||||
if (NULL != jmsg) {
|
||||
json_value_free(jmsg);
|
||||
}
|
||||
}
|
||||
|
||||
return PNPBRIDGE_OK;
|
||||
}
|
||||
|
||||
PNPBRIDGE_RESULT PnpBridge_Main() {
|
||||
PNPBRIDGE_RESULT result = PNPBRIDGE_OK;
|
||||
JSON_Value* config = NULL;
|
||||
PPNP_BRIDGE pnpBridge = NULL;
|
||||
|
||||
TRY
|
||||
{
|
||||
LogInfo("Starting Azure PnpBridge");
|
||||
|
||||
// Read the config file from a file
|
||||
result = PnpBridgeConfig_ReadConfigurationFromFile("config.json", &config);
|
||||
if (PNPBRIDGE_OK != result) {
|
||||
LogError("Failed to parse configuration. Check if config file is present and ensure its formatted correctly");
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
// Check if config file has mandatory parameters
|
||||
result = PnpBridgeConfig_ValidateConfiguration(config);
|
||||
if (PNPBRIDGE_OK != result) {
|
||||
LogError("Config file is invalid");
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
result = PnpBridge_Initialize(&pnpBridge, config);
|
||||
if (PNPBRIDGE_OK != result) {
|
||||
LogError("PnpBridge_Initialize failed: %d", result);
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
g_PnpBridge = pnpBridge;
|
||||
|
||||
LogInfo("Connected to Azure IoT Hub");
|
||||
|
||||
// Load all the adapters in interface manifest that implement Azure IoT PnP Interface
|
||||
// PnpBridge will call into corresponding adapter when a device is reported by
|
||||
// DiscoveryExtension
|
||||
result = PnpAdapterManager_Create(&pnpBridge->adapterMgr, pnpBridge->configuration);
|
||||
if (PNPBRIDGE_OK != result) {
|
||||
LogError("PnpAdapterManager_Create failed: %d", result);
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
// Load all the extensions that are capable of discovering devices
|
||||
// and reporting back to PnpBridge
|
||||
result = DiscoveryAdapterManager_Create(&pnpBridge->discoveryMgr);
|
||||
if (PNPBRIDGE_OK != result) {
|
||||
LogError("DiscoveryAdapterManager_Create failed: %d", result);
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
THREAD_HANDLE workerThreadHandle = NULL;
|
||||
if (THREADAPI_OK != ThreadAPI_Create(&workerThreadHandle, PnpBridge_Worker_Thread, pnpBridge)) {
|
||||
LogError("Failed to create PnpBridge_Worker_Thread");
|
||||
workerThreadHandle = NULL;
|
||||
}
|
||||
else {
|
||||
ThreadAPI_Join(workerThreadHandle, NULL);
|
||||
}
|
||||
}
|
||||
FINALLY
|
||||
{
|
||||
g_PnpBridge = NULL;
|
||||
|
||||
PnpBridge_Release(pnpBridge);
|
||||
|
||||
if (NULL != config) {
|
||||
json_value_free(config);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void PnpBridge_Stop(PPNP_BRIDGE pnpBridge) {
|
||||
Lock(pnpBridge->dispatchLock);
|
||||
pnpBridge->shutdown = true;
|
||||
Unlock(pnpBridge->dispatchLock);
|
||||
}
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
BOOL WINAPI CtrlHandler(DWORD fdwCtrlType)
|
||||
{
|
||||
switch (fdwCtrlType)
|
||||
{
|
||||
// Handle the CTRL-C signal.
|
||||
case CTRL_C_EVENT:
|
||||
PnpBridge_Stop(g_PnpBridge);
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
if (SetConsoleCtrlHandler(CtrlHandler, TRUE))
|
||||
{
|
||||
printf("\n -- Press Ctrl+C to stop PnpBridge\n");
|
||||
}
|
||||
|
||||
PnpBridge_Main();
|
||||
}
|
|
@ -1,40 +1,81 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <pnp_interface_client.h>
|
||||
|
||||
typedef enum _PNPBRIDGE_INTERFACE_CHANGE_TYPE {
|
||||
PNPBRIDGE_INTERFACE_CHANGE_INVALID,
|
||||
PNPBRIDGE_INTERFACE_CHANGE_ARRIVAL,
|
||||
PNPBRIDGE_INTERFACE_CHANGE_REMOVAL
|
||||
} PNPBRIDGE_INTERFACE_CHANGE_TYPE;
|
||||
|
||||
typedef struct _PNPBRIDGE_DEVICE_CHANGE_PAYLOAD {
|
||||
const char* Message;
|
||||
int MessageLength;
|
||||
PNPBRIDGE_INTERFACE_CHANGE_TYPE ChangeType;
|
||||
void* Context;
|
||||
} PNPBRIDGE_DEVICE_CHANGE_PAYLOAD, *PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD;
|
||||
|
||||
#include <DiscoveryAdapterInterface.h>
|
||||
#include <PnpAdapterInterface.h>
|
||||
|
||||
int
|
||||
PnpBridge_UploadToBlobAsync(
|
||||
_In_z_ const char* pszDestination,
|
||||
_In_reads_bytes_(cbData) const unsigned char* pbData,
|
||||
_In_ size_t cbData,
|
||||
_In_ IOTHUB_CLIENT_FILE_UPLOAD_CALLBACK iotHubClientFileUploadCallback,
|
||||
_In_opt_ void* context
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
/*
|
||||
___ ___ _ _
|
||||
| _ \_ _ _ __| _ )_ _(_)__| |__ _ ___
|
||||
| _/ ' \| '_ \ _ \ '_| / _` / _` / -_)
|
||||
|_| |_||_| .__/___/_| |_\__,_\__, \___|
|
||||
|_| |___/
|
||||
*/
|
||||
|
||||
// TODO: REMOVE THE COMMENTS
|
||||
// NOTES TO SELF:
|
||||
|
||||
//
|
||||
// Config update requires bridge tear down and restart
|
||||
//
|
||||
|
||||
//
|
||||
// Discovered Device -> Bind -> CreatePnpInterfaces -> Create Pnp Interface client ->
|
||||
// Create Pnp Adapter Interface -> Associate it with the adapter and store the device config pointer -> Get All interface for all adapters -> publish
|
||||
//
|
||||
|
||||
/*
|
||||
|
||||
0. TEST FOR MEMORY LEAKS USING APPVERIFIER
|
||||
|
||||
SerialPnp
|
||||
1. Closing serial handle
|
||||
2. Test publishing 2 interfaces (multiple)
|
||||
3. Test overlapped IO
|
||||
|
||||
PnpBridge
|
||||
4. DPS connection & test
|
||||
|
||||
5. FT to create a tear down in a loop *** MOCK the PNP CLIENT SDK
|
||||
6. Release PnpInterfaces.. - DONE
|
||||
7. Persistent device should get callback when device is discovered
|
||||
7.1 Use event to notify PnpBridgeWorker thread exit
|
||||
|
||||
CoreDevice
|
||||
7. Enumerate devices
|
||||
8. Add properties based on original device schema
|
||||
|
||||
CMAKE
|
||||
9. Clean up warnings to get a clean build
|
||||
10. Creating VS filters: https://stackoverflow.com/questions/33808087/cmake-how-to-create-visual-studio-filters
|
||||
|
||||
*/
|
||||
// ***************
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <pnp_interface_client.h>
|
||||
#include <core/PnpBridgeMemory.h>
|
||||
|
||||
typedef enum _PNPBRIDGE_INTERFACE_CHANGE_TYPE {
|
||||
PNPBRIDGE_INTERFACE_CHANGE_INVALID,
|
||||
PNPBRIDGE_INTERFACE_CHANGE_ARRIVAL,
|
||||
PNPBRIDGE_INTERFACE_CHANGE_PERSIST,
|
||||
PNPBRIDGE_INTERFACE_CHANGE_REMOVAL
|
||||
} PNPBRIDGE_INTERFACE_CHANGE_TYPE;
|
||||
|
||||
typedef struct _PNPBRIDGE_DEVICE_CHANGE_PAYLOAD {
|
||||
const char* Message;
|
||||
int MessageLength;
|
||||
PNPBRIDGE_INTERFACE_CHANGE_TYPE ChangeType;
|
||||
void* Context;
|
||||
} PNPBRIDGE_DEVICE_CHANGE_PAYLOAD, *PPNPBRIDGE_DEVICE_CHANGE_PAYLOAD;
|
||||
|
||||
#include <DiscoveryAdapterInterface.h>
|
||||
#include <PnpAdapterInterface.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1 @@
|
|||
C:\Program Files (x86)\Microsoft Visual Studio\2019\Preview\MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets(775,5): error : The OutputPath property is not set for project 'PnpBridge.vcxproj'. Please check to make sure that you have specified a valid combination of Configuration and Platform for this project. Configuration='Debug' Platform='x64'. This error may also appear if some other project is trying to follow a project-to-project reference to this project, this project has been unloaded or is not included in the solution, and the referencing project does not build using the same or an equivalent Configuration or Platform.
|
|
@ -23,7 +23,7 @@
|
|||
<ProjectGuid>{8756FD40-34AF-4000-AAB9-C2A14E75B23B}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>PnpBridge</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
|
@ -155,9 +155,6 @@
|
|||
<AdditionalDependencies>..\..\deps\azure-iot-sdk-c-pnp\$(Platform)_$(Configuration)\$(Configuration)\parson.lib;..\..\deps\azure-iot-sdk-c-pnp\$(Platform)_$(Configuration)\iothub_client\$(Configuration)\iothub_client.lib;..\..\deps\azure-iot-sdk-c-pnp\$(Platform)_$(Configuration)\pnp_client\$(Configuration)\pnp_client.lib;..\..\deps\azure-iot-sdk-c-pnp\$(Platform)_$(Configuration)\iothub_client\$(Configuration)\iothub_client_http_transport.lib;..\..\deps\azure-iot-sdk-c-pnp\$(Platform)_$(Configuration)\iothub_client\$(Configuration)\iothub_client_amqp_transport.lib;..\..\deps\azure-iot-sdk-c-pnp\$(Platform)_$(Configuration)\iothub_client\$(Configuration)\iothub_client_amqp_ws_transport.lib;..\..\deps\azure-iot-sdk-c-pnp\$(Platform)_$(Configuration)\iothub_client\$(Configuration)\iothub_client_mqtt_transport.lib;..\..\deps\azure-iot-sdk-c-pnp\$(Platform)_$(Configuration)\iothub_client\$(Configuration)\iothub_client_mqtt_ws_transport.lib;..\..\deps\azure-iot-sdk-c-pnp\$(Platform)_$(Configuration)\umqtt\$(Configuration)\umqtt.lib;..\..\deps\azure-iot-sdk-c-pnp\$(Platform)_$(Configuration)\$(Configuration)\parson.lib;..\..\deps\azure-iot-sdk-c-pnp\$(Platform)_$(Configuration)\c-utility\$(Configuration)\aziotsharedutil.lib;crypt32.lib;winhttp.lib;crypt32.lib;winhttp.lib;ws2_32.lib;secur32.lib;advapi32.lib;ncrypt.lib;rpcrt4.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;Cfgmgr32.lib;mfplat.lib;mfsensorgroup.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="ReadMe.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Adapters\Camera\CameraCaptureEngine.h" />
|
||||
<ClInclude Include="Adapters\Camera\CameraCaptureEngineCallbacks.h" />
|
||||
|
@ -167,8 +164,10 @@
|
|||
<ClInclude Include="Adapters\Camera\CameraStatConsumer.h" />
|
||||
<ClInclude Include="Adapters\Camera\JsonWrapper.h" />
|
||||
<ClInclude Include="Adapters\Camera\pch.h" />
|
||||
<ClInclude Include="adapters\CmdAndPropHandler.h" />
|
||||
<ClInclude Include="Adapters\CoreDeviceHealth\CoreDeviceHealth.h" />
|
||||
<ClInclude Include="Adapters\CoreDeviceHealth\WindowsPnpDeviceDiscovery.h" />
|
||||
<ClInclude Include="IotHubComms.h" />
|
||||
<ClInclude Include="PnpBridge.h" />
|
||||
<ClInclude Include="ConfigurationParser.h" />
|
||||
<ClInclude Include="DiscoveryAdapterInterface.h" />
|
||||
|
@ -193,14 +192,15 @@
|
|||
<ClCompile Include="Adapters\CoreDeviceHealth\WindowsPnPDeviceDiscovery.c" />
|
||||
<ClCompile Include="Adapters\SerialPnp\SerialPnp.c" />
|
||||
<ClCompile Include="ConfigurationParser.c" />
|
||||
<ClCompile Include="core\PnpAdapterInterface.c" />
|
||||
<ClCompile Include="core\PnpBridgeMemory.c" />
|
||||
<ClCompile Include="IotHubComms.c" />
|
||||
<ClCompile Include="PnpBridge.c" />
|
||||
<ClCompile Include="DiscoveryManager.c" />
|
||||
<ClCompile Include="PnpAdapterManger.c" />
|
||||
<ClCompile Include="PnpBridgeService.c" />
|
||||
<ClCompile Include="utility.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CmdAndPropHandler.h" />
|
||||
<None Include="config.json">
|
||||
<DeploymentContent>true</DeploymentContent>
|
||||
</None>
|
||||
|
|
|
@ -13,27 +13,24 @@
|
|||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Adapters">
|
||||
<UniqueIdentifier>{3524bf36-1d0b-46dc-ada9-78d0803fe1ec}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Adapters\CoreDeviceHealth">
|
||||
<UniqueIdentifier>{28fe5595-e94e-4bac-ac50-03299b219cd8}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\inc">
|
||||
<UniqueIdentifier>{92a538f9-7056-4277-a567-906bc28ce6a8}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Adapters\Camera">
|
||||
<Filter Include="Source Files\core">
|
||||
<UniqueIdentifier>{2ed2ef04-8f74-4d43-87b5-1da519b4d2f3}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\adapters">
|
||||
<UniqueIdentifier>{3524bf36-1d0b-46dc-ada9-78d0803fe1ec}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\adapters\CoreDeviceHealth">
|
||||
<UniqueIdentifier>{28fe5595-e94e-4bac-ac50-03299b219cd8}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\adapters\Camera">
|
||||
<UniqueIdentifier>{83239274-3c8a-4c29-a27a-4d7aafc2f2e3}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Adapters\SerialPnp">
|
||||
<Filter Include="Source Files\adapters\SerialPnp">
|
||||
<UniqueIdentifier>{611fd0c7-a77f-4116-bf8a-c41bded6d8a3}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Adapters\Sample">
|
||||
<UniqueIdentifier>{05fcc339-7478-4508-9685-0279a2e32c46}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="ReadMe.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="targetver.h">
|
||||
|
@ -55,34 +52,34 @@
|
|||
<Filter>Source Files\inc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Adapters\CoreDeviceHealth\WindowsPnpDeviceDiscovery.h">
|
||||
<Filter>Source Files\Adapters\CoreDeviceHealth</Filter>
|
||||
<Filter>Source Files\adapters\CoreDeviceHealth</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PnpBridgeCommon.h">
|
||||
<Filter>Source Files\inc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Adapters\CoreDeviceHealth\CoreDeviceHealth.h">
|
||||
<Filter>Source Files\Adapters\CoreDeviceHealth</Filter>
|
||||
<Filter>Source Files\adapters\CoreDeviceHealth</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Adapters\Camera\CameraIotPnpDevice.h">
|
||||
<Filter>Source Files\Adapters\Camera</Filter>
|
||||
<Filter>Source Files\adapters\Camera</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Adapters\Camera\CameraPnpDiscovery.h">
|
||||
<Filter>Source Files\Adapters\Camera</Filter>
|
||||
<Filter>Source Files\adapters\Camera</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Adapters\Camera\CameraStatConsumer.h">
|
||||
<Filter>Source Files\Adapters\Camera</Filter>
|
||||
<Filter>Source Files\adapters\Camera</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Adapters\Camera\pch.h">
|
||||
<Filter>Source Files\Adapters\Camera</Filter>
|
||||
<Filter>Source Files\adapters\Camera</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Adapters\Camera\JsonWrapper.h">
|
||||
<Filter>Source Files\Adapters\Camera</Filter>
|
||||
<Filter>Source Files\adapters\Camera</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Adapters\Camera\CameraIotPnpAPIs.h">
|
||||
<Filter>Source Files\Adapters\Camera</Filter>
|
||||
<Filter>Source Files\adapters\Camera</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Adapters\SerialPnp\SerialPnp.h">
|
||||
<Filter>Source Files\Adapters\SerialPnp</Filter>
|
||||
<Filter>Source Files\adapters\SerialPnp</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PnpBridgeh.h">
|
||||
<Filter>Source Files\inc</Filter>
|
||||
|
@ -91,10 +88,16 @@
|
|||
<Filter>Source Files\inc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Adapters\Camera\CameraCaptureEngine.h">
|
||||
<Filter>Source Files\Adapters\Camera</Filter>
|
||||
<Filter>Source Files\adapters\Camera</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Adapters\Camera\CameraCaptureEngineCallbacks.h">
|
||||
<Filter>Source Files\Adapters\Camera</Filter>
|
||||
<Filter>Source Files\adapters\Camera</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="adapters\CmdAndPropHandler.h">
|
||||
<Filter>Source Files\adapters</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="IotHubComms.h">
|
||||
<Filter>Source Files\inc</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -108,7 +111,7 @@
|
|||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Adapters\CoreDeviceHealth\WindowsPnPDeviceDiscovery.c">
|
||||
<Filter>Source Files\Adapters\CoreDeviceHealth</Filter>
|
||||
<Filter>Source Files\adapters\CoreDeviceHealth</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PnpAdapterManger.c">
|
||||
<Filter>Source Files</Filter>
|
||||
|
@ -120,40 +123,46 @@
|
|||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Adapters\CoreDeviceHealth\CoreDeviceHealth.c">
|
||||
<Filter>Source Files\Adapters\CoreDeviceHealth</Filter>
|
||||
<Filter>Source Files\adapters\CoreDeviceHealth</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Adapters\Camera\CameraIotPnpDevice.cpp">
|
||||
<Filter>Source Files\Adapters\Camera</Filter>
|
||||
<Filter>Source Files\adapters\Camera</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Adapters\Camera\CameraPnpDiscovery.cpp">
|
||||
<Filter>Source Files\Adapters\Camera</Filter>
|
||||
<Filter>Source Files\adapters\Camera</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Adapters\Camera\CameraStatConsumer.cpp">
|
||||
<Filter>Source Files\Adapters\Camera</Filter>
|
||||
<Filter>Source Files\adapters\Camera</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Adapters\Camera\JsonWrapper.cpp">
|
||||
<Filter>Source Files\Adapters\Camera</Filter>
|
||||
<Filter>Source Files\adapters\Camera</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Adapters\Camera\CameraIotPnpAPIs.cpp">
|
||||
<Filter>Source Files\Adapters\Camera</Filter>
|
||||
<Filter>Source Files\adapters\Camera</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Adapters\SerialPnp\SerialPnp.c">
|
||||
<Filter>Source Files\Adapters\SerialPnp</Filter>
|
||||
<Filter>Source Files\adapters\SerialPnp</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Adapters\AdapterManifest.c">
|
||||
<Filter>Source Files\Adapters</Filter>
|
||||
<Filter>Source Files\adapters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Adapters\Camera\CameraCaptureEngine.cpp">
|
||||
<Filter>Source Files\Adapters\Camera</Filter>
|
||||
<Filter>Source Files\adapters\Camera</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Adapters\Camera\CameraCaptureEngineCallbacks.cpp">
|
||||
<Filter>Source Files\Adapters\Camera</Filter>
|
||||
<Filter>Source Files\adapters\Camera</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="core\PnpBridgeMemory.c">
|
||||
<Filter>Source Files\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="core\PnpAdapterInterface.c">
|
||||
<Filter>Source Files\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IotHubComms.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="config.json" />
|
||||
<None Include="CmdAndPropHandler.h">
|
||||
<Filter>Source Files\Adapters</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -39,9 +39,11 @@ extern "C"
|
|||
|
||||
#include "parson.h"
|
||||
|
||||
|
||||
/** @brief Enumeration specifying the status of calls to various APIs in this module.
|
||||
*/
|
||||
#define TRY
|
||||
#define LEAVE goto __tryLabel;
|
||||
#define FINALLY goto __tryLabel; __tryLabel:
|
||||
#undef __try
|
||||
#undef __finally
|
||||
|
||||
#define PNPBRIDGE_RESULT_VALUES \
|
||||
PNPBRIDGE_OK, \
|
||||
|
@ -53,6 +55,8 @@ extern "C"
|
|||
|
||||
DEFINE_ENUM(PNPBRIDGE_RESULT, PNPBRIDGE_RESULT_VALUES);
|
||||
|
||||
#define PNPBRIDGE_SUCCESS(Result) (Result == PNPBRIDGE_OK)
|
||||
|
||||
#include "ConfigurationParser.h"
|
||||
|
||||
MAP_RESULT Map_Add_Index(MAP_HANDLE handle, const char* key, int value);
|
||||
|
@ -61,6 +65,19 @@ int Map_GetIndexValueFromKey(MAP_HANDLE handle, const char* key);
|
|||
|
||||
#include <PnpBridge.h>
|
||||
|
||||
#define PNP_CONFIG_IDENTITY_NAME "Identity"
|
||||
#define PNP_CONFIG_NAME_INTERFACE_ID "InterfaceId"
|
||||
#define PNP_CONFIG_NAME_PUBLISH_MODE "PublishMode"
|
||||
#define PNP_CONFIG_MATCH_FILTERS_NAME "MatchFilters"
|
||||
#define PNP_CONFIG_MATCH_TYPE_NAME "MatchType"
|
||||
#define PNP_CONFIG_NAME_MATCH_PARAMETERS "MatchParameters"
|
||||
#define PNP_CONFIG_DISCOVERY_ADAPTER_NAME "DiscoveryAdapter"
|
||||
#define PNP_CONFIG_NAME_PNP_PARAMETERS "PnpParameters"
|
||||
#define PNP_CONFIG_NAME_DISCOVERY_PARAMETERS "DiscoveryParameters"
|
||||
#define PNP_CONFIG_NAME_PNP_ADAPTERS "PnpAdapters"
|
||||
#define PNP_CONFIG_NAME_DISCOVERY_ADAPTERS "DiscoveryAdapters"
|
||||
#define PNP_CONFIG_NAME_SELF_DESCRIBING "SelfDescribing"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
// Placeholder for code to make PnpBridge a NT service
|
|
@ -18,21 +18,19 @@ typedef struct _PNP_BRIDGE {
|
|||
PDISCOVERY_MANAGER discoveryMgr;
|
||||
|
||||
// Manages loading all pnp adapter plugins and their lifetime
|
||||
PPNP_ADAPTER_MANAGER interfaceMgr;
|
||||
|
||||
// List of publised pnp interfaces
|
||||
SINGLYLINKEDLIST_HANDLE publishedInterfaces;
|
||||
|
||||
// Number of published pnp interfaces
|
||||
int publishedInterfaceCount;
|
||||
PPNP_ADAPTER_MANAGER adapterMgr;
|
||||
|
||||
LOCK_HANDLE dispatchLock;
|
||||
|
||||
// PnpBridge config document
|
||||
JSON_Value* configuration;
|
||||
|
||||
bool shutdown;
|
||||
|
||||
} PNP_BRIDGE, *PPNP_BRIDGE;
|
||||
|
||||
void PnpBridge_Release(PPNP_BRIDGE pnpBridge);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -1,7 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <pnp_device_client.h>
|
||||
#include "PnPAdapterInterface.h"
|
||||
|
|
@ -1,81 +1,65 @@
|
|||
{
|
||||
"_comment_PnpBridgeParameters": "PnpBridge configurable parameters",
|
||||
"PnpBridgeParameters": {
|
||||
"ConnectionString": "HostName=iot-pnp-hub1.azure-devices.net;DeviceId=win-gateway2;SharedAccessKey=YgPpLi1YFDMFxPTbsu+EEIROPyODcqEL+B+Z59XSk4M="
|
||||
},
|
||||
"_comment_Devices": "Array of devices for Azure Pnp interface should be published",
|
||||
"Devices": [
|
||||
{
|
||||
"_comment": "DEVICE1 - USB device",
|
||||
"MatchFilters": {
|
||||
"MatchType": "Exact",
|
||||
"MatchParameters": {
|
||||
"HardwareId": "USB\\VID_06CB&PID_00B3"
|
||||
}
|
||||
},
|
||||
"InterfaceId": "http://windows.com/coredevicehealth/v1",
|
||||
"PnpParameters": {
|
||||
"Identity": "core-device-health"
|
||||
}
|
||||
},
|
||||
{
|
||||
"_comment": "DEVICE2 - MCU sensor hub which reports Azure IoT Pnp interfaces",
|
||||
"MatchFilters": {
|
||||
"MatchType": "*"
|
||||
},
|
||||
"PnpParameters": {
|
||||
"Identity": "serial-pnp-interface"
|
||||
},
|
||||
"DiscoveryParameters": {
|
||||
"Identity": "serial-pnp-discovery",
|
||||
"ComPort": "COM4",
|
||||
"_comment": "NOTE: ComPort parameter will be used when UseComDeviceInterface is set to true. In case of windows iot edition, the COMXX symbolic links are not created. Setting UseComDeviceInterface to false will pick the first available COM interface.",
|
||||
"UseComDeviceInterface": "false",
|
||||
"BaudRate": "115200"
|
||||
}
|
||||
},
|
||||
{
|
||||
"_comment": "DEVICE3 - Standard Video Camera connected to a PC, for now the first camera only.",
|
||||
"MatchFilters": {
|
||||
"MatchType": "*"
|
||||
},
|
||||
"InterfaceId": "http://windows.com/camera_health_monitor/1.0.0",
|
||||
"PnpParameters": {
|
||||
"Identity": "camera-health-monitor"
|
||||
}
|
||||
}
|
||||
],
|
||||
"DiscoveryAdapters": {
|
||||
"EnabledAdapters": {
|
||||
},
|
||||
"Parameters": [
|
||||
{
|
||||
"Identity": "windows-pnp-discovery",
|
||||
"_comment1": "USB Device class",
|
||||
"DeviceInterfaceClasses": [
|
||||
"A5DCBF10-6530-11D2-901F-00C04FB951ED"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Identity": "camera-health-monitor",
|
||||
"_comment1": "USB Device class",
|
||||
"DeviceInterfaceClasses": [
|
||||
"A5DCBF10-6530-11D2-901F-00C04FB951ED"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"PnpAdapters": {
|
||||
"EnabledAdapters": {
|
||||
},
|
||||
"Parameters": [
|
||||
{
|
||||
"Identity": "camera-health-monitor",
|
||||
"_comment1": "USB Device class",
|
||||
"DeviceInterfaceClasses": [
|
||||
"A5DCBF10-6530-11D2-901F-00C04FB951ED"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
{
|
||||
"_comment_PnpBridgeParameters": "PnpBridge configurable parameters",
|
||||
"PnpBridgeParameters": {
|
||||
"ConnectionString": "HostName=iot-pnp-hub1.azure-devices.net;DeviceId=win-gateway2;SharedAccessKey=YgPpLi1YFDMFxPTbsu+EEIROPyODcqEL+B+Z59XSk4M="
|
||||
},
|
||||
"_comment_Devices": "Array of devices for Azure Pnp interface should be published",
|
||||
"Devices": [
|
||||
{
|
||||
"_comment": "DEVICE1 - USB device",
|
||||
"MatchFilters": {
|
||||
"MatchType": "Exact",
|
||||
"MatchParameters": {
|
||||
"HardwareId": "USB\\VID_06CB&PID_00B3"
|
||||
}
|
||||
},
|
||||
"InterfaceId": "http://windows.com/coredevicehealth/1.0.0",
|
||||
"PnpParameters": {
|
||||
"Identity": "core-device-health"
|
||||
}
|
||||
},
|
||||
{
|
||||
"_comment": "DEVICE2 - MCU sensor hub which reports Azure IoT Pnp interfaces",
|
||||
"MatchFilters": {
|
||||
"MatchType": "Exact"
|
||||
},
|
||||
"SelfDescribing": "true",
|
||||
"PnpParameters": {
|
||||
"Identity": "serial-pnp-interface"
|
||||
},
|
||||
"DiscoveryParameters": {
|
||||
"Identity": "serial-pnp-discovery",
|
||||
"ComPort": "COM4",
|
||||
"_comment": "NOTE: ComPort parameter will be used when UseComDeviceInterface is set to true. In case of windows iot edition, the COMXX symbolic links are not created. Setting UseComDeviceInterface to false will pick the first available COM interface.",
|
||||
"UseComDeviceInterface": "false",
|
||||
"BaudRate": "115200"
|
||||
}
|
||||
},
|
||||
{
|
||||
"_comment": "DEVICE3 - Standard Video Camera connected to a PC, for now the first camera only.",
|
||||
"MatchFilters": {
|
||||
"MatchType": "Exact",
|
||||
"MatchParameters": {
|
||||
"HardwareId": "UVC_Webcam_00"
|
||||
}
|
||||
},
|
||||
"InterfaceId": "http://windows.com/camera_health_monitor/v1",
|
||||
"PnpParameters": {
|
||||
"Identity": "camera-health-monitor"
|
||||
}
|
||||
}
|
||||
],
|
||||
"DiscoveryAdapters": {
|
||||
"EnabledAdapters": {
|
||||
},
|
||||
"Parameters": [
|
||||
{
|
||||
"Identity": "windows-pnp-discovery",
|
||||
"_comment1": "USB Device class",
|
||||
"DeviceInterfaceClasses": [
|
||||
"A5DCBF10-6530-11D2-901F-00C04FB951ED"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
#include "PnpBridgeCommon.h"
|
||||
#include "PnpAdapterInterface.h"
|
||||
#include "PnpAdapterManager.h"
|
||||
|
||||
int PnpAdapterInterface_Create(PNPADAPTER_CONTEXT adapterHandle, const char* interfaceId,
|
||||
PNP_INTERFACE_CLIENT_HANDLE pnpInterface,
|
||||
PPNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface,
|
||||
PPNPADPATER_INTERFACE_INIT_PARAMS params)
|
||||
{
|
||||
int result = 0;
|
||||
PPNPADAPTER_INTERFACE_TAG interface = NULL;
|
||||
PPNP_ADAPTER_CONTEXT_TAG adapterContext = adapterHandle;
|
||||
|
||||
TRY
|
||||
{
|
||||
// validate params
|
||||
if (NULL == params || NULL == params->releaseInterface || NULL == pnpInterface) {
|
||||
result = -1;
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
// Create a pnp adapter interface
|
||||
interface = calloc(1, sizeof(PNPADAPTER_INTERFACE_TAG));
|
||||
if (NULL == interface) {
|
||||
result = -1;
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
interface->pnpInterfaceClient = pnpInterface;
|
||||
interface->interfaceId = malloc(strlen(interfaceId) + 1);
|
||||
if (NULL == interface->interfaceId) {
|
||||
result = -1;
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
// Make a copy of interface id
|
||||
strcpy_s(interface->interfaceId, strlen(interfaceId)+1, interfaceId);
|
||||
|
||||
// Copy the params
|
||||
memcpy(&interface->params, params, sizeof(interface->params));
|
||||
|
||||
// Copy adapter context
|
||||
interface->adapterContext = calloc(1, sizeof(PPNP_ADAPTER_CONTEXT_TAG));
|
||||
if (NULL == interface->adapterContext) {
|
||||
result = -1;
|
||||
LEAVE;
|
||||
}
|
||||
memcpy(interface->adapterContext, adapterContext, sizeof(interface->adapterContext));
|
||||
|
||||
// Add this interface to the list of interfaces under the adapter context
|
||||
PnpAdapterManager_AddInterface(adapterContext->adapter, interface);
|
||||
|
||||
*pnpAdapterInterface = interface;
|
||||
}
|
||||
FINALLY
|
||||
{
|
||||
if (result < 0) {
|
||||
/* PnpAdapterManager_RemoveInterface(adapterContext->adapter, pnpAdapterInterface);*/
|
||||
PnpAdapterInterface_Destroy(interface);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void PnpAdapterInterface_Destroy(PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface) {
|
||||
if (NULL == pnpAdapterInterface) {
|
||||
return;
|
||||
}
|
||||
|
||||
PPNPADAPTER_INTERFACE_TAG interface = (PPNPADAPTER_INTERFACE_TAG)pnpAdapterInterface;
|
||||
if (NULL != interface->interfaceId) {
|
||||
free(interface->interfaceId);
|
||||
}
|
||||
|
||||
if (NULL != interface->adapterContext) {
|
||||
PPNP_ADAPTER_CONTEXT_TAG adapterContext = (PPNP_ADAPTER_CONTEXT_TAG)interface->adapterContext;
|
||||
if (NULL != interface->adapterEntry) {
|
||||
PnpAdapterManager_RemoveInterface(adapterContext->adapter, pnpAdapterInterface);
|
||||
}
|
||||
free(interface->adapterContext);
|
||||
}
|
||||
}
|
||||
|
||||
PNP_INTERFACE_CLIENT_HANDLE PnpAdapterInterface_GetPnpInterfaceClient(PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface) {
|
||||
if (NULL == pnpAdapterInterface) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PPNPADAPTER_INTERFACE_TAG interfaceClient = (PPNPADAPTER_INTERFACE_TAG)pnpAdapterInterface;
|
||||
return interfaceClient->pnpInterfaceClient;
|
||||
}
|
||||
|
||||
PNPBRIDGE_RESULT PnpAdapterInterface_SetContext(PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface, void* context) {
|
||||
if (NULL == pnpAdapterInterface) {
|
||||
return PNPBRIDGE_INVALID_ARGS;
|
||||
}
|
||||
|
||||
PPNPADAPTER_INTERFACE_TAG interfaceClient = (PPNPADAPTER_INTERFACE_TAG)pnpAdapterInterface;
|
||||
interfaceClient->context = context;
|
||||
|
||||
return PNPBRIDGE_OK;
|
||||
}
|
||||
|
||||
void* PnpAdapterInterface_GetContext(PNPADAPTER_INTERFACE_HANDLE pnpAdapterInterface) {
|
||||
if (NULL == pnpAdapterInterface) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PPNPADAPTER_INTERFACE_TAG adapterInterface = (PPNPADAPTER_INTERFACE_TAG)pnpAdapterInterface;
|
||||
return adapterInterface->context;
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
#include <stdio.h>
|
||||
#include "azure_c_shared_utility/refcount.h"
|
||||
#include "core/PnpBridgeMemory.h"
|
||||
|
||||
int PnpBridgeMemory_Create(PPNPBRIDGE_OBJECT_PARAMS params, int size, PNPBRIDGE_MEMORY* memory) {
|
||||
if (NULL == params || NULL == params->destroyCallback) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
PPNPBRIDGE_MEMORY_TAG mem = calloc(1, sizeof(PNPBRIDGE_MEMORY_TAG) + size);
|
||||
if (NULL == mem) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
INIT_REF_VAR(mem->count);
|
||||
mem->size = size;
|
||||
|
||||
*memory = (PNPBRIDGE_MEMORY*)mem;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PnpBridgeMemory_AddReference(PNPBRIDGE_MEMORY memory) {
|
||||
PPNPBRIDGE_MEMORY_TAG mem = (PPNPBRIDGE_MEMORY_TAG)memory;
|
||||
DEC_REF_VAR(mem->count);
|
||||
}
|
||||
|
||||
void PnpBridgeMemory_ReleaseReference(PNPBRIDGE_MEMORY memory) {
|
||||
PPNPBRIDGE_MEMORY_TAG mem = (PPNPBRIDGE_MEMORY_TAG)memory;
|
||||
if (DEC_RETURN_ZERO == DEC_REF_VAR(mem->count)) {
|
||||
mem->params.destroyCallback();
|
||||
}
|
||||
}
|
||||
|
||||
void* PnpMemory_GetBuffer(PNPBRIDGE_MEMORY memory, int* size) {
|
||||
PPNPBRIDGE_MEMORY_TAG mem = (PPNPBRIDGE_MEMORY_TAG)memory;
|
||||
if (NULL != size) {
|
||||
*size = mem->size;
|
||||
}
|
||||
return mem->memory;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
#ifndef PNPBRIDGE_OBJECT_H
|
||||
#define PNPBRIDGE_OBJECT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef void* PNPBRIDGE_MEMORY;
|
||||
|
||||
typedef int(*PNPBRIDGE_MEMORY_DESTROY) ();
|
||||
|
||||
typedef struct _PNPBRIDGE_MEMORY_PARAMS {
|
||||
PNPBRIDGE_MEMORY_DESTROY destroyCallback;
|
||||
} PNPBRIDGE_MEMORY_PARAMS, *PPNPBRIDGE_OBJECT_PARAMS;
|
||||
|
||||
typedef struct _PNPBRIDGE_MEMORY_TAG {
|
||||
volatile long count;
|
||||
int size;
|
||||
void* memory;
|
||||
PNPBRIDGE_MEMORY_PARAMS params;
|
||||
} PNPBRIDGE_MEMORY_TAG, *PPNPBRIDGE_MEMORY_TAG;
|
||||
|
||||
int PnpBridgeMemory_Create(PPNPBRIDGE_OBJECT_PARAMS params, int size, PNPBRIDGE_MEMORY* memory);
|
||||
|
||||
void PnpBridgeMemory_AddReference(PNPBRIDGE_MEMORY memory);
|
||||
|
||||
void PnpBridgeMemory_ReleaseReference(PNPBRIDGE_MEMORY memory);
|
||||
|
||||
void* PnpMemory_GetBuffer(PNPBRIDGE_MEMORY memory, int* size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PNPBRIDGE_OBJECT_H */
|
|
@ -1,8 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
// Including SDKDDKVer.h defines the highest available Windows platform.
|
||||
|
||||
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
|
||||
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
|
||||
|
||||
#include <SDKDDKVer.h>
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
MAP_RESULT Map_Add_Index(MAP_HANDLE handle, const char* key, int value) {
|
||||
char a[2] = { 0 };
|
||||
a[0] = value;
|
||||
a[0] = (char)value;
|
||||
return Map_Add(handle, key, a);
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче