3149 lines
102 KiB
C
3149 lines
102 KiB
C
//
|
||
// --------------------------------------------------------------------------
|
||
// Gurux Ltd
|
||
//
|
||
//
|
||
//
|
||
// Filename: $HeadURL$
|
||
//
|
||
// Version: $Revision$,
|
||
// $Date$
|
||
// $Author$
|
||
//
|
||
// Copyright (c) Gurux Ltd
|
||
//
|
||
//---------------------------------------------------------------------------
|
||
//
|
||
// DESCRIPTION
|
||
//
|
||
// This file is a part of Gurux Device Framework.
|
||
//
|
||
// Gurux Device Framework is Open Source software; you can redistribute it
|
||
// and/or modify it under the terms of the GNU General Public License
|
||
// as published by the Free Software Foundation; version 2 of the License.
|
||
// Gurux Device Framework is distributed in the hope that it will be useful,
|
||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||
// See the GNU General Public License for more details.
|
||
//
|
||
// This code is licensed under the GNU General Public License v2.
|
||
// Full text may be retrieved at http://www.gnu.org/licenses/gpl-2.0.txt
|
||
//---------------------------------------------------------------------------
|
||
|
||
#include "gxignore.h"
|
||
#ifndef DLMS_IGNORE_SERVER
|
||
|
||
#if defined(_WIN32) || defined(_WIN64) || defined(__linux__)
|
||
#include <assert.h>
|
||
#endif
|
||
|
||
#include "gxmem.h"
|
||
#if _MSC_VER > 1400
|
||
#include <crtdbg.h>
|
||
#endif
|
||
#include <string.h>
|
||
|
||
#include "cosem.h"
|
||
#include "dlms.h"
|
||
#include "gxset.h"
|
||
#include "gxinvoke.h"
|
||
#include "helpers.h"
|
||
#include "objectarray.h"
|
||
#include "ciphering.h"
|
||
#include "gxget.h"
|
||
#include "gxkey.h"
|
||
#include "serverevents.h"
|
||
|
||
#ifndef DLMS_IGNORE_CHARGE
|
||
|
||
int invoke_Charge(
|
||
gxCharge* object,
|
||
unsigned char index,
|
||
dlmsVARIANT* value)
|
||
{
|
||
gxChargeTable* ct, * it;
|
||
int ret = 0, pos;
|
||
//Update unit charge.
|
||
if (index == 1)
|
||
{
|
||
for (pos = 0; pos != object->unitChargePassive.chargeTables.size; ++pos)
|
||
{
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
ret = arr_getByIndex(&object->unitChargePassive.chargeTables, pos, (void**)&ct, sizeof(gxCharge));
|
||
#else
|
||
ret = arr_getByIndex(&object->unitChargePassive.chargeTables, pos, (void**)&ct);
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
if (ret != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
ct->chargePerUnit = (short)var_toInteger(value);
|
||
}
|
||
}
|
||
//Activate passive unit charge.
|
||
else if (index == 2)
|
||
{
|
||
object->unitChargeActive.chargePerUnitScaling = object->unitChargePassive.chargePerUnitScaling;
|
||
object->unitChargeActive.commodity = object->unitChargePassive.commodity;
|
||
for (pos = 0; pos != object->unitChargePassive.chargeTables.size; ++pos)
|
||
{
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
if ((ret = arr_getByIndex(&object->unitChargePassive.chargeTables, pos, (void**)&ct, sizeof(gxChargeTable))) != 0 ||
|
||
(ret = arr_getByIndex(&object->unitChargeActive.chargeTables, object->unitChargeActive.chargeTables.size, (void**)&it, sizeof(gxChargeTable))) != 0)
|
||
{
|
||
break;
|
||
}
|
||
++object->unitChargeActive.chargeTables.size;
|
||
#else
|
||
if ((ret = arr_getByIndex(&object->unitChargePassive.chargeTables, pos, (void**)&ct)) != 0)
|
||
{
|
||
break;
|
||
}
|
||
it = (gxChargeTable*)gxmalloc(sizeof(gxChargeTable));
|
||
arr_push(&object->unitChargeActive.chargeTables, it);
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
it->chargePerUnit = ct->chargePerUnit;
|
||
it->index = ct->index;
|
||
}
|
||
}
|
||
//Update total amount remaining.
|
||
else if (index == 4)
|
||
{
|
||
object->totalAmountRemaining += var_toInteger(value);
|
||
}
|
||
else
|
||
{
|
||
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
|
||
}
|
||
return ret;
|
||
}
|
||
#endif //DLMS_IGNORE_CHARGE
|
||
#ifndef DLMS_IGNORE_CREDIT
|
||
int invoke_Credit(
|
||
gxCredit* object,
|
||
unsigned char index,
|
||
dlmsVARIANT* value)
|
||
{
|
||
int ret = 0;
|
||
//Update amount.
|
||
if (index == 1)
|
||
{
|
||
object->currentCreditAmount += var_toInteger(value);
|
||
}
|
||
//Set amount to value.
|
||
else if (index == 2)
|
||
{
|
||
object->currentCreditAmount = var_toInteger(value);
|
||
}
|
||
else if (index == 3)
|
||
{
|
||
// The mechanism for selecting the <20>Credit<69> is not in the scope of COSEM and
|
||
// shall be specified by the implementer (e.g. button push, meter process, script etc.).
|
||
object->status |= 4;
|
||
}
|
||
else
|
||
{
|
||
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
|
||
}
|
||
return ret;
|
||
}
|
||
#endif //DLMS_IGNORE_CREDIT
|
||
#ifndef DLMS_IGNORE_TOKEN_GATEWAY
|
||
int invoke_gxTokenGateway(
|
||
gxTokenGateway* object,
|
||
unsigned char index,
|
||
dlmsVARIANT* value)
|
||
{
|
||
int ret = 0;
|
||
//Update token.
|
||
if (index == 1)
|
||
{
|
||
bb_clear(&object->token);
|
||
if (value->vt == DLMS_DATA_TYPE_OCTET_STRING)
|
||
{
|
||
bb_set(&object->token, value->byteArr->data, value->byteArr->size);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
|
||
}
|
||
return ret;
|
||
}
|
||
#endif //DLMS_IGNORE_TOKEN_GATEWAY
|
||
|
||
#ifndef DLMS_IGNORE_ASSOCIATION_LOGICAL_NAME
|
||
int invoke_AssociationLogicalName(
|
||
dlmsServerSettings* settings,
|
||
gxValueEventArg* e)
|
||
{
|
||
int ret = 0;
|
||
gxAssociationLogicalName* object = (gxAssociationLogicalName*)e->target;
|
||
// Check reply_to_HLS_authentication
|
||
if (e->index == 1)
|
||
{
|
||
#ifndef DLMS_IGNORE_HIGH_GMAC
|
||
unsigned char ch;
|
||
gxByteBuffer tmp;
|
||
#endif //DLMS_IGNORE_HIGH_GMAC
|
||
unsigned char tmp2[64];
|
||
unsigned char equal;
|
||
uint32_t ic = 0;
|
||
gxByteBuffer bb;
|
||
gxByteBuffer* readSecret;
|
||
BYTE_BUFFER_INIT(&bb);
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
uint16_t count;
|
||
if ((ret = bb_getUInt8(e->parameters.byteArr, &ch)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
if (ch != DLMS_DATA_TYPE_OCTET_STRING)
|
||
{
|
||
#ifdef DLMS_DEBUG
|
||
svr_notifyTrace("High authentication failed. ", DLMS_ERROR_CODE_INVALID_PARAMETER);
|
||
#endif //DLMS_DEBUG
|
||
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
||
}
|
||
if ((ret = hlp_getObjectCount2(e->parameters.byteArr, &count)) != 0)
|
||
{
|
||
#ifdef DLMS_DEBUG
|
||
svr_notifyTrace("High authentication failed. ", DLMS_ERROR_CODE_INVALID_PARAMETER);
|
||
#endif //DLMS_DEBUG
|
||
return ret;
|
||
}
|
||
if (count > bb_available(e->parameters.byteArr))
|
||
{
|
||
#ifdef DLMS_DEBUG
|
||
svr_notifyTrace("High authentication failed. ", DLMS_ERROR_CODE_INVALID_PARAMETER);
|
||
#endif //DLMS_DEBUG
|
||
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
||
}
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
|
||
#ifndef DLMS_IGNORE_HIGH_GMAC
|
||
if (settings->base.authentication == DLMS_AUTHENTICATION_HIGH_GMAC)
|
||
{
|
||
bb_attach(&tmp, settings->base.sourceSystemTitle, sizeof(settings->base.sourceSystemTitle), sizeof(settings->base.sourceSystemTitle));
|
||
if ((ret = bb_getUInt8(e->parameters.byteArr, &ch)) != 0 ||
|
||
(ret = bb_getUInt32(e->parameters.byteArr, &ic)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
//IC is also compared.
|
||
e->parameters.byteArr->position -= 5;
|
||
readSecret = &tmp;
|
||
}
|
||
else
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
{
|
||
readSecret = &object->secret;
|
||
}
|
||
|
||
BYTE_BUFFER_INIT(&bb);
|
||
bb_attach(&bb, tmp2, 0, sizeof(tmp2));
|
||
if ((ret = dlms_secure(&settings->base,
|
||
ic,
|
||
&settings->base.stoCChallenge,
|
||
readSecret,
|
||
&bb)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
equal = bb_available(e->parameters.byteArr) != 0 &&
|
||
bb_compare(&bb,
|
||
e->parameters.byteArr->data + e->parameters.byteArr->position,
|
||
bb_available(e->parameters.byteArr));
|
||
bb_clear(&settings->info.data);
|
||
if (equal)
|
||
{
|
||
#ifndef DLMS_IGNORE_HIGH_GMAC
|
||
if (settings->base.authentication == DLMS_AUTHENTICATION_HIGH_GMAC)
|
||
{
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
bb_attach(&tmp, settings->base.cipher.systemTitle, sizeof(settings->base.cipher.systemTitle), sizeof(settings->base.cipher.systemTitle));
|
||
readSecret = &tmp;
|
||
#else
|
||
readSecret = &settings->base.cipher.systemTitle;
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
ic = settings->base.cipher.invocationCounter;
|
||
}
|
||
#endif //DLMS_IGNORE_HIGH_GMAC
|
||
e->byteArray = 1;
|
||
if ((ret = dlms_secure(&settings->base,
|
||
ic,
|
||
&settings->base.ctoSChallenge,
|
||
readSecret,
|
||
&settings->info.data)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
bb_insertUInt8(&settings->info.data, 0, DLMS_DATA_TYPE_OCTET_STRING);
|
||
bb_insertUInt8(&settings->info.data, 1, (unsigned char)(settings->info.data.size - 1));
|
||
object->associationStatus = DLMS_ASSOCIATION_STATUS_ASSOCIATED;
|
||
}
|
||
else
|
||
{
|
||
object->associationStatus = DLMS_ASSOCIATION_STATUS_NON_ASSOCIATED;
|
||
ret = DLMS_ERROR_CODE_READ_WRITE_DENIED;
|
||
}
|
||
}
|
||
else if (e->index == 2)
|
||
{
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
ret = cosem_getOctetString(e->parameters.byteArr, &object->secret);
|
||
#else
|
||
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
|
||
uint32_t size = bb_available(e->parameters.byteArr);
|
||
#else
|
||
uint16_t size = bb_available(e->parameters.byteArr);
|
||
#endif
|
||
if (size == 0)
|
||
{
|
||
ret = DLMS_ERROR_CODE_INCONSISTENT_CLASS_OR_OBJECT;
|
||
}
|
||
else
|
||
{
|
||
bb_clear(&object->secret);
|
||
ret = bb_set(&object->secret, e->parameters.byteArr->data + e->parameters.byteArr->position, size);
|
||
}
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
}
|
||
else if (e->index == 5)
|
||
{
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
gxUser* it;
|
||
if (!(object->userList.size < arr_getCapacity(&object->userList)))
|
||
{
|
||
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
|
||
}
|
||
else
|
||
{
|
||
++object->userList.size;
|
||
if ((ret = arr_getByIndex(&object->userList, object->userList.size - 1, (void**)&it, sizeof(gxUser))) == 0)
|
||
{
|
||
if ((ret = cosem_checkStructure(e->parameters.byteArr, 2)) != 0 ||
|
||
(ret = cosem_getUInt8(e->parameters.byteArr, &it->id)) != 0 ||
|
||
(ret = cosem_getString2(e->parameters.byteArr, it->name, sizeof(it->name))) != 0)
|
||
{
|
||
//Error code is returned at the end of the function.
|
||
}
|
||
}
|
||
}
|
||
#else
|
||
if (e->parameters.vt != DLMS_DATA_TYPE_STRUCTURE || e->parameters.Arr->size != 2)
|
||
{
|
||
ret = DLMS_ERROR_CODE_INCONSISTENT_CLASS_OR_OBJECT;
|
||
}
|
||
else
|
||
{
|
||
dlmsVARIANT* tmp;
|
||
char* name;
|
||
gxKey2* it = (gxKey2*)gxmalloc(sizeof(gxKey2));
|
||
if ((ret = va_getByIndex(e->parameters.Arr, 0, &tmp)) != 0)
|
||
{
|
||
gxfree(it);
|
||
return ret;
|
||
}
|
||
it->key = tmp->bVal;
|
||
if ((ret = va_getByIndex(e->parameters.Arr, 1, &tmp)) != 0)
|
||
{
|
||
gxfree(it);
|
||
return ret;
|
||
}
|
||
name = gxmalloc(tmp->strVal->size + 1);
|
||
it->value = name;
|
||
*(name + tmp->strVal->size) = '\0';
|
||
memcpy(it->value, tmp->strVal->data, tmp->strVal->size);
|
||
ret = arr_push(&((gxAssociationLogicalName*)e->target)->userList, it);
|
||
}
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
}
|
||
else if (e->index == 6)
|
||
{
|
||
int pos;
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
gxUser* it;
|
||
unsigned char id;
|
||
char name[MAX_SAP_ITEM_NAME_LENGTH];
|
||
if ((ret = cosem_checkStructure(e->parameters.byteArr, 2)) == 0 &&
|
||
(ret = cosem_getUInt8(e->parameters.byteArr, &id)) == 0 &&
|
||
(ret = cosem_getString2(e->parameters.byteArr, name, sizeof(name))) == 0)
|
||
{
|
||
uint16_t size = (uint16_t)strlen(name);
|
||
for (pos = 0; pos != ((gxAssociationLogicalName*)e->target)->userList.size; ++pos)
|
||
{
|
||
if ((ret = arr_getByIndex(&((gxAssociationLogicalName*)e->target)->userList, pos, (void**)&it, sizeof(gxUser))) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
if (it->id == id && memcmp(it->name, name, size) == 0)
|
||
{
|
||
int pos2;
|
||
gxUser* it2;
|
||
for (pos2 = pos + 1; pos2 < ((gxAssociationLogicalName*)e->target)->userList.size; ++pos2)
|
||
{
|
||
if ((ret = arr_getByIndex(&((gxAssociationLogicalName*)e->target)->userList, pos2, (void**)&it2, sizeof(gxUser))) != 0)
|
||
{
|
||
break;
|
||
}
|
||
memcpy(it, it2, sizeof(gxUser));
|
||
it = it2;
|
||
}
|
||
--((gxAssociationLogicalName*)e->target)->userList.size;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
#else
|
||
if (e->parameters.Arr->size != 2)
|
||
{
|
||
return DLMS_ERROR_CODE_INCONSISTENT_CLASS_OR_OBJECT;
|
||
}
|
||
else
|
||
{
|
||
gxKey2* it;
|
||
unsigned char id;
|
||
dlmsVARIANT* tmp;
|
||
unsigned char* name;
|
||
ret = va_getByIndex(e->parameters.Arr, 0, &tmp);
|
||
id = tmp->bVal;
|
||
ret = va_getByIndex(e->parameters.Arr, 1, &tmp);
|
||
name = tmp->strVal->data;
|
||
int len = tmp->strVal->size;
|
||
for (pos = 0; pos != ((gxAssociationLogicalName*)e->target)->userList.size; ++pos)
|
||
{
|
||
ret = arr_getByIndex(&((gxAssociationLogicalName*)e->target)->userList, pos, (void**)&it);
|
||
if (ret != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
if (it->key == id && memcmp(it->value, name, len) == 0)
|
||
{
|
||
ret = arr_removeByIndex(&((gxAssociationLogicalName*)e->target)->userList, pos, (void**)&it);
|
||
gxfree(it->value);
|
||
gxfree(it);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
}
|
||
else
|
||
{
|
||
ret = DLMS_ERROR_CODE_READ_WRITE_DENIED;
|
||
}
|
||
return ret;
|
||
}
|
||
#endif //DLMS_IGNORE_ASSOCIATION_LOGICAL_NAME
|
||
|
||
#ifndef DLMS_IGNORE_IMAGE_TRANSFER
|
||
int invoke_ImageTransfer(
|
||
gxImageTransfer* target,
|
||
gxValueEventArg* e)
|
||
{
|
||
int pos, ret = 0;
|
||
//Image transfer initiate
|
||
if (e->index == 1)
|
||
{
|
||
gxByteBuffer tmp;
|
||
gxImageActivateInfo* it, * item = NULL;
|
||
target->imageFirstNotTransferredBlockNumber = 0;
|
||
ba_clear(&target->imageTransferredBlocksStatus);
|
||
dlmsVARIANT* imageIdentifier, * size;
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
dlmsVARIANT imageIdentifier2, size2;
|
||
uint16_t count;
|
||
unsigned char ch;
|
||
if ((ret = cosem_checkStructure(e->parameters.byteArr, 2)) != 0 ||
|
||
(ret = bb_getUInt8(e->parameters.byteArr, &ch)) != 0 ||
|
||
ch != DLMS_DATA_TYPE_OCTET_STRING ||
|
||
(ret = hlp_getObjectCount2(e->parameters.byteArr, &count)) != 0)
|
||
{
|
||
e->error = DLMS_ERROR_CODE_HARDWARE_FAULT;
|
||
return ret;
|
||
}
|
||
imageIdentifier2.vt = DLMS_DATA_TYPE_OCTET_STRING;
|
||
size2.vt = DLMS_DATA_TYPE_UINT32;
|
||
//Attach image identifier so heap is not used.
|
||
gxByteBuffer bb;
|
||
bb_attach(&bb, e->parameters.byteArr->data + e->parameters.byteArr->position, count, count);
|
||
imageIdentifier2.byteArr = &bb;
|
||
e->parameters.byteArr->position += count;
|
||
if ((ret = cosem_getUInt32(e->parameters.byteArr, &size2.ulVal)) != 0)
|
||
{
|
||
e->error = DLMS_ERROR_CODE_HARDWARE_FAULT;
|
||
return ret;
|
||
}
|
||
imageIdentifier = &imageIdentifier2;
|
||
size = &size2;
|
||
#else
|
||
if ((ret = va_getByIndex(e->parameters.Arr, 0, &imageIdentifier)) != 0 ||
|
||
(ret = va_getByIndex(e->parameters.Arr, 1, &size)) != 0)
|
||
{
|
||
e->error = DLMS_ERROR_CODE_HARDWARE_FAULT;
|
||
return ret;
|
||
}
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
target->imageTransferStatus = DLMS_IMAGE_TRANSFER_STATUS_INITIATED;
|
||
unsigned char exists = 0;
|
||
for (pos = 0; pos != target->imageActivateInfo.size; ++pos)
|
||
{
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
if ((ret = arr_getByIndex(&target->imageActivateInfo, pos, (void**)&it, sizeof(gxImageActivateInfo))) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
#else
|
||
if ((ret = arr_getByIndex(&target->imageActivateInfo, pos, (void**)&it)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
bb_attach(&tmp, it->identification.data, it->identification.size, it->identification.size);
|
||
if (bb_size(imageIdentifier->byteArr) != 0 &&
|
||
bb_compare(&tmp, imageIdentifier->byteArr->data, imageIdentifier->byteArr->size))
|
||
{
|
||
item = it;
|
||
exists = 1;
|
||
}
|
||
}
|
||
if (!exists)
|
||
{
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
++target->imageActivateInfo.size;
|
||
if ((ret = arr_getByIndex(&target->imageActivateInfo, pos, (void**)&item, sizeof(gxImageActivateInfo))) != 0)
|
||
{
|
||
--target->imageActivateInfo.size;
|
||
return ret;
|
||
}
|
||
#else
|
||
item = (gxImageActivateInfo*)gxmalloc(sizeof(gxImageActivateInfo));
|
||
BYTE_BUFFER_INIT(&item->identification);
|
||
BYTE_BUFFER_INIT(&item->signature);
|
||
arr_push(&target->imageActivateInfo, item);
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
item->size = var_toInteger(size);
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
item->identification.size = (uint16_t)imageIdentifier->byteArr->size;
|
||
if ((ret = bb_get(imageIdentifier->byteArr, item->identification.data, imageIdentifier->byteArr->size)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
#else
|
||
item->identification.size = 0;
|
||
if ((ret = bb_set2(&item->identification, imageIdentifier->byteArr, 0, bb_size(imageIdentifier->byteArr))) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
uint16_t cnt = (uint16_t)(item->size / target->imageBlockSize);
|
||
if (item->size % target->imageBlockSize != 0)
|
||
{
|
||
++cnt;
|
||
}
|
||
cnt = ba_getByteCount(cnt);
|
||
#ifndef GX_DLMS_MICROCONTROLLER
|
||
target->imageTransferredBlocksStatus.position = 0;
|
||
#endif //GX_DLMS_MICROCONTROLLER
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
//Image transferred blocks status must handle in server side when malloc is not used if image size is huge.
|
||
if (target->imageTransferredBlocksStatus.capacity != 0)
|
||
{
|
||
if (cnt > ba_getCapacity(&target->imageTransferredBlocksStatus))
|
||
{
|
||
e->error = DLMS_ERROR_CODE_HARDWARE_FAULT;
|
||
return ret;
|
||
}
|
||
else
|
||
{
|
||
target->imageTransferredBlocksStatus.size = 0;
|
||
if ((ret = ba_capacity(&target->imageTransferredBlocksStatus, cnt)) == 0)
|
||
{
|
||
for (pos = 0; pos != cnt; ++pos)
|
||
{
|
||
ba_set(&target->imageTransferredBlocksStatus, 0);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
#else
|
||
target->imageTransferredBlocksStatus.size = 0;
|
||
if ((ret = ba_capacity(&target->imageTransferredBlocksStatus, cnt)) == 0)
|
||
{
|
||
for (pos = 0; pos != cnt; ++pos)
|
||
{
|
||
ba_set(&target->imageTransferredBlocksStatus, 0);
|
||
}
|
||
}
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
}
|
||
}
|
||
//Image block transfer
|
||
else if (e->index == 2)
|
||
{
|
||
uint32_t index;
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
if ((ret = cosem_checkStructure(e->parameters.byteArr, 2)) != 0 ||
|
||
(ret = cosem_getUInt32(e->parameters.byteArr, &index)) != 0)
|
||
{
|
||
e->error = DLMS_ERROR_CODE_HARDWARE_FAULT;
|
||
return ret;
|
||
}
|
||
#else
|
||
dlmsVARIANT* imageIndex;
|
||
if ((ret = va_getByIndex(e->parameters.Arr, 0, &imageIndex)) != 0)
|
||
{
|
||
e->error = DLMS_ERROR_CODE_HARDWARE_FAULT;
|
||
return ret;
|
||
}
|
||
index = (uint16_t)var_toInteger(imageIndex);
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
if ((ret = ba_setByIndex(&target->imageTransferredBlocksStatus, (uint16_t)index, 1)) == 0)
|
||
{
|
||
target->imageFirstNotTransferredBlockNumber = index + 1;
|
||
target->imageTransferStatus = DLMS_IMAGE_TRANSFER_STATUS_INITIATED;
|
||
}
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
bb_clear(e->parameters.byteArr);
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
}
|
||
//Image verify
|
||
else if (e->index == 3)
|
||
{
|
||
ret = 0;
|
||
}
|
||
//Image activate.
|
||
else if (e->index == 4)
|
||
{
|
||
ret = 0;
|
||
}
|
||
else
|
||
{
|
||
ret = DLMS_ERROR_CODE_READ_WRITE_DENIED;
|
||
}
|
||
return ret;
|
||
}
|
||
#endif //DLMS_IGNORE_IMAGE_TRANSFER
|
||
|
||
#ifndef DLMS_IGNORE_SAP_ASSIGNMENT
|
||
int invoke_SapAssigment(
|
||
gxSapAssignment* target,
|
||
gxValueEventArg* e)
|
||
{
|
||
int pos, ret = 0;
|
||
uint16_t id;
|
||
gxSapItem* it;
|
||
//Image transfer initiate
|
||
if (e->index == 1)
|
||
{
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
if (e->parameters.vt != DLMS_DATA_TYPE_OCTET_STRING)
|
||
{
|
||
ret = DLMS_ERROR_CODE_INCONSISTENT_CLASS_OR_OBJECT;
|
||
}
|
||
else if ((ret = cosem_checkStructure(e->parameters.byteArr, 2)) == 0 &&
|
||
(ret = cosem_getUInt16(e->parameters.byteArr, &id)) == 0)
|
||
{
|
||
if (id == 0)
|
||
{
|
||
uint16_t size;
|
||
unsigned char name[MAX_SAP_ITEM_NAME_LENGTH];
|
||
if ((ret = cosem_getOctetString2(e->parameters.byteArr, name, sizeof(name), &size)) == 0)
|
||
{
|
||
name[size] = 0;
|
||
for (pos = 0; pos != target->sapAssignmentList.size; ++pos)
|
||
{
|
||
if ((ret = arr_getByIndex(&target->sapAssignmentList, pos, (void**)&it, sizeof(gxSapItem))) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
if (it->name.size == size && memcmp(it->name.value, name, size) == 0)
|
||
{
|
||
if ((ret = arr_removeByIndex(&target->sapAssignmentList, pos, sizeof(gxSapItem))) == 0)
|
||
{
|
||
//arr_removeByIndex is decreasing amount already.
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//If buffer is full.
|
||
if (!(target->sapAssignmentList.size < target->sapAssignmentList.capacity))
|
||
{
|
||
ret = DLMS_ERROR_CODE_INCONSISTENT_CLASS_OR_OBJECT;
|
||
}
|
||
else
|
||
{
|
||
++target->sapAssignmentList.size;
|
||
if ((ret = arr_getByIndex(&target->sapAssignmentList, target->sapAssignmentList.size - 1, (void**)&it, sizeof(gxSapItem))) == 0 &&
|
||
(ret = cosem_getOctetString2(e->parameters.byteArr, it->name.value, sizeof(it->name.value), &it->name.size)) == 0)
|
||
{
|
||
it->id = id;
|
||
}
|
||
else
|
||
{
|
||
--target->sapAssignmentList.size;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
#else
|
||
dlmsVARIANT* tmp;
|
||
if ((ret = va_getByIndex(e->parameters.Arr, 0, &tmp)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
id = tmp->uiVal;
|
||
if ((ret = va_getByIndex(e->parameters.Arr, 1, &tmp)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
|
||
gxByteBuffer* name;
|
||
if (tmp->vt == DLMS_DATA_TYPE_OCTET_STRING)
|
||
{
|
||
name = tmp->byteArr;
|
||
}
|
||
else
|
||
{
|
||
name = tmp->strVal;
|
||
}
|
||
if (id == 0)
|
||
{
|
||
for (pos = 0; pos != target->sapAssignmentList.size; ++pos)
|
||
{
|
||
if ((ret = arr_getByIndex(&target->sapAssignmentList, pos, (void**)&it)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
it->name.position = 0;
|
||
if (name != NULL && bb_compare(&it->name, name->data, bb_size(name)))
|
||
{
|
||
ret = arr_removeByIndex(&target->sapAssignmentList, pos, (void**)&it);
|
||
bb_clear(&it->name);
|
||
gxfree(it);
|
||
return ret;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
it = (gxSapItem*)gxmalloc(sizeof(gxSapItem));
|
||
it->id = id;
|
||
BYTE_BUFFER_INIT(&it->name);
|
||
bb_set(&it->name, name->data, name->size);
|
||
arr_push(&target->sapAssignmentList, it);
|
||
}
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
}
|
||
else
|
||
{
|
||
ret = DLMS_ERROR_CODE_READ_WRITE_DENIED;
|
||
}
|
||
return ret;
|
||
}
|
||
#endif //DLMS_IGNORE_SAP_ASSIGNMENT
|
||
|
||
#ifndef DLMS_IGNORE_SECURITY_SETUP
|
||
int invoke_SecuritySetup(dlmsServerSettings* settings, gxSecuritySetup* target, gxValueEventArg* e)
|
||
{
|
||
int ret = 0;
|
||
#ifndef DLMS_IGNORE_HIGH_GMAC
|
||
int pos;
|
||
#endif //DLMS_IGNORE_HIGH_GMAC
|
||
if (e->index == 1)
|
||
{
|
||
//The security policy can only be strengthened.
|
||
if (target->securityPolicy > var_toInteger(&e->parameters))
|
||
{
|
||
ret = DLMS_ERROR_CODE_INCONSISTENT_CLASS_OR_OBJECT;
|
||
}
|
||
else
|
||
{
|
||
target->securityPolicy = var_toInteger(&e->parameters);
|
||
}
|
||
}
|
||
else if (e->index == 2)
|
||
{
|
||
#ifdef DLMS_IGNORE_HIGH_GMAC
|
||
ret = DLMS_ERROR_CODE_INCONSISTENT_CLASS_OR_OBJECT;
|
||
#else
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
if (e->parameters.vt != DLMS_DATA_TYPE_OCTET_STRING)
|
||
{
|
||
ret = DLMS_ERROR_CODE_INCONSISTENT_CLASS_OR_OBJECT;
|
||
}
|
||
else
|
||
{
|
||
unsigned char TMP[24];
|
||
gxByteBuffer tmp;
|
||
BB_ATTACH(tmp, TMP, 0);
|
||
unsigned char BUFF[24];
|
||
gxByteBuffer bb;
|
||
BB_ATTACH(bb, BUFF, 0);
|
||
unsigned char type;
|
||
uint16_t count = 10;
|
||
if ((ret = cosem_checkArray(e->parameters.byteArr, &count)) == 0)
|
||
{
|
||
for (pos = 0; pos != count; ++pos)
|
||
{
|
||
if ((ret = cosem_checkStructure(e->parameters.byteArr, 2)) != 0 ||
|
||
(ret = cosem_getEnum(e->parameters.byteArr, &type)) != 0 ||
|
||
(ret = cosem_getOctetString(e->parameters.byteArr, &tmp)) != 0 ||
|
||
(ret = cip_decryptKey(settings->base.kek, sizeof(settings->base.kek), &tmp, &bb)) != 0)
|
||
{
|
||
break;
|
||
}
|
||
if (bb.size != 16)
|
||
{
|
||
e->error = DLMS_ERROR_CODE_INCONSISTENT_CLASS_OR_OBJECT;
|
||
break;
|
||
}
|
||
switch (type)
|
||
{
|
||
case DLMS_GLOBAL_KEY_TYPE_UNICAST_ENCRYPTION:
|
||
memcpy(settings->base.cipher.blockCipherKey, BUFF, bb.size);
|
||
break;
|
||
case DLMS_GLOBAL_KEY_TYPE_BROADCAST_ENCRYPTION:
|
||
//Invalid type
|
||
ret = DLMS_ERROR_CODE_INCONSISTENT_CLASS_OR_OBJECT;
|
||
break;
|
||
case DLMS_GLOBAL_KEY_TYPE_AUTHENTICATION:
|
||
memcpy(settings->base.cipher.authenticationKey, BUFF, bb.size);
|
||
break;
|
||
case DLMS_GLOBAL_KEY_TYPE_KEK:
|
||
memcpy(settings->base.kek, BUFF, bb.size);
|
||
break;
|
||
default:
|
||
//Invalid type
|
||
ret = DLMS_ERROR_CODE_INCONSISTENT_CLASS_OR_OBJECT;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
#else
|
||
dlmsVARIANT* it, * type, * data;
|
||
if (e->parameters.vt != DLMS_DATA_TYPE_ARRAY)
|
||
{
|
||
ret = DLMS_ERROR_CODE_INCONSISTENT_CLASS_OR_OBJECT;
|
||
}
|
||
else
|
||
{
|
||
gxByteBuffer bb;
|
||
BYTE_BUFFER_INIT(&bb);
|
||
for (pos = 0; pos != e->parameters.Arr->size; ++pos)
|
||
{
|
||
bb_clear(&bb);
|
||
if ((ret = va_getByIndex(e->parameters.Arr, pos, &it)) != 0 ||
|
||
(ret = va_getByIndex(it->Arr, 0, &type)) != 0 ||
|
||
(ret = va_getByIndex(it->Arr, 1, &data)) != 0 ||
|
||
(ret = cip_decryptKey(settings->base.kek.data, (unsigned char)settings->base.kek.size, data->byteArr, &bb)) != 0)
|
||
{
|
||
break;
|
||
}
|
||
if (bb.size != 16)
|
||
{
|
||
e->error = DLMS_ERROR_CODE_INCONSISTENT_CLASS_OR_OBJECT;
|
||
break;
|
||
}
|
||
switch (type->cVal)
|
||
{
|
||
case DLMS_GLOBAL_KEY_TYPE_UNICAST_ENCRYPTION:
|
||
bb_clear(&settings->base.cipher.blockCipherKey);
|
||
bb_set(&settings->base.cipher.blockCipherKey, bb.data, bb.size);
|
||
break;
|
||
case DLMS_GLOBAL_KEY_TYPE_BROADCAST_ENCRYPTION:
|
||
//Invalid type
|
||
ret = DLMS_ERROR_CODE_INCONSISTENT_CLASS_OR_OBJECT;
|
||
break;
|
||
case DLMS_GLOBAL_KEY_TYPE_AUTHENTICATION:
|
||
bb_clear(&settings->base.cipher.authenticationKey);
|
||
bb_set(&settings->base.cipher.authenticationKey, bb.data, bb.size);
|
||
break;
|
||
case DLMS_GLOBAL_KEY_TYPE_KEK:
|
||
bb_clear(&settings->base.kek);
|
||
bb_set(&settings->base.kek, bb.data, bb.size);
|
||
break;
|
||
default:
|
||
//Invalid type
|
||
ret = DLMS_ERROR_CODE_INCONSISTENT_CLASS_OR_OBJECT;
|
||
break;
|
||
}
|
||
}
|
||
bb_clear(&bb);
|
||
}
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
#endif //DLMS_IGNORE_HIGH_GMAC
|
||
}
|
||
else
|
||
{
|
||
ret = DLMS_ERROR_CODE_READ_WRITE_DENIED;
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
#endif //DLMS_IGNORE_SECURITY_SETUP
|
||
|
||
#ifndef DLMS_IGNORE_ASSOCIATION_SHORT_NAME
|
||
int invoke_AssociationShortName(
|
||
dlmsServerSettings* settings,
|
||
gxValueEventArg* e)
|
||
{
|
||
int ret;
|
||
unsigned char equal;
|
||
uint32_t ic = 0;
|
||
#ifndef DLMS_IGNORE_HIGH_GMAC
|
||
gxByteBuffer bb;
|
||
#endif //DLMS_IGNORE_HIGH_GMAC
|
||
gxByteBuffer* readSecret;
|
||
// Check reply_to_HLS_authentication
|
||
if (e->index == 8)
|
||
{
|
||
#ifndef DLMS_IGNORE_HIGH_GMAC
|
||
if (settings->base.authentication == DLMS_AUTHENTICATION_HIGH_GMAC)
|
||
{
|
||
unsigned char ch;
|
||
bb_attach(&bb, settings->base.sourceSystemTitle, sizeof(settings->base.sourceSystemTitle), sizeof(settings->base.sourceSystemTitle));
|
||
readSecret = &bb;
|
||
if ((ret = bb_getUInt8(&settings->info.data, &ch)) != 0 ||
|
||
(ret = bb_getUInt32(&settings->info.data, &ic)) != 0)
|
||
{
|
||
bb_clear(&settings->info.data);
|
||
return ret;
|
||
}
|
||
}
|
||
else
|
||
#endif //DLMS_IGNORE_HIGH_GMAC
|
||
{
|
||
readSecret = &((gxAssociationShortName*)e->target)->secret;
|
||
}
|
||
bb_clear(&settings->info.data);
|
||
if ((ret = dlms_secure(&settings->base, ic,
|
||
&settings->base.stoCChallenge, readSecret, &settings->info.data)) != 0)
|
||
{
|
||
bb_clear(&settings->info.data);
|
||
return ret;
|
||
}
|
||
equal = bb_size(e->parameters.byteArr) != 0 &&
|
||
bb_compare(&settings->info.data,
|
||
e->parameters.byteArr->data,
|
||
e->parameters.byteArr->size);
|
||
bb_clear(&settings->info.data);
|
||
if (equal)
|
||
{
|
||
e->byteArray = 1;
|
||
#ifndef DLMS_IGNORE_HIGH_GMAC
|
||
if (settings->base.authentication == DLMS_AUTHENTICATION_HIGH_GMAC)
|
||
{
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
bb_attach(&bb, settings->base.cipher.systemTitle, sizeof(settings->base.cipher.systemTitle), sizeof(settings->base.cipher.systemTitle));
|
||
readSecret = &bb;
|
||
#else
|
||
readSecret = &settings->base.cipher.systemTitle;
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
ic = settings->base.cipher.invocationCounter;
|
||
}
|
||
#endif //DLMS_IGNORE_HIGH_GMAC
|
||
if ((ret = dlms_secure(&settings->base,
|
||
ic,
|
||
&settings->base.ctoSChallenge,
|
||
readSecret,
|
||
&settings->info.data)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
bb_insertUInt8(&settings->info.data, 0, DLMS_DATA_TYPE_OCTET_STRING);
|
||
bb_insertUInt8(&settings->info.data, 1, (unsigned char)(settings->info.data.size - 1));
|
||
}
|
||
else
|
||
{
|
||
return 0;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
return DLMS_ERROR_CODE_READ_WRITE_DENIED;
|
||
}
|
||
return 0;
|
||
}
|
||
#endif //DLMS_IGNORE_ASSOCIATION_SHORT_NAME
|
||
#ifndef DLMS_IGNORE_SCRIPT_TABLE
|
||
int invoke_ScriptTable(
|
||
dlmsServerSettings* settings,
|
||
gxValueEventArg* e)
|
||
{
|
||
gxScript* s;
|
||
gxScriptAction* sa;
|
||
gxValueEventArg* e1;
|
||
int ret = 0, pos, pos2;
|
||
unsigned char id = var_toInteger(&e->parameters);
|
||
//Find index and execute it.
|
||
if (e->index == 1)
|
||
{
|
||
gxValueEventCollection args;
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
gxValueEventArg tmp[1];
|
||
ve_init(&tmp[0]);
|
||
vec_attach(&args, tmp, 1, 1);
|
||
e1 = &tmp[0];
|
||
#else
|
||
e1 = (gxValueEventArg*)gxmalloc(sizeof(gxValueEventArg));
|
||
ve_init(e1);
|
||
vec_init(&args);
|
||
vec_push(&args, e1);
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
for (pos = 0; pos != ((gxScriptTable*)e->target)->scripts.size; ++pos)
|
||
{
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
if ((ret = arr_getByIndex(&((gxScriptTable*)e->target)->scripts, pos, (void**)&s, sizeof(gxScript))) != 0)
|
||
#else
|
||
if ((ret = arr_getByIndex(&((gxScriptTable*)e->target)->scripts, pos, (void**)&s)) != 0)
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
{
|
||
break;
|
||
}
|
||
if (s->id == id)
|
||
{
|
||
for (pos2 = 0; pos2 != s->actions.size; ++pos2)
|
||
{
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
if ((ret = arr_getByIndex(&s->actions, pos2, (void**)&sa, sizeof(gxScriptAction))) != 0)
|
||
#else
|
||
if ((ret = arr_getByIndex(&s->actions, pos2, (void**)&sa)) != 0)
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
{
|
||
break;
|
||
}
|
||
if (sa->type == DLMS_SCRIPT_ACTION_TYPE_WRITE)
|
||
{
|
||
e1->value = sa->parameter;
|
||
}
|
||
else
|
||
{
|
||
e1->parameters = sa->parameter;
|
||
}
|
||
e1->index = sa->index;
|
||
#ifndef DLMS_IGNORE_OBJECT_POINTERS
|
||
e1->target = sa->target;
|
||
#else
|
||
if ((ret = oa_findByLN(&settings->base.objects, sa->objectType, sa->logicalName, &e1->target)) != 0)
|
||
{
|
||
break;
|
||
}
|
||
if (e1->target == NULL)
|
||
{
|
||
ret = DLMS_ERROR_CODE_INCONSISTENT_CLASS_OR_OBJECT;
|
||
break;
|
||
}
|
||
#endif //DLMS_IGNORE_OBJECT_POINTERS
|
||
if (sa->type == DLMS_SCRIPT_ACTION_TYPE_WRITE)
|
||
{
|
||
svr_preWrite(&settings->base, &args);
|
||
if (e1->error != 0)
|
||
{
|
||
ret = e1->error;
|
||
}
|
||
else if (!e1->handled)
|
||
{
|
||
//Set action to true to indicate that this is called from the action method.
|
||
e1->action = 1;
|
||
if ((ret = cosem_setValue(&settings->base, e1)) != 0)
|
||
{
|
||
break;
|
||
}
|
||
svr_postWrite(&settings->base, &args);
|
||
if (e1->error != 0)
|
||
{
|
||
ret = e1->error;
|
||
}
|
||
}
|
||
}
|
||
else if (sa->type == DLMS_SCRIPT_ACTION_TYPE_EXECUTE)
|
||
{
|
||
svr_preAction(&settings->base, &args);
|
||
if (e1->error != 0)
|
||
{
|
||
ret = e1->error;
|
||
}
|
||
else if (!e1->handled)
|
||
{
|
||
if ((ret = cosem_invoke(settings, e1)) != 0)
|
||
{
|
||
break;
|
||
}
|
||
svr_postAction(&settings->base, &args);
|
||
if (e1->error != 0)
|
||
{
|
||
ret = e1->error;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ret = DLMS_ERROR_CODE_INCONSISTENT_CLASS_OR_OBJECT;
|
||
}
|
||
if (ret != 0)
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
vec_clear(&args);
|
||
}
|
||
else
|
||
{
|
||
ret = DLMS_ERROR_CODE_INCONSISTENT_CLASS_OR_OBJECT;
|
||
}
|
||
var_clear(&e->value);
|
||
return ret;
|
||
}
|
||
#endif //DLMS_IGNORE_SCRIPT_TABLE
|
||
|
||
#ifndef DLMS_IGNORE_ZIG_BEE_NETWORK_CONTROL
|
||
int invoke_zigbeeNetworkControl(gxZigBeeNetworkControl* object, unsigned char index, dlmsVARIANT* value)
|
||
{
|
||
int ret = 0, pos;
|
||
#ifndef DLMS_IGNORE_MALLOC
|
||
dlmsVARIANT* it;
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
gxActiveDevice* ad;
|
||
uint32_t v;
|
||
//Register device.
|
||
if (index == 1)
|
||
{
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
if ((ret = arr_getByIndex(&object->activeDevices, object->activeDevices.size, (void**)&ad, sizeof(gxActiveDevice))) == 0)
|
||
{
|
||
++object->activeDevices.size;
|
||
BYTE_BUFFER_INIT(&ad->macAddress);
|
||
if ((ret = cosem_getOctetString(value->byteArr, &ad->macAddress)) == 0 &&
|
||
(ret = cosem_getIntegerFromBitString(value->byteArr, &v)) == 0)
|
||
{
|
||
ad->status = (DLMS_ZIG_BEE_STATUS)v;
|
||
}
|
||
}
|
||
#else
|
||
if ((ret = va_getByIndex(value->Arr, 0, &it)) == 0)
|
||
{
|
||
ad = (gxActiveDevice*)gxcalloc(1, sizeof(gxActiveDevice));
|
||
BYTE_BUFFER_INIT(&ad->macAddress);
|
||
if ((ret = bb_set(&ad->macAddress, it->byteArr->data, it->byteArr->size)) == 0 &&
|
||
(ret = cosem_getIntegerFromBitString(it->byteArr, &v)) == 0)
|
||
{
|
||
ad->status = (DLMS_ZIG_BEE_STATUS)v;
|
||
arr_push(&object->activeDevices, ad);
|
||
}
|
||
else
|
||
{
|
||
gxfree(ad);
|
||
}
|
||
}
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
}
|
||
//Unregister device.
|
||
else if (index == 2)
|
||
{
|
||
for (pos = 0; pos != object->activeDevices.size; ++pos)
|
||
{
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
if ((ret = arr_getByIndex(&object->activeDevices, pos, (void**)&ad, sizeof(gxActiveDevice))) != 0)
|
||
{
|
||
break;
|
||
}
|
||
if (memcpy(&ad->macAddress, &value->byteArr, 8) == 0)
|
||
{
|
||
int pos2;
|
||
gxActiveDevice* ad2;
|
||
for (pos2 = pos + 1; pos2 < object->activeDevices.size; ++pos2)
|
||
{
|
||
if ((ret = arr_getByIndex(&object->activeDevices, pos2, (void**)&ad2, sizeof(gxActiveDevice))) != 0)
|
||
{
|
||
break;
|
||
}
|
||
memcpy(ad, ad2, sizeof(gxActiveDevice));
|
||
ad = ad2;
|
||
}
|
||
--object->activeDevices.size;
|
||
break;
|
||
}
|
||
#else
|
||
ret = arr_getByIndex(&object->activeDevices, pos, (void**)&ad);
|
||
if (ret != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
if (memcpy(&ad->macAddress, &value->byteArr, 8) == 0)
|
||
{
|
||
ret = arr_removeByIndex(&object->activeDevices, pos, (void**)&ad);
|
||
if (ret != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
gxfree(ad);
|
||
break;
|
||
}
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
}
|
||
}
|
||
//Unregister all device.
|
||
else if (index == 3)
|
||
{
|
||
ret = obj_clearActiveDevices(&object->activeDevices);
|
||
}
|
||
//backup PAN
|
||
else if (index == 4)
|
||
{
|
||
}
|
||
//Restore PAN,
|
||
else if (index == 5)
|
||
{
|
||
// This method instructs the coordinator to restore a PAN using backup information.
|
||
// The storage location of the back-up is not currently defined and is an internal function
|
||
// of the DLMS/COSEM Server.
|
||
}
|
||
else
|
||
{
|
||
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
|
||
}
|
||
return ret;
|
||
}
|
||
#endif //DLMS_IGNORE_ZIG_BEE_NETWORK_CONTROL
|
||
#ifndef DLMS_IGNORE_EXTENDED_REGISTER
|
||
int invoke_ExtendedRegister(
|
||
dlmsServerSettings* settings,
|
||
gxExtendedRegister* object,
|
||
unsigned char index)
|
||
{
|
||
int ret = 0;
|
||
//Reset.
|
||
if (index == 1)
|
||
{
|
||
ret = var_clear(&object->value);
|
||
if (ret != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
if (settings->defaultClock != NULL)
|
||
{
|
||
object->captureTime = settings->defaultClock->time;
|
||
}
|
||
else
|
||
{
|
||
time_clear(&object->captureTime);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
|
||
}
|
||
return ret;
|
||
}
|
||
#endif //DLMS_IGNORE_EXTENDED_REGISTER
|
||
|
||
#ifndef DLMS_IGNORE_DEMAND_REGISTER
|
||
int invoke_DemandRegister(
|
||
dlmsServerSettings* settings,
|
||
gxDemandRegister* object,
|
||
unsigned char index)
|
||
{
|
||
int ret = 0;
|
||
//Reset.
|
||
if (index == 1)
|
||
{
|
||
if ((ret = var_clear(&object->currentAverageValue)) != 0 ||
|
||
(ret = var_clear(&object->lastAverageValue)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
if (settings->defaultClock != NULL)
|
||
{
|
||
object->startTimeCurrent = object->captureTime = settings->defaultClock->time;
|
||
}
|
||
else
|
||
{
|
||
time_clear(&object->captureTime);
|
||
time_clear(&object->startTimeCurrent);
|
||
}
|
||
}
|
||
else if (index == 1)
|
||
{
|
||
if ((ret = var_copy(&object->lastAverageValue, &object->currentAverageValue)) != 0 ||
|
||
(ret = var_clear(&object->currentAverageValue)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
if (settings->defaultClock != NULL)
|
||
{
|
||
object->startTimeCurrent = object->captureTime = settings->defaultClock->time;
|
||
}
|
||
else
|
||
{
|
||
time_clear(&object->captureTime);
|
||
time_clear(&object->startTimeCurrent);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
|
||
}
|
||
return ret;
|
||
}
|
||
#endif //DLMS_IGNORE_DEMAND_REGISTER
|
||
|
||
|
||
#ifndef DLMS_IGNORE_CLOCK
|
||
int invoke_Clock(gxClock* object, unsigned char index, dlmsVARIANT* value)
|
||
{
|
||
int ret = 0;
|
||
#ifndef DLMS_IGNORE_MALLOC
|
||
dlmsVARIANT* it;
|
||
dlmsVARIANT tmp;
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
// Resets the value to the default value.
|
||
// The default value is an instance specific constant.
|
||
if (index == 1)
|
||
{
|
||
#ifdef DLMS_USE_EPOCH_TIME
|
||
int minutes = time_getMinutes(&object->time);
|
||
#else
|
||
int minutes = object->time.value.tm_min;
|
||
#endif // DLMS_USE_EPOCH_TIME
|
||
if (minutes < 8)
|
||
{
|
||
minutes = 0;
|
||
}
|
||
else if (minutes < 23)
|
||
{
|
||
minutes = 15;
|
||
}
|
||
else if (minutes < 38)
|
||
{
|
||
minutes = 30;
|
||
}
|
||
else if (minutes < 53)
|
||
{
|
||
minutes = 45;
|
||
}
|
||
else
|
||
{
|
||
minutes = 0;
|
||
time_addHours(&object->time, 1);
|
||
}
|
||
#ifdef DLMS_USE_EPOCH_TIME
|
||
time_addTime(&object->time, 0, -time_getMinutes(&object->time) + minutes, -time_getSeconds(&object->time));
|
||
#else
|
||
time_addTime(&object->time, 0, -object->time.value.tm_min + minutes, -object->time.value.tm_sec);
|
||
#endif // DLMS_USE_EPOCH_TIME
|
||
}
|
||
// Sets the meter's time to the nearest minute.
|
||
else if (index == 3)
|
||
{
|
||
#ifdef DLMS_USE_EPOCH_TIME
|
||
int s = time_getSeconds(&object->time);
|
||
#else
|
||
int s = object->time.value.tm_sec;
|
||
#endif // DLMS_USE_EPOCH_TIME
|
||
if (s > 30)
|
||
{
|
||
time_addTime(&object->time, 0, 1, 0);
|
||
}
|
||
time_addTime(&object->time, 0, 0, -s);
|
||
}
|
||
//Adjust to preset time.
|
||
else if (index == 4)
|
||
{
|
||
object->time = object->presetTime;
|
||
}
|
||
// Presets the time to a new value (preset_time) and defines
|
||
// avalidity_interval within which the new time can be activated.
|
||
else if (index == 5)
|
||
{
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
ret = cosem_getDateFromOctetString(value->byteArr, &object->presetTime);
|
||
#else
|
||
ret = var_init(&tmp);
|
||
if (ret != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
ret = va_getByIndex(value->Arr, 0, &it);
|
||
if (ret != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
ret = dlms_changeType2(it, DLMS_DATA_TYPE_DATETIME, &tmp);
|
||
if (ret != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
object->presetTime = *tmp.dateTime;
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
}
|
||
// Shifts the time.
|
||
else if (index == 6)
|
||
{
|
||
time_addTime(&object->time, 0, 0, var_toInteger(value));
|
||
}
|
||
else
|
||
{
|
||
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
|
||
}
|
||
return ret;
|
||
}
|
||
#endif //DLMS_IGNORE_CLOCK
|
||
#ifndef DLMS_IGNORE_REGISTER
|
||
int invoke_Register(
|
||
gxRegister* object,
|
||
gxValueEventArg* e)
|
||
{
|
||
int ret = 0;
|
||
//Reset.
|
||
if (e->index == 1)
|
||
{
|
||
ret = var_clear(&object->value);
|
||
}
|
||
else
|
||
{
|
||
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
|
||
}
|
||
return ret;
|
||
}
|
||
#endif //DLMS_IGNORE_REGISTER
|
||
|
||
#ifndef DLMS_IGNORE_PROFILE_GENERIC
|
||
/*
|
||
* Copies the values of the objects to capture into the buffer by reading
|
||
* capture objects.
|
||
*/
|
||
int capture(dlmsSettings* settings,
|
||
gxProfileGeneric* object)
|
||
{
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
gxValueEventArg e;
|
||
gxValueEventCollection args;
|
||
ve_init(&e);
|
||
e.action = 1;
|
||
e.target = &object->base;
|
||
e.index = 2;
|
||
gxValueEventArg p[1] = { e };
|
||
vec_attach(&args, p, 1, 1);
|
||
svr_preGet(settings, &args);
|
||
svr_postGet(settings, &args);
|
||
vec_empty(&args);
|
||
#else
|
||
int ret, pos;
|
||
gxKey* kv;
|
||
dlmsVARIANT* value;
|
||
variantArray* row;
|
||
gxValueEventArg e;
|
||
gxValueEventCollection args;
|
||
ve_init(&e);
|
||
e.action = 1;
|
||
e.target = &object->base;
|
||
e.index = 2;
|
||
vec_init(&args);
|
||
vec_push(&args, &e);
|
||
svr_preGet(settings, &args);
|
||
if (!e.handled)
|
||
{
|
||
gxValueEventArg e2;
|
||
ve_init(&e2);
|
||
row = (variantArray*)gxmalloc(sizeof(variantArray));
|
||
va_init(row);
|
||
for (pos = 0; pos != object->captureObjects.size; ++pos)
|
||
{
|
||
ret = arr_getByIndex(&object->captureObjects, pos, (void**)&kv);
|
||
if (ret != DLMS_ERROR_CODE_OK)
|
||
{
|
||
return ret;
|
||
}
|
||
e2.target = (gxObject*)kv->key;
|
||
e2.index = ((gxTarget*)kv->value)->attributeIndex;
|
||
if ((ret = cosem_getData(&e2)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
value = (dlmsVARIANT*)gxmalloc(sizeof(dlmsVARIANT));
|
||
var_init(value);
|
||
var_copy(value, &e.value);
|
||
va_push(row, value);
|
||
}
|
||
// Remove first item if buffer is full.
|
||
if (object->profileEntries == object->buffer.size)
|
||
{
|
||
variantArray* removedRow;
|
||
arr_removeByIndex(&object->buffer, 0, (void**)&removedRow);
|
||
va_clear(removedRow);
|
||
}
|
||
arr_push(&object->buffer, row);
|
||
object->entriesInUse = object->buffer.size;
|
||
}
|
||
svr_postGet(settings, &args);
|
||
vec_empty(&args);
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
return 0;
|
||
}
|
||
|
||
int invoke_ProfileGeneric(
|
||
dlmsServerSettings* settings,
|
||
gxProfileGeneric* object,
|
||
unsigned char index)
|
||
{
|
||
int ret = 0;
|
||
//Reset.
|
||
if (index == 1)
|
||
{
|
||
#ifndef DLMS_IGNORE_MALLOC
|
||
ret = obj_clearProfileGenericBuffer(&object->buffer);
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
}
|
||
//Capture.
|
||
else if (index == 2)
|
||
{
|
||
// Capture.
|
||
ret = capture(&settings->base, object);
|
||
}
|
||
else
|
||
{
|
||
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
|
||
}
|
||
return ret;
|
||
}
|
||
#endif //DLMS_IGNORE_PROFILE_GENERIC
|
||
|
||
|
||
#ifndef DLMS_IGNORE_COMPACT_DATA
|
||
int compactDataAppend(unsigned char byteArray, dlmsVARIANT* value3, gxByteBuffer* bb)
|
||
{
|
||
if (byteArray && value3->vt == DLMS_DATA_TYPE_OCTET_STRING)
|
||
{
|
||
if (bb_size(value3->byteArr) == 1)
|
||
{
|
||
bb_setUInt8(bb, 0);
|
||
}
|
||
else
|
||
{
|
||
bb_set(bb, value3->byteArr->data + 1, value3->byteArr->size - 1);
|
||
}
|
||
return 0;
|
||
}
|
||
int ret;
|
||
uint16_t startPos = (uint16_t)bb->size;
|
||
if ((ret = dlms_setData(bb, value3->vt, value3)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
//If data is empty.
|
||
if (bb->size - startPos == 1)
|
||
{
|
||
bb_setUInt8(bb, 0);
|
||
}
|
||
else
|
||
{
|
||
ret = bb_move(bb, startPos + 1, startPos, bb->size - startPos - 1);
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
int compactDataAppendArray(dlmsVARIANT* value, gxByteBuffer* bb, uint16_t dataIndex)
|
||
{
|
||
int ret, pos;
|
||
int cnt = value->Arr->size;
|
||
if (dataIndex != 0)
|
||
{
|
||
cnt = dataIndex;
|
||
--dataIndex;
|
||
}
|
||
dlmsVARIANT* value2;
|
||
for (pos = dataIndex; pos != cnt; ++pos)
|
||
{
|
||
if ((ret = va_getByIndex(value->Arr, pos, &value2)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
if (value2->vt == DLMS_DATA_TYPE_STRUCTURE)
|
||
{
|
||
dlmsVARIANT* value3;
|
||
int pos1;
|
||
for (pos1 = 0; pos1 != value2->Arr->size; ++pos1)
|
||
{
|
||
if ((ret = va_getByIndex(value2->Arr, pos1, &value3)) != 0 ||
|
||
(ret = compactDataAppend(0, value3, bb)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ((ret = compactDataAppend(0, value2, bb)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
* Copies the values of the objects to capture into the buffer by reading
|
||
* capture objects.
|
||
*/
|
||
int cosem_captureCompactData(
|
||
dlmsSettings* settings,
|
||
gxCompactData* object)
|
||
{
|
||
int ret = 0;
|
||
uint16_t pos;
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
gxTarget* kv;
|
||
#else
|
||
gxKey* kv;
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
gxValueEventArg e;
|
||
gxValueEventCollection args;
|
||
bb_clear(&object->buffer);
|
||
ve_init(&e);
|
||
e.action = 1;
|
||
e.target = &object->base;
|
||
e.index = 2;
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
//Allocate space where captured values are saved before they are added to the buffer.
|
||
// We can't use server buffer because there might be transaction on progress when this is called.
|
||
unsigned char tmp[MAX_CAPTURE_OBJECT_BUFFER_SIZE];
|
||
gxByteBuffer bb;
|
||
bb_attach(&bb, tmp, 0, sizeof(tmp));
|
||
gxValueEventArg p[1] = { e };
|
||
vec_attach(&args, p, 1, 1);
|
||
#else
|
||
vec_init(&args);
|
||
vec_push(&args, &e);
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
svr_preGet(settings, &args);
|
||
if (!e.handled)
|
||
{
|
||
uint16_t dataIndex;
|
||
for (pos = 0; pos != object->captureObjects.size; ++pos)
|
||
{
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
ret = arr_getByIndex(&object->captureObjects, pos, (void**)&kv, sizeof(gxTarget));
|
||
#else
|
||
ret = arr_getByIndex(&object->captureObjects, pos, (void**)&kv);
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
if (ret != DLMS_ERROR_CODE_OK)
|
||
{
|
||
bb_clear(&object->buffer);
|
||
break;
|
||
}
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
e.value.byteArr = &bb;
|
||
e.value.vt = DLMS_DATA_TYPE_OCTET_STRING;
|
||
e.target = kv->target;
|
||
e.index = kv->attributeIndex;
|
||
dataIndex = kv->dataIndex;
|
||
#else
|
||
e.target = (gxObject*)kv->key;
|
||
e.index = ((gxTarget*)kv->value)->attributeIndex;
|
||
dataIndex = ((gxTarget*)kv->value)->dataIndex;
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
if ((ret = cosem_getValue(settings, &e)) != 0)
|
||
{
|
||
bb_clear(&object->buffer);
|
||
break;
|
||
}
|
||
if (e.byteArray && e.value.vt == DLMS_DATA_TYPE_OCTET_STRING)
|
||
{
|
||
gxDataInfo info;
|
||
dlmsVARIANT value;
|
||
di_init(&info);
|
||
var_init(&value);
|
||
if ((ret = dlms_getData(e.value.byteArr, &info, &value)) != 0)
|
||
{
|
||
var_clear(&value);
|
||
break;
|
||
}
|
||
if (value.vt == DLMS_DATA_TYPE_STRUCTURE ||
|
||
value.vt == DLMS_DATA_TYPE_ARRAY)
|
||
{
|
||
#ifdef DLMS_ITALIAN_STANDARD
|
||
//Some meters require that there is a array count in data.
|
||
if (value.vt == DLMS_DATA_TYPE_ARRAY && object->appendAA)
|
||
{
|
||
bb_setUInt8(&object->buffer, (unsigned char)value.Arr->size);
|
||
}
|
||
#endif //DLMS_ITALIAN_STANDARD
|
||
if ((ret = compactDataAppendArray(&value, &object->buffer, dataIndex)) != 0)
|
||
{
|
||
var_clear(&value);
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ((ret = compactDataAppend(1, &e.value, &object->buffer)) != 0)
|
||
{
|
||
var_clear(&value);
|
||
break;
|
||
}
|
||
}
|
||
var_clear(&value);
|
||
}
|
||
else if ((ret = compactDataAppend(0, &e.value, &object->buffer)) != 0)
|
||
{
|
||
break;
|
||
}
|
||
ve_clear(&e);
|
||
}
|
||
}
|
||
svr_postGet(settings, &args);
|
||
if (ret != 0)
|
||
{
|
||
bb_clear(&object->buffer);
|
||
}
|
||
vec_empty(&args);
|
||
return ret;
|
||
}
|
||
|
||
int invoke_CompactData(
|
||
dlmsServerSettings* settings,
|
||
gxCompactData* object,
|
||
unsigned char index)
|
||
{
|
||
int ret = 0;
|
||
//Reset.
|
||
if (index == 1)
|
||
{
|
||
ret = bb_clear(&object->buffer);
|
||
}
|
||
//Capture.
|
||
else if (index == 2)
|
||
{
|
||
// Capture.
|
||
ret = cosem_captureCompactData(&settings->base, object);
|
||
}
|
||
else
|
||
{
|
||
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
|
||
}
|
||
return ret;
|
||
}
|
||
#endif //DLMS_IGNORE_COMPACT_DATA
|
||
|
||
#ifndef DLMS_IGNORE_DISCONNECT_CONTROL
|
||
int invoke_DisconnectControl(
|
||
dlmsServerSettings* settings,
|
||
gxDisconnectControl* object,
|
||
unsigned char index)
|
||
{
|
||
int ret = 0;
|
||
//Reset.
|
||
if (index == 1)
|
||
{
|
||
object->controlState = DLMS_CONTROL_STATE_DISCONNECTED;
|
||
object->outputState = 0;
|
||
}
|
||
//Capture.
|
||
else if (index == 2)
|
||
{
|
||
object->controlState = DLMS_CONTROL_STATE_CONNECTED;
|
||
object->outputState = 1;
|
||
}
|
||
else
|
||
{
|
||
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
|
||
}
|
||
return ret;
|
||
}
|
||
#endif //DLMS_IGNORE_DISCONNECT_CONTROL
|
||
|
||
#ifndef DLMS_IGNORE_LLC_SSCS_SETUP
|
||
int invoke_LlcSscsSetup(
|
||
gxLlcSscsSetup* object,
|
||
unsigned char index)
|
||
{
|
||
int ret = 0;
|
||
//Reset.
|
||
if (index == 1)
|
||
{
|
||
object->serviceNodeAddress = 0xFFE;
|
||
object->baseNodeAddress = 0;
|
||
}
|
||
else
|
||
{
|
||
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
|
||
}
|
||
return ret;
|
||
}
|
||
#endif //DLMS_IGNORE_LLC_SSCS_SETUP
|
||
|
||
#ifndef DLMS_IGNORE_PRIME_NB_OFDM_PLC_PHYSICAL_LAYER_COUNTERS
|
||
int invoke_PrimeNbOfdmPlcPhysicalLayerCounters(
|
||
gxPrimeNbOfdmPlcPhysicalLayerCounters* object,
|
||
unsigned char index)
|
||
{
|
||
int ret = 0;
|
||
//Reset.
|
||
if (index == 1)
|
||
{
|
||
object->crcIncorrectCount = object->crcFailedCount = object->txDropCount = object->rxDropCount = 0;
|
||
}
|
||
else
|
||
{
|
||
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
|
||
}
|
||
return ret;
|
||
}
|
||
#endif //DLMS_IGNORE_PRIME_NB_OFDM_PLC_PHYSICAL_LAYER_COUNTERS
|
||
|
||
#ifndef DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_COUNTERS
|
||
int invoke_PrimeNbOfdmPlcMacCounters(
|
||
gxPrimeNbOfdmPlcMacCounters* object,
|
||
unsigned char index)
|
||
{
|
||
int ret = 0;
|
||
//Reset.
|
||
if (index == 1)
|
||
{
|
||
object->txDataPktCount = object->rxDataPktCount = object->txCtrlPktCount = object->rxCtrlPktCount = object->csmaFailCount = object->csmaChBusyCount = 0;
|
||
}
|
||
else
|
||
{
|
||
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
|
||
}
|
||
return ret;
|
||
}
|
||
#endif //DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_COUNTERS
|
||
|
||
#ifndef DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_NETWORK_ADMINISTRATION_DATA
|
||
int invoke_PrimeNbOfdmPlcMacNetworkAdministrationData(
|
||
gxPrimeNbOfdmPlcMacNetworkAdministrationData* object,
|
||
unsigned char index)
|
||
{
|
||
int ret = 0;
|
||
//Reset.
|
||
if (index == 1)
|
||
{
|
||
arr_clear(&object->multicastEntries);
|
||
arr_empty(&object->switchTable);
|
||
arr_clear(&object->directTable);
|
||
obj_clearAvailableSwitches(&object->availableSwitches);
|
||
arr_clear(&object->communications);
|
||
}
|
||
else
|
||
{
|
||
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
|
||
}
|
||
return ret;
|
||
}
|
||
#endif //DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_NETWORK_ADMINISTRATION_DATA
|
||
|
||
#ifndef DLMS_IGNORE_SPECIAL_DAYS_TABLE
|
||
int invoke_SpecialDaysTable(
|
||
gxSpecialDaysTable* object,
|
||
gxValueEventArg* e)
|
||
{
|
||
int ret = 0;
|
||
uint16_t pos, index;
|
||
gxSpecialDay* specialDay;
|
||
//Insert.
|
||
if (e->index == 1)
|
||
{
|
||
unsigned char append = 1;
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
if ((ret = cosem_checkStructure(e->parameters.byteArr, 3)) == 0 &&
|
||
(ret = cosem_getUInt16(e->parameters.byteArr, &index)) == 0)
|
||
{
|
||
for (pos = 0; pos != object->entries.size; ++pos)
|
||
{
|
||
if ((ret = arr_getByIndex(&object->entries, object->entries.size - 1, (void**)&specialDay, sizeof(gxSpecialDay))) != 0)
|
||
{
|
||
break;
|
||
}
|
||
//Overwrite existing item.
|
||
if (specialDay->index == index)
|
||
{
|
||
if ((ret = cosem_getDateFromOctetString(e->parameters.byteArr, &specialDay->date)) != 0 ||
|
||
(ret = cosem_getUInt8(e->parameters.byteArr, &specialDay->dayId)) != 0)
|
||
{
|
||
}
|
||
append = 0;
|
||
break;
|
||
}
|
||
}
|
||
if (ret == 0 && append)
|
||
{
|
||
++object->entries.size;
|
||
if ((ret = arr_getByIndex(&object->entries, object->entries.size - 1, (void**)&specialDay, sizeof(gxSpecialDay))) != 0)
|
||
{
|
||
--object->entries.size;
|
||
}
|
||
else
|
||
{
|
||
specialDay->index = index;
|
||
if ((ret = cosem_getDateFromOctetString(e->parameters.byteArr, &specialDay->date)) != 0 ||
|
||
(ret = cosem_getUInt8(e->parameters.byteArr, &specialDay->dayId)) != 0)
|
||
{
|
||
}
|
||
}
|
||
}
|
||
}
|
||
#else
|
||
dlmsVARIANT* tmp3;
|
||
dlmsVARIANT tmp2;
|
||
if (e->parameters.Arr != NULL)
|
||
{
|
||
ret = va_getByIndex(e->parameters.Arr, 0, &tmp3);
|
||
if (ret != DLMS_ERROR_CODE_OK)
|
||
{
|
||
return ret;
|
||
}
|
||
index = (uint16_t)var_toInteger(tmp3);
|
||
for (pos = 0; pos != object->entries.size; ++pos)
|
||
{
|
||
if ((ret = arr_getByIndex(&object->entries, object->entries.size - 1, (void**)&specialDay)) != 0)
|
||
{
|
||
break;
|
||
}
|
||
//Overwrite existing item.
|
||
if (specialDay->index == index)
|
||
{
|
||
append = 0;
|
||
break;
|
||
}
|
||
}
|
||
if (append)
|
||
{
|
||
specialDay = (gxSpecialDay*)gxmalloc(sizeof(gxSpecialDay));
|
||
if (specialDay == NULL)
|
||
{
|
||
return DLMS_ERROR_CODE_OUTOFMEMORY;
|
||
}
|
||
arr_push(&object->entries, specialDay);
|
||
}
|
||
specialDay->index = index;
|
||
ret = va_getByIndex(e->parameters.Arr, 1, &tmp3);
|
||
if (ret != DLMS_ERROR_CODE_OK)
|
||
{
|
||
return ret;
|
||
}
|
||
var_init(&tmp2);
|
||
ret = dlms_changeType2(tmp3, DLMS_DATA_TYPE_DATE, &tmp2);
|
||
if (ret != DLMS_ERROR_CODE_OK)
|
||
{
|
||
return ret;
|
||
}
|
||
time_copy(&specialDay->date, tmp2.dateTime);
|
||
var_clear(&tmp2);
|
||
ret = va_getByIndex(e->parameters.Arr, 2, &tmp3);
|
||
if (ret != DLMS_ERROR_CODE_OK)
|
||
{
|
||
return ret;
|
||
}
|
||
specialDay->dayId = (unsigned char)var_toInteger(tmp3);
|
||
}
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
}
|
||
//Remove.
|
||
else if (e->index == 2)
|
||
{
|
||
uint16_t pos, index = e->parameters.uiVal;
|
||
for (pos = 0; pos != object->entries.size; ++pos)
|
||
{
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
if ((ret = arr_getByIndex(&object->entries, pos, (void**)&specialDay, sizeof(gxSpecialDay))) != 0)
|
||
#else
|
||
if ((ret = arr_getByIndex(&object->entries, pos, (void**)&specialDay)) != 0)
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
{
|
||
break;
|
||
}
|
||
if (specialDay->index == index)
|
||
{
|
||
//Remove item.
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
ret = arr_removeByIndex(&object->entries, pos, sizeof(gxSpecialDay));
|
||
#else
|
||
ret = arr_removeByIndex(&object->entries, pos, NULL);
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
|
||
}
|
||
return ret;
|
||
}
|
||
#endif //DLMS_IGNORE_SPECIAL_DAYS_TABLE
|
||
|
||
#ifndef DLMS_IGNORE_REGISTER_ACTIVATION
|
||
int invoke_RegisterActivation(
|
||
dlmsServerSettings* settings,
|
||
gxRegisterActivation* object,
|
||
gxValueEventArg* e)
|
||
{
|
||
int ret = 0;
|
||
uint16_t count;
|
||
gxRegisterActivationMask* k;
|
||
uint16_t pos;
|
||
#ifdef DLMS_IGNORE_OBJECT_POINTERS
|
||
gxObjectDefinition* it;
|
||
#else
|
||
gxObject* it;
|
||
#endif //DLMS_IGNORE_OBJECT_POINTERS
|
||
//Add Register.
|
||
if (e->index == 1)
|
||
{
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
uint16_t ot;
|
||
unsigned char ln[6];
|
||
#if !(defined(DLMS_IGNORE_OBJECT_POINTERS) || defined(DLMS_IGNORE_MALLOC))
|
||
uint16_t count = oa_getCapacity(&object->registerAssignment);
|
||
#else
|
||
count = arr_getCapacity(&object->registerAssignment);
|
||
if (!(object->registerAssignment.size < count))
|
||
{
|
||
return DLMS_ERROR_CODE_OUTOFMEMORY;
|
||
}
|
||
#endif //!(defined(DLMS_IGNORE_OBJECT_POINTERS) || defined(DLMS_IGNORE_MALLOC))
|
||
if ((ret = cosem_checkStructure(e->parameters.byteArr, 2)) != 0 ||
|
||
#ifndef DLMS_IGNORE_OBJECT_POINTERS
|
||
(ret = cosem_getUInt16(e->parameters.byteArr, &ot)) != 0 ||
|
||
(ret = cosem_getOctetString2(e->parameters.byteArr, ln, 6, NULL)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
if ((ret = oa_findByLN(&settings->base.objects, (DLMS_OBJECT_TYPE)ot, ln, &it)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
if (it == NULL)
|
||
{
|
||
return DLMS_ERROR_CODE_OUTOFMEMORY;
|
||
}
|
||
if ((ret = arr_setByIndexRef(&object->registerAssignment, (void**)it)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
#endif //DLMS_IGNORE_OBJECT_POINTERS
|
||
#else
|
||
dlmsVARIANT* tmp, * tmp3;
|
||
if (e->parameters.Arr != NULL)
|
||
{
|
||
short type;
|
||
ret = va_getByIndex(e->parameters.Arr, 0, &tmp);
|
||
if (ret != DLMS_ERROR_CODE_OK)
|
||
{
|
||
return ret;
|
||
}
|
||
ret = va_getByIndex(tmp->Arr, 0, &tmp3);
|
||
if (ret != DLMS_ERROR_CODE_OK)
|
||
{
|
||
return ret;
|
||
}
|
||
type = var_toInteger(tmp3);
|
||
ret = va_getByIndex(tmp->Arr, 1, &tmp3);
|
||
if (ret != DLMS_ERROR_CODE_OK)
|
||
{
|
||
return ret;
|
||
}
|
||
const unsigned char* ln = tmp3->byteArr->data;
|
||
#ifdef DLMS_IGNORE_OBJECT_POINTERS
|
||
it = (gxObjectDefinition*)gxmalloc(sizeof(gxObjectDefinition));
|
||
it->objectType = (DLMS_OBJECT_TYPE)type;
|
||
memcpy(it->logicalName, ln, 6);
|
||
#else
|
||
if ((ret = oa_findByLN(&settings->base.objects, type, ln, &it)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
if (it == NULL)
|
||
{
|
||
return DLMS_ERROR_CODE_OUTOFMEMORY;
|
||
}
|
||
#endif //DLMS_IGNORE_OBJECT_POINTERS
|
||
#if !defined(DLMS_IGNORE_OBJECT_POINTERS) && !defined(DLMS_COSEM_EXACT_DATA_TYPES)
|
||
oa_push(&object->registerAssignment, it);
|
||
#else
|
||
arr_push(&object->registerAssignment, it);
|
||
#endif //DLMS_IGNORE_OBJECT_POINTERS
|
||
}
|
||
#ifdef DLMS_IGNORE_OBJECT_POINTERS
|
||
if (ret != 0 && objectDefinition != NULL)
|
||
{
|
||
gxfree(objectDefinition);
|
||
}
|
||
#endif //DLMS_IGNORE_OBJECT_POINTERS
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
}
|
||
else if (e->index == 2)
|
||
{
|
||
count = arr_getCapacity(&object->maskList);
|
||
if (!(object->registerAssignment.size < count))
|
||
{
|
||
return DLMS_ERROR_CODE_OUTOFMEMORY;
|
||
}
|
||
++object->maskList.size;
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
uint16_t size;
|
||
if ((ret = cosem_checkStructure(e->parameters.byteArr, 2)) == 0 &&
|
||
(ret = arr_getByIndex(&object->maskList, object->maskList.size - 1, (void**)&k, sizeof(gxRegisterActivationMask))) == 0 &&
|
||
(ret = cosem_getOctetString2(e->parameters.byteArr, k->name, sizeof(k->name), &size)) == 0)
|
||
{
|
||
k->length = (unsigned char)size;
|
||
size = sizeof(k->indexes);
|
||
if ((ret = cosem_checkArray(e->parameters.byteArr, &size)) == 0)
|
||
{
|
||
k->count = (unsigned char)size;
|
||
for (pos = 0; pos != k->count; ++pos)
|
||
{
|
||
if ((ret = cosem_getUInt8(e->parameters.byteArr, &k->indexes[pos])) != 0)
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
#else
|
||
#endif //DLMS_IGNORE_OBJECT_POINTERS
|
||
}
|
||
//Remove mask.
|
||
else if (e->index == 3)
|
||
{
|
||
unsigned char ch;
|
||
if ((ret = bb_getUInt8(e->parameters.byteArr, &ch)) == 0)
|
||
{
|
||
if (ch != DLMS_DATA_TYPE_OCTET_STRING)
|
||
{
|
||
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
|
||
}
|
||
else
|
||
{
|
||
uint16_t count;
|
||
if ((ret = hlp_getObjectCount2(e->parameters.byteArr, &count)) == 0)
|
||
{
|
||
for (pos = 0; pos != object->maskList.size; ++pos)
|
||
{
|
||
if ((ret = arr_getByIndex2(&object->maskList, pos, (void**)&k, sizeof(gxRegisterActivationMask))) != 0)
|
||
{
|
||
break;
|
||
}
|
||
#if defined(DLMS_IGNORE_MALLOC)
|
||
if (bb_available(e->parameters.byteArr) == k->length &&
|
||
memcmp(k->name, e->parameters.byteArr->data + e->parameters.byteArr->position, count) == 0)
|
||
{
|
||
//arr_removeByIndex is decreasing amount already.
|
||
ret = arr_removeByIndex(&object->maskList, pos, sizeof(gxRegisterActivationMask));
|
||
break;
|
||
}
|
||
#else
|
||
if (bb_available(e->parameters.byteArr) == k->name.size &&
|
||
memcmp(k->name.data, e->parameters.byteArr->data + e->parameters.byteArr->position, count) == 0)
|
||
{
|
||
//arr_removeByIndex is decreasing amount already.
|
||
if ((ret = arr_removeByIndex(&object->maskList, pos, (void**)&k)) == 0)
|
||
{
|
||
bb_clear(&k->name);
|
||
bb_clear(&k->indexes);
|
||
gxfree(k);
|
||
}
|
||
break;
|
||
}
|
||
#endif //defined(DLMS_IGNORE_MALLOC)
|
||
e->parameters.byteArr->position += count;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
bb_clear(e->parameters.byteArr);
|
||
}
|
||
else
|
||
{
|
||
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
|
||
}
|
||
return ret;
|
||
}
|
||
#endif //DLMS_IGNORE_REGISTER_ACTIVATION
|
||
|
||
|
||
#ifndef DLMS_IGNORE_ACTIVITY_CALENDAR
|
||
|
||
int invoke_copySeasonProfile(gxArray* target, gxArray* source)
|
||
{
|
||
int ret = obj_clearSeasonProfile(target);
|
||
if (ret == 0)
|
||
{
|
||
int pos;
|
||
gxSeasonProfile* sp, * it;
|
||
#if defined(DLMS_IGNORE_MALLOC)
|
||
target->size = source->size;
|
||
#endif //
|
||
for (pos = 0; pos != source->size; ++pos)
|
||
{
|
||
if (ret == 0)
|
||
{
|
||
if ((ret = arr_getByIndex2(source, pos, (void**)&sp, sizeof(gxSeasonProfile))) != 0)
|
||
{
|
||
break;
|
||
}
|
||
#if defined(DLMS_IGNORE_MALLOC)
|
||
if ((ret = arr_getByIndex2(target, pos, (void**)&it, sizeof(gxSeasonProfile))) != 0)
|
||
{
|
||
break;
|
||
}
|
||
memcpy(&it->name, &sp->name, sizeof(gxSeasonProfileName));
|
||
it->start = sp->start;
|
||
memcpy(&it->weekName, &sp->weekName, sizeof(gxSeasonProfileWeekName));
|
||
#else
|
||
it = gxmalloc(sizeof(gxSeasonProfile));
|
||
arr_push(target, it);
|
||
BYTE_BUFFER_INIT(&it->name);
|
||
BYTE_BUFFER_INIT(&it->weekName);
|
||
bb_set(&it->name, sp->name.data, sp->name.size);
|
||
it->start = sp->start;
|
||
bb_set(&it->weekName, sp->weekName.data, sp->weekName.size);
|
||
#endif //#if defined(DLMS_IGNORE_MALLOC)
|
||
}
|
||
}
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
int invoke_copyWeekProfileTable(gxArray* target, gxArray* source)
|
||
{
|
||
int ret = obj_clearWeekProfileTable(target);
|
||
if (ret == 0)
|
||
{
|
||
int pos;
|
||
gxWeekProfile* wp, * it;
|
||
#if defined(DLMS_IGNORE_MALLOC)
|
||
target->size = source->size;
|
||
#endif //
|
||
for (pos = 0; pos != source->size; ++pos)
|
||
{
|
||
if (ret == 0)
|
||
{
|
||
if ((ret = arr_getByIndex2(source, pos, (void**)&wp, sizeof(gxWeekProfile))) != 0)
|
||
{
|
||
break;
|
||
}
|
||
#if defined(DLMS_IGNORE_MALLOC)
|
||
if ((ret = arr_getByIndex2(target, pos, (void**)&it, sizeof(gxWeekProfile))) != 0)
|
||
{
|
||
break;
|
||
}
|
||
memcpy(&it->name, &wp->name, sizeof(gxWeekProfileName));
|
||
#else
|
||
it = gxmalloc(sizeof(gxWeekProfile));
|
||
arr_push(target, it);
|
||
BYTE_BUFFER_INIT(&it->name);
|
||
bb_set(&it->name, wp->name.data, wp->name.size);
|
||
#endif //#if defined(DLMS_IGNORE_MALLOC)
|
||
it->monday = wp->monday;
|
||
it->tuesday = wp->tuesday;
|
||
it->wednesday = wp->wednesday;
|
||
it->thursday = wp->thursday;
|
||
it->friday = wp->friday;
|
||
it->saturday = wp->saturday;
|
||
it->sunday = wp->sunday;
|
||
}
|
||
}
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
int invoke_copyDayProfileTable(gxArray* target, gxArray* source)
|
||
{
|
||
int ret = obj_clearDayProfileTable(target);
|
||
if (ret == 0)
|
||
{
|
||
int pos, pos2;
|
||
gxDayProfile* it, * it2;
|
||
gxDayProfileAction* dp, * dp2;
|
||
#if defined(DLMS_IGNORE_MALLOC)
|
||
target->size = source->size;
|
||
#endif //
|
||
for (pos = 0; pos != source->size; ++pos)
|
||
{
|
||
if (ret == 0)
|
||
{
|
||
if ((ret = arr_getByIndex2(source, pos, (void**)&it, sizeof(gxDayProfile))) != 0)
|
||
{
|
||
break;
|
||
}
|
||
#if defined(DLMS_IGNORE_MALLOC)
|
||
if ((ret = arr_getByIndex2(target, pos, (void**)&it2, sizeof(gxDayProfile))) != 0)
|
||
{
|
||
break;
|
||
}
|
||
it2->daySchedules.size = it->daySchedules.size;
|
||
#else
|
||
it2 = gxmalloc(sizeof(gxDayProfile));
|
||
arr_push(target, it);
|
||
#endif //#if defined(DLMS_IGNORE_MALLOC)
|
||
it2->dayId = it->dayId;
|
||
for (pos2 = 0; pos2 != it->daySchedules.size; ++pos2)
|
||
{
|
||
if ((ret = arr_getByIndex2(&it->daySchedules, pos2, (void**)&dp, sizeof(gxDayProfileAction))) != DLMS_ERROR_CODE_OK)
|
||
{
|
||
break;
|
||
}
|
||
#if defined(DLMS_IGNORE_MALLOC)
|
||
if ((ret = arr_getByIndex2(&it2->daySchedules, pos2, (void**)&dp2, sizeof(gxDayProfileAction))) != DLMS_ERROR_CODE_OK)
|
||
{
|
||
break;
|
||
}
|
||
#else
|
||
dp2 = gxmalloc(sizeof(gxDayProfileAction));
|
||
arr_push(&it2->daySchedules, dp2);
|
||
#endif //#if defined(DLMS_IGNORE_MALLOC)
|
||
dp2->startTime = dp->startTime;
|
||
#ifndef DLMS_IGNORE_OBJECT_POINTERS
|
||
dp2->script = dp->script;
|
||
#else
|
||
memcpy(dp2->scriptLogicalName, dp->scriptLogicalName, 6);
|
||
#endif //DLMS_IGNORE_OBJECT_POINTERS
|
||
dp2->scriptSelector = dp->scriptSelector;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
int invoke_ActivityCalendar(gxValueEventArg* e)
|
||
{
|
||
int ret;
|
||
if (e->index == 1)
|
||
{
|
||
//Copy all passive items to active.
|
||
gxActivityCalendar* object = (gxActivityCalendar*)e->target;
|
||
bb_clear(&object->calendarNameActive);
|
||
if ((ret = bb_set(&object->calendarNameActive, object->calendarNamePassive.data, object->calendarNamePassive.size)) != 0 ||
|
||
(ret = invoke_copyDayProfileTable(&object->dayProfileTableActive, &object->dayProfileTablePassive)) != 0 ||
|
||
(ret = invoke_copyWeekProfileTable(&object->weekProfileTableActive, &object->weekProfileTablePassive)) != 0 ||
|
||
(ret = invoke_copySeasonProfile(&object->seasonProfileActive, &object->seasonProfilePassive)) != 0)
|
||
{
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
|
||
}
|
||
return ret;
|
||
}
|
||
#endif //DLMS_IGNORE_ACTIVITY_CALENDAR
|
||
|
||
#ifndef DLMS_IGNORE_ARRAY_MANAGER
|
||
|
||
int invoke_ArrayManagerInsertEntry(
|
||
dlmsServerSettings* settings,
|
||
gxValueEventArg* e, uint16_t index)
|
||
{
|
||
int ret;
|
||
uint16_t count, pos, totalCount;
|
||
uint16_t origPos = 0;
|
||
unsigned char ch;
|
||
dlmsVARIANT value;
|
||
gxDataInfo info;
|
||
di_init(&info);
|
||
var_init(&value);
|
||
//Move new data to the begin of the buffer.
|
||
ret = bb_move(e->value.byteArr, e->value.byteArr->position, 0, bb_available(e->value.byteArr));
|
||
uint16_t newDataSize = (uint16_t)e->value.byteArr->size;
|
||
if ((ret = cosem_getValue(&settings->base, e)) == 0 && bb_size(e->value.byteArr) != 0)
|
||
{
|
||
if ((ret = bb_getUInt8(e->value.byteArr, &ch)) != 0 ||
|
||
ch != DLMS_DATA_TYPE_ARRAY)
|
||
{
|
||
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
||
}
|
||
if ((ret = hlp_getObjectCount2(e->value.byteArr, &totalCount)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
//Change index to zero-based.
|
||
count = (uint16_t)e->value.byteArr->size;
|
||
e->value.byteArr->size = newDataSize + 1;
|
||
if ((ret = hlp_setObjectCount(1 + totalCount, e->value.byteArr)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
totalCount = 0;
|
||
//Return original size.
|
||
e->value.byteArr->size = count;
|
||
for (pos = (uint16_t)e->value.byteArr->position; pos != bb_size(e->value.byteArr); ++pos)
|
||
{
|
||
//Get data type.
|
||
if ((ret = bb_getUInt8ByIndex(e->value.byteArr, e->value.byteArr->position, &ch)) != 0)
|
||
{
|
||
break;
|
||
}
|
||
if (ch == DLMS_DATA_TYPE_ARRAY || ch == DLMS_DATA_TYPE_STRUCTURE)
|
||
{
|
||
if (index == 0)
|
||
{
|
||
//Save start position.
|
||
origPos = (uint16_t)e->value.byteArr->position;
|
||
}
|
||
++e->value.byteArr->position;
|
||
if ((ret = hlp_getObjectCount2(e->value.byteArr, &count)) != 0)
|
||
{
|
||
break;
|
||
}
|
||
totalCount += 1 + count;
|
||
}
|
||
else
|
||
{
|
||
if ((ret = dlms_getData(e->value.byteArr, &info, &value)) != 0)
|
||
{
|
||
var_clear(&value);
|
||
break;
|
||
}
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
if (value.vt == DLMS_DATA_TYPE_OCTET_STRING)
|
||
{
|
||
++e->value.byteArr->position;
|
||
if ((ret = hlp_getObjectCount2(e->value.byteArr, &count)) != 0)
|
||
{
|
||
var_clear(&value);
|
||
break;
|
||
}
|
||
if (e->value.byteArr->size < e->value.byteArr->position + count)
|
||
{
|
||
ret = DLMS_ERROR_CODE_OUTOFMEMORY;
|
||
var_clear(&value);
|
||
break;
|
||
}
|
||
e->value.byteArr->position += count;
|
||
}
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
di_init(&info);
|
||
var_clear(&value);
|
||
}
|
||
--totalCount;
|
||
if (index == 0 && totalCount == 0)
|
||
{
|
||
if (bb_available(e->value.byteArr) == 0)
|
||
{
|
||
//Move first item to last.
|
||
ret = bb_move(e->value.byteArr, 0, e->value.byteArr->size, newDataSize);
|
||
//Move all items to begin.
|
||
ret = bb_move(e->value.byteArr, newDataSize, 0, e->value.byteArr->size - newDataSize);
|
||
e->value.byteArr->position = 0;
|
||
ret = cosem_setValue(&settings->base, e);
|
||
bb_clear(e->value.byteArr);
|
||
break;
|
||
}
|
||
else if (index == 0)
|
||
{
|
||
//Make space for the new item.
|
||
ret = bb_move(e->value.byteArr, origPos,
|
||
origPos + newDataSize, e->value.byteArr->size - newDataSize);
|
||
//Move new item to new location.
|
||
totalCount = (uint16_t)e->value.byteArr->size;
|
||
ret = bb_move(e->value.byteArr, 0, origPos, newDataSize);
|
||
e->value.byteArr->size = totalCount;
|
||
//Move all items to first.
|
||
ret = bb_move(e->value.byteArr, newDataSize, 0, e->value.byteArr->size - newDataSize);
|
||
e->value.byteArr->position = 0;
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
ret = cosem_setValue(&settings->base, e);
|
||
bb_clear(e->value.byteArr);
|
||
#else
|
||
gxByteBuffer* bb = e->value.byteArr;
|
||
e->value.vt = DLMS_DATA_TYPE_NONE;
|
||
if ((ret = dlms_getData(e->value.byteArr, &info, &e->value)))
|
||
{
|
||
bb_clear(bb);
|
||
var_clear(&value);
|
||
break;
|
||
}
|
||
bb_clear(bb);
|
||
if ((ret = cosem_setValue(&settings->base, e)) != 0)
|
||
{
|
||
var_clear(&value);
|
||
break;
|
||
}
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
break;
|
||
}
|
||
--index;
|
||
}
|
||
}
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
int invoke_ArrayManagerDeleteEntry(
|
||
dlmsServerSettings* settings,
|
||
gxValueEventArg* e,
|
||
uint16_t from, uint16_t to)
|
||
{
|
||
int ret;
|
||
uint16_t count, pos, totalCount;
|
||
uint16_t origPos = 0;
|
||
unsigned char ch;
|
||
dlmsVARIANT value;
|
||
gxDataInfo info;
|
||
di_init(&info);
|
||
var_init(&value);
|
||
if ((ret = cosem_getValue(&settings->base, e)) == 0 && bb_size(e->value.byteArr) != 0)
|
||
{
|
||
if ((ret = bb_getUInt8(e->value.byteArr, &ch)) != 0 ||
|
||
ch != DLMS_DATA_TYPE_ARRAY)
|
||
{
|
||
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
||
}
|
||
if ((ret = hlp_getObjectCount2(e->value.byteArr, &totalCount)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
//Change from to zero-based.
|
||
--from;
|
||
if (to - from < totalCount)
|
||
{
|
||
totalCount -= to - from;
|
||
}
|
||
else
|
||
{
|
||
totalCount = from;
|
||
to = from + 1;
|
||
}
|
||
count = (uint16_t)e->value.byteArr->size;
|
||
e->value.byteArr->size = 1;
|
||
if ((ret = hlp_setObjectCount(totalCount, e->value.byteArr)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
totalCount = 0;
|
||
//Return original size.
|
||
e->value.byteArr->size = count;
|
||
for (pos = (uint16_t)e->value.byteArr->position; pos != bb_size(e->value.byteArr); ++pos)
|
||
{
|
||
//Get data type.
|
||
if ((ret = bb_getUInt8ByIndex(e->value.byteArr, e->value.byteArr->position, &ch)) != 0)
|
||
{
|
||
break;
|
||
}
|
||
if (ch == DLMS_DATA_TYPE_ARRAY || ch == DLMS_DATA_TYPE_STRUCTURE)
|
||
{
|
||
if (from == 0)
|
||
{
|
||
//Save start position.
|
||
origPos = (uint16_t)e->value.byteArr->position;
|
||
}
|
||
++e->value.byteArr->position;
|
||
if ((ret = hlp_getObjectCount2(e->value.byteArr, &count)) != 0)
|
||
{
|
||
break;
|
||
}
|
||
totalCount += 1 + count;
|
||
}
|
||
else
|
||
{
|
||
if ((ret = dlms_getData(e->value.byteArr, &info, &value)) != 0)
|
||
{
|
||
var_clear(&value);
|
||
break;
|
||
}
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
if (value.vt == DLMS_DATA_TYPE_OCTET_STRING)
|
||
{
|
||
++e->value.byteArr->position;
|
||
if ((ret = hlp_getObjectCount2(e->value.byteArr, &count)) != 0)
|
||
{
|
||
break;
|
||
}
|
||
if (e->value.byteArr->size < e->value.byteArr->position + count)
|
||
{
|
||
ret = DLMS_ERROR_CODE_OUTOFMEMORY;
|
||
break;
|
||
}
|
||
e->value.byteArr->position += count;
|
||
}
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
di_init(&info);
|
||
var_clear(&value);
|
||
}
|
||
--totalCount;
|
||
if (totalCount == 0)
|
||
{
|
||
--to;
|
||
if (to == 0)
|
||
{
|
||
ret = bb_move(e->value.byteArr, e->value.byteArr->position, origPos,
|
||
bb_available(e->value.byteArr));
|
||
e->value.byteArr->position = 0;
|
||
ret = cosem_setValue(&settings->base, e);
|
||
bb_clear(e->value.byteArr);
|
||
break;
|
||
}
|
||
--from;
|
||
}
|
||
}
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
int invoke_ArrayManager(
|
||
dlmsServerSettings* settings,
|
||
gxValueEventArg* e)
|
||
{
|
||
int pos, ret = 0;
|
||
gxArrayManagerItem* it;
|
||
gxArrayManager* object = (gxArrayManager*)e->target;
|
||
unsigned char ch, found = 0;
|
||
uint16_t count, totalCount;
|
||
dlmsVARIANT tmp;
|
||
dlmsVARIANT value;
|
||
gxDataInfo info;
|
||
#ifndef DLMS_IGNORE_MALLOC
|
||
dlmsVARIANT* tmp2, * tmp3;
|
||
e->value.byteArr = &settings->info.data;
|
||
#endif//DLMS_IGNORE_MALLOC
|
||
e->byteArray = 1;
|
||
unsigned char id;
|
||
uint16_t index = 0, from = 0, to = 0, origSize, origPos = 0;
|
||
if (e->index == 1)
|
||
{
|
||
id = e->parameters.bVal;
|
||
bb_clear(e->value.byteArr);
|
||
}
|
||
else if (e->index == 3 || e->index == 4)
|
||
{
|
||
//Insert or update entry.
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
if ((ret = cosem_getStructure(e->parameters.byteArr, &count)) != 0 ||
|
||
(ret = cosem_getUInt8(e->parameters.byteArr, &id)) != 0 ||
|
||
(ret = cosem_getStructure(e->parameters.byteArr, &count)) != 0 ||
|
||
(ret = cosem_getUInt16(e->parameters.byteArr, &index)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
#else
|
||
if ((ret = va_getByIndex(e->parameters.Arr, 0, &tmp2)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
id = tmp2->bVal;
|
||
if ((ret = va_getByIndex(e->parameters.Arr, 1, &tmp3)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
if ((ret = va_getByIndex(tmp3->Arr, 0, &tmp2)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
from = tmp2->uiVal;
|
||
if ((ret = va_getByIndex(tmp3->Arr, 1, &tmp2)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
to = tmp2->uiVal;
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
}
|
||
else
|
||
{
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
if ((ret = cosem_getStructure(e->parameters.byteArr, &count)) != 0 ||
|
||
(ret = cosem_getUInt8(e->parameters.byteArr, &id)) != 0 ||
|
||
(ret = cosem_getStructure(e->parameters.byteArr, &count)) != 0 ||
|
||
(ret = cosem_getUInt16(e->parameters.byteArr, &from)) != 0 ||
|
||
(ret = cosem_getUInt16(e->parameters.byteArr, &to)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
#else
|
||
if ((ret = va_getByIndex(e->parameters.Arr, 0, &tmp2)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
id = tmp2->bVal;
|
||
if ((ret = va_getByIndex(e->parameters.Arr, 1, &tmp3)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
if ((ret = va_getByIndex(tmp3->Arr, 0, &tmp2)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
from = tmp2->uiVal;
|
||
if ((ret = va_getByIndex(tmp3->Arr, 1, &tmp2)) != 0)
|
||
{
|
||
return ret;
|
||
}
|
||
to = tmp2->uiVal;
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
bb_clear(e->value.byteArr);
|
||
}
|
||
for (pos = 0; pos != object->elements.size; ++pos)
|
||
{
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
ret = arr_getByIndex(&object->elements, pos, (void**)&it, sizeof(gxArrayManagerItem));
|
||
#else
|
||
ret = arr_getByIndex(&object->elements, pos, (void**)&it);
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
if (ret != 0)
|
||
{
|
||
break;
|
||
}
|
||
if (it->id == id)
|
||
{
|
||
if (e->index == 1)
|
||
{
|
||
//Number Of Entries.
|
||
if (it->element.target->objectType == DLMS_OBJECT_TYPE_PROFILE_GENERIC
|
||
&& it->element.attributeIndex == 2)
|
||
{
|
||
//Entries in use is returned when buffer size is asked.
|
||
GX_UINT32(tmp) = ((gxProfileGeneric*)it->element.target)->entriesInUse;
|
||
}
|
||
else
|
||
{
|
||
e->index = it->element.attributeIndex;
|
||
e->target = it->element.target;
|
||
if ((ret = cosem_getValue(&settings->base, e)) != 0 ||
|
||
(ret = bb_getUInt8(e->value.byteArr, &ch)) != 0)
|
||
{
|
||
break;
|
||
}
|
||
if (ch != DLMS_DATA_TYPE_ARRAY)
|
||
{
|
||
ret = DLMS_ERROR_CODE_READ_WRITE_DENIED;
|
||
break;
|
||
}
|
||
if (hlp_getObjectCount2(e->value.byteArr, &count) != 0)
|
||
{
|
||
break;
|
||
}
|
||
if (count < 0x100)
|
||
{
|
||
GX_UINT8(tmp) = (unsigned char)count;
|
||
}
|
||
else
|
||
{
|
||
GX_UINT16(tmp) = count;
|
||
}
|
||
}
|
||
bb_clear(e->value.byteArr);
|
||
if ((ret = dlms_setData(e->value.byteArr, tmp.vt, &tmp)) != 0)
|
||
{
|
||
break;
|
||
}
|
||
found = 1;
|
||
break;
|
||
}
|
||
else if (e->index == 2)
|
||
{
|
||
//Retrieve entries.
|
||
if (it->element.target->objectType == DLMS_OBJECT_TYPE_PROFILE_GENERIC)
|
||
{
|
||
|
||
}
|
||
if (!found)
|
||
{
|
||
di_init(&info);
|
||
var_init(&value);
|
||
e->index = it->element.attributeIndex;
|
||
e->target = it->element.target;
|
||
if ((ret = cosem_getValue(&settings->base, e)) == 0 && bb_size(e->value.byteArr) != 0)
|
||
{
|
||
if ((ret = bb_getUInt8(e->value.byteArr, &ch)) != 0 ||
|
||
ch != DLMS_DATA_TYPE_ARRAY)
|
||
{
|
||
break;
|
||
}
|
||
if ((ret = hlp_getObjectCount2(e->value.byteArr, &totalCount)) != 0)
|
||
{
|
||
break;
|
||
}
|
||
//Change from to zero-based.
|
||
--from;
|
||
if (to - from < totalCount)
|
||
{
|
||
totalCount = to - from;
|
||
}
|
||
else if (totalCount < to)
|
||
{
|
||
if (totalCount == 0)
|
||
{
|
||
to = 1;
|
||
}
|
||
else
|
||
{
|
||
to = totalCount;
|
||
}
|
||
}
|
||
count = (uint16_t)e->value.byteArr->size;
|
||
e->value.byteArr->size = 1;
|
||
if ((ret = hlp_setObjectCount(totalCount, e->value.byteArr)) != 0)
|
||
{
|
||
break;
|
||
}
|
||
totalCount = 0;
|
||
origSize = (uint16_t)e->value.byteArr->size;
|
||
//Return original size.
|
||
e->value.byteArr->size = count;
|
||
for (pos = e->value.byteArr->position; pos != bb_size(e->value.byteArr); ++pos)
|
||
{
|
||
//Get data type.
|
||
if ((ret = bb_getUInt8ByIndex(e->value.byteArr, e->value.byteArr->position, &ch)) != 0)
|
||
{
|
||
break;
|
||
}
|
||
if (ch == DLMS_DATA_TYPE_ARRAY || ch == DLMS_DATA_TYPE_STRUCTURE)
|
||
{
|
||
if (from == 0)
|
||
{
|
||
//Save start position.
|
||
origPos = (uint16_t)e->value.byteArr->position;
|
||
}
|
||
++e->value.byteArr->position;
|
||
if ((ret = hlp_getObjectCount2(e->value.byteArr, &count)) != 0)
|
||
{
|
||
break;
|
||
}
|
||
totalCount += 1 + count;
|
||
}
|
||
else
|
||
{
|
||
if ((ret = dlms_getData(e->value.byteArr, &info, &value)) != 0)
|
||
{
|
||
var_clear(&value);
|
||
break;
|
||
}
|
||
#ifdef DLMS_IGNORE_MALLOC
|
||
if (value.vt == DLMS_DATA_TYPE_OCTET_STRING)
|
||
{
|
||
++e->value.byteArr->position;
|
||
if ((ret = hlp_getObjectCount2(e->value.byteArr, &count)) != 0)
|
||
{
|
||
break;
|
||
}
|
||
if (e->value.byteArr->size < e->value.byteArr->position + count)
|
||
{
|
||
ret = DLMS_ERROR_CODE_OUTOFMEMORY;
|
||
break;
|
||
}
|
||
e->value.byteArr->position += count;
|
||
}
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
|
||
di_init(&info);
|
||
var_clear(&value);
|
||
}
|
||
--totalCount;
|
||
if (totalCount == 0)
|
||
{
|
||
--to;
|
||
if (to == 0)
|
||
{
|
||
ret = bb_move(e->value.byteArr, origPos,
|
||
origSize, e->value.byteArr->position - origPos);
|
||
e->value.byteArr->position = 0;
|
||
break;
|
||
}
|
||
--from;
|
||
}
|
||
}
|
||
found = 1;
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
else if (e->index == 3)
|
||
{
|
||
e->index = it->element.attributeIndex;
|
||
e->target = it->element.target;
|
||
ret = invoke_ArrayManagerInsertEntry(settings, e, index);
|
||
found = 1;
|
||
break;
|
||
}
|
||
else if (e->index == 4)
|
||
{
|
||
e->index = it->element.attributeIndex;
|
||
e->target = it->element.target;
|
||
ret = invoke_ArrayManagerDeleteEntry(settings, e, index, index);
|
||
ret = invoke_ArrayManagerInsertEntry(settings, e, index);
|
||
found = 1;
|
||
break;
|
||
}
|
||
else if (e->index == 5)
|
||
{
|
||
e->index = it->element.attributeIndex;
|
||
e->target = it->element.target;
|
||
ret = invoke_ArrayManagerDeleteEntry(settings, e, from, to);
|
||
found = 1;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (!found)
|
||
{
|
||
bb_clear(e->value.byteArr);
|
||
ret = DLMS_ERROR_CODE_READ_WRITE_DENIED;
|
||
}
|
||
return ret;
|
||
}
|
||
#endif //DLMS_IGNORE_ARRAY_MANAGER
|
||
|
||
#ifndef DLMS_IGNORE_G3_PLC_MAC_SETUP
|
||
int invoke_G3_PLC_MAC_Setup(
|
||
dlmsServerSettings* settings,
|
||
gxG3PlcMacSetup* object,
|
||
gxValueEventArg* e)
|
||
{
|
||
uint16_t address, pos, count = 0;
|
||
int ret = 0;
|
||
e->byteArray = 1;
|
||
bb_clear(&settings->info.data);
|
||
e->value.byteArr = &settings->info.data;
|
||
if (e->parameters.vt != DLMS_DATA_TYPE_UINT16)
|
||
{
|
||
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
||
}
|
||
address = e->parameters.uiVal;
|
||
if (e->index == 1)
|
||
{
|
||
//Get amount of neighbour tables.
|
||
gxNeighbourTable* it;
|
||
for (pos = 0; pos < (uint16_t)object->neighbourTable.size; ++pos)
|
||
{
|
||
#ifndef DLMS_IGNORE_MALLOC
|
||
if ((ret = arr_getByIndex(&object->neighbourTable, pos, (void**)&it)) != 0)
|
||
{
|
||
break;
|
||
}
|
||
#else
|
||
if ((ret = arr_getByIndex(&object->neighbourTable, pos,
|
||
(void**)&it, sizeof(gxNeighbourTable))) != 0)
|
||
{
|
||
break;
|
||
}
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
if (it->shortAddress == address)
|
||
{
|
||
++count;
|
||
}
|
||
}
|
||
if (ret == 0)
|
||
{
|
||
return cosem_getG3PlcMacSetupNeighbourTables(&object->neighbourTable, address, count, e);
|
||
}
|
||
}
|
||
else if (e->index == 2)
|
||
{
|
||
gxMacPosTable* it;
|
||
//Get amount of MAC POS tables.
|
||
for (pos = 0; pos < object->macPosTable.size; ++pos)
|
||
{
|
||
#ifndef DLMS_IGNORE_MALLOC
|
||
if ((ret = arr_getByIndex(&object->macPosTable, pos, (void**)&it)) != 0)
|
||
{
|
||
break;
|
||
}
|
||
#else
|
||
if ((ret = arr_getByIndex(&object->macPosTable, pos, (void**)&it, sizeof(gxMacPosTable))) != 0)
|
||
{
|
||
break;
|
||
}
|
||
#endif //DLMS_IGNORE_MALLOC
|
||
if (it->shortAddress == address)
|
||
{
|
||
++count;
|
||
}
|
||
}
|
||
if (ret == 0)
|
||
{
|
||
return cosem_getG3PlcMacSetupPosTables(&object->macPosTable, address, count, e);
|
||
}
|
||
}
|
||
bb_clear(e->value.byteArr);
|
||
return DLMS_ERROR_CODE_READ_WRITE_DENIED;
|
||
}
|
||
#endif //DLMS_IGNORE_G3_PLC_MAC_SETUP
|
||
|
||
int cosem_invoke(
|
||
dlmsServerSettings* settings,
|
||
gxValueEventArg* e)
|
||
{
|
||
int ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
|
||
//If invoke index is invalid.
|
||
if (e->index < 1 || e->index > obj_methodCount(e->target))
|
||
{
|
||
return DLMS_ERROR_CODE_INVALID_PARAMETER;
|
||
}
|
||
switch (e->target->objectType)
|
||
{
|
||
#ifndef DLMS_IGNORE_REGISTER
|
||
case DLMS_OBJECT_TYPE_REGISTER:
|
||
ret = invoke_Register(
|
||
(gxRegister*)e->target,
|
||
e);
|
||
break;
|
||
#endif //DLMS_IGNORE_REGISTER
|
||
#ifndef DLMS_IGNORE_CLOCK
|
||
case DLMS_OBJECT_TYPE_CLOCK:
|
||
ret = invoke_Clock(
|
||
(gxClock*)e->target,
|
||
e->index, &e->parameters);
|
||
break;
|
||
#endif //DLMS_IGNORE_CLOCK
|
||
#ifndef DLMS_IGNORE_EXTENDED_REGISTER
|
||
case DLMS_OBJECT_TYPE_EXTENDED_REGISTER:
|
||
ret = invoke_ExtendedRegister(settings,
|
||
(gxExtendedRegister*)e->target,
|
||
e->index);
|
||
break;
|
||
#endif //DLMS_IGNORE_EXTENDED_REGISTER
|
||
#ifndef DLMS_IGNORE_DEMAND_REGISTER
|
||
case DLMS_OBJECT_TYPE_DEMAND_REGISTER:
|
||
ret = invoke_DemandRegister(settings,
|
||
(gxDemandRegister*)e->target,
|
||
e->index);
|
||
break;
|
||
#endif //DLMS_IGNORE_DEMAND_REGISTER
|
||
#ifndef DLMS_IGNORE_PROFILE_GENERIC
|
||
case DLMS_OBJECT_TYPE_PROFILE_GENERIC:
|
||
ret = invoke_ProfileGeneric(
|
||
settings,
|
||
(gxProfileGeneric*)e->target,
|
||
e->index);
|
||
break;
|
||
#endif //DLMS_IGNORE_PROFILE_GENERIC
|
||
#ifndef DLMS_IGNORE_SCRIPT_TABLE
|
||
case DLMS_OBJECT_TYPE_SCRIPT_TABLE:
|
||
ret = invoke_ScriptTable(settings, e);
|
||
break;
|
||
#endif //DLMS_IGNORE_SCRIPT_TABLE
|
||
#ifndef DLMS_IGNORE_ZIG_BEE_NETWORK_CONTROL
|
||
case DLMS_OBJECT_TYPE_ZIG_BEE_NETWORK_CONTROL:
|
||
ret = invoke_zigbeeNetworkControl(
|
||
(gxZigBeeNetworkControl*)e->target,
|
||
e->index,
|
||
&e->parameters);
|
||
break;
|
||
#endif //DLMS_IGNORE_ZIG_BEE_NETWORK_CONTROL
|
||
#ifndef DLMS_IGNORE_CHARGE
|
||
case DLMS_OBJECT_TYPE_CHARGE:
|
||
ret = invoke_Charge(
|
||
(gxCharge*)e->target,
|
||
e->index,
|
||
&e->parameters);
|
||
break;
|
||
#endif //DLMS_IGNORE_CHARGE
|
||
#ifndef DLMS_IGNORE_CREDIT
|
||
case DLMS_OBJECT_TYPE_CREDIT:
|
||
ret = invoke_Credit(
|
||
(gxCredit*)e->target,
|
||
e->index,
|
||
&e->parameters);
|
||
break;
|
||
#endif //DLMS_IGNORE_CREDIT
|
||
#ifndef DLMS_IGNORE_TOKEN_GATEWAY
|
||
case DLMS_OBJECT_TYPE_TOKEN_GATEWAY:
|
||
ret = invoke_gxTokenGateway(
|
||
(gxTokenGateway*)e->target,
|
||
e->index,
|
||
&e->parameters);
|
||
break;
|
||
#endif //DLMS_IGNORE_TOKEN_GATEWAY
|
||
#ifndef DLMS_IGNORE_ASSOCIATION_SHORT_NAME
|
||
case DLMS_OBJECT_TYPE_ASSOCIATION_SHORT_NAME:
|
||
#ifndef DLMS_IGNORE_ASSOCIATION_SHORT_NAME
|
||
ret = invoke_AssociationShortName(settings, e);
|
||
#endif //DLMS_IGNORE_ASSOCIATION_SHORT_NAME
|
||
break;
|
||
#endif //ASSOCIATION_SHORT_NAME
|
||
#ifndef DLMS_IGNORE_ASSOCIATION_LOGICAL_NAME
|
||
case DLMS_OBJECT_TYPE_ASSOCIATION_LOGICAL_NAME:
|
||
ret = invoke_AssociationLogicalName(settings, e);
|
||
break;
|
||
#endif //DLMS_IGNORE_ASSOCIATION_LOGICAL_NAME
|
||
#ifndef DLMS_IGNORE_IMAGE_TRANSFER
|
||
case DLMS_OBJECT_TYPE_IMAGE_TRANSFER:
|
||
ret = invoke_ImageTransfer((gxImageTransfer*)e->target, e);
|
||
break;
|
||
#endif //DLMS_IGNORE_IMAGE_TRANSFER
|
||
#ifndef DLMS_IGNORE_SAP_ASSIGNMENT
|
||
case DLMS_OBJECT_TYPE_SAP_ASSIGNMENT:
|
||
ret = invoke_SapAssigment((gxSapAssignment*)e->target, e);
|
||
break;
|
||
#endif //DLMS_IGNORE_SAP_ASSIGNMENT
|
||
#ifndef DLMS_IGNORE_SECURITY_SETUP
|
||
case DLMS_OBJECT_TYPE_SECURITY_SETUP:
|
||
ret = invoke_SecuritySetup(settings, (gxSecuritySetup*)e->target, e);
|
||
break;
|
||
#endif //DLMS_IGNORE_SECURITY_SETUP
|
||
#ifndef DLMS_IGNORE_COMPACT_DATA
|
||
case DLMS_OBJECT_TYPE_COMPACT_DATA:
|
||
ret = invoke_CompactData(settings, (gxCompactData*)e->target, e->index);
|
||
break;
|
||
#endif //DLMS_IGNORE_COMPACT_DATA
|
||
#ifndef DLMS_IGNORE_DISCONNECT_CONTROL
|
||
case DLMS_OBJECT_TYPE_DISCONNECT_CONTROL:
|
||
ret = invoke_DisconnectControl(settings, (gxDisconnectControl*)e->target, e->index);
|
||
break;
|
||
#endif //DLMS_IGNORE_DISCONNECT_CONTROL
|
||
#ifndef DLMS_IGNORE_LLC_SSCS_SETUP
|
||
case DLMS_OBJECT_TYPE_LLC_SSCS_SETUP:
|
||
ret = invoke_LlcSscsSetup((gxLlcSscsSetup*)e->target, e->index);
|
||
break;
|
||
#endif //DLMS_IGNORE_LLC_SSCS_SETUP
|
||
#ifndef DLMS_IGNORE_PRIME_NB_OFDM_PLC_PHYSICAL_LAYER_COUNTERS
|
||
case DLMS_OBJECT_TYPE_PRIME_NB_OFDM_PLC_PHYSICAL_LAYER_COUNTERS:
|
||
ret = invoke_PrimeNbOfdmPlcPhysicalLayerCounters((gxPrimeNbOfdmPlcPhysicalLayerCounters*)e->target, e->index);
|
||
break;
|
||
#endif //DLMS_IGNORE_PRIME_NB_OFDM_PLC_PHYSICAL_LAYER_COUNTERS
|
||
#ifndef DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_COUNTERS
|
||
case DLMS_OBJECT_TYPE_PRIME_NB_OFDM_PLC_MAC_COUNTERS:
|
||
ret = invoke_PrimeNbOfdmPlcMacCounters((gxPrimeNbOfdmPlcMacCounters*)e->target, e->index);
|
||
break;
|
||
#endif //DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_COUNTERS
|
||
#ifndef DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_NETWORK_ADMINISTRATION_DATA
|
||
case DLMS_OBJECT_TYPE_PRIME_NB_OFDM_PLC_MAC_NETWORK_ADMINISTRATION_DATA:
|
||
ret = invoke_PrimeNbOfdmPlcMacNetworkAdministrationData((gxPrimeNbOfdmPlcMacNetworkAdministrationData*)e->target, e->index);
|
||
break;
|
||
#endif //DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_NETWORK_ADMINISTRATION_DATA
|
||
#ifndef DLMS_IGNORE_SPECIAL_DAYS_TABLE
|
||
case DLMS_OBJECT_TYPE_SPECIAL_DAYS_TABLE:
|
||
ret = invoke_SpecialDaysTable((gxSpecialDaysTable*)e->target, e);
|
||
break;
|
||
#endif //DLMS_IGNORE_SPECIAL_DAYS_TABLE
|
||
#ifndef DLMS_IGNORE_REGISTER_ACTIVATION
|
||
case DLMS_OBJECT_TYPE_REGISTER_ACTIVATION:
|
||
ret = invoke_RegisterActivation(settings, (gxRegisterActivation*)e->target, e);
|
||
break;
|
||
#endif //DLMS_IGNORE_REGISTER_ACTIVATION
|
||
#ifndef DLMS_IGNORE_ACTIVITY_CALENDAR
|
||
case DLMS_OBJECT_TYPE_ACTIVITY_CALENDAR:
|
||
ret = invoke_ActivityCalendar(e);
|
||
break;
|
||
#endif //DLMS_IGNORE_ACTIVITY_CALENDAR
|
||
#ifndef DLMS_IGNORE_ARRAY_MANAGER
|
||
case DLMS_OBJECT_TYPE_ARRAY_MANAGER:
|
||
ret = invoke_ArrayManager(settings, e);
|
||
break;
|
||
#endif //DLMS_IGNORE_ARRAY_MANAGER
|
||
#ifndef DLMS_IGNORE_G3_PLC_MAC_SETUP
|
||
case DLMS_OBJECT_TYPE_G3_PLC_MAC_SETUP:
|
||
ret = invoke_G3_PLC_MAC_Setup(settings, (gxG3PlcMacSetup*)e->target, e);
|
||
break;
|
||
#endif //DLMS_IGNORE_G3_PLC_MAC_SETUP
|
||
default:
|
||
//Unknown type.
|
||
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
|
||
}
|
||
return ret;
|
||
}
|
||
#endif //DLMS_IGNORE_SERVER
|