blob: 31be50bf741756a4d2ef06276329a88298fb8d7c [file] [log] [blame]
#
# Copyright (c) 2020 Google LLC.
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
# @file
# Python interface for WeaveDataManagementClient
#
from __future__ import absolute_import
from __future__ import print_function
from ctypes import *
from .WeaveStack import *
from .GenericTraitUpdatableDataSink import *
from .ResourceIdentifier import *
from .WeaveUtility import WeaveUtility
__all__ = [ 'WdmClient', 'WdmFlushUpdateStatusStruct', 'WdmClientFlushUpdateError', 'WdmClientFlushUpdateDeviceError' ]
WEAVE_ERROR_STATUS_REPORT = 4044
class WdmFlushUpdateStatusStruct(Structure):
_fields_ = [
("errorCode", c_uint32),
("DeviceStatus", DeviceStatusStruct),
("path", c_void_p),
("pathLen", c_uint32),
("dataSink", c_void_p),
]
class WdmClientFlushUpdateError(WeaveStackError):
def __init__(self, err, path, dataSink, msg=None):
super(WdmClientFlushUpdateError, self).__init__(err, msg)
self.path = path
self.dataSink = dataSink
def __str__(self):
return "WdmClientFlushUpdateError path:{}, trait profileId:{}, trait InstanceId:{}, msg:{} ".format(self.path, self.dataSink.profileId, self.dataSink.instanceId, self.msg)
class WdmClientFlushUpdateDeviceError(DeviceError):
def __init__(self, profileId, statusCode, systemErrorCode, path, dataSink, msg=None):
super(WdmClientFlushUpdateDeviceError, self).__init__(profileId, statusCode, systemErrorCode, msg)
self.path = path
self.dataSink = dataSink
def __str__(self):
return "WdmClientFlushUpdateDeviceError path:{}, trait profileId:{}, trait InstanceId:{}, msg:{} ".format(self.path, self.dataSink.profileId, self.dataSink.instanceId, self.msg)
_CompleteFunct = CFUNCTYPE(None, c_void_p, c_void_p)
_ErrorFunct = CFUNCTYPE(None, c_void_p, c_void_p, c_ulong, POINTER(DeviceStatusStruct))
_FlushUpdateCompleteFunct = CFUNCTYPE(None, c_void_p, c_void_p, c_uint16, POINTER(WdmFlushUpdateStatusStruct))
class WdmClient():
def __init__(self):
self._wdmClientPtr = None
self._weaveStack = WeaveStack()
self._datamanagmentLib = None
self._traitTable = {}
self._InitLib()
wdmClient = c_void_p(None)
res = self._datamanagmentLib.nl_Weave_WdmClient_NewWdmClient(pointer(wdmClient), self._weaveStack.devMgr)
if (res != 0):
raise self._weaveStack.ErrorToException(res)
self._wdmClientPtr = wdmClient
def __del__(self):
self.close()
self._weaveStack = None
self._datamanagmentLib = None
def close(self):
if (self._traitTable != None):
for key in self._traitTable.keys():
if self._traitTable[key] != None:
val = self._traitTable[key]
val.close()
self._traitTable.clear()
self._traitTable = None
if (self._wdmClientPtr != None):
self._weaveStack.Call(
lambda: self._datamanagmentLib.nl_Weave_WdmClient_DeleteWdmClient(self._wdmClientPtr)
)
self._wdmClientPtr = None
def setNodeId(self, nodeId):
self._ensureNotClosed()
self._weaveStack.Call(
lambda: self._datamanagmentLib.nl_Weave_WdmClient_SetNodeId(self._wdmClientPtr, nodeId)
)
def newDataSink(self, resourceIdentifier, profileId, instanceId, path):
self._ensureNotClosed()
traitInstance = c_void_p(None)
_resourceIdentifier = ResourceIdentifierStruct.fromResourceIdentifier(resourceIdentifier)
res = self._weaveStack.Call(
lambda: self._datamanagmentLib.nl_Weave_WdmClient_NewDataSink(self._wdmClientPtr, _resourceIdentifier, profileId, instanceId, path, pointer(traitInstance))
)
if (res != 0):
raise self._weaveStack.ErrorToException(res)
addr = traitInstance.value
if addr not in self._traitTable.keys():
self._traitTable[addr] = GenericTraitUpdatableDataSink(resourceIdentifier, profileId, instanceId, path, traitInstance, self)
return self._traitTable[addr]
def removeDataSinkRef(self, traitInstance):
addr = id(traitInstance)
if addr in self._traitTable.keys():
self._traitTable[addr] = None
def flushUpdate(self):
self._ensureNotClosed()
def HandleFlushUpdateComplete(appState, reqState, pathCount, statusResultsPtr):
statusResults = []
for i in range(pathCount):
path = WeaveUtility.VoidPtrToByteArray(statusResultsPtr[i].path, statusResultsPtr[i].pathLen).decode()
addr = statusResultsPtr[i].dataSink
if addr in self._traitTable.keys():
dataSink = self._traitTable[addr]
else:
print("unexpected, trait %d does not exist in traitTable", i)
dataSink = None
if statusResultsPtr[i].errorCode == WEAVE_ERROR_STATUS_REPORT:
statusResults.append(WdmClientFlushUpdateDeviceError(statusResultsPtr[i].DeviceStatus.ProfileId, statusResultsPtr[i].DeviceStatus.StatusCode, statusResultsPtr[i].DeviceStatus.SysErrorCode, path, dataSink))
else:
statusResults.append(WdmClientFlushUpdateError(statusResultsPtr[i].errorCode, path, dataSink))
print(statusResults[-1])
self._weaveStack.callbackRes = statusResults
self._weaveStack.completeEvent.set()
cbHandleComplete = _FlushUpdateCompleteFunct(HandleFlushUpdateComplete)
return self._weaveStack.CallAsync(
lambda: self._datamanagmentLib.nl_Weave_WdmClient_FlushUpdate(self._wdmClientPtr, cbHandleComplete, self._weaveStack.cbHandleError)
)
def refreshData(self):
self._ensureNotClosed()
return self._weaveStack.CallAsync(
lambda: self._datamanagmentLib.nl_Weave_WdmClient_RefreshData(self._wdmClientPtr, self._weaveStack.cbHandleComplete, self._weaveStack.cbHandleError)
)
def _ensureNotClosed(self):
if (self._wdmClientPtr == None):
raise ValueError("wdmClient is not ready")
# ----- Private Members -----
def _InitLib(self):
if (self._datamanagmentLib == None):
self._datamanagmentLib = CDLL(self._weaveStack.LocateWeaveDLL())
self._datamanagmentLib.nl_Weave_WdmClient_Init.argtypes = [ ]
self._datamanagmentLib.nl_Weave_WdmClient_Init.restype = c_uint32
self._datamanagmentLib.nl_Weave_WdmClient_Shutdown.argtypes = [ ]
self._datamanagmentLib.nl_Weave_WdmClient_Shutdown.restype = c_uint32
self._datamanagmentLib.nl_Weave_WdmClient_SetNodeId.argtypes = [ c_void_p, c_uint64]
self._datamanagmentLib.nl_Weave_WdmClient_SetNodeId.restype = None
self._datamanagmentLib.nl_Weave_WdmClient_NewWdmClient.argtypes = [ POINTER(c_void_p), c_void_p]
self._datamanagmentLib.nl_Weave_WdmClient_NewWdmClient.restype = c_uint32
self._datamanagmentLib.nl_Weave_WdmClient_DeleteWdmClient.argtypes = [ c_void_p ]
self._datamanagmentLib.nl_Weave_WdmClient_DeleteWdmClient.restype = None
self._datamanagmentLib.nl_Weave_WdmClient_NewDataSink.argtypes = [ c_void_p, POINTER(ResourceIdentifierStruct), c_uint32, c_uint64, c_char_p, c_void_p ]
self._datamanagmentLib.nl_Weave_WdmClient_NewDataSink.restype = c_uint32
self._datamanagmentLib.nl_Weave_WdmClient_FlushUpdate.argtypes = [ c_void_p, _FlushUpdateCompleteFunct, _ErrorFunct ]
self._datamanagmentLib.nl_Weave_WdmClient_FlushUpdate.restype = c_uint32
self._datamanagmentLib.nl_Weave_WdmClient_RefreshData.argtypes = [ c_void_p, _CompleteFunct, _ErrorFunct ]
self._datamanagmentLib.nl_Weave_WdmClient_RefreshData.restype = c_uint32
res = self._datamanagmentLib.nl_Weave_WdmClient_Init()
if (res != 0):
raise self._weaveStack.ErrorToException(res)