diff --git a/apps/aqhome-data/c_addvalue.c b/apps/aqhome-data/c_addvalue.c index 4f68626..3a60fce 100644 --- a/apps/aqhome-data/c_addvalue.c +++ b/apps/aqhome-data/c_addvalue.c @@ -17,7 +17,7 @@ #include "aqhome/ipc/data/ipc_data.h" #include "aqhome/ipc/endpoint_ipc.h" #include "aqhome/ipc/msg_ipc_result.h" -#include "aqhome/ipc/data/msg_data_value.h" +#include "aqhome/ipc/data/msg_data_values.h" #include "aqhome/ipc/msg_ipc_tag16.h" #include @@ -45,36 +45,23 @@ * ------------------------------------------------------------------------------------------------ */ -void AqHomeData_HandleAddValue(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const GWEN_MSG *msg) +void AqHomeData_HandleAddValue(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, GWEN_MSG *msg) { GWEN_MSG *outMsg; int resultCode=AQH_MSG_IPC_SUCCESS; - GWEN_TAG16_LIST *tagList; - AQH_VALUE *value; - char *valueName=NULL; - char *valueUnits=NULL; - int valueType; + AQH_VALUE *recvdValue; - tagList=AQH_Tag16IpcMsg_ParseTags(msg, 0); - if (tagList) { - const GWEN_TAG16 *tag; + AQH_ValuesDataIpcMsg_Parse(msg, 0); + recvdValue=AQH_ValuesDataIpcMsg_ReadFirstValue(msg); + if (recvdValue) { + AQH_VALUE *value; - tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_VALUE_TAGS_NAME); - valueName=tag?GWEN_Tag16_GetTagDataAsNewString(tag, NULL):NULL; - - tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_VALUE_TAGS_UNITS); - valueUnits=tag?GWEN_Tag16_GetTagDataAsNewString(tag, NULL):NULL; - - tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_VALUE_TAGS_TYPE); - valueType=tag?GWEN_Tag16_GetTagDataAsUint32(tag, 0):0; + value=AqHomeData_GetOrCreateValueForDriverWithTemplate(aqh, ep, recvdValue); + if (value==NULL) + resultCode=AQH_MSG_IPC_ERROR_PERMS; + AQH_Value_free(recvdValue); } - value=AqHomeData_GetOrCreateValueForDriver(aqh, ep, valueName, valueUnits, valueType); - if (value==NULL) - resultCode=AQH_MSG_IPC_ERROR_PERMS; - free(valueUnits); - free(valueName); - outMsg=AQH_ResultIpcMsg_new(AQH_MSGTYPE_IPC_DATA_RESULT, resultCode); GWEN_MsgEndpoint_AddSendMessage(ep, outMsg); } diff --git a/apps/aqhome-data/c_addvalue.h b/apps/aqhome-data/c_addvalue.h index 7587902..8220873 100644 --- a/apps/aqhome-data/c_addvalue.h +++ b/apps/aqhome-data/c_addvalue.h @@ -13,7 +13,7 @@ #include "./aqhome_data.h" -void AqHomeData_HandleAddValue(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const GWEN_MSG *msg); +void AqHomeData_HandleAddValue(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, GWEN_MSG *msg); diff --git a/apps/aqhome-data/c_setdata.c b/apps/aqhome-data/c_setdata.c index 4711f37..97db15e 100644 --- a/apps/aqhome-data/c_setdata.c +++ b/apps/aqhome-data/c_setdata.c @@ -15,7 +15,7 @@ #include "./aqhome_data_p.h" #include "./loop.h" #include "aqhome/ipc/data/ipc_data.h" -#include "aqhome/ipc/data/msg_data_singledata.h" +#include "aqhome/ipc/data/msg_data_multidata.h" #include "aqhome/ipc/endpoint_ipc.h" #include "aqhome/ipc/msg_ipc_result.h" #include "aqhome/ipc/msg_ipc_tag16.h" @@ -46,45 +46,50 @@ static int _forwardDataToDriver(AQHOME_DATA *aqh, const AQH_VALUE *v, uint64_t t * ------------------------------------------------------------------------------------------------ */ -void AqHomeData_HandleSetData(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *epSrc, const GWEN_MSG *recvdMsg) +void AqHomeData_HandleSetData(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *epSrc, GWEN_MSG *recvdMsg) { GWEN_MSG *outMsg; int resultCode=AQH_MSG_IPC_SUCCESS; - GWEN_TAG16_LIST *tagList; - AQH_VALUE *value; - char *valueName=NULL; - uint64_t timestamp=0; - union {double f; uint64_t i;} u; + AQH_VALUE *recvdValue; + const char *valueName; + const GWEN_TAG16 *tag; + const uint64_t *dataPoints; + unsigned int numberOfPoints; - tagList=AQH_Tag16IpcMsg_ParseTags(recvdMsg, 0); - if (tagList) { - const GWEN_TAG16 *tag; + AQH_MultiDataDataIpcMsg_Parse(recvdMsg, 0); + recvdValue=AQH_MultiDataDataIpcMsg_ReadValue(recvdMsg); + valueName=recvdValue?AQH_Value_GetNameForDriver(recvdValue):NULL; + tag=AQH_Tag16IpcMsg_FindFirstTagByType(recvdMsg, AQH_MSGDATA_MULTIDATA_TAGS_DATA); + dataPoints=tag?((const uint64_t*)GWEN_Tag16_GetTagData(tag)):NULL; + numberOfPoints=(tag?GWEN_Tag16_GetTagLength(tag):0)/(2*sizeof(uint64_t)); - tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_SINGLEDATA_TAGS_NAME); - valueName=tag?GWEN_Tag16_GetTagDataAsNewString(tag, NULL):NULL; + if (numberOfPoints>0) { + AQH_VALUE *value; - tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_SINGLEDATA_TAGS_TIME); - timestamp=tag?GWEN_Tag16_GetTagDataAsUint64(tag, 0):0; + value=AQH_Storage_GetValueByNameForSystem(aqh->storage, valueName); + if (value) { + if (AQH_Value_GetValueType(value)==AQH_ValueType_Actor) { + union {double f; uint64_t i;} u; - tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_SINGLEDATA_TAGS_DATA); - u.i=tag?GWEN_Tag16_GetTagDataAsUint64(tag, 0):0; - } - - value=AQH_Storage_GetValueByNameForSystem(aqh->storage, valueName); - if (value) { - if (AQH_Value_GetValueType(value)==AQH_ValueType_Actor) { - resultCode=_forwardDataToDriver(aqh, value, timestamp, u.f); + u.i=dataPoints[1]; + resultCode=_forwardDataToDriver(aqh, value, dataPoints[0], u.f); + } + else { + DBG_INFO(NULL, "Value \"%s\" is not an actor", valueName); + resultCode=AQH_MSG_IPC_ERROR_INVALID; + } } else { - DBG_INFO(NULL, "Value \"%s\" is not an actor", valueName); - resultCode=AQH_MSG_IPC_ERROR_INVALID; + DBG_INFO(NULL, "No permissions to add datapoint for value \"%s\"", valueName); + resultCode=AQH_MSG_IPC_ERROR_PERMS; } } else { - DBG_INFO(NULL, "Actor value \"%s\" does not exist", valueName); - resultCode=AQH_MSG_IPC_ERROR_NOTFOUND; + DBG_INFO(NULL, "No datapoints"); + resultCode=AQH_MSG_IPC_ERROR_INVALID; } - free(valueName); + AQH_Value_free(recvdValue); + outMsg=AQH_ResultIpcMsg_new(AQH_MSGTYPE_IPC_DATA_RESULT, resultCode); GWEN_MsgEndpoint_AddSendMessage(epSrc, outMsg); @@ -105,13 +110,7 @@ int _forwardDataToDriver(AQHOME_DATA *aqh, const AQH_VALUE *v, uint64_t timestam GWEN_MSG *driverMsg; DBG_INFO(AQH_LOGDOMAIN, "Sending SETDATA msg to driver endpoint (%s)", GWEN_MsgEndpoint_GetName(ep)); - driverMsg=AQH_SingleDataDataIpcMsg_new(AQH_MSGTYPE_IPC_DATA_SETDATA, - AQH_Value_GetNameForDriver(v), - AQH_Value_GetValueUnits(v), - AQH_Value_GetValueType(v), - NULL, - timestamp, - datapoint); + driverMsg=AQH_MultiDataDataIpcMsg_newForOne(AQH_MSGTYPE_IPC_DATA_SETDATA, v, timestamp, datapoint); GWEN_MsgEndpoint_AddSendMessage(ep, driverMsg); return AQH_MSG_IPC_SUCCESS; } diff --git a/apps/aqhome-data/c_setdata.h b/apps/aqhome-data/c_setdata.h index 4780614..f4c0566 100644 --- a/apps/aqhome-data/c_setdata.h +++ b/apps/aqhome-data/c_setdata.h @@ -13,7 +13,7 @@ #include "./aqhome_data.h" -void AqHomeData_HandleSetData(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const GWEN_MSG *recvdMsg); +void AqHomeData_HandleSetData(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, GWEN_MSG *recvdMsg); diff --git a/apps/aqhome-tool/data/setdata.c b/apps/aqhome-tool/data/setdata.c index 80ae13c..52331cb 100644 --- a/apps/aqhome-tool/data/setdata.c +++ b/apps/aqhome-tool/data/setdata.c @@ -15,7 +15,7 @@ #include "aqhome/msg/msg_node.h" #include "aqhome/ipc/msg_ipc_result.h" -#include "aqhome/ipc/data/msg_data_singledata.h" +#include "aqhome/ipc/data/msg_data_multidata.h" #include "aqhome/ipc/data/ipc_data.h" #include @@ -262,8 +262,14 @@ int _doSetData(GWEN_DB_NODE *dbArgs) void _sendCommand(GWEN_MSG_ENDPOINT *epTcp, const char *valueName, const char *valueUnits, double dataToSend) { GWEN_MSG *msgOut; + AQH_VALUE *v; - msgOut=AQH_SingleDataDataIpcMsg_new(AQH_MSGTYPE_IPC_DATA_SETDATA, valueName, valueUnits, NULL, 0, 0, dataToSend); + v=AQH_Value_new(); + AQH_Value_SetNameForSystem(v, valueName); + AQH_Value_SetValueUnits(v, valueUnits); + + msgOut=AQH_MultiDataDataIpcMsg_newForOne(AQH_MSGTYPE_IPC_DATA_SETDATA, v, 0, dataToSend); + AQH_Value_free(v); GWEN_MsgEndpoint_AddSendMessage(epTcp, msgOut); } diff --git a/aqhome/ipc/data/0BUILD b/aqhome/ipc/data/0BUILD index 240f832..ca213aa 100644 --- a/aqhome/ipc/data/0BUILD +++ b/aqhome/ipc/data/0BUILD @@ -49,8 +49,6 @@ msg_data_values.h msg_data_datapoints.h msg_data_connect.h - msg_data_value.h - msg_data_singledata.h msg_data_multidata.h msg_data_getdata.h @@ -67,8 +65,6 @@ msg_data_values.c msg_data_datapoints.c msg_data_connect.c - msg_data_value.c - msg_data_singledata.c msg_data_multidata.c msg_data_getdata.c diff --git a/aqhome/ipc/data/msg_data_singledata.c b/aqhome/ipc/data/msg_data_singledata.c deleted file mode 100644 index 75702d8..0000000 --- a/aqhome/ipc/data/msg_data_singledata.c +++ /dev/null @@ -1,109 +0,0 @@ -/**************************************************************************** - * This file is part of the project AqHome. - * AqHome (c) by 2023 Martin Preuss, all rights reserved. - * - * The license for this file can be found in the file COPYING which you - * should have received along with this file. - ****************************************************************************/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include - -#include -#include - -#include -#include - - - -#define AQH_MSGDATA_SINGLEDATA_MINSIZE GWEN_MSGIPC_OFFS_PAYLOAD - - - - -GWEN_MSG *AQH_SingleDataDataIpcMsg_new(uint16_t code, - const char *valueName, - const char *valueUnits, - int valueType, - const char *deviceName, - uint64_t timestamp, - double datapoint) -{ - GWEN_MSG *msg; - GWEN_BUFFER *buf; - union {double f; uint64_t i;} u; - - u.f=datapoint; - buf=GWEN_Buffer_new(0, 256, 0, 1); - if (valueName && *valueName) - GWEN_Tag16_WriteStringTagToBuffer(AQH_MSGDATA_SINGLEDATA_TAGS_NAME, valueName, buf); - if (valueUnits && *valueUnits) - GWEN_Tag16_WriteStringTagToBuffer(AQH_MSGDATA_SINGLEDATA_TAGS_UNITS, valueUnits, buf); - GWEN_Tag16_WriteUint32TagToBuffer(AQH_MSGDATA_SINGLEDATA_TAGS_TYPE, valueType, buf); - if (deviceName && *deviceName) - GWEN_Tag16_WriteStringTagToBuffer(AQH_MSGDATA_SINGLEDATA_TAGS_DEV, deviceName, buf); - GWEN_Tag16_WriteUint64TagToBuffer(AQH_MSGDATA_SINGLEDATA_TAGS_TIME, timestamp, buf); - GWEN_Tag16_WriteUint64TagToBuffer(AQH_MSGDATA_SINGLEDATA_TAGS_DATA, u.i, buf); - - msg=AQH_Tag16IpcMsg_new(AQH_IPC_PROTOCOL_DATA_ID, AQH_IPC_PROTOCOL_DATA_VERSION, code, - GWEN_Buffer_GetUsedBytes(buf), (const uint8_t*) GWEN_Buffer_GetStart(buf)); - GWEN_Buffer_free(buf); - return msg; -} - - - -void AQH_SingleDataDataIpcMsg_Parse(GWEN_MSG *msg, int doCopy) -{ - AQH_Tag16IpcMsg_ExtendAndParse(msg, doCopy); -} - - - - -void AQH_SingleDataDataIpcMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText) -{ - if (GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSGDATA_SINGLEDATA_MINSIZE) { - char *valueName=NULL; - char *valueUnits=NULL; - int valueType; - char *deviceName=NULL; - uint64_t timestamp; - union {double f; uint64_t i;} u; - - valueName=AQH_Tag16IpcMsg_GetTagDataAsNewString(msg, AQH_MSGDATA_SINGLEDATA_TAGS_NAME, NULL); - valueUnits=AQH_Tag16IpcMsg_GetTagDataAsNewString(msg, AQH_MSGDATA_SINGLEDATA_TAGS_UNITS, NULL); - valueType=AQH_Tag16IpcMsg_GetTagDataAsUint32(msg, AQH_MSGDATA_SINGLEDATA_TAGS_TYPE, 0); - deviceName=AQH_Tag16IpcMsg_GetTagDataAsNewString(msg, AQH_MSGDATA_SINGLEDATA_TAGS_DEV, NULL); - timestamp=AQH_Tag16IpcMsg_GetTagDataAsUint64(msg, AQH_MSGDATA_SINGLEDATA_TAGS_TIME, 0); - u.i=AQH_Tag16IpcMsg_GetTagDataAsUint64(msg, AQH_MSGDATA_SINGLEDATA_TAGS_DATA, 0); - - GWEN_Buffer_AppendArgs(dbuf, - "SINGLEDATA (code=%d, proto=%d, proto version=%d, name=%s, units=%s, type=%d, dev=%s, time=%lu, data=%f)\n", - GWEN_IpcMsg_GetCode(msg), - GWEN_IpcMsg_GetProtoId(msg), - GWEN_IpcMsg_GetProtoVersion(msg), - valueName?valueName:"", - valueUnits?valueUnits:"", - valueType, - deviceName?deviceName:"", - (unsigned long int) timestamp, - u.f); - free(deviceName); - free(valueUnits); - free(valueName); - } -} - - - - - - - diff --git a/aqhome/ipc/data/msg_data_singledata.h b/aqhome/ipc/data/msg_data_singledata.h deleted file mode 100644 index 0793d9c..0000000 --- a/aqhome/ipc/data/msg_data_singledata.h +++ /dev/null @@ -1,54 +0,0 @@ -/**************************************************************************** - * This file is part of the project AqHome. - * AqHome (c) by 2023 Martin Preuss, all rights reserved. - * - * The license for this file can be found in the file COPYING which you - * should have received along with this file. - ****************************************************************************/ - -#ifndef AQH_MSG_IPC_DATA_SINGLEDATA_H -#define AQH_MSG_IPC_DATA_SINGLEDATA_H - - -#include - -#include - -#include - - -/** - * This message is used in request AQH_MSGTYPE_IPC_DATA_ADDVALUE_REQ. - */ - -#define AQH_MSGDATA_SINGLEDATA_TAGS_NAME 0x0001 -#define AQH_MSGDATA_SINGLEDATA_TAGS_UNITS 0x0002 -#define AQH_MSGDATA_SINGLEDATA_TAGS_TYPE 0x0003 -#define AQH_MSGDATA_SINGLEDATA_TAGS_DEV 0x0004 -#define AQH_MSGDATA_SINGLEDATA_TAGS_TIME 0x0010 -#define AQH_MSGDATA_SINGLEDATA_TAGS_DATA 0x0011 - - - -AQHOME_API GWEN_MSG *AQH_SingleDataDataIpcMsg_new(uint16_t code, - const char *valueName, - const char *valueUnits, - int valueType, - const char *deviceName, - uint64_t timestamp, - double datapoint); - -AQHOME_API void AQH_SingleDataDataIpcMsg_Parse(GWEN_MSG *msg, int doCopy); - -AQHOME_API void AQH_SingleDataDataIpcMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText); - - - - - - - -#endif - - - diff --git a/aqhome/ipc/data/msg_data_value.c b/aqhome/ipc/data/msg_data_value.c deleted file mode 100644 index 3447b96..0000000 --- a/aqhome/ipc/data/msg_data_value.c +++ /dev/null @@ -1,111 +0,0 @@ -/**************************************************************************** - * This file is part of the project AqHome. - * AqHome (c) by 2023 Martin Preuss, all rights reserved. - * - * The license for this file can be found in the file COPYING which you - * should have received along with this file. - ****************************************************************************/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include - -#include -#include - -#include -#include - - - -#define AQH_MSGDATA_VALUE_MINSIZE GWEN_MSGIPC_OFFS_PAYLOAD - - - - -GWEN_MSG *AQH_ValueDataIpcMsg_new(uint16_t code, - const char *valueName, - const char *valueUnits, - int valueType) -{ - GWEN_MSG *msg; - GWEN_BUFFER *buf; - - buf=GWEN_Buffer_new(0, 256, 0, 1); - - if (valueName && *valueName) - GWEN_Tag16_WriteStringTagToBuffer(AQH_MSGDATA_VALUE_TAGS_NAME, valueName, buf); - if (valueUnits && *valueUnits) - GWEN_Tag16_WriteStringTagToBuffer(AQH_MSGDATA_VALUE_TAGS_UNITS, valueUnits, buf); - GWEN_Tag16_WriteUint32TagToBuffer(AQH_MSGDATA_VALUE_TAGS_TYPE, valueType, buf); - - msg=AQH_Tag16IpcMsg_new(AQH_IPC_PROTOCOL_DATA_ID, AQH_IPC_PROTOCOL_DATA_VERSION, code, - GWEN_Buffer_GetUsedBytes(buf), (const uint8_t*) GWEN_Buffer_GetStart(buf)); - GWEN_Buffer_free(buf); - return msg; -} - - - -void AQH_ValueDataIpcMsg_Parse(GWEN_MSG *msg, int doCopy) -{ - AQH_Tag16IpcMsg_ExtendAndParse(msg, doCopy); -} - - - -AQH_VALUE *AQH_ValueDataIpcMsg_ReadValue(const GWEN_MSG *msg) -{ - //return AQH_DataIpc_ReadValueFromTagList(AQH_Tag16IpcMsg_GetTags(msg), AQH_MSGDATA_VALUES_TAGS_VALUE); -} - - - - -void AQH_ValueDataIpcMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText) -{ - if (GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSGDATA_VALUE_MINSIZE) { - GWEN_TAG16_LIST *tagList; - char *valueName=NULL; - char *valueUnits=NULL; - int valueType; - - - tagList=AQH_Tag16IpcMsg_ParseTags(msg, 0); - if (tagList) { - const GWEN_TAG16 *tag; - - tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_VALUE_TAGS_NAME); - valueName=tag?GWEN_Tag16_GetTagDataAsNewString(tag, NULL):NULL; - - tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_VALUE_TAGS_UNITS); - valueUnits=tag?GWEN_Tag16_GetTagDataAsNewString(tag, NULL):NULL; - - tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_VALUE_TAGS_TYPE); - valueType=tag?GWEN_Tag16_GetTagDataAsUint32(tag, 0):0; - } - - GWEN_Buffer_AppendArgs(dbuf, - "VALUE (code=%d, proto=%d, proto version=%d, name=%s, units=%s, type=%d)\n", - GWEN_IpcMsg_GetCode(msg), - GWEN_IpcMsg_GetProtoId(msg), - GWEN_IpcMsg_GetProtoVersion(msg), - valueName?valueName:"", - valueUnits?valueUnits:"", - valueType); - free(valueUnits); - free(valueName); - GWEN_Tag16_List_free(tagList); - } -} - - - - - - - diff --git a/aqhome/ipc/data/msg_data_value.h b/aqhome/ipc/data/msg_data_value.h deleted file mode 100644 index 1c7dd99..0000000 --- a/aqhome/ipc/data/msg_data_value.h +++ /dev/null @@ -1,50 +0,0 @@ -/**************************************************************************** - * This file is part of the project AqHome. - * AqHome (c) by 2023 Martin Preuss, all rights reserved. - * - * The license for this file can be found in the file COPYING which you - * should have received along with this file. - ****************************************************************************/ - -#ifndef AQH_MSG_IPC_DATA_VALUE_H -#define AQH_MSG_IPC_DATA_VALUE_H - - -#include - -#include - -#include - - -/** - * This message is used in request AQH_MSGTYPE_IPC_DATA_ADDVALUE_REQ. - */ - -#define AQH_MSGDATA_VALUE_TAGS_NAME 0x0001 -#define AQH_MSGDATA_VALUE_TAGS_UNITS 0x0002 -#define AQH_MSGDATA_VALUE_TAGS_TYPE 0x0003 - - - -AQHOME_API GWEN_DEPRECATED GWEN_MSG *AQH_ValueDataIpcMsg_new(uint16_t code, - const char *valueName, - const char *valueUnits, - int valueType); - -AQHOME_API void AQH_ValueDataIpcMsg_Parse(GWEN_MSG *msg, int doCopy); -AQHOME_API AQH_VALUE *AQH_ValueDataIpcMsg_ReadValue(const GWEN_MSG *msg); - - -AQHOME_API void AQH_ValueDataIpcMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText); - - - - - - - -#endif - - -