// // -------------------------------------------------------------------------- // 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" #if !defined(DLMS_IGNORE_MALLOC) && !defined(DLMS_COSEM_EXACT_DATA_TYPES) #if defined(_WIN32) || defined(_WIN64) || defined(__linux__) #include #endif #include "gxmem.h" #if _MSC_VER > 1400 #include #endif #include #include #include "gxset.h" #include "dlms.h" #include "gxkey.h" #include "cosem.h" #include "gxget.h" #include "server.h" #ifndef DLMS_IGNORE_DATA int cosem_setData(gxValueEventArg* e) { int ret; if (e->index == 2) { ret = var_copy(&((gxData*)e->target)->value, &e->value); } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_DATA #ifndef DLMS_IGNORE_REGISTER int cosem_setRegister(gxRegister* object, unsigned char index, dlmsVARIANT* value) { int ret = 0; if (index == 2) { ret = var_copy(&object->value, value); } else if (index == 3) { dlmsVARIANT* tmp; if (value->vt != DLMS_DATA_TYPE_STRUCTURE) { return DLMS_ERROR_CODE_INVALID_PARAMETER; } ret = va_getByIndex(value->Arr, 0, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->scaler = (char)var_toInteger(tmp); ret = va_getByIndex(value->Arr, 1, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->unit = (unsigned char)var_toInteger(tmp); object->unitRead = 1; } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_REGISTER #ifndef DLMS_IGNORE_REGISTER_TABLE int cosem_setRegistertable(gxRegisterTable* object, unsigned char index, dlmsVARIANT* value) { int pos, ret = 0; dlmsVARIANT_PTR tmp; if (index == 2) { if (value->Arr != NULL) { dlmsVARIANT* tmp2; for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } tmp2 = (dlmsVARIANT*)gxmalloc(sizeof(dlmsVARIANT)); var_init(tmp2); ret = var_copy(tmp2, tmp); if (ret != 0) { break; } va_push(&object->tableCellValues, tmp2); } } } else if (index == 4) { if (value->vt != DLMS_DATA_TYPE_STRUCTURE) { return DLMS_ERROR_CODE_INVALID_PARAMETER; } ret = va_getByIndex(value->Arr, 0, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->scaler = (char)var_toInteger(tmp); ret = va_getByIndex(value->Arr, 1, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->unit = (unsigned char)var_toInteger(tmp); object->unitRead = 1; } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_REGISTER_TABLE #ifndef DLMS_IGNORE_CLOCK int cosem_setClock(dlmsSettings* settings, gxClock* object, unsigned char index, dlmsVARIANT* value) { int ret = DLMS_ERROR_CODE_OK; dlmsVARIANT tmp; if (index == 2) { //Some meters are returning empty octet string here. if (value->vt == DLMS_DATA_TYPE_OCTET_STRING && value->byteArr != NULL) { var_init(&tmp); ret = dlms_changeType2(value, DLMS_DATA_TYPE_DATETIME, &tmp); if (ret != 0) { return ret; } time_copy(&object->time, tmp.dateTime); //If user set's new time transform it to the same time zone as the server is. #ifndef DLMS_IGNORE_SERVER if (settings->server) { //Convert time to UCT if time zone is given. time_toUTC(&object->time); clock_updateDST(object, &object->time); } #endif// DLMS_IGNORE_SERVER var_clear(&tmp); } else { time_clear(&object->time); } } else if (index == 3) { object->timeZone = (short)var_toInteger(value); } else if (index == 4) { object->status = (DLMS_CLOCK_STATUS)var_toInteger(value); } else if (index == 5) { //Some meters are returning empty octet string here. if (value->vt == DLMS_DATA_TYPE_OCTET_STRING && value->byteArr != NULL) { var_init(&tmp); ret = dlms_changeType2(value, DLMS_DATA_TYPE_DATETIME, &tmp); if (ret != 0) { return ret; } time_copy(&object->begin, tmp.dateTime); var_clear(&tmp); } else { time_clear(&object->begin); } } else if (index == 6) { //Some meters are returning empty octet string here. if (value->vt == DLMS_DATA_TYPE_OCTET_STRING && value->byteArr != NULL) { var_init(&tmp); ret = dlms_changeType2(value, DLMS_DATA_TYPE_DATETIME, &tmp); if (ret != 0) { return ret; } time_copy(&object->end, tmp.dateTime); var_clear(&tmp); } else { time_clear(&object->end); } } else if (index == 7) { object->deviation = (char)var_toInteger(value); #ifndef DLMS_IGNORE_SERVER if (settings->server) { clock_updateDST(object, &object->time); } #endif// DLMS_IGNORE_SERVER } else if (index == 8) { object->enabled = (unsigned char)var_toInteger(value); #ifndef DLMS_IGNORE_SERVER if (settings->server) { clock_updateDST(object, &object->time); } #endif //DLMS_IGNORE_SERVER } else if (index == 9) { object->clockBase = (DLMS_CLOCK_BASE)var_toInteger(value); } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_CLOCK #ifndef DLMS_IGNORE_ACTIVITY_CALENDAR // The season profiles list is sorted according to season_start (in increasing order). int cosem_orderSeasonProfile(gxArray* profile) { int ret = 0; uint16_t pos, pos2, minPos = 0; gxSeasonProfile* sp, * sp2; uint32_t tmp, next1, next2; for (pos = 0; pos < profile->size - 1; ++pos) { if ((ret = arr_getByIndex(profile, pos, (void**)&sp)) != 0) { break; } next1 = time_toUnixTime2(&sp->start); next2 = 0xFFFFFFFF; for (pos2 = pos + 1; pos2 < profile->size; ++pos2) { if ((ret = arr_getByIndex(profile, pos2, (void**)&sp2)) != 0) { break; } tmp = time_toUnixTime2(&sp2->start); if (tmp < next2) { next2 = tmp; minPos = pos2; } } if (ret != 0) { break; } if (next2 < next1) { if ((ret = arr_swap(profile, pos, minPos)) != 0) { break; } } } return ret; } int updateSeasonProfile(gxArray* profile, dlmsVARIANT* data) { int ret = DLMS_ERROR_CODE_OK, pos; gxSeasonProfile* sp = NULL; obj_clearSeasonProfile(profile); dlmsVARIANT tm; dlmsVARIANT* tmp, * it; var_init(&tm); for (pos = 0; pos != data->Arr->size; ++pos) { sp = (gxSeasonProfile*)gxmalloc(sizeof(gxSeasonProfile)); if (sp == NULL) { return DLMS_ERROR_CODE_OUTOFMEMORY; } ret = va_getByIndex(data->Arr, pos, &it); if (ret != DLMS_ERROR_CODE_OK) { break; } ret = va_getByIndex(it->Arr, 0, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } BYTE_BUFFER_INIT(&sp->name); bb_set2(&sp->name, tmp->byteArr, 0, bb_size(tmp->byteArr)); ret = va_getByIndex(it->Arr, 1, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } ret = dlms_changeType2(tmp, DLMS_DATA_TYPE_DATETIME, &tm); if (ret != DLMS_ERROR_CODE_OK) { break; } time_copy(&sp->start, tm.dateTime); var_clear(&tm); ret = va_getByIndex(it->Arr, 2, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } BYTE_BUFFER_INIT(&sp->weekName); bb_set2(&sp->weekName, tmp->byteArr, 0, bb_size(tmp->byteArr)); arr_push(profile, sp); } if (ret != 0 && sp != NULL) { gxfree(sp); } return ret; } int updateWeekProfileTable(gxArray* profile, dlmsVARIANT* data) { int ret = DLMS_ERROR_CODE_OK, pos; gxWeekProfile* wp = NULL; obj_clearWeekProfileTable(profile); dlmsVARIANT* tmp, * it; for (pos = 0; pos != data->Arr->size; ++pos) { wp = (gxWeekProfile*)gxmalloc(sizeof(gxWeekProfile)); if (wp == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } ret = va_getByIndex(data->Arr, pos, &it); if (ret != DLMS_ERROR_CODE_OK) { break; } ret = va_getByIndex(it->Arr, 0, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } BYTE_BUFFER_INIT(&wp->name); bb_set2(&wp->name, tmp->byteArr, 0, bb_size(tmp->byteArr)); ret = va_getByIndex(it->Arr, 1, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } wp->monday = (unsigned char)var_toInteger(tmp); ret = va_getByIndex(it->Arr, 2, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } wp->tuesday = (unsigned char)var_toInteger(tmp); ret = va_getByIndex(it->Arr, 3, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } wp->wednesday = (unsigned char)var_toInteger(tmp); ret = va_getByIndex(it->Arr, 4, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } wp->thursday = (unsigned char)var_toInteger(tmp); ret = va_getByIndex(it->Arr, 5, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } wp->friday = (unsigned char)var_toInteger(tmp); ret = va_getByIndex(it->Arr, 6, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } wp->saturday = (unsigned char)var_toInteger(tmp); ret = va_getByIndex(it->Arr, 7, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } wp->sunday = (unsigned char)var_toInteger(tmp); arr_push(profile, wp); } if (ret != 0 && wp != NULL) { gxfree(wp); } return ret; } int updateDayProfileTable(dlmsSettings* settings, gxArray* profile, dlmsVARIANT* data) { int ret = DLMS_ERROR_CODE_OK, pos, pos2; gxDayProfile* dp = NULL; gxDayProfileAction* ac = NULL; obj_clearDayProfileTable(profile); dlmsVARIANT* tmp, * tmp2, * it, * it2; dlmsVARIANT tm; for (pos = 0; pos != data->Arr->size; ++pos) { dp = (gxDayProfile*)gxmalloc(sizeof(gxDayProfile)); if (dp == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } arr_init(&dp->daySchedules); ret = va_getByIndex(data->Arr, pos, &it); if (ret != DLMS_ERROR_CODE_OK) { break; } ret = va_getByIndex(it->Arr, 0, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } dp->dayId = (unsigned char)var_toInteger(tmp); ret = va_getByIndex(it->Arr, 1, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } for (pos2 = 0; pos2 != tmp->Arr->size; ++pos2) { ac = (gxDayProfileAction*)gxmalloc(sizeof(gxDayProfileAction)); if (ac == NULL) { return DLMS_ERROR_CODE_OUTOFMEMORY; } ret = va_getByIndex(tmp->Arr, pos2, &it2); if (ret != DLMS_ERROR_CODE_OK) { break; } //Get start time. ret = va_getByIndex(it2->Arr, 0, &tmp2); if (ret != DLMS_ERROR_CODE_OK) { break; } var_init(&tm); ret = dlms_changeType2(tmp2, DLMS_DATA_TYPE_TIME, &tm); if (ret != DLMS_ERROR_CODE_OK) { break; } time_copy(&ac->startTime, tm.dateTime); var_clear(&tm); //Get script logical name. ret = va_getByIndex(it2->Arr, 1, &tmp2); if (ret != DLMS_ERROR_CODE_OK) { break; } if (tmp2->vt == DLMS_DATA_TYPE_OCTET_STRING && tmp2->byteArr != NULL) { #ifndef DLMS_IGNORE_OBJECT_POINTERS if ((ret = oa_findByLN(&settings->objects, DLMS_OBJECT_TYPE_SCRIPT_TABLE, tmp2->byteArr->data, &ac->script)) != 0) { break; } if (ac->script == NULL) { if ((ret = cosem_createObject(DLMS_OBJECT_TYPE_SCRIPT_TABLE, &ac->script)) != 0) { return ret; } memcpy(ac->script->logicalName, tmp2->byteArr->data, tmp2->byteArr->size); //Add object to released objects list. ret = oa_push(&settings->releasedObjects, ac->script); if (ret != DLMS_ERROR_CODE_OK) { return ret; } } #else memcpy(ac->scriptLogicalName, tmp2->byteArr->data, 6); #endif //DLMS_IGNORE_OBJECT_POINTERS } ret = va_getByIndex(it2->Arr, 2, &tmp2); if (ret != DLMS_ERROR_CODE_OK) { break; } ac->scriptSelector = (uint16_t)var_toInteger(tmp2); arr_push(&dp->daySchedules, ac); } if (ret != 0) { break; } arr_push(profile, dp); } if (ret != 0) { if (dp) { gxfree(dp); } if (ac) { gxfree(ac); } } return ret; } int cosem_setActivityCalendar(dlmsSettings* settings, gxActivityCalendar* object, unsigned char index, dlmsVARIANT* value) { int ret = DLMS_ERROR_CODE_OK; dlmsVARIANT tm; if (index == 2) { bb_clear(&object->calendarNameActive); ret = bb_set2(&object->calendarNameActive, value->byteArr, 0, bb_size(value->byteArr)); } else if (index == 3) { ret = updateSeasonProfile(&object->seasonProfileActive, value); } else if (index == 4) { ret = updateWeekProfileTable(&object->weekProfileTableActive, value); } else if (index == 5) { ret = updateDayProfileTable(settings, &object->dayProfileTableActive, value); } else if (index == 6) { bb_clear(&object->calendarNamePassive); ret = bb_set2(&object->calendarNamePassive, value->byteArr, 0, bb_size(value->byteArr)); } else if (index == 7) { ret = updateSeasonProfile(&object->seasonProfilePassive, value); } else if (index == 8) { ret = updateWeekProfileTable(&object->weekProfileTablePassive, value); } else if (index == 9) { ret = updateDayProfileTable(settings, &object->dayProfileTablePassive, value); } else if (index == 10) { //Some meters are returning empty octet string here. if (value->vt == DLMS_DATA_TYPE_OCTET_STRING && value->byteArr != NULL) { var_init(&tm); ret = dlms_changeType2(value, DLMS_DATA_TYPE_DATETIME, &tm); if (ret != DLMS_ERROR_CODE_OK) { return ret; } time_copy(&object->time, tm.dateTime); var_clear(&tm); } else { time_clear(&object->time); } } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif // DLMS_IGNORE_ACTIVITY_CALENDAR #ifndef DLMS_IGNORE_ACTION_SCHEDULE int cosem_setActionSchedule( dlmsSettings* settings, gxActionSchedule* object, unsigned char index, dlmsVARIANT* value) { int ret = 0, pos; dlmsVARIANT* tmp; gxtime* tm; if (index == 2) { ret = va_getByIndex(value->Arr, 0, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } #ifndef DLMS_IGNORE_OBJECT_POINTERS if (ret == 0) { if ((ret = oa_findByLN(&settings->objects, DLMS_OBJECT_TYPE_SCRIPT_TABLE, tmp->byteArr->data, (gxObject**)&object->executedScript)) != 0) { //Error code is returned at the end of the function. } if (object->executedScript == NULL) { //create object. ret = cosem_createObject(DLMS_OBJECT_TYPE_SCRIPT_TABLE, (gxObject**)&object->executedScript); if (ret == DLMS_ERROR_CODE_OK) { ret = cosem_setLogicalName((gxObject*)object->executedScript, tmp->byteArr->data); if (ret == DLMS_ERROR_CODE_OK) { //Add object to released objects list. ret = oa_push(&settings->releasedObjects, (gxObject*)object->executedScript); } } } } #else memcpy(object->executedScriptLogicalName, tmp->byteArr->data, 6); #endif //DLMS_IGNORE_OBJECT_POINTERS ret = va_getByIndex(value->Arr, 1, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->executedScriptSelector = (uint16_t)var_toInteger(tmp); } else if (index == 3) { object->type = (DLMS_SINGLE_ACTION_SCHEDULE_TYPE)var_toInteger(value); } else if (index == 4) { arr_clear(&object->executionTime); dlmsVARIANT time, date; dlmsVARIANT* tmp2; var_init(&time); var_init(&date); if (value->Arr != NULL) { arr_capacity(&object->executionTime, value->Arr->size); for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = va_getByIndex(tmp->Arr, 0, &tmp2); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = dlms_changeType2(tmp2, DLMS_DATA_TYPE_TIME, &time); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = va_getByIndex(tmp->Arr, 1, &tmp2); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = dlms_changeType2(tmp2, DLMS_DATA_TYPE_DATE, &date); if (ret != DLMS_ERROR_CODE_OK) { return ret; } #ifdef DLMS_USE_EPOCH_TIME time_addHours(date.dateTime, time_getHours(time.dateTime)); time_addMinutes(date.dateTime, time_getMinutes(time.dateTime)); time_addSeconds(date.dateTime, time_getSeconds(time.dateTime)); date.dateTime->skip = (DATETIME_SKIPS)(date.dateTime->skip & time.dateTime->skip); #else date.dateTime->value.tm_hour = time.dateTime->value.tm_hour; date.dateTime->value.tm_min = time.dateTime->value.tm_min; date.dateTime->value.tm_sec = time.dateTime->value.tm_sec; date.dateTime->skip &= ~(DATETIME_SKIPS_HOUR | DATETIME_SKIPS_MINUTE | DATETIME_SKIPS_SECOND | DATETIME_SKIPS_MS); date.dateTime->skip |= time.dateTime->skip & (DATETIME_SKIPS_HOUR | DATETIME_SKIPS_MINUTE | DATETIME_SKIPS_SECOND | DATETIME_SKIPS_MS); #endif // DLMS_USE_EPOCH_TIME date.dateTime->deviation = (short)0x8000; date.dateTime->skip |= DATETIME_SKIPS_DEVITATION; tm = (gxtime*)gxmalloc(sizeof(gxtime)); if (tm == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } time_copy(tm, date.dateTime); arr_push(&object->executionTime, tm); var_clear(&time); var_clear(&date); } } } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_ACTION_SCHEDULE int cosem_updateAttributeAccessModes(gxObject* object, variantArray* arr) { unsigned char id; int ret; uint16_t pos, cnt; dlmsVARIANT* tmp, * it, * value; //If accessmodes are not returned. Some meters do not return them. if (arr->size != 2) { return 0; } ret = va_getByIndex(arr, 0, &tmp); if (ret != 0) { return ret; } //If access modes are not retrieved yet. if (object->access == NULL || object->access->attributeAccessModes.size == 0) { if (object->access == NULL) { object->access = (gxAccess*)gxcalloc(1, sizeof(gxAccess)); } cnt = obj_attributeCount(object); bb_capacity(&object->access->attributeAccessModes, cnt); object->access->attributeAccessModes.size = object->access->attributeAccessModes.capacity; cnt = obj_methodCount(object); bb_capacity(&object->access->methodAccessModes, cnt); object->access->methodAccessModes.size = object->access->methodAccessModes.capacity; } for (pos = 0; pos != tmp->Arr->size; ++pos) { ret = va_getByIndex(tmp->Arr, pos, &it); if (ret != 0) { return ret; } if (it->vt != DLMS_DATA_TYPE_STRUCTURE || it->Arr->size != 3) { return DLMS_ERROR_CODE_INVALID_PARAMETER; } //Get ID. ret = va_getByIndex(it->Arr, 0, &value); if (ret != 0) { return ret; } id = (unsigned char)var_toInteger(value); if (!(id > object->access->attributeAccessModes.size)) { ret = va_getByIndex(it->Arr, 1, &value); if (ret != 0) { return ret; } //DLMS_ACCESS_MODE object->access->attributeAccessModes.data[id - 1] = (unsigned char)var_toInteger(value); } } //Get method access modes. ret = va_getByIndex(arr, 1, &tmp); if (ret != 0) { return ret; } for (pos = 0; pos != tmp->Arr->size; ++pos) { ret = va_getByIndex(tmp->Arr, pos, &it); if (ret != 0) { return ret; } if (it->vt != DLMS_DATA_TYPE_STRUCTURE || it->Arr->size != 2) { return DLMS_ERROR_CODE_INVALID_PARAMETER; } //Get ID. ret = va_getByIndex(it->Arr, 0, &value); if (ret != 0) { return ret; } id = (unsigned char)var_toInteger(value); if (!(id > object->access->methodAccessModes.size)) { ret = va_getByIndex(it->Arr, 1, &value); if (ret != 0) { return ret; } //DLMS_METHOD_ACCESS_MODE object->access->methodAccessModes.data[id - 1] = (unsigned char)var_toInteger(value); } } return ret; } #ifndef DLMS_IGNORE_ASSOCIATION_LOGICAL_NAME int cosem_parseLNObjects(dlmsSettings* settings, gxByteBuffer* data, objectArray* objects) { gxObject* object; int ret; uint16_t pos, count; unsigned char size; oa_clear(&settings->objects, 1); unsigned char version; gxDataInfo info; DLMS_OBJECT_TYPE class_id = 0; dlmsVARIANT value; dlmsVARIANT* it1 = NULL, * it2 = NULL, * it3 = NULL, * ln = NULL; var_init(&value); //Get array tag. ret = bb_getUInt8(data, &size); if (ret != DLMS_ERROR_CODE_OK) { return ret; } //Check that data is in the array if (size != DLMS_DATA_TYPE_ARRAY) { return DLMS_ERROR_CODE_INVALID_RESPONSE; } //get object count if (hlp_getObjectCount2(data, &count) != 0) { return DLMS_ERROR_CODE_OUTOFMEMORY; } oa_capacity(objects, (uint16_t)count); for (pos = 0; pos != count; ++pos) { var_clear(&value); object = NULL; di_init(&info); if ((ret = dlms_getData(data, &info, &value)) != 0) { //This fixs Iskraemeco (MT-880) bug. if (ret == DLMS_ERROR_CODE_OUTOFMEMORY) { ret = 0; } break; } if (value.vt != DLMS_DATA_TYPE_STRUCTURE || value.Arr->size != 4) { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; break; } if ((ret = va_getByIndex(value.Arr, 0, &it1)) != 0 || (ret = va_getByIndex(value.Arr, 1, &it2)) != 0 || (ret = va_getByIndex(value.Arr, 2, &ln)) != 0 || (ret = va_getByIndex(value.Arr, 3, &it3)) != 0) { break; } if (it1->vt != DLMS_DATA_TYPE_UINT16 || it2->vt != DLMS_DATA_TYPE_UINT8 || ln->vt != DLMS_DATA_TYPE_OCTET_STRING || it3->vt != DLMS_DATA_TYPE_STRUCTURE || it3->Arr->size != 2) { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; break; } class_id = (DLMS_OBJECT_TYPE)var_toInteger(it1); version = (unsigned char)var_toInteger(it2); ret = cosem_createObject(class_id, &object); //If known object. if (ret == 0) { object->version = version; ret = cosem_updateAttributeAccessModes(object, it3->Arr); if (ret != 0) { break; } cosem_setLogicalName(object, ln->byteArr->data); oa_push(&settings->objects, object); oa_push(&settings->releasedObjects, object); } else { if (ret != DLMS_ERROR_CODE_UNAVAILABLE_OBJECT) { break; } ret = 0; } } var_clear(&value); return ret; } int cosem_setAssociationLogicalName( dlmsSettings* settings, gxAssociationLogicalName* object, unsigned char index, dlmsVARIANT* value) { int ret = 0, pos = 0; dlmsVARIANT* tmp, * tmp2; unsigned char ch; if (index == 2) { gxObject* obj = NULL; unsigned char version; DLMS_OBJECT_TYPE type; oa_empty(&object->objectList); if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = va_getByIndex(tmp->Arr, 0, &tmp2); if (ret != DLMS_ERROR_CODE_OK) { return ret; } type = (DLMS_OBJECT_TYPE)var_toInteger(tmp2); ret = va_getByIndex(tmp->Arr, 1, &tmp2); if (ret != DLMS_ERROR_CODE_OK) { return ret; } version = (unsigned char)var_toInteger(tmp2); //Get Logical name. ret = va_getByIndex(tmp->Arr, 2, &tmp2); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = oa_findByLN(&settings->objects, type, tmp2->byteArr->data, &obj); if (ret != DLMS_ERROR_CODE_OK) { return ret; } if (obj == NULL) { ret = cosem_createObject(type, &obj); if (ret != DLMS_ERROR_CODE_OK) { //If unknown object. if (ret == DLMS_ERROR_CODE_UNAVAILABLE_OBJECT || ret == DLMS_ERROR_CODE_INVALID_PARAMETER) { continue; } return ret; } ret = cosem_setLogicalName(obj, tmp2->byteArr->data); if (ret != DLMS_ERROR_CODE_OK) { return ret; } obj->version = (unsigned char)version; //Add object to released objects list. ret = oa_push(&settings->releasedObjects, obj); if (ret != DLMS_ERROR_CODE_OK) { return ret; } } ret = va_getByIndex(tmp->Arr, 3, &tmp2); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = cosem_updateAttributeAccessModes(obj, tmp2->Arr); if (ret != DLMS_ERROR_CODE_OK) { return ret; } oa_push(&object->objectList, obj); } } } else if (index == 3) { ret = va_getByIndex(value->Arr, 0, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->clientSAP = (unsigned char)var_toInteger(tmp); ret = va_getByIndex(value->Arr, 1, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->serverSAP = (uint16_t)var_toInteger(tmp); } else if (index == 4) { //Value of the object identifier encoded in BER if (value->vt == DLMS_DATA_TYPE_OCTET_STRING) { if (value->byteArr->data[0] == 0x60) { object->applicationContextName.jointIsoCtt = 0; object->applicationContextName.country = 0; object->applicationContextName.countryName = 0; ret = bb_getUInt8ByIndex(value->byteArr, 3, &object->applicationContextName.identifiedOrganization); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = bb_getUInt8ByIndex(value->byteArr, 4, &object->applicationContextName.dlmsUA); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = bb_getUInt8ByIndex(value->byteArr, 5, &object->applicationContextName.applicationContext); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = bb_getUInt8ByIndex(value->byteArr, 6, &object->applicationContextName.contextId); if (ret != DLMS_ERROR_CODE_OK) { return ret; } } else { //Get Tag. ret = bb_getUInt8(value->byteArr, &ch); if (ret != DLMS_ERROR_CODE_OK || ch != 2) { return DLMS_ERROR_CODE_INVALID_PARAMETER; } //Get Len. ret = bb_getUInt8(value->byteArr, &ch); if (ret != DLMS_ERROR_CODE_OK || ch != 7) { return DLMS_ERROR_CODE_INVALID_PARAMETER; } //Get tag ret = bb_getUInt8(value->byteArr, &ch); if (ret != DLMS_ERROR_CODE_OK || ch != 0x11) { return DLMS_ERROR_CODE_INVALID_PARAMETER; } ret = bb_getUInt8(value->byteArr, &object->applicationContextName.jointIsoCtt); if (ret != DLMS_ERROR_CODE_OK) { return DLMS_ERROR_CODE_INVALID_PARAMETER; } //Get tag ret = bb_getUInt8(value->byteArr, &ch); if (ret != DLMS_ERROR_CODE_OK || ch != 0x11) { return DLMS_ERROR_CODE_INVALID_PARAMETER; } ret = bb_getUInt8(value->byteArr, &object->applicationContextName.country); if (ret != DLMS_ERROR_CODE_OK) { return DLMS_ERROR_CODE_INVALID_PARAMETER; } //Get tag ret = bb_getUInt8(value->byteArr, &ch); if (ret != DLMS_ERROR_CODE_OK || ch != 0x12) { return DLMS_ERROR_CODE_INVALID_PARAMETER; } ret = bb_getUInt16(value->byteArr, &object->applicationContextName.countryName); if (ret != DLMS_ERROR_CODE_OK || ch != 0x12) { return DLMS_ERROR_CODE_INVALID_PARAMETER; } //Get tag ret = bb_getUInt8(value->byteArr, &ch); if (ret != DLMS_ERROR_CODE_OK || ch != 0x11) { return DLMS_ERROR_CODE_INVALID_PARAMETER; } ret = bb_getUInt8(value->byteArr, &object->applicationContextName.identifiedOrganization); if (ret != DLMS_ERROR_CODE_OK) { return DLMS_ERROR_CODE_INVALID_PARAMETER; } //Get tag ret = bb_getUInt8(value->byteArr, &ch); if (ret != DLMS_ERROR_CODE_OK || ch != 0x11) { return DLMS_ERROR_CODE_INVALID_PARAMETER; } ret = bb_getUInt8(value->byteArr, &object->applicationContextName.dlmsUA); if (ret != DLMS_ERROR_CODE_OK) { return DLMS_ERROR_CODE_INVALID_PARAMETER; } //Get tag ret = bb_getUInt8(value->byteArr, &ch); if (ret != DLMS_ERROR_CODE_OK || ch != 0x11) { return DLMS_ERROR_CODE_INVALID_PARAMETER; } ret = bb_getUInt8(value->byteArr, &object->applicationContextName.applicationContext); if (ret != DLMS_ERROR_CODE_OK) { return DLMS_ERROR_CODE_INVALID_PARAMETER; } //Get tag ret = bb_getUInt8(value->byteArr, &ch); if (ret != DLMS_ERROR_CODE_OK || ch != 0x11) { return DLMS_ERROR_CODE_INVALID_PARAMETER; } ret = bb_getUInt8(value->byteArr, &object->applicationContextName.contextId); if (ret != DLMS_ERROR_CODE_OK) { return DLMS_ERROR_CODE_INVALID_PARAMETER; } } } else if (value->vt == DLMS_DATA_TYPE_STRUCTURE) { ret = va_getByIndex(value->Arr, 0, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->applicationContextName.jointIsoCtt = (unsigned char)var_toInteger(tmp); ret = va_getByIndex(value->Arr, 1, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->applicationContextName.country = (unsigned char)var_toInteger(tmp); ret = va_getByIndex(value->Arr, 2, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->applicationContextName.countryName = (uint16_t)var_toInteger(tmp); ret = va_getByIndex(value->Arr, 3, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->applicationContextName.identifiedOrganization = (unsigned char)var_toInteger(tmp); ret = va_getByIndex(value->Arr, 4, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->applicationContextName.dlmsUA = (unsigned char)var_toInteger(tmp); ret = va_getByIndex(value->Arr, 5, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->applicationContextName.applicationContext = (unsigned char)var_toInteger(tmp); ret = va_getByIndex(value->Arr, 6, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->applicationContextName.contextId = (unsigned char)var_toInteger(tmp); } } else if (index == 5) { ret = va_getByIndex(value->Arr, 0, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->xDLMSContextInfo.conformance = (DLMS_CONFORMANCE)var_toInteger(tmp); ret = va_getByIndex(value->Arr, 1, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->xDLMSContextInfo.maxReceivePduSize = (uint16_t)var_toInteger(tmp); ret = va_getByIndex(value->Arr, 2, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->xDLMSContextInfo.maxSendPduSize = (uint16_t)var_toInteger(tmp); ret = va_getByIndex(value->Arr, 3, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->xDLMSContextInfo.dlmsVersionNumber = (unsigned char)var_toInteger(tmp); ret = va_getByIndex(value->Arr, 4, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->xDLMSContextInfo.qualityOfService = (unsigned char)var_toInteger(tmp); ret = va_getByIndex(value->Arr, 5, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } bb_clear(&object->xDLMSContextInfo.cypheringInfo); if (tmp->byteArr != NULL) { bb_set2(&object->xDLMSContextInfo.cypheringInfo, tmp->byteArr, 0, tmp->byteArr->size); } } else if (index == 6) { //Value of the object identifier encoded in BER if (value->vt == DLMS_DATA_TYPE_OCTET_STRING) { if (value->byteArr->data[0] == 0x60) { object->authenticationMechanismName.jointIsoCtt = 0; object->authenticationMechanismName.country = 0; object->authenticationMechanismName.countryName = 0; pos += 2; object->authenticationMechanismName.identifiedOrganization = value->byteArr->data[++pos]; object->authenticationMechanismName.dlmsUA = value->byteArr->data[++pos]; object->authenticationMechanismName.authenticationMechanismName = value->byteArr->data[++pos]; object->authenticationMechanismName.mechanismId = (DLMS_AUTHENTICATION)value->byteArr->data[++pos]; } else { if ((ret = cosem_checkStructure(value->byteArr, 7)) == 0 && (ret = cosem_getUInt8(value->byteArr, &object->authenticationMechanismName.jointIsoCtt)) == 0 && (ret = cosem_getUInt8(value->byteArr, &object->authenticationMechanismName.country)) == 0 && (ret = cosem_getUInt16(value->byteArr, &object->authenticationMechanismName.countryName)) == 0 && (ret = cosem_getUInt8(value->byteArr, &object->authenticationMechanismName.identifiedOrganization)) == 0 && (ret = cosem_getUInt8(value->byteArr, &object->authenticationMechanismName.dlmsUA)) == 0 && (ret = cosem_getUInt8(value->byteArr, &object->authenticationMechanismName.authenticationMechanismName)) == 0 && (ret = cosem_getUInt8(value->byteArr, &ch)) == 0) { object->authenticationMechanismName.mechanismId = (DLMS_AUTHENTICATION)ch; } } } else if (value->vt == DLMS_DATA_TYPE_STRUCTURE) { ret = va_getByIndex(value->Arr, 0, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->authenticationMechanismName.jointIsoCtt = (unsigned char)var_toInteger(tmp); ret = va_getByIndex(value->Arr, 1, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->authenticationMechanismName.country = (unsigned char)var_toInteger(tmp); ret = va_getByIndex(value->Arr, 2, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->authenticationMechanismName.countryName = (uint16_t)var_toInteger(tmp); ret = va_getByIndex(value->Arr, 3, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->authenticationMechanismName.identifiedOrganization = (unsigned char)var_toInteger(tmp); ret = va_getByIndex(value->Arr, 4, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->authenticationMechanismName.dlmsUA = (unsigned char)var_toInteger(tmp); ret = va_getByIndex(value->Arr, 5, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->authenticationMechanismName.authenticationMechanismName = (unsigned char)var_toInteger(tmp); ret = va_getByIndex(value->Arr, 6, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->authenticationMechanismName.mechanismId = (DLMS_AUTHENTICATION)var_toInteger(tmp); } } else if (index == 7) { bb_clear(&object->secret); if (value->byteArr != NULL) { ret = bb_set2(&object->secret, value->byteArr, 0, bb_size(value->byteArr)); } } else if (index == 8) { object->associationStatus = (DLMS_ASSOCIATION_STATUS)var_toInteger(value); } else if (index == 9) { if (bb_size(value->byteArr) != 6) { return DLMS_ERROR_CODE_UNMATCH_TYPE; } #if !(defined(DLMS_IGNORE_OBJECT_POINTERS) || defined(DLMS_IGNORE_SECURITY_SETUP)) ret = oa_findByLN(&settings->objects, DLMS_OBJECT_TYPE_SECURITY_SETUP, value->byteArr->data, (gxObject**)&object->securitySetup); #else memcpy(object->securitySetupReference, value->byteArr->data, 6); #endif //!(defined(DLMS_IGNORE_OBJECT_POINTERS) || defined(DLMS_IGNORE_SECURITY_SETUP)) } else if (index == 10) { obj_clearUserList(&object->userList); if (value->Arr != NULL) { gxKey2* it; for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = va_getByIndex(tmp->Arr, 0, &tmp2); if (ret != DLMS_ERROR_CODE_OK) { return ret; } it = (gxKey2*)gxmalloc(sizeof(gxKey2)); if (it == NULL) { return DLMS_ERROR_CODE_OUTOFMEMORY; } it->key = (unsigned char)var_toInteger(tmp2); ret = va_getByIndex(tmp->Arr, 1, &tmp2); if (ret != DLMS_ERROR_CODE_OK) { return ret; } it->value = (char*)gxmalloc(tmp->strVal->size + 1); if (it->value == NULL) { return DLMS_ERROR_CODE_OUTOFMEMORY; } ((char*)it->value)[tmp->strVal->size] = 0; memcpy(it->value, tmp->strVal->data, tmp->strVal->size); arr_push(&object->userList, it); } } } else if (index == 11) { if (object->currentUser.value != NULL) { gxfree(object->currentUser.value); } if (value->Arr->size == 2) { ret = va_getByIndex(value->Arr, 0, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->currentUser.key = (unsigned char)var_toInteger(tmp); ret = va_getByIndex(value->Arr, 1, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } if (tmp->strVal != NULL && tmp->strVal->size != 0) { object->currentUser.value = gxmalloc(tmp->strVal->size + 1); if (object->currentUser.value == NULL) { return DLMS_ERROR_CODE_OUTOFMEMORY; } memcpy(object->currentUser.value, tmp->strVal, tmp->strVal->size); } } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_ASSOCIATION_LOGICAL_NAME #ifndef DLMS_IGNORE_ASSOCIATION_SHORT_NAME int updateSNAccessRights( objectArray* objectList, variantArray* data) { uint16_t sn; int pos, ret; dlmsVARIANT* it, * tmp; gxObject* obj = NULL; for (pos = 0; pos != data->size; ++pos) { ret = va_getByIndex(data, pos, &it); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = va_getByIndex(it->Arr, 0, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } sn = (uint16_t)var_toInteger(tmp); ret = oa_findBySN(objectList, sn, &obj); if (ret != DLMS_ERROR_CODE_OK) { return ret; } if (obj != NULL) { ret = cosem_updateAttributeAccessModes(obj, it->Arr); if (ret != DLMS_ERROR_CODE_OK) { return ret; } /* ret = va_getByIndex(it->Arr, 1, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } //Update attribute Access for(pos2 = 0; pos2 != tmp->Arr.size; ++pos2) { ret = va_getByIndex(tmp->Arr, pos, &access); if (ret != DLMS_ERROR_CODE_OK) { return ret; } //Get attribute ID. ret = va_getByIndex(&access->Arr, 0, &tmp2); if (ret != DLMS_ERROR_CODE_OK) { return ret; } //TODO: id = var_toInteger(tmp2); //Get access mode. ret = va_getByIndex(&access->Arr, 1, &tmp2); if (ret != DLMS_ERROR_CODE_OK) { return ret; } //TODO: obj->SetAccess(id, (DLMS_ACCESS_MODE) var_toInteger(tmp2)); } //Update method Access ret = va_getByIndex(it->Arr, 1, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } for(pos2 = 0; pos2 != tmp->Arr.size; ++pos2) { ret = va_getByIndex(tmp->Arr, pos, &access); if (ret != DLMS_ERROR_CODE_OK) { return ret; } //Get attribute ID. ret = va_getByIndex(&access->Arr, 0, &tmp2); if (ret != DLMS_ERROR_CODE_OK) { return ret; } //TODO: id = var_toInteger(tmp2); //Get access mode. ret = va_getByIndex(&access->Arr, 1, &tmp2); if (ret != DLMS_ERROR_CODE_OK) { return ret; } //TODO: obj->SetMethodAccess(id, (DLMS_ACCESS_MODE) var_toInteger(tmp2)); } */ } } return DLMS_ERROR_CODE_OK; } int cosem_parseSNObjects(dlmsSettings* settings, gxByteBuffer* data, objectArray* objects) { gxDataInfo info; short sn; DLMS_OBJECT_TYPE class_id; dlmsVARIANT value; dlmsVARIANT* it1 = NULL, * it2 = NULL, * it3 = NULL, * ln = NULL; gxObject* object; int ret; uint16_t count, pos; unsigned char size, version; var_init(&value); //Get array tag. if ((ret = bb_getUInt8(data, &size)) != DLMS_ERROR_CODE_OK) { return 0; } //Check that data is in the array if (size != 0x01) { return DLMS_ERROR_CODE_INVALID_RESPONSE; } //get object count if ((ret = hlp_getObjectCount2(data, &count)) != 0) { return ret; } oa_capacity(objects, (uint16_t)count); for (pos = 0; pos != count; ++pos) { var_clear(&value); object = NULL; di_init(&info); if ((ret = dlms_getData(data, &info, &value)) != 0) { break; } if (value.vt != DLMS_DATA_TYPE_STRUCTURE || value.Arr->size != 4) { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; break; } if ((ret = va_getByIndex(value.Arr, 0, &it1)) != 0 || (ret = va_getByIndex(value.Arr, 1, &it2)) != 0 || (ret = va_getByIndex(value.Arr, 2, &it3)) != 0 || (ret = va_getByIndex(value.Arr, 3, &ln)) != 0) { break; } if (it1->vt != DLMS_DATA_TYPE_INT16 || it2->vt != DLMS_DATA_TYPE_UINT16 || it3->vt != DLMS_DATA_TYPE_UINT8 || ln->vt != DLMS_DATA_TYPE_OCTET_STRING) { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; break; } sn = (short)var_toInteger(it1); class_id = (DLMS_OBJECT_TYPE)var_toInteger(it2); version = (unsigned char)var_toInteger(it3); ret = cosem_createObject(class_id, &object); //If known object. if (ret == 0) { object->shortName = sn; object->version = version; cosem_setLogicalName(object, ln->byteArr->data); oa_push(objects, object); oa_push(&settings->releasedObjects, object); } else { if (ret != DLMS_ERROR_CODE_UNAVAILABLE_OBJECT) { break; } ret = 0; } } var_clear(&value); return ret; } int cosem_setAssociationShortName( dlmsSettings* settings, gxAssociationShortName* object, unsigned char index, dlmsVARIANT* value) { int ret; int pos; if (index == 2) { dlmsVARIANT* it, * it1 = NULL, * it2 = NULL, * it3 = NULL, * ln = NULL; unsigned char version; short sn; DLMS_OBJECT_TYPE class_id; gxObject* obj; oa_empty(&object->objectList); if ((ret = oa_capacity(&object->objectList, value->Arr->size)) == 0) { for (pos = 0; pos != value->Arr->size; ++pos) { obj = NULL; if ((ret = va_getByIndex(value->Arr, 0, &it)) != 0 || (ret = va_getByIndex(it->Arr, 0, &it1)) != 0 || (ret = va_getByIndex(it->Arr, 1, &it2)) != 0 || (ret = va_getByIndex(it->Arr, 2, &it3)) != 0 || (ret = va_getByIndex(it->Arr, 3, &ln)) != 0) { break; } if (it1->vt != DLMS_DATA_TYPE_INT16 || it2->vt != DLMS_DATA_TYPE_UINT16 || it3->vt != DLMS_DATA_TYPE_UINT8 || ln->vt != DLMS_DATA_TYPE_OCTET_STRING) { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; break; } sn = (short)var_toInteger(it1); class_id = (DLMS_OBJECT_TYPE)var_toInteger(it2); version = (unsigned char)var_toInteger(it3); ret = cosem_createObject(class_id, &obj); //If known object. if (ret == 0) { obj->shortName = sn; obj->version = version; cosem_setLogicalName(obj, ln->byteArr->data); oa_push(&object->objectList, obj); oa_push(&settings->releasedObjects, obj); } else { if (ret != DLMS_ERROR_CODE_UNAVAILABLE_OBJECT) { break; } ret = 0; } } } } else if (index == 3) { ret = updateSNAccessRights(&object->objectList, value->Arr); } else if (index == 4) { if (bb_size(value->byteArr) != 6) { ret = DLMS_ERROR_CODE_UNMATCH_TYPE; } else { #ifndef DLMS_IGNORE_SECURITY_SETUP #ifndef DLMS_IGNORE_OBJECT_POINTERS ret = oa_findByLN(&settings->objects, DLMS_OBJECT_TYPE_SECURITY_SETUP, value->byteArr->data, (gxObject**)&object->securitySetup); #else memcpy(object->securitySetupReference, value->byteArr->data, 6); #endif //DLMS_IGNORE_OBJECT_POINTERS #endif // DLMS_IGNORE_SECURITY_SETUP } } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_ASSOCIATION_SHORT_NAME #ifndef DLMS_IGNORE_AUTO_ANSWER int cosem_setAutoAnswer(gxAutoAnswer* object, unsigned char index, dlmsVARIANT* value) { int ret = 0, pos; dlmsVARIANT* tmp; if (index == 2) { object->mode = (DLMS_AUTO_ANSWER_MODE)var_toInteger(value); } else if (index == 3) { arr_clearKeyValuePair(&object->listeningWindow); dlmsVARIANT* tmp3; dlmsVARIANT start, end; gxtime* s, * e; if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = va_getByIndex(tmp->Arr, 0, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { return ret; } var_init(&start); var_init(&end); ret = dlms_changeType2(tmp3, DLMS_DATA_TYPE_DATETIME, &start); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = va_getByIndex(tmp->Arr, 1, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = dlms_changeType2(tmp3, DLMS_DATA_TYPE_DATETIME, &end); if (ret != DLMS_ERROR_CODE_OK) { return ret; } s = (gxtime*)gxmalloc(sizeof(gxtime)); e = (gxtime*)gxmalloc(sizeof(gxtime)); time_copy(s, start.dateTime); time_copy(e, end.dateTime); arr_push(&object->listeningWindow, key_init(s, e)); var_clear(&start); var_clear(&end); } } } else if (index == 4) { object->status = (DLMS_AUTO_ANSWER_STATUS)var_toInteger(value); } else if (index == 5) { object->numberOfCalls = (unsigned char)var_toInteger(value); } else if (index == 6) { ret = va_getByIndex(value->Arr, 0, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->numberOfRingsInListeningWindow = (unsigned char)var_toInteger(tmp); ret = va_getByIndex(value->Arr, 1, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->numberOfRingsOutListeningWindow = (unsigned char)var_toInteger(tmp); } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_AUTO_ANSWER #ifndef DLMS_IGNORE_AUTO_CONNECT int cosem_setAutoConnect(gxAutoConnect* object, unsigned char index, dlmsVARIANT* value) { int ret = 0, pos; if (index == 2) { object->mode = (DLMS_AUTO_CONNECT_MODE)var_toInteger(value); } else if (index == 3) { object->repetitions = (unsigned char)var_toInteger(value); } else if (index == 4) { object->repetitionDelay = (uint16_t)var_toInteger(value); } else if (index == 5) { dlmsVARIANT* tmp, * tmp3; dlmsVARIANT start, end; arr_clearKeyValuePair(&object->callingWindow); if (value->Arr != NULL) { if ((ret = arr_capacity(&object->callingWindow, value->Arr->size)) == 0) { for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = va_getByIndex(tmp->Arr, 0, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { return ret; } gxtime* s, * e; var_init(&start); var_init(&end); ret = dlms_changeType2(tmp3, DLMS_DATA_TYPE_DATETIME, &start); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = va_getByIndex(tmp->Arr, 1, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = dlms_changeType2(tmp3, DLMS_DATA_TYPE_DATETIME, &end); if (ret != DLMS_ERROR_CODE_OK) { return ret; } s = (gxtime*)gxmalloc(sizeof(gxtime)); e = (gxtime*)gxmalloc(sizeof(gxtime)); arr_push(&object->callingWindow, key_init(s, e)); time_copy(s, start.dateTime); time_copy(e, end.dateTime); var_clear(&start); var_clear(&end); } } } } else if (index == 6) { dlmsVARIANT* tmp; gxByteBuffer* str; arr_clearStrings(&object->destinations); if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } str = (gxByteBuffer*)gxmalloc(sizeof(gxByteBuffer)); BYTE_BUFFER_INIT(str); bb_set2(str, tmp->byteArr, 0, bb_size(tmp->byteArr)); arr_push(&object->destinations, str); } } } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_AUTO_CONNECT #ifndef DLMS_IGNORE_DEMAND_REGISTER int cosem_setDemandRegister(gxDemandRegister* object, unsigned char index, dlmsVARIANT* value) { int ret = DLMS_ERROR_CODE_OK; dlmsVARIANT* tmp; dlmsVARIANT tmp2; if (index == 2) { ret = var_copy(&object->currentAverageValue, value); } else if (index == 3) { ret = var_copy(&object->lastAverageValue, value); } else if (index == 4) { if (value->vt != DLMS_DATA_TYPE_STRUCTURE) { return DLMS_ERROR_CODE_INVALID_PARAMETER; } ret = va_getByIndex(value->Arr, 0, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->scaler = (char)var_toInteger(tmp); ret = va_getByIndex(value->Arr, 1, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->unit = (unsigned char)var_toInteger(tmp); object->unitRead = 1; } else if (index == 5) { ret = var_copy(&object->status, value); } else if (index == 6) { //Some meters are returning empty octet string here. if (value->vt == DLMS_DATA_TYPE_OCTET_STRING && value->byteArr != NULL) { ret = var_init(&tmp2); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = dlms_changeType2(value, DLMS_DATA_TYPE_DATETIME, &tmp2); if (ret != DLMS_ERROR_CODE_OK) { return ret; } time_copy(&object->captureTime, tmp2.dateTime); var_clear(&tmp2); } else { time_clear(&object->captureTime); } } else if (index == 7) { //Some meters are returning empty octet string here. if (value->vt == DLMS_DATA_TYPE_OCTET_STRING && value->byteArr != NULL) { ret = var_init(&tmp2); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = dlms_changeType2(value, DLMS_DATA_TYPE_DATETIME, &tmp2); if (ret != DLMS_ERROR_CODE_OK) { return ret; } time_copy(&object->startTimeCurrent, tmp2.dateTime); var_clear(&tmp2); } else { time_clear(&object->startTimeCurrent); } } else if (index == 8) { object->period = var_toInteger(value); } else if (index == 9) { object->numberOfPeriods = (uint16_t)var_toInteger(value); } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_DEMAND_REGISTER #ifndef DLMS_IGNORE_MAC_ADDRESS_SETUP int cosem_setMacAddressSetup(gxMacAddressSetup* object, unsigned char index, dlmsVARIANT* value) { int ret = DLMS_ERROR_CODE_OK; if (index == 2) { bb_clear(&object->macAddress); ret = bb_set2(&object->macAddress, value->byteArr, 0, bb_size(value->byteArr)); } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_MAC_ADDRESS_SETUP #ifndef DLMS_IGNORE_EXTENDED_REGISTER int cosem_setExtendedRegister(gxExtendedRegister* object, unsigned char index, dlmsVARIANT* value) { int ret = DLMS_ERROR_CODE_OK; dlmsVARIANT* tmp; dlmsVARIANT tmp2; if (index == 2) { ret = var_copy(&object->value, value); } else if (index == 3) { if (value->vt != DLMS_DATA_TYPE_STRUCTURE) { return DLMS_ERROR_CODE_INVALID_PARAMETER; } ret = va_getByIndex(value->Arr, 0, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->scaler = (char)var_toInteger(tmp); ret = va_getByIndex(value->Arr, 1, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->unit = (unsigned char)var_toInteger(tmp); } else if (index == 4) { ret = var_copy(&object->status, value); } else if (index == 5) { if (value->vt == DLMS_DATA_TYPE_OCTET_STRING) { ret = var_init(&tmp2); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = dlms_changeType2(value, DLMS_DATA_TYPE_DATETIME, &tmp2); if (ret == 0) { time_copy(&object->captureTime, tmp2.dateTime); var_clear(&tmp2); } } else { time_copy(&object->captureTime, value->dateTime); } } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_EXTENDED_REGISTER #ifndef DLMS_IGNORE_GPRS_SETUP int cosem_setGprsSetup(gxGPRSSetup* object, unsigned char index, dlmsVARIANT* value) { int ret; if (index == 2) { bb_clear(&object->apn); if (value->vt == DLMS_DATA_TYPE_STRING) { bb_set(&object->apn, (unsigned char*)value->strVal->data, value->strVal->size); } else { bb_set2(&object->apn, value->byteArr, 0, bb_size(value->byteArr)); } } else if (index == 3) { object->pinCode = value->uiVal; } else if (index == 4) { dlmsVARIANT* tmp; dlmsVARIANT* tmp3; ret = va_getByIndex(value->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; } object->defaultQualityOfService.precedence = (unsigned char)var_toInteger(tmp3); ret = va_getByIndex(tmp->Arr, 1, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->defaultQualityOfService.delay = (unsigned char)var_toInteger(tmp3); ret = va_getByIndex(tmp->Arr, 2, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->defaultQualityOfService.reliability = (unsigned char)var_toInteger(tmp3); ret = va_getByIndex(tmp->Arr, 3, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->defaultQualityOfService.peakThroughput = (unsigned char)var_toInteger(tmp3); ret = va_getByIndex(tmp->Arr, 4, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->defaultQualityOfService.meanThroughput = (unsigned char)var_toInteger(tmp3); ret = va_getByIndex(value->Arr, 1, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = va_getByIndex(tmp->Arr, 0, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->requestedQualityOfService.precedence = (unsigned char)var_toInteger(tmp3); ret = va_getByIndex(tmp->Arr, 1, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->requestedQualityOfService.delay = (unsigned char)var_toInteger(tmp3); ret = va_getByIndex(tmp->Arr, 2, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->requestedQualityOfService.reliability = (unsigned char)var_toInteger(tmp3); ret = va_getByIndex(tmp->Arr, 3, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->requestedQualityOfService.peakThroughput = (unsigned char)var_toInteger(tmp3); ret = va_getByIndex(tmp->Arr, 4, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->requestedQualityOfService.meanThroughput = (unsigned char)var_toInteger(tmp3); } else { return DLMS_ERROR_CODE_INVALID_PARAMETER; } return DLMS_ERROR_CODE_OK; } #endif //DLMS_IGNORE_GPRS_SETUP #ifndef DLMS_IGNORE_SECURITY_SETUP int cosem_setSecuritySetup(dlmsSettings* settings, gxSecuritySetup* object, unsigned char index, dlmsVARIANT* value) { int pos, ret = 0; gxCertificateInfo* it = NULL; dlmsVARIANT* tmp, * tmp3; switch (index) { case 2: object->securityPolicy = (DLMS_SECURITY_POLICY)var_toInteger(value); break; case 3: object->securitySuite = (DLMS_SECURITY_SUITE)var_toInteger(value); break; case 4: if ((ret = bb_clear(&object->clientSystemTitle)) == 0) { if (!(value->byteArr == NULL || bb_available(value->byteArr) != 8)) { ret = bb_set2(&object->clientSystemTitle, value->byteArr, value->byteArr->position, 8); } } break; case 5: if ((ret = bb_clear(&object->serverSystemTitle)) == 0) { if (!(value->byteArr == NULL || bb_available(value->byteArr) != 8)) { ret = bb_set2(&object->serverSystemTitle, value->byteArr, value->byteArr->position, 8); } } break; case 6: obj_clearCertificateInfo(&object->certificates); if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { if ((ret = va_getByIndex(value->Arr, pos, &tmp)) != DLMS_ERROR_CODE_OK) { break; } it = (gxCertificateInfo*)gxmalloc(sizeof(gxCertificateInfo)); if (it == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } //entity if ((ret = va_getByIndex(tmp->Arr, 0, &tmp3)) != DLMS_ERROR_CODE_OK) { break; } it->entity = (DLMS_CERTIFICATE_ENTITY)var_toInteger(tmp3); //type if ((ret = va_getByIndex(tmp->Arr, 1, &tmp3)) != DLMS_ERROR_CODE_OK) { break; } it->type = (DLMS_CERTIFICATE_TYPE)var_toInteger(tmp3); //serialNumber if ((ret = va_getByIndex(tmp->Arr, 2, &tmp3)) != DLMS_ERROR_CODE_OK) { break; } if (tmp3->byteArr != NULL && tmp3->byteArr->size != 0) { it->serialNumber = gxmalloc(tmp3->byteArr->size + 1); if (it->serialNumber == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; } memcpy(it->serialNumber, tmp3->byteArr->data, tmp3->byteArr->size); it->serialNumber[tmp3->byteArr->size] = 0; } else { it->serialNumber = NULL; } //issuer if ((ret = va_getByIndex(tmp->Arr, 3, &tmp3)) != DLMS_ERROR_CODE_OK) { break; } if (tmp3->byteArr != NULL && tmp3->byteArr->size != 0) { it->issuer = gxmalloc(tmp3->byteArr->size + 1); if (it->issuer == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } memcpy(it->issuer, tmp3->byteArr->data, tmp3->byteArr->size); it->issuer[tmp3->byteArr->size] = 0; } else { it->issuer = NULL; } //subject if ((ret = va_getByIndex(tmp->Arr, 4, &tmp3)) != DLMS_ERROR_CODE_OK) { break; } if (tmp3->byteArr != NULL && tmp3->byteArr->size != 0) { it->subject = gxmalloc(tmp3->byteArr->size + 1); if (it->subject == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } memcpy(it->subject, tmp3->byteArr->data, tmp3->byteArr->size); it->subject[tmp3->byteArr->size] = 0; } else { it->subject = NULL; } //subjectAltName. if ((ret = va_getByIndex(tmp->Arr, 5, &tmp3)) != DLMS_ERROR_CODE_OK) { break; } if (tmp3->byteArr != NULL && tmp3->byteArr->size != 0) { it->subjectAltName = gxmalloc(tmp3->byteArr->size + 1); if (it->subjectAltName == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } memcpy(it->subjectAltName, tmp3->byteArr->data, tmp3->byteArr->size); it->subjectAltName[tmp3->byteArr->size] = 0; } else { it->subjectAltName = NULL; } arr_push(&object->certificates, it); } if (ret != 0 && it != NULL) { if (it->serialNumber != NULL) { gxfree(it->serialNumber); } if (it->subject != NULL) { gxfree(it->subject); } if (it->issuer != NULL) { gxfree(it->issuer); } gxfree(it); } } break; default: ret = DLMS_ERROR_CODE_READ_WRITE_DENIED; } return ret; } #endif //DLMS_IGNORE_SECURITY_SETUP #ifndef DLMS_IGNORE_IEC_HDLC_SETUP int cosem_setIecHdlcSetup(gxIecHdlcSetup* object, unsigned char index, dlmsVARIANT* value) { if (index == 2) { object->communicationSpeed = (DLMS_BAUD_RATE)var_toInteger(value); } else if (index == 3) { object->windowSizeTransmit = (unsigned char)var_toInteger(value); } else if (index == 4) { object->windowSizeReceive = (unsigned char)var_toInteger(value); } else if (index == 5) { object->maximumInfoLengthTransmit = (uint16_t)var_toInteger(value); } else if (index == 6) { object->maximumInfoLengthReceive = (uint16_t)var_toInteger(value); } else if (index == 7) { object->interCharachterTimeout = (uint16_t)var_toInteger(value); } else if (index == 8) { object->inactivityTimeout = (uint16_t)var_toInteger(value); } else if (index == 9) { object->deviceAddress = (uint16_t)var_toInteger(value); } else { return DLMS_ERROR_CODE_INVALID_PARAMETER; } return DLMS_ERROR_CODE_OK; } #endif //DLMS_IGNORE_IEC_HDLC_SETUP #ifndef DLMS_IGNORE_IEC_LOCAL_PORT_SETUP int cosem_setIecLocalPortSetup(gxLocalPortSetup* object, unsigned char index, dlmsVARIANT* value) { int ret = 0; if (index == 2) { object->defaultMode = (DLMS_OPTICAL_PROTOCOL_MODE)var_toInteger(value); } else if (index == 3) { object->defaultBaudrate = (DLMS_BAUD_RATE)var_toInteger(value); } else if (index == 4) { object->proposedBaudrate = (DLMS_BAUD_RATE)var_toInteger(value); } else if (index == 5) { object->responseTime = (DLMS_LOCAL_PORT_RESPONSE_TIME)var_toInteger(value); } else if (index == 6) { bb_clear(&object->deviceAddress); ret = bb_set2(&object->deviceAddress, value->byteArr, 0, bb_size(value->byteArr)); } else if (index == 7) { bb_clear(&object->password1); ret = bb_set2(&object->password1, value->byteArr, 0, bb_size(value->byteArr)); } else if (index == 8) { bb_clear(&object->password2); ret = bb_set2(&object->password2, value->byteArr, 0, bb_size(value->byteArr)); } else if (index == 9) { bb_clear(&object->password5); ret = bb_set2(&object->password5, value->byteArr, 0, bb_size(value->byteArr)); } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_IEC_LOCAL_PORT_SETUP #ifndef DLMS_IGNORE_IEC_TWISTED_PAIR_SETUP int cosem_setIecTwistedPairSetup(gxIecTwistedPairSetup* object, unsigned char index, dlmsVARIANT* value) { int pos, ret = 0; dlmsVARIANT* tmp; if (index == 2) { object->mode = var_toInteger(value); } else if (index == 3) { object->speed = var_toInteger(value); } else if (index == 4) { bb_clear(&object->primaryAddresses); if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { if ((ret = va_getByIndex(value->Arr, pos, &tmp)) != DLMS_ERROR_CODE_OK || (ret = bb_setUInt8(&object->primaryAddresses, tmp->bVal)) != DLMS_ERROR_CODE_OK) { break; } } } } else if (index == 5) { bb_clear(&object->tabis); if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { if ((ret = va_getByIndex(value->Arr, pos, &tmp)) != DLMS_ERROR_CODE_OK || (ret = bb_setUInt8(&object->tabis, tmp->bVal)) != DLMS_ERROR_CODE_OK) { break; } } } } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_IEC_TWISTED_PAIR_SETUP #ifndef DLMS_IGNORE_IP4_SETUP int cosem_setIP4Setup(dlmsSettings* settings, gxIp4Setup* object, unsigned char index, dlmsVARIANT* value) { int ret = 0, pos; dlmsVARIANT* tmp, * tmp3; gxip4SetupIpOption* ipItem = NULL; if (index == 2) { #ifndef DLMS_IGNORE_OBJECT_POINTERS if ((ret = oa_findByLN(&settings->objects, DLMS_OBJECT_TYPE_NONE, value->byteArr->data, &object->dataLinkLayer)) != 0) { return ret; } #else ret = bb_get(value->byteArr, object->dataLinkLayerReference, 6); #endif //DLMS_IGNORE_OBJECT_POINTERS } else if (index == 3) { object->ipAddress = var_toInteger(value); } else if (index == 4) { va_clear(&object->multicastIPAddress); if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { if ((ret = va_getByIndex(value->Arr, pos, &tmp)) != DLMS_ERROR_CODE_OK) { break; } tmp3 = (dlmsVARIANT*)gxmalloc(sizeof(dlmsVARIANT)); if ((ret = var_init(tmp3)) != 0 || (ret = var_copy(tmp, tmp3)) != 0 || (ret = va_push(&object->multicastIPAddress, tmp3)) != 0) { break; } } } } else if (index == 5) { arr_clear(&object->ipOptions); if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { ipItem = NULL; ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } ret = va_getByIndex(tmp->Arr, 0, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } ipItem = (gxip4SetupIpOption*)gxmalloc(sizeof(gxip4SetupIpOption)); if (ipItem == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } BYTE_BUFFER_INIT(&ipItem->data); ipItem->type = (DLMS_IP_OPTION_TYPE)var_toInteger(tmp3); ret = va_getByIndex(tmp->Arr, 1, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } ipItem->length = (unsigned char)var_toInteger(tmp3); ret = va_getByIndex(tmp->Arr, 2, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } bb_set(&ipItem->data, tmp3->byteArr->data, tmp3->byteArr->size); arr_push(&object->ipOptions, ipItem); } if (ret != DLMS_ERROR_CODE_OK && ipItem != NULL) { gxfree(ipItem); } } } else if (index == 6) { object->subnetMask = var_toInteger(value); } else if (index == 7) { object->gatewayIPAddress = var_toInteger(value); } else if (index == 8) { object->useDHCP = value->boolVal; } else if (index == 9) { object->primaryDNSAddress = var_toInteger(value); } else if (index == 10) { object->secondaryDNSAddress = var_toInteger(value); } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_IP4_SETUP #ifndef DLMS_IGNORE_IP6_SETUP int cosem_setIP6Setup(dlmsSettings* settings, gxIp6Setup* object, unsigned char index, dlmsVARIANT* value) { int ret = 0, pos; dlmsVARIANT* tmp, * tmp3; IN6_ADDR* ip; gxNeighborDiscoverySetup* it; if (index == 2) { #ifndef DLMS_IGNORE_OBJECT_POINTERS if ((ret = oa_findByLN(&settings->objects, DLMS_OBJECT_TYPE_NONE, value->byteArr->data, &object->dataLinkLayer)) != 0) { return ret; } #else ret = bb_get(value->byteArr, object->dataLinkLayerReference, 6); #endif //DLMS_IGNORE_OBJECT_POINTERS } else if (index == 3) { object->addressConfigMode = var_toInteger(value); } else if (index == 4) { arr_clear(&object->unicastIPAddress); if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { if ((ret = va_getByIndex(value->Arr, pos, &tmp)) != DLMS_ERROR_CODE_OK) { break; } if (tmp->byteArr->size != 16) { ret = DLMS_ERROR_CODE_INCONSISTENT_CLASS_OR_OBJECT; break; } ip = (IN6_ADDR*)gxmalloc(sizeof(IN6_ADDR)); memcpy(ip, tmp->byteArr->data, tmp->byteArr->size); if ((ret = arr_push(&object->unicastIPAddress, ip)) != 0) { break; } } } } else if (index == 5) { arr_clear(&object->multicastIPAddress); if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { if ((ret = va_getByIndex(value->Arr, pos, &tmp)) != DLMS_ERROR_CODE_OK) { break; } if (tmp->byteArr->size != 16) { ret = DLMS_ERROR_CODE_INCONSISTENT_CLASS_OR_OBJECT; break; } ip = (IN6_ADDR*)gxmalloc(sizeof(IN6_ADDR)); memcpy(ip, tmp->byteArr->data, tmp->byteArr->size); if ((ret = arr_push(&object->multicastIPAddress, ip)) != 0) { break; } } } } else if (index == 6) { arr_clear(&object->gatewayIPAddress); if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { if ((ret = va_getByIndex(value->Arr, pos, &tmp)) != DLMS_ERROR_CODE_OK) { break; } if (tmp->byteArr->size != 16) { ret = DLMS_ERROR_CODE_INCONSISTENT_CLASS_OR_OBJECT; break; } ip = (IN6_ADDR*)gxmalloc(sizeof(IN6_ADDR)); memcpy(ip, tmp->byteArr->data, tmp->byteArr->size); if ((ret = arr_push(&object->gatewayIPAddress, ip)) != 0) { break; } } } } else if (index == 7) { if (bb_size(value->byteArr) == 0) { memset(&object->primaryDNSAddress, 0, sizeof(IN6_ADDR)); } else if (bb_size(value->byteArr) != 16) { ret = DLMS_ERROR_CODE_INCONSISTENT_CLASS_OR_OBJECT; } else { memcpy(&object->primaryDNSAddress, value->byteArr->data, value->byteArr->size); } } else if (index == 8) { if (bb_size(value->byteArr) == 0) { memset(&object->secondaryDNSAddress, 0, sizeof(IN6_ADDR)); } else if (bb_size(value->byteArr) != 16) { ret = DLMS_ERROR_CODE_INCONSISTENT_CLASS_OR_OBJECT; } else { memcpy(&object->secondaryDNSAddress, value->byteArr->data, value->byteArr->size); } } else if (index == 9) { object->trafficClass = (DLMS_IP6_ADDRESS_CONFIG_MODE)var_toInteger(value); } else if (index == 10) { arr_clear(&object->neighborDiscoverySetup); if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { if ((ret = va_getByIndex(value->Arr, pos, &tmp)) != DLMS_ERROR_CODE_OK) { break; } it = (gxNeighborDiscoverySetup*)gxmalloc(sizeof(gxNeighborDiscoverySetup)); if (it == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } if ((ret = va_getByIndex(tmp->Arr, 0, &tmp3)) != DLMS_ERROR_CODE_OK) { break; } it->maxRetry = (unsigned char)var_toInteger(tmp3); if ((ret = va_getByIndex(tmp->Arr, 1, &tmp3)) != DLMS_ERROR_CODE_OK) { break; } it->retryWaitTime = (uint16_t)var_toInteger(tmp3); if ((ret = va_getByIndex(tmp->Arr, 2, &tmp3)) != DLMS_ERROR_CODE_OK) { break; } it->sendPeriod = var_toInteger(tmp3); if ((ret = arr_push(&object->neighborDiscoverySetup, it)) != 0) { break; } } } } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_IP6_SETUP #ifndef DLMS_IGNORE_UTILITY_TABLES int cosem_setUtilityTables(gxUtilityTables* object, unsigned char index, dlmsVARIANT* value) { if (index == 2) { object->tableId = (uint16_t)var_toInteger(value); } else if (index == 3) { //Skip length. } else if (index == 4) { bb_clear(&object->buffer); bb_set2(&object->buffer, value->byteArr, 0, bb_size(value->byteArr)); } else { return DLMS_ERROR_CODE_INVALID_PARAMETER; } return DLMS_ERROR_CODE_OK; } #endif //DLMS_IGNORE_UTILITY_TABLES #ifndef DLMS_IGNORE_MBUS_SLAVE_PORT_SETUP int cosem_setMbusSlavePortSetup(gxMbusSlavePortSetup* object, unsigned char index, dlmsVARIANT* value) { if (index == 2) { object->defaultBaud = (DLMS_BAUD_RATE)var_toInteger(value); } else if (index == 3) { object->availableBaud = (DLMS_BAUD_RATE)var_toInteger(value); } else if (index == 4) { object->addressState = (DLMS_ADDRESS_STATE)var_toInteger(value); } else if (index == 5) { object->busAddress = (unsigned char)var_toInteger(value); } else { return DLMS_ERROR_CODE_INVALID_PARAMETER; } return DLMS_ERROR_CODE_OK; } #endif //DLMS_IGNORE_MBUS_SLAVE_PORT_SETUP #ifndef DLMS_IGNORE_DISCONNECT_CONTROL int cosem_setDisconnectControl(gxDisconnectControl* object, unsigned char index, dlmsVARIANT* value) { if (index == 2) { object->outputState = value->boolVal; } else if (index == 3) { object->controlState = (DLMS_CONTROL_STATE)var_toInteger(value); } else if (index == 4) { object->controlMode = (DLMS_CONTROL_MODE)var_toInteger(value); } else { return DLMS_ERROR_CODE_INVALID_PARAMETER; } return DLMS_ERROR_CODE_OK; } #endif //DLMS_IGNORE_DISCONNECT_CONTROL #ifndef DLMS_IGNORE_LIMITER int cosem_setLimiter(dlmsSettings* settings, gxLimiter* object, unsigned char index, dlmsVARIANT* value) { DLMS_OBJECT_TYPE ot; int ret = DLMS_ERROR_CODE_OK, pos; dlmsVARIANT* tmp, * tmp3; dlmsVARIANT tmp2; if (index == 2) { if (value->vt != DLMS_DATA_TYPE_STRUCTURE) { #if defined(_WIN32) || defined(_WIN64) || defined(__linux__) assert(0); #endif return DLMS_ERROR_CODE_INVALID_PARAMETER; } ret = va_getByIndex(value->Arr, 0, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ot = (DLMS_OBJECT_TYPE)var_toInteger(tmp); //Get LN. ret = va_getByIndex(value->Arr, 1, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { return ret; } //Get attribute index. ret = va_getByIndex(value->Arr, 2, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->selectedAttributeIndex = (unsigned char)var_toInteger(tmp); if (ot != 0) { if ((ret = oa_findByLN(&settings->objects, ot, tmp3->byteArr->data, &object->monitoredValue)) == 0 && object->monitoredValue == NULL) { if ((ret = cosem_createObject(ot, &object->monitoredValue)) != 0) { return ret; } memcpy(object->monitoredValue->logicalName, tmp3->byteArr->data, tmp3->byteArr->size); //Add object to released objects list. ret = oa_push(&settings->releasedObjects, object->monitoredValue); if (ret != DLMS_ERROR_CODE_OK) { return ret; } } } else { object->monitoredValue = NULL; } } else if (index == 3) { ret = var_copy(&object->thresholdActive, value); } else if (index == 4) { ret = var_copy(&object->thresholdNormal, value); } else if (index == 5) { ret = var_copy(&object->thresholdEmergency, value); } else if (index == 6) { object->minOverThresholdDuration = var_toInteger(value); } else if (index == 7) { object->minUnderThresholdDuration = var_toInteger(value); } else if (index == 8) { ret = va_getByIndex(value->Arr, 0, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->emergencyProfile.id = (uint16_t)var_toInteger(tmp); ret = va_getByIndex(value->Arr, 1, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = var_init(&tmp2); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = dlms_changeType2(tmp, DLMS_DATA_TYPE_DATETIME, &tmp2); if (ret != DLMS_ERROR_CODE_OK) { return ret; } time_copy(&object->emergencyProfile.activationTime, tmp2.dateTime); var_clear(&tmp2); ret = va_getByIndex(value->Arr, 2, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->emergencyProfile.duration = var_toInteger(tmp); } else if (index == 9) { va_clear(&object->emergencyProfileGroupIDs); if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } tmp3 = (dlmsVARIANT*)gxmalloc(sizeof(dlmsVARIANT)); var_init(tmp3); ret = var_copy(tmp3, tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } va_push(&object->emergencyProfileGroupIDs, tmp3); } } } else if (index == 10) { object->emergencyProfileActive = value->boolVal; } else if (index == 11) { ret = va_getByIndex(value->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; } #ifndef DLMS_IGNORE_OBJECT_POINTERS if ((ret = oa_findByLN(&settings->objects, DLMS_OBJECT_TYPE_SCRIPT_TABLE, tmp3->byteArr->data, (gxObject**)&object->actionOverThreshold.script)) != 0) { return ret; } if (object->actionOverThreshold.script == NULL) { if ((ret = cosem_createObject(DLMS_OBJECT_TYPE_SCRIPT_TABLE, (gxObject**)&object->actionOverThreshold.script)) != 0) { return ret; } memcpy(object->actionOverThreshold.script->base.logicalName, tmp3->byteArr->data, tmp3->byteArr->size); //Add object to released objects list. ret = oa_push(&settings->releasedObjects, (gxObject*)object->actionOverThreshold.script); if (ret != DLMS_ERROR_CODE_OK) { return ret; } } #else memcpy(object->actionOverThreshold.logicalName, tmp3->byteArr->data, 6); #endif //DLMS_IGNORE_OBJECT_POINTERS ret = va_getByIndex(tmp->Arr, 1, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->actionOverThreshold.scriptSelector = (uint16_t)var_toInteger(tmp3); ret = va_getByIndex(value->Arr, 1, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = va_getByIndex(tmp->Arr, 0, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { return ret; } #ifndef DLMS_IGNORE_OBJECT_POINTERS if ((ret = oa_findByLN(&settings->objects, DLMS_OBJECT_TYPE_SCRIPT_TABLE, tmp3->byteArr->data, (gxObject**)&object->actionUnderThreshold.script)) != 0) { return ret; } if (object->actionUnderThreshold.script == NULL) { if ((ret = cosem_createObject(DLMS_OBJECT_TYPE_SCRIPT_TABLE, (gxObject**)&object->actionUnderThreshold.script)) != 0) { return ret; } memcpy(object->actionUnderThreshold.script->base.logicalName, tmp3->byteArr->data, tmp3->byteArr->size); //Add object to released objects list. ret = oa_push(&settings->releasedObjects, (gxObject*)object->actionUnderThreshold.script); if (ret != DLMS_ERROR_CODE_OK) { return ret; } } #else memcpy(object->actionUnderThreshold.logicalName, tmp3->byteArr->data, 6); #endif //DLMS_IGNORE_OBJECT_POINTERS ret = va_getByIndex(tmp->Arr, 1, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->actionUnderThreshold.scriptSelector = (uint16_t)var_toInteger(tmp3); } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_LIMITER #ifndef DLMS_IGNORE_MBUS_CLIENT int cosem_setmMbusClient(dlmsSettings* settings, gxMBusClient* object, unsigned char index, dlmsVARIANT* value) { int ret = DLMS_ERROR_CODE_OK, pos; if (index == 2) { #ifndef DLMS_IGNORE_OBJECT_POINTERS if ((ret = oa_findByLN(&settings->objects, DLMS_OBJECT_TYPE_MBUS_MASTER_PORT_SETUP, value->byteArr->data, &object->mBusPort)) != 0) { return ret; } if (object->mBusPort == NULL) { if ((ret = cosem_createObject(DLMS_OBJECT_TYPE_MBUS_MASTER_PORT_SETUP, &object->mBusPort)) != 0) { return ret; } memcpy(object->mBusPort->logicalName, value->byteArr->data, value->byteArr->size); //Add object to released objects list. ret = oa_push(&settings->releasedObjects, object->mBusPort); if (ret != DLMS_ERROR_CODE_OK) { return ret; } } #else ret = bb_get(value->byteArr, object->mBusPortReference, 6); #endif //DLMS_IGNORE_OBJECT_POINTERS } else if (index == 3) { arr_clearKeyValuePair(&object->captureDefinition); dlmsVARIANT* tmp, * tmp3; gxByteBuffer* start, * end; if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } ret = va_getByIndex(tmp->Arr, 0, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } start = (gxByteBuffer*)gxmalloc(sizeof(gxByteBuffer)); end = (gxByteBuffer*)gxmalloc(sizeof(gxByteBuffer)); BYTE_BUFFER_INIT(start); BYTE_BUFFER_INIT(end); bb_set(start, tmp3->byteArr->data, tmp3->byteArr->size); ret = va_getByIndex(tmp->Arr, 1, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { gxfree(start); gxfree(end); break; } bb_set(end, tmp3->byteArr->data, tmp3->byteArr->size); arr_push(&object->captureDefinition, key_init(start, end)); } } } else if (index == 4) { object->capturePeriod = var_toInteger(value); } else if (index == 5) { object->primaryAddress = (unsigned char)var_toInteger(value); } else if (index == 6) { object->identificationNumber = var_toInteger(value); } else if (index == 7) { object->manufacturerID = (uint16_t)var_toInteger(value); } else if (index == 8) { object->dataHeaderVersion = (unsigned char)var_toInteger(value); } else if (index == 9) { object->deviceType = (unsigned char)var_toInteger(value); } else if (index == 10) { object->accessNumber = (unsigned char)var_toInteger(value); } else if (index == 11) { object->status = (unsigned char)var_toInteger(value); } else if (index == 12) { object->alarm = (unsigned char)var_toInteger(value); } else if (index == 13 && object->base.version != 0) { object->configuration = (uint16_t)var_toInteger(value); } else if (index == 14 && object->base.version != 0) { object->encryptionKeyStatus = (DLMS_MBUS_ENCRYPTION_KEY_STATUS)var_toInteger(value); } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_MBUS_CLIENT #ifndef DLMS_IGNORE_MODEM_CONFIGURATION int cosem_setModemConfiguration(gxModemConfiguration* object, unsigned char index, dlmsVARIANT* value) { int ret = 0, pos; gxModemInitialisation* modemInit; dlmsVARIANT* tmp, * tmp3; gxByteBuffer* str; if (index == 2) { object->communicationSpeed = (DLMS_BAUD_RATE)var_toInteger(value); } else if (index == 3) { obj_clearModemConfigurationInitialisationStrings(&object->initialisationStrings); if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } ret = va_getByIndex(tmp->Arr, 0, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } modemInit = (gxModemInitialisation*)gxmalloc(sizeof(gxModemInitialisation)); if (modemInit == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } BYTE_BUFFER_INIT(&modemInit->request); BYTE_BUFFER_INIT(&modemInit->response); bb_set(&modemInit->request, tmp3->byteArr->data, tmp3->byteArr->size); ret = va_getByIndex(tmp->Arr, 1, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } bb_set(&modemInit->response, tmp3->byteArr->data, tmp3->byteArr->size); if (tmp->Arr->size > 2) { ret = va_getByIndex(tmp->Arr, 2, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } modemInit->delay = tmp3->uiVal; } arr_push(&object->initialisationStrings, modemInit); } } } else if (index == 4) { arr_clearStrings(&object->modemProfile); if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } str = (gxByteBuffer*)gxmalloc(sizeof(gxByteBuffer)); BYTE_BUFFER_INIT(str); bb_set2(str, tmp->byteArr, 0, bb_size(tmp->byteArr)); arr_push(&object->modemProfile, str); } } } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_MODEM_CONFIGURATION #ifndef DLMS_IGNORE_PPP_SETUP int cosem_setPppSetup(dlmsSettings* settings, gxPppSetup* object, unsigned char index, dlmsVARIANT* value) { int ret = DLMS_ERROR_CODE_OK, pos; gxpppSetupLcpOption* lcpItem = NULL; gxpppSetupIPCPOption* ipcpItem = NULL; dlmsVARIANT* tmp; dlmsVARIANT* tmp3; if (index == 2) { #ifndef DLMS_IGNORE_OBJECT_POINTERS if ((ret = oa_findByLN(&settings->objects, DLMS_OBJECT_TYPE_NONE, value->byteArr->data, &object->phy)) != 0) { return ret; } if (object->phy == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; } #else ret = bb_get(value->byteArr, object->PHYReference, 6); #endif //DLMS_IGNORE_OBJECT_POINTERS } else if (index == 3) { arr_clear(&object->lcpOptions); if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { lcpItem = NULL; ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } ret = va_getByIndex(tmp->Arr, 0, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } lcpItem = (gxpppSetupLcpOption*)gxmalloc(sizeof(gxpppSetupLcpOption)); if (lcpItem == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } var_init(&lcpItem->data); lcpItem->type = (DLMS_PPP_SETUP_LCP_OPTION_TYPE)var_toInteger(tmp3); ret = va_getByIndex(tmp->Arr, 1, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } lcpItem->length = (unsigned char)var_toInteger(tmp3); ret = va_getByIndex(tmp->Arr, 2, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } ret = var_copy(&lcpItem->data, tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } arr_push(&object->lcpOptions, lcpItem); } if (ret != 0 && lcpItem != NULL) { gxfree(lcpItem); } } } else if (index == 4) { arr_clear(&object->ipcpOptions); if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } ret = va_getByIndex(tmp->Arr, 0, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } ipcpItem = (gxpppSetupIPCPOption*)gxmalloc(sizeof(gxpppSetupIPCPOption)); if (ipcpItem == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } var_init(&ipcpItem->data); ipcpItem->type = (DLMS_PPP_SETUP_IPCP_OPTION_TYPE)var_toInteger(tmp3); ret = va_getByIndex(tmp->Arr, 1, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } ipcpItem->length = (unsigned char)var_toInteger(tmp3); ret = va_getByIndex(tmp->Arr, 2, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } ret = var_copy(&ipcpItem->data, tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } arr_push(&object->ipcpOptions, ipcpItem); } if (ret != 0 && ipcpItem != NULL) { gxfree(ipcpItem); } } } else if (index == 5) { if (value->Arr == NULL || value->Arr->size == 0) { bb_clear(&object->userName); bb_clear(&object->password); } else if (value->Arr->size == 2) { //Get user name. ret = va_getByIndex(value->Arr, 0, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } bb_clear(&object->userName); bb_set2(&object->userName, tmp->byteArr, 0, bb_size(tmp->byteArr)); //Get password. ret = va_getByIndex(value->Arr, 1, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } bb_clear(&object->password); bb_set2(&object->password, tmp->byteArr, 0, bb_size(tmp->byteArr)); } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_PPP_SETUP #ifndef DLMS_IGNORE_REGISTER_ACTIVATION int cosem_setRegisterActivation(dlmsSettings* settings, gxValueEventArg* e) { int ret = 0, pos; gxRegisterActivation* object = (gxRegisterActivation*)e->target; unsigned char index = e->index; dlmsVARIANT* value = &e->value; #ifdef DLMS_IGNORE_OBJECT_POINTERS gxObjectDefinition* objectDefinition; #else gxObject* objectDefinition; #endif //DLMS_IGNORE_OBJECT_POINTERS if (index == 2) { obj_clearRegisterActivationAssignment(&object->registerAssignment); dlmsVARIANT* tmp, * tmp3; if (value->Arr != NULL) { short type; for (pos = 0; pos != value->Arr->size; ++pos) { objectDefinition = NULL; ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } ret = va_getByIndex(tmp->Arr, 0, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } type = (short)var_toInteger(tmp3); ret = va_getByIndex(tmp->Arr, 1, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } unsigned char* ln = tmp3->byteArr->data; #ifdef DLMS_IGNORE_OBJECT_POINTERS objectDefinition = (gxObjectDefinition*)gxmalloc(sizeof(gxObjectDefinition)); objectDefinition->objectType = (DLMS_OBJECT_TYPE)type; memcpy(objectDefinition->logicalName, ln, 6); arr_push(&object->registerAssignment, objectDefinition); #else if (type != 0) { if ((ret = cosem_findObjectByLN(settings, type, ln, &objectDefinition)) != 0) { break; } oa_push(&object->registerAssignment, objectDefinition); } #endif //DLMS_IGNORE_OBJECT_POINTERS } #ifdef DLMS_IGNORE_OBJECT_POINTERS if (ret != 0 && objectDefinition != NULL) { gxfree(objectDefinition); } #endif //DLMS_IGNORE_OBJECT_POINTERS } } else if (index == 3) { obj_clearRegisterActivationMaskList(&object->maskList); int pos2; gxByteBuffer* start = NULL, * end = NULL; dlmsVARIANT* tmp, * tmp3; if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { if ((ret = va_getByIndex(value->Arr, pos, &tmp)) != DLMS_ERROR_CODE_OK) { break; } ret = va_getByIndex(tmp->Arr, 0, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } start = (gxByteBuffer*)gxmalloc(sizeof(gxByteBuffer)); BYTE_BUFFER_INIT(start); end = (gxByteBuffer*)gxmalloc(sizeof(gxByteBuffer)); BYTE_BUFFER_INIT(end); bb_set(start, tmp3->byteArr->data, tmp3->byteArr->size); ret = va_getByIndex(tmp->Arr, 1, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } for (pos2 = 0; pos2 != tmp3->Arr->size; ++pos2) { if ((ret = va_getByIndex(tmp3->Arr, pos2, &tmp)) != 0 || (ret = bb_setUInt8(end, (unsigned char)var_toInteger(tmp))) != 0) { break; } } if (ret != DLMS_ERROR_CODE_OK) { break; } arr_push(&object->maskList, key_init(start, end)); } if (ret != 0) { if (start != NULL) { gxfree(start); } if (end != NULL) { gxfree(end); } } } } else if (index == 4) { bb_clear(&object->activeMask); ret = bb_set2(&object->activeMask, value->byteArr, 0, bb_size(value->byteArr)); } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_REGISTER_ACTIVATION #ifndef DLMS_IGNORE_REGISTER_MONITOR int cosem_setRegisterMonitor(dlmsSettings* settings, gxRegisterMonitor* object, unsigned char index, dlmsVARIANT* value) { int ret = 0, pos; gxActionSet* actionSet = NULL; dlmsVARIANT* tmp; dlmsVARIANT* tmp3, * tmp4; if (index == 2) { va_clear(&object->thresholds); if (value->Arr != NULL) { va_capacity(&object->thresholds, value->Arr->size); for (pos = 0; pos != value->Arr->size; ++pos) { tmp3 = NULL; ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } tmp3 = (dlmsVARIANT*)gxmalloc(sizeof(dlmsVARIANT)); if (tmp3 == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } var_init(tmp3); ret = var_copy(tmp3, tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } va_push(&object->thresholds, tmp3); } } } else if (index == 3) { #ifndef DLMS_IGNORE_OBJECT_POINTERS signed short type; #endif //DLMS_IGNORE_OBJECT_POINTERS ret = va_getByIndex(value->Arr, 0, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } #ifndef DLMS_IGNORE_OBJECT_POINTERS type = (short)var_toInteger(tmp); #else object->monitoredValue.objectType = (DLMS_OBJECT_TYPE)var_toInteger(tmp); #endif //DLMS_IGNORE_OBJECT_POINTERS ret = va_getByIndex(value->Arr, 1, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } #ifndef DLMS_IGNORE_OBJECT_POINTERS if ((ret = oa_findByLN(&settings->objects, type, tmp->byteArr->data, &object->monitoredValue.target)) != 0) { return ret; } if (object->monitoredValue.target == NULL) { ret = cosem_createObject(type, &object->monitoredValue.target); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = cosem_setLogicalName(object->monitoredValue.target, tmp->byteArr->data); if (ret != DLMS_ERROR_CODE_OK) { return ret; } //Add object to released objects list. ret = oa_push(&settings->releasedObjects, object->monitoredValue.target); } #else memcpy(object->monitoredValue.logicalName, tmp->byteArr->data, 6); #endif //DLMS_IGNORE_OBJECT_POINTERS ret = va_getByIndex(value->Arr, 2, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->monitoredValue.attributeIndex = (unsigned char)var_toInteger(tmp); } else if (index == 4) { obj_clearRegisterMonitorActions(&object->actions); if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { actionSet = NULL; ret = va_getByIndex(value->Arr, pos, &tmp4); if (ret != DLMS_ERROR_CODE_OK) { break; } actionSet = (gxActionSet*)gxmalloc(sizeof(gxActionSet)); //Update action up. ret = va_getByIndex(tmp4->Arr, 0, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } ret = va_getByIndex(tmp3->Arr, 0, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } #ifndef DLMS_IGNORE_OBJECT_POINTERS actionSet->actionUp.script = NULL; if ((ret = oa_findByLN(&settings->objects, DLMS_OBJECT_TYPE_SCRIPT_TABLE, tmp->byteArr->data, (gxObject**)&actionSet->actionUp.script)) != 0) { return ret; } if (actionSet->actionUp.script == NULL) { ret = cosem_createObject(DLMS_OBJECT_TYPE_SCRIPT_TABLE, (gxObject**)&actionSet->actionUp.script); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = cosem_setLogicalName((gxObject*)actionSet->actionUp.script, tmp->byteArr->data); if (ret != DLMS_ERROR_CODE_OK) { return ret; } //Add object to released objects list. ret = oa_push(&settings->releasedObjects, (gxObject*)actionSet->actionUp.script); } #else memcpy(actionSet->actionUp.logicalName, tmp->byteArr->data, 6); #endif //DLMS_IGNORE_OBJECT_POINTERS ret = va_getByIndex(tmp3->Arr, 1, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } actionSet->actionUp.scriptSelector = (uint16_t)var_toInteger(tmp); //Update action down. ret = va_getByIndex(tmp4->Arr, 1, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } ret = va_getByIndex(tmp3->Arr, 0, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } #ifndef DLMS_IGNORE_OBJECT_POINTERS actionSet->actionDown.script = NULL; if ((ret = oa_findByLN(&settings->objects, DLMS_OBJECT_TYPE_SCRIPT_TABLE, tmp->byteArr->data, (gxObject**)&actionSet->actionDown.script)) != 0) { return ret; } if (actionSet->actionDown.script == NULL) { ret = cosem_createObject(DLMS_OBJECT_TYPE_SCRIPT_TABLE, (gxObject**)&actionSet->actionDown.script); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = cosem_setLogicalName((gxObject*)actionSet->actionDown.script, tmp->byteArr->data); if (ret != DLMS_ERROR_CODE_OK) { return ret; } //Add object to released objects list. ret = oa_push(&settings->releasedObjects, (gxObject*)actionSet->actionDown.script); } #else memcpy(actionSet->actionDown.logicalName, tmp->byteArr->data, 6); #endif //DLMS_IGNORE_OBJECT_POINTERS ret = va_getByIndex(tmp3->Arr, 1, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } actionSet->actionDown.scriptSelector = (uint16_t)var_toInteger(tmp); arr_push(&object->actions, actionSet); } if (ret != 0 && actionSet != NULL) { gxfree(actionSet); } } } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_REGISTER_MONITOR #ifndef DLMS_IGNORE_SAP_ASSIGNMENT int cosem_setSapAssignment(gxSapAssignment* object, unsigned char index, dlmsVARIANT* value) { int ret = DLMS_ERROR_CODE_OK, pos; gxSapItem* it = NULL; if (index == 2) { obj_clearSapList(&object->sapAssignmentList); dlmsVARIANT* tmp, * tmp2; if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { it = NULL; ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } ret = va_getByIndex(tmp->Arr, 0, &tmp2); if (ret != DLMS_ERROR_CODE_OK) { break; } it = (gxSapItem*)gxmalloc(sizeof(gxSapItem)); if (it == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } BYTE_BUFFER_INIT(&it->name); it->id = (uint16_t)var_toInteger(tmp2); ret = va_getByIndex(tmp->Arr, 1, &tmp2); if (ret != DLMS_ERROR_CODE_OK) { break; } bb_set(&it->name, tmp2->byteArr->data, tmp2->byteArr->size); arr_push(&object->sapAssignmentList, it); } if (ret != 0 && it != NULL) { gxfree(it); } } } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_SAP_ASSIGNMENT #ifndef DLMS_IGNORE_SCHEDULE int cosem_setSchedule(dlmsSettings* settings, gxSchedule* object, unsigned char index, dlmsVARIANT* value) { gxScheduleEntry* se; int ret = 0, pos; if (index == 2) { obj_clearScheduleEntries(&object->entries); dlmsVARIANT* tmp, * it; dlmsVARIANT tmp3; var_init(&tmp3); if (value->Arr != NULL) { se = NULL; for (pos = 0; pos != value->Arr->size; ++pos) { se = NULL; ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } se = (gxScheduleEntry*)gxmalloc(sizeof(gxScheduleEntry)); if (se == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } se->execWeekdays = 0; ba_init(&se->execSpecDays); ret = va_getByIndex(tmp->Arr, 0, &it); if (ret != DLMS_ERROR_CODE_OK) { break; } se->index = (uint16_t)var_toInteger(it); ret = va_getByIndex(tmp->Arr, 1, &it); if (ret != DLMS_ERROR_CODE_OK) { break; } se->enable = (unsigned char)var_toInteger(it); ret = va_getByIndex(tmp->Arr, 2, &it); if (ret != DLMS_ERROR_CODE_OK) { break; } #ifndef DLMS_IGNORE_OBJECT_POINTERS if ((ret = oa_findByLN(&settings->objects, DLMS_OBJECT_TYPE_SCRIPT_TABLE, it->byteArr->data, (gxObject**)&se->scriptTable)) != 0) { break; } if (se->scriptTable == NULL) { ret = cosem_createObject(DLMS_OBJECT_TYPE_SCRIPT_TABLE, (gxObject**)&se->scriptTable); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = cosem_setLogicalName((gxObject*)se->scriptTable, tmp->byteArr->data); if (ret != DLMS_ERROR_CODE_OK) { return ret; } //Add object to released objects list. ret = oa_push(&settings->releasedObjects, (gxObject*)se->scriptTable); } #else memcpy(se->logicalName, it->byteArr->data, bb_size(it->byteArr)); #endif //DLMS_IGNORE_OBJECT_POINTERS ret = va_getByIndex(tmp->Arr, 3, &it); if (ret != DLMS_ERROR_CODE_OK) { break; } se->scriptSelector = (uint16_t)var_toInteger(it); ret = va_getByIndex(tmp->Arr, 4, &it); if (ret != DLMS_ERROR_CODE_OK) { break; } ret = dlms_changeType2(it, DLMS_DATA_TYPE_TIME, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } time_copy(&se->switchTime, tmp3.dateTime); ret = va_getByIndex(tmp->Arr, 5, &it); if (ret != DLMS_ERROR_CODE_OK) { break; } se->validityWindow = (uint16_t)var_toInteger(it); ret = va_getByIndex(tmp->Arr, 6, &it); if (ret != DLMS_ERROR_CODE_OK) { break; } if (it->bitArr != NULL) { uint32_t val; if ((ret = ba_toInteger(it->bitArr, &val)) == 0) { se->execWeekdays = val; } } ret = va_getByIndex(tmp->Arr, 7, &it); if (ret != DLMS_ERROR_CODE_OK) { break; } if (it->bitArr != NULL) { ba_copy(&se->execSpecDays, it->bitArr->data, (uint16_t)it->bitArr->size); } ret = va_getByIndex(tmp->Arr, 8, &it); if (ret != DLMS_ERROR_CODE_OK) { break; } ret = dlms_changeType2(it, DLMS_DATA_TYPE_DATE, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } time_copy(&se->beginDate, tmp3.dateTime); var_clear(&tmp3); ret = va_getByIndex(tmp->Arr, 9, &it); if (ret != DLMS_ERROR_CODE_OK) { break; } ret = dlms_changeType2(it, DLMS_DATA_TYPE_DATE, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } time_copy(&se->endDate, tmp3.dateTime); arr_push(&object->entries, se); var_clear(&tmp3); } if (ret != 0 && se != NULL) { gxfree(se); } } } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_SCHEDULE #ifndef DLMS_IGNORE_SCRIPT_TABLE int cosem_setScriptTable(dlmsSettings* settings, gxScriptTable* object, unsigned char index, dlmsVARIANT* value) { int ret = 0, pos, pos2; gxScriptAction* scriptAction; gxScript* script; if (index == 2) { obj_clearScriptTable(&object->scripts); #ifndef DLMS_IGNORE_OBJECT_POINTERS uint16_t type; #endif //DLMS_IGNORE_OBJECT_POINTERS dlmsVARIANT* tmp, * tmp2, * tmp3; if (value->Arr->size != 0) { script = NULL; ret = va_getByIndex(value->Arr, 0, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } //Fix Xemex bug here. //Xemex meters do not return array as they should be according standard. if (value->vt == DLMS_DATA_TYPE_ARRAY) { for (pos = 0; pos != value->Arr->size; ++pos) { script = NULL; ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } ret = va_getByIndex(tmp->Arr, 0, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } script = (gxScript*)gxmalloc(sizeof(gxScript)); if (script == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } arr_init(&script->actions); script->id = (uint16_t)var_toInteger(tmp3); arr_push(&object->scripts, script); ret = va_getByIndex(tmp->Arr, 1, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } scriptAction = NULL; for (pos2 = 0; pos2 != tmp3->Arr->size; ++pos2) { scriptAction = NULL; ret = va_getByIndex(tmp3->Arr, pos2, &tmp2); if (ret != DLMS_ERROR_CODE_OK) { break; } ret = va_getByIndex(tmp2->Arr, 0, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } scriptAction = (gxScriptAction*)gxmalloc(sizeof(gxScriptAction)); if (scriptAction == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } var_init(&scriptAction->parameter); scriptAction->type = (DLMS_SCRIPT_ACTION_TYPE)var_toInteger(tmp); ret = va_getByIndex(tmp2->Arr, 1, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } #ifdef DLMS_IGNORE_OBJECT_POINTERS scriptAction->objectType = (DLMS_OBJECT_TYPE)var_toInteger(tmp); #else type = (DLMS_OBJECT_TYPE)var_toInteger(tmp); #endif //DLMS_IGNORE_OBJECT_POINTERS ret = va_getByIndex(tmp2->Arr, 2, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } #ifdef DLMS_IGNORE_OBJECT_POINTERS if (bb_size(tmp->byteArr) == 6) { memcpy(scriptAction->logicalName, tmp->byteArr->data, 6); } #else if ((ret = oa_findByLN(&settings->objects, type, tmp->byteArr->data, &scriptAction->target)) != 0) { break; } #endif //DLMS_IGNORE_OBJECT_POINTERS ret = va_getByIndex(tmp2->Arr, 3, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } scriptAction->index = (char)var_toInteger(tmp); ret = va_getByIndex(tmp2->Arr, 4, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } var_copy(&scriptAction->parameter, tmp); arr_push(&script->actions, scriptAction); } if (ret != DLMS_ERROR_CODE_OK) { if (scriptAction != NULL) { gxfree(scriptAction); } break; } } if (ret != 0 && script != NULL) { gxfree(script); } } else //Read Xemex meter here. { ret = va_getByIndex(value->Arr, 0, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = va_getByIndex(tmp->Arr, 1, &tmp2); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = va_getByIndex(tmp2->Arr, 2, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { return ret; } script = (gxScript*)gxmalloc(sizeof(gxScript)); if (script == NULL) { return DLMS_ERROR_CODE_OUTOFMEMORY; } arr_init(&script->actions); script->id = (uint16_t)var_toInteger(tmp3); arr_push(&object->scripts, script); ret = va_getByIndex(tmp->Arr, 3, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { return ret; } scriptAction = (gxScriptAction*)gxmalloc(sizeof(gxScriptAction)); if (scriptAction == NULL) { return DLMS_ERROR_CODE_OUTOFMEMORY; } var_init(&scriptAction->parameter); scriptAction->type = (DLMS_SCRIPT_ACTION_TYPE)var_toInteger(tmp3); ret = va_getByIndex(tmp2->Arr, 4, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { return ret; } #ifdef DLMS_IGNORE_OBJECT_POINTERS scriptAction->objectType = (DLMS_OBJECT_TYPE)var_toInteger(tmp3); #else type = (uint16_t)var_toInteger(tmp3); #endif //DLMS_IGNORE_OBJECT_POINTERS ret = va_getByIndex(tmp2->Arr, 5, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { return ret; } #ifdef DLMS_IGNORE_OBJECT_POINTERS memcpy(scriptAction->logicalName, tmp3->byteArr->data, 6); #else if ((ret = oa_findByLN(&settings->objects, type, tmp3->byteArr->data, &scriptAction->target)) != 0) { return ret; } #endif //DLMS_IGNORE_OBJECT_POINTERS ret = va_getByIndex(tmp2->Arr, 6, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { return ret; } scriptAction->index = (char)var_toInteger(tmp3); ret = va_getByIndex(tmp2->Arr, 7, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { return ret; } var_copy(&scriptAction->parameter, tmp); arr_push(&script->actions, scriptAction); } } } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_SCRIPT_TABLE #ifndef DLMS_IGNORE_SPECIAL_DAYS_TABLE int cosem_setSpecialDaysTable(gxSpecialDaysTable* object, unsigned char index, dlmsVARIANT* value) { int ret = 0, pos; gxSpecialDay* specialDay; if (index == 2) { arr_clear(&object->entries); dlmsVARIANT* tmp, * tmp3; dlmsVARIANT tmp2; if (value->Arr != NULL) { specialDay = NULL; for (pos = 0; pos != value->Arr->size; ++pos) { specialDay = NULL; ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } specialDay = (gxSpecialDay*)gxmalloc(sizeof(gxSpecialDay)); if (specialDay == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } ret = va_getByIndex(tmp->Arr, 0, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { return ret; } specialDay->index = (uint16_t)var_toInteger(tmp3); ret = va_getByIndex(tmp->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(tmp->Arr, 2, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { return ret; } specialDay->dayId = (unsigned char)var_toInteger(tmp3); arr_push(&object->entries, specialDay); } if (ret != 0 && specialDay != NULL) { gxfree(specialDay); } } } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_SPECIAL_DAYS_TABLE #ifndef DLMS_IGNORE_TCP_UDP_SETUP int cosem_setTcpUdpSetup(dlmsSettings* settings, gxTcpUdpSetup* object, unsigned char index, dlmsVARIANT* value) { int ret = 0; if (index == 2) { object->port = (uint16_t)var_toInteger(value); } else if (index == 3) { if (value->vt == DLMS_DATA_TYPE_NONE) { #ifndef DLMS_IGNORE_OBJECT_POINTERS object->ipSetup = NULL; #else memset(object->ipReference, 0, 6); #endif //DLMS_IGNORE_OBJECT_POINTERS } else { #ifndef DLMS_IGNORE_OBJECT_POINTERS unsigned char ln[6]; if ((ret = bb_get(value->byteArr, ln, 6)) != 0 || (ret = oa_findByLN(&settings->objects, DLMS_OBJECT_TYPE_IP4_SETUP, ln, &object->ipSetup)) != 0) { } #else ret = bb_get(value->byteArr, object->ipReference, 6); #endif //DLMS_IGNORE_OBJECT_POINTERS } } else if (index == 4) { object->maximumSegmentSize = (uint16_t)var_toInteger(value); } else if (index == 5) { object->maximumSimultaneousConnections = (unsigned char)var_toInteger(value); } else if (index == 6) { object->inactivityTimeout = (uint16_t)var_toInteger(value); } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_TCP_UDP_SETUP #ifndef DLMS_IGNORE_MBUS_DIAGNOSTIC int cosem_setMbusDiagnostic(gxMbusDiagnostic* object, unsigned char index, dlmsVARIANT* value) { int pos, ret = 0; dlmsVARIANT* tmp, * tmp3; gxBroadcastFrameCounter* item; if (index == 2) { object->receivedSignalStrength = (unsigned char)var_toInteger(value); } else if (index == 3) { object->channelId = (unsigned char)var_toInteger(value); } else if (index == 4) { object->linkStatus = (DLMS_MBUS_LINK_STATUS)var_toInteger(value); } else if (index == 5) { for (pos = 0; pos != value->Arr->size; ++pos) { item = NULL; ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } item = (gxBroadcastFrameCounter*)gxmalloc(sizeof(gxBroadcastFrameCounter)); if (item == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } ret = va_getByIndex(tmp->Arr, 0, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { gxfree(item); break; } item->clientId = (unsigned char)var_toInteger(tmp3); ret = va_getByIndex(tmp->Arr, 1, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { gxfree(item); break; } item->counter = tmp3->ulVal; ret = va_getByIndex(tmp->Arr, 2, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { gxfree(item); break; } item->timeStamp = *tmp3->dateTime; arr_push(&object->broadcastFrames, item); } } else if (index == 6) { object->transmissions = value->ulVal; } else if (index == 7) { object->receivedFrames = value->ulVal; } else if (index == 8) { object->failedReceivedFrames = value->ulVal; } else if (index == 9) { if ((ret = va_getByIndex(value->Arr, 0, &tmp)) == DLMS_ERROR_CODE_OK) { object->captureTime.attributeId = tmp->bVal; if ((ret = va_getByIndex(value->Arr, 1, &tmp)) == DLMS_ERROR_CODE_OK) { object->captureTime.timeStamp = *tmp->dateTime; } } } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_MBUS_DIAGNOSTIC #ifndef DLMS_IGNORE_MBUS_PORT_SETUP int cosem_setMbusPortSetup(gxMBusPortSetup* object, unsigned char index, dlmsVARIANT* value) { int pos, ret = 0; dlmsVARIANT* tmp, * tmp3; if (index == 2) { memcpy(object->profileSelection, value->byteArr->data, value->byteArr->size); } else if (index == 3) { object->portCommunicationStatus = (DLMS_MBUS_PORT_COMMUNICATION_STATE)var_toInteger(value); } else if (index == 4) { object->dataHeaderType = (DLMS_MBUS_DATA_HEADER_TYPE)var_toInteger(value); } else if (index == 5) { object->primaryAddress = (unsigned char)var_toInteger(value); } else if (index == 6) { object->identificationNumber = (uint32_t)var_toInteger(value); } else if (index == 7) { object->manufacturerId = (uint16_t)var_toInteger(value); } else if (index == 8) { object->mBusVersion = (unsigned char)var_toInteger(value); } else if (index == 9) { object->deviceType = (DLMS_MBUS_METER_TYPE)var_toInteger(value); } else if (index == 10) { object->maxPduSize = (uint16_t)var_toInteger(value); } else if (index == 11) { arr_clearKeyValuePair(&object->listeningWindow); dlmsVARIANT start, end; gxtime* s, * e; if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } ret = va_getByIndex(tmp->Arr, 0, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } var_init(&start); var_init(&end); ret = dlms_changeType2(tmp3, DLMS_DATA_TYPE_DATETIME, &start); if (ret != DLMS_ERROR_CODE_OK) { break; } ret = va_getByIndex(tmp->Arr, 1, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } ret = dlms_changeType2(tmp3, DLMS_DATA_TYPE_DATETIME, &end); if (ret != DLMS_ERROR_CODE_OK) { break; } s = (gxtime*)gxmalloc(sizeof(gxtime)); e = (gxtime*)gxmalloc(sizeof(gxtime)); time_copy(s, start.dateTime); time_copy(e, end.dateTime); arr_push(&object->listeningWindow, key_init(s, e)); var_clear(&start); var_clear(&end); } } } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_MBUS_PORT_SETUP #ifndef DLMS_IGNORE_MBUS_MASTER_PORT_SETUP int cosem_setMbusMasterPortSetup(gxMBusMasterPortSetup* object, unsigned char index, dlmsVARIANT* value) { if (index == 2) { object->commSpeed = (DLMS_BAUD_RATE)var_toInteger(value); } else { return DLMS_ERROR_CODE_INVALID_PARAMETER; } return DLMS_ERROR_CODE_OK; } #endif //DLMS_IGNORE_MBUS_MASTER_PORT_SETUP #ifndef DLMS_IGNORE_G3_PLC_MAC_LAYER_COUNTERS int cosem_setG3PlcMacLayerCounters(gxG3PlcMacLayerCounters* object, unsigned char index, dlmsVARIANT* value) { int ret = 0; if (index == 2) { object->txDataPacketCount = value->ulVal; } else if (index == 3) { object->rxDataPacketCount = value->ulVal; } else if (index == 4) { object->txCmdPacketCount = value->ulVal; } else if (index == 5) { object->rxCmdPacketCount = value->ulVal; } else if (index == 6) { object->cSMAFailCount = value->ulVal; } else if (index == 7) { object->cSMANoAckCount = value->ulVal; } else if (index == 8) { object->badCrcCount = value->ulVal; } else if (index == 9) { object->txDataBroadcastCount = value->ulVal; } else if (index == 10) { object->rxDataBroadcastCount = value->ulVal; } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_G3_PLC_MAC_LAYER_COUNTERS #ifndef DLMS_IGNORE_G3_PLC_MAC_SETUP int cosem_setG3PlcMacSetup(gxG3PlcMacSetup* object, unsigned char index, dlmsVARIANT* value) { int pos, ret = 0; if (index == 2) { object->shortAddress = value->uiVal; } else if (index == 3) { object->rcCoord = value->uiVal; } else if (index == 4) { object->panId = value->uiVal; } else if (index == 5) { arr_clear(&object->keyTable); gxG3MacKeyTable* it; dlmsVARIANT* tmp, * tmp2; if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } it = (gxG3MacKeyTable*)gxmalloc(sizeof(gxG3MacKeyTable)); if (it == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } if ((ret = va_getByIndex(tmp->Arr, 0, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->id = tmp2->bVal; if ((ret = va_getByIndex(tmp->Arr, 1, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } memcpy(it->key, tmp2->byteArr->data, bb_size(tmp2->byteArr)); arr_push(&object->keyTable, it); } } } else if (index == 6) { object->frameCounter = value->ulVal; } else if (index == 7) { ba_clear(&object->toneMask); if (value->bitArr != NULL) { ba_copy(&object->toneMask, value->bitArr->data, ba_size(value->bitArr)); } } else if (index == 8) { object->tmrTtl = value->bVal; } else if (index == 9) { object->maxFrameRetries = value->bVal; } else if (index == 10) { object->neighbourTableEntryTtl = value->bVal; } else if (index == 11) { gxNeighbourTable* it; obj_clearNeighbourTable(&object->neighbourTable); dlmsVARIANT* tmp, * tmp2; if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } it = (gxNeighbourTable*)gxmalloc(sizeof(gxNeighbourTable)); if (it == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } ba_init(&it->txCoeff); ba_init(&it->toneMap); if ((ret = va_getByIndex(tmp->Arr, 0, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->shortAddress = tmp2->uiVal; if ((ret = va_getByIndex(tmp->Arr, 1, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->payloadModulationScheme = tmp2->bVal; if ((ret = va_getByIndex(tmp->Arr, 2, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } if (tmp2->bitArr != NULL) { ba_copy(&it->toneMap, tmp2->bitArr->data, ba_size(tmp2->bitArr)); } if ((ret = va_getByIndex(tmp->Arr, 3, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->modulation = tmp2->bVal; if ((ret = va_getByIndex(tmp->Arr, 4, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->txGain = tmp2->cVal; if ((ret = va_getByIndex(tmp->Arr, 5, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->txRes = tmp2->bVal; if ((ret = va_getByIndex(tmp->Arr, 6, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } if (tmp2->bitArr != NULL) { ba_copy(&it->txCoeff, tmp2->bitArr->data, ba_size(tmp2->bitArr)); } if ((ret = va_getByIndex(tmp->Arr, 7, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->lqi = tmp2->bVal; if ((ret = va_getByIndex(tmp->Arr, 8, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->phaseDifferential = tmp2->cVal; if ((ret = va_getByIndex(tmp->Arr, 9, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->tmrValidTime = tmp2->bVal; if ((ret = va_getByIndex(tmp->Arr, 10, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } arr_push(&object->neighbourTable, it); } } } else if (index == 12) { object->highPriorityWindowSize = value->bVal; } else if (index == 13) { object->cscmFairnessLimit = value->bVal; } else if (index == 14) { object->beaconRandomizationWindowLength = value->bVal; } else if (index == 15) { object->macA = value->bVal; } else if (index == 16) { object->macK = value->bVal; } else if (index == 17) { object->minCwAttempts = value->bVal; } else if (index == 18) { object->cenelecLegacyMode = value->bVal; } else if (index == 19) { object->fccLegacyMode = value->bVal; } else if (index == 20) { object->maxBe = value->bVal; } else if (index == 21) { object->maxCsmaBackoffs = value->bVal; } else if (index == 22) { object->minBe = value->bVal; } else if (index == 23) { object->macBroadcastMaxCwEnabled = value->bVal; } else if (index == 24) { object->macTransmitAtten = value->bVal; } else if (index == 25) { arr_clear(&object->macPosTable); gxMacPosTable* it; dlmsVARIANT* tmp, * tmp2; if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } it = (gxMacPosTable*)gxmalloc(sizeof(gxMacPosTable)); if (it == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } if ((ret = va_getByIndex(tmp->Arr, 0, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->shortAddress = tmp2->uiVal; if ((ret = va_getByIndex(tmp->Arr, 1, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->lqi = tmp2->cVal; if ((ret = va_getByIndex(tmp->Arr, 2, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->validTime = tmp2->cVal; arr_push(&object->macPosTable, it); } } } else if (object->base.version > 2 && index == 26) { object->macDuplicateDetectionTTL = value->bVal; } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_G3_PLC_MAC_SETUP #ifndef DLMS_IGNORE_G3_PLC_6LO_WPAN int cosem_getUint16Array(variantArray* arr, dlmsVARIANT* value) { int pos, ret = 0; dlmsVARIANT* it; va_clear(arr); dlmsVARIANT* tmp; if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } it = (dlmsVARIANT*)gxmalloc(sizeof(dlmsVARIANT)); if (it == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } var_init(it); ret = var_copy(it, tmp); if (ret != 0) { break; } va_push(arr, it); } } return ret; } int cosem_setG3Plc6LoWPAN(gxG3Plc6LoWPAN* object, unsigned char index, dlmsVARIANT* value) { int pos, ret = 0; if (index == 2) { object->maxHops = value->bVal; } else if (index == 3) { object->weakLqiValue = value->bVal; } else if (index == 4) { object->securityLevel = value->bVal; } else if (index == 5) { bb_clear(&object->prefixTable); dlmsVARIANT* tmp; if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { if ((ret = va_getByIndex(value->Arr, pos, &tmp)) != DLMS_ERROR_CODE_OK) { break; } if ((ret = bb_setUInt8(&object->prefixTable, tmp->bVal)) != 0) { break; } } } } else if (index == 6) { arr_clear(&object->routingConfiguration); gxRoutingConfiguration* it; dlmsVARIANT* tmp, * tmp2; if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } it = (gxRoutingConfiguration*)gxmalloc(sizeof(gxRoutingConfiguration)); if (it == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } if ((ret = va_getByIndex(tmp->Arr, 0, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->netTraversalTime = tmp2->bVal; if ((ret = va_getByIndex(tmp->Arr, 1, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->routingTableEntryTtl = tmp2->uiVal; if ((ret = va_getByIndex(tmp->Arr, 2, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->kr = tmp2->cVal; if ((ret = va_getByIndex(tmp->Arr, 3, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->km = tmp2->cVal; if ((ret = va_getByIndex(tmp->Arr, 4, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->kc = tmp2->cVal; if ((ret = va_getByIndex(tmp->Arr, 5, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->kq = tmp2->cVal; if ((ret = va_getByIndex(tmp->Arr, 6, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->kh = tmp2->cVal; if ((ret = va_getByIndex(tmp->Arr, 7, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->krt = tmp2->cVal; if ((ret = va_getByIndex(tmp->Arr, 8, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->rReqRetries = tmp2->cVal; if ((ret = va_getByIndex(tmp->Arr, 9, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->rReqReqWait = tmp2->cVal; if ((ret = va_getByIndex(tmp->Arr, 10, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->blacklistTableEntryTtl = tmp2->uiVal; if ((ret = va_getByIndex(tmp->Arr, 11, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->unicastRreqGenEnable = tmp2->cVal; if ((ret = va_getByIndex(tmp->Arr, 12, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->rlcEnabled = tmp2->cVal; if ((ret = va_getByIndex(tmp->Arr, 13, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->addRevLinkCost = tmp2->cVal; arr_push(&object->routingConfiguration, it); } } } else if (index == 7) { object->broadcastLogTableEntryTtl = value->uiVal; } else if (index == 8) { arr_clear(&object->routingTable); gxRoutingTable* it; dlmsVARIANT* tmp, * tmp2; if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } it = (gxRoutingTable*)gxmalloc(sizeof(gxRoutingTable)); if (it == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } if ((ret = va_getByIndex(tmp->Arr, 0, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->destinationAddress = tmp2->uiVal; if ((ret = va_getByIndex(tmp->Arr, 1, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->nextHopAddress = tmp2->uiVal; if ((ret = va_getByIndex(tmp->Arr, 2, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->routeCost = tmp2->uiVal; if ((ret = va_getByIndex(tmp->Arr, 3, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->hopCount = tmp2->bVal; if ((ret = va_getByIndex(tmp->Arr, 4, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->weakLinkCount = tmp2->bVal; if ((ret = va_getByIndex(tmp->Arr, 5, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->validTime = tmp2->uiVal; arr_push(&object->routingTable, it); } } } else if (index == 9) { arr_clear(&object->contextInformationTable); gxContextInformationTable* it; uint32_t v; dlmsVARIANT* tmp, * tmp2; if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } it = (gxContextInformationTable*)gxmalloc(sizeof(gxContextInformationTable)); if (it == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } if ((ret = va_getByIndex(tmp->Arr, 0, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } if ((ret = ba_toInteger(tmp2->bitArr, &v)) != DLMS_ERROR_CODE_OK) { break; } it->cid = (unsigned char)v; if ((ret = va_getByIndex(tmp->Arr, 1, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->contextLength = tmp2->bVal; if ((ret = va_getByIndex(tmp->Arr, 2, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } if (tmp2->byteArr != NULL) { int size = bb_size(tmp2->byteArr); if (size > 16) { size = 16; } memcpy(it->context, tmp2->byteArr->data, size); } if ((ret = va_getByIndex(tmp->Arr, 3, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->compression = tmp2->bVal; if ((ret = va_getByIndex(tmp->Arr, 4, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->validLifetime = tmp2->uiVal; arr_push(&object->contextInformationTable, it); } } } else if (index == 10) { arr_clear(&object->blacklistTable); gxBlacklistTable* it; dlmsVARIANT* tmp, * tmp2; if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } it = (gxBlacklistTable*)gxmalloc(sizeof(gxBlacklistTable)); if (it == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } if ((ret = va_getByIndex(tmp->Arr, 0, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->neighbourAddress = tmp2->uiVal; if ((ret = va_getByIndex(tmp->Arr, 1, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->validTime = tmp2->uiVal; arr_push(&object->blacklistTable, it); } } } else if (index == 11) { gxBroadcastLogTable* it; arr_clear(&object->broadcastLogTable); dlmsVARIANT* tmp, * tmp2; if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } it = (gxBroadcastLogTable*)gxmalloc(sizeof(gxBroadcastLogTable)); if (it == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } if ((ret = va_getByIndex(tmp->Arr, 0, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->sourceAddress = tmp2->uiVal; if ((ret = va_getByIndex(tmp->Arr, 1, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->sequenceNumber = tmp2->bVal; if ((ret = va_getByIndex(tmp->Arr, 2, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->validTime = tmp2->uiVal; if ((ret = va_getByIndex(tmp->Arr, 4, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } arr_push(&object->broadcastLogTable, it); } } } else if (index == 12) { ret = cosem_getUint16Array(&object->groupTable, value); } else if (index == 13) { object->maxJoinWaitTime = value->uiVal; } else if (index == 14) { object->pathDiscoveryTime = value->bVal; } else if (index == 15) { object->activeKeyIndex = value->bVal; } else if (index == 16) { object->metricType = value->bVal; } else if (index == 17) { object->coordShortAddress = value->uiVal; } else if (index == 18) { object->disableDefaultRouting = value->bVal; } else if (index == 19) { object->deviceType = (DLMS_PAN_DEVICE_TYPE)value->bVal; } else if (index == 20) { object->defaultCoordRouteEnabled = value->bVal; } else if (index == 21) { ret = cosem_getUint16Array(&object->destinationAddress, value); } else if (index == 22) { object->lowLQI = value->bVal; } else if (index == 23) { object->highLQI = value->bVal; } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_G3_PLC_6LO_WPAN #ifndef DLMS_IGNORE_FUNCTION_CONTROL int cosem_setFunctionControl( dlmsSettings* settings, gxFunctionControl* object, unsigned char index, dlmsVARIANT* value) { int pos, pos2, ret = 0; if (index == 2) { functionStatus* it; obj_clearActivationStatus(&object->activationStatus); dlmsVARIANT* tmp, * tmp2; if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } it = (functionStatus*)gxmalloc(sizeof(functionStatus)); if (it == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } if ((ret = va_getByIndex(tmp->Arr, 0, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } bb_init(&it->name); bb_set2(&it->name, tmp2->byteArr, 0, bb_size(tmp2->byteArr)); if ((ret = va_getByIndex(tmp->Arr, 1, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->status = tmp2->bVal; arr_push(&object->activationStatus, it); } } } else if (index == 3) { functionalBlock* it; gxObject* target; obj_clearFunctionList(&object->functions); dlmsVARIANT* tmp, * tmp2, * tmp3, * tmp4; if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } it = (functionalBlock*)gxmalloc(sizeof(functionalBlock)); if (it == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } oa_init(&it->functionSpecifications); if ((ret = va_getByIndex(tmp->Arr, 0, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } bb_init(&it->name); bb_set2(&it->name, tmp2->byteArr, 0, bb_size(tmp2->byteArr)); if ((ret = va_getByIndex(tmp->Arr, 1, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } for (pos2 = 0; pos2 != tmp2->Arr->size; ++pos2) { if ((ret = va_getByIndex(tmp2->Arr, pos, &tmp3)) != DLMS_ERROR_CODE_OK) { break; } if ((ret = va_getByIndex(tmp3->Arr, 0, &tmp4)) != DLMS_ERROR_CODE_OK) { break; } uint16_t ot = tmp4->uiVal; //Get LN. if ((ret = va_getByIndex(tmp3->Arr, 1, &tmp4)) != DLMS_ERROR_CODE_OK) { break; } if ((ret = oa_findByLN(&settings->objects, ot, tmp4->byteArr->data, &target)) != 0) { return ret; } if (target == NULL) { if ((ret = cosem_createObject(ot, &target)) != 0) { return ret; } oa_push(&settings->releasedObjects, target); memcpy(target->logicalName, tmp4->byteArr->data, bb_size(tmp4->byteArr)); } oa_push(&it->functionSpecifications, target); } arr_push(&object->functions, it); } } } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_FUNCTION_CONTROL #ifndef DLMS_IGNORE_ARRAY_MANAGER int cosem_setArrayManager( dlmsSettings* settings, gxArrayManager* object, unsigned char index, dlmsVARIANT* value) { int pos, ret = 0; if (index == 2) { arr_clear(&object->elements); gxArrayManagerItem* it; dlmsVARIANT* tmp, * tmp2, * tmp3; uint16_t ot; if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } it = (gxArrayManagerItem*)gxmalloc(sizeof(gxArrayManagerItem)); if (it == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } if ((ret = va_getByIndex(tmp->Arr, 0, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->id = tmp2->bVal; if ((ret = va_getByIndex(tmp->Arr, 1, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } if ((ret = va_getByIndex(tmp2->Arr, 0, &tmp3)) != DLMS_ERROR_CODE_OK) { break; } ot = tmp3->uiVal; if ((ret = va_getByIndex(tmp2->Arr, 2, &tmp3)) != DLMS_ERROR_CODE_OK) { break; } it->element.attributeIndex = tmp3->bVal; //Get LN. if ((ret = va_getByIndex(tmp2->Arr, 1, &tmp3)) != DLMS_ERROR_CODE_OK) { break; } it->element.target = NULL; if ((ret = oa_findByLN(&settings->objects, ot, tmp3->byteArr->data, &it->element.target)) != 0) { return ret; } if (it->element.target == NULL) { if ((ret = cosem_createObject(ot, &it->element.target)) != 0) { return ret; } oa_push(&settings->releasedObjects, it->element.target); memcpy(it->element.target->logicalName, tmp3->byteArr->data, tmp3->byteArr->size); } arr_push(&object->elements, it); } } } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_ARRAY_MANAGER #ifndef DLMS_IGNORE_PUSH_SETUP int cosem_setPushSetup(dlmsSettings* settings, gxPushSetup* object, unsigned char index, dlmsVARIANT* value) { int ret, pos; gxTarget* it; gxObject* obj; dlmsVARIANT* tmp, * tmp3; gxtime* s, * e; if (index == 2) { DLMS_OBJECT_TYPE type = DLMS_OBJECT_TYPE_NONE; obj_clearPushObjectList(&object->pushObjectList); if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &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 = (DLMS_OBJECT_TYPE)var_toInteger(tmp3); //Get LN. ret = va_getByIndex(tmp->Arr, 1, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { return ret; } obj = NULL; if ((ret = oa_findByLN(&settings->objects, type, tmp3->byteArr->data, &obj)) != 0) { return ret; } if (obj == NULL) { if ((ret = cosem_createObject(type, &obj)) != 0) { return ret; } oa_push(&settings->releasedObjects, obj); memcpy(obj->logicalName, tmp3->byteArr->data, tmp3->byteArr->size); } it = (gxTarget*)gxmalloc(sizeof(gxTarget)); if (it == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } ret = va_getByIndex(tmp->Arr, 2, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } it->attributeIndex = (unsigned char)var_toInteger(tmp3); ret = va_getByIndex(tmp->Arr, 3, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } it->dataIndex = (unsigned char)var_toInteger(tmp3); arr_push(&object->pushObjectList, key_init(obj, it)); } } } else if (index == 3) { bb_clear(&object->destination); //Get service. ret = va_getByIndex(value->Arr, 0, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->service = (DLMS_SERVICE_TYPE)var_toInteger(tmp); //Destination. ret = va_getByIndex(value->Arr, 1, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } if (tmp->byteArr != NULL && tmp->byteArr->size != 0) { bb_clear(&object->destination); bb_set(&object->destination, tmp->byteArr->data, tmp->byteArr->size); } //Message. ret = va_getByIndex(value->Arr, 2, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->message = (DLMS_MESSAGE_TYPE)var_toInteger(tmp); } else if (index == 4) { arr_clearKeyValuePair(&object->communicationWindow); if (value->Arr != NULL) { dlmsVARIANT start, end; var_init(&start); var_init(&end); for (pos = 0; pos != value->Arr->size; ++pos) { if ((ret = va_getByIndex(value->Arr, pos, &tmp)) != 0 || (ret = va_getByIndex(tmp->Arr, 0, &tmp3)) != 0 || (ret = dlms_changeType2(tmp3, DLMS_DATA_TYPE_DATETIME, &start)) != 0 || (ret = va_getByIndex(tmp->Arr, 1, &tmp3)) != 0 || (ret = dlms_changeType2(tmp3, DLMS_DATA_TYPE_DATETIME, &end)) != 0) { break; } s = (gxtime*)gxmalloc(sizeof(gxtime)); e = (gxtime*)gxmalloc(sizeof(gxtime)); time_copy(s, start.dateTime); time_copy(e, end.dateTime); arr_push(&object->communicationWindow, key_init(s, e)); } var_clear(&start); var_clear(&end); } } else if (index == 5) { object->randomisationStartInterval = (uint16_t)var_toInteger(value); } else if (index == 6) { object->numberOfRetries = (unsigned char)var_toInteger(value); } else if (index == 7) { object->repetitionDelay = (uint16_t)var_toInteger(value); } else { return DLMS_ERROR_CODE_INVALID_PARAMETER; } return DLMS_ERROR_CODE_OK; } #endif //DLMS_IGNORE_PUSH_SETUP #ifndef DLMS_IGNORE_CHARGE int setUnitCharge(dlmsSettings* settings, gxUnitCharge* target, dlmsVARIANT* value) { gxChargeTable* ct; int ret, pos; ret = obj_clearChargeTables(&target->chargeTables); if (ret != 0) { return ret; } #ifndef DLMS_IGNORE_OBJECT_POINTERS signed short type; #endif //DLMS_IGNORE_OBJECT_POINTERS dlmsVARIANT* it, * it2, * tmp; //charge per unit scaling ret = va_getByIndex(value->Arr, 0, &it); if (ret != 0) { return ret; } //commodity scale ret = va_getByIndex(it->Arr, 0, &it2); if (ret != 0) { return ret; } target->chargePerUnitScaling.commodityScale = (char)var_toInteger(it2); //price scale ret = va_getByIndex(it->Arr, 1, &it2); if (ret != 0) { return ret; } target->chargePerUnitScaling.priceScale = (char)var_toInteger(it2); //commodity ret = va_getByIndex(value->Arr, 1, &it); if (ret != 0) { return ret; } //type ret = va_getByIndex(it->Arr, 0, &it2); if (ret != 0) { return ret; } #ifndef DLMS_IGNORE_OBJECT_POINTERS type = (DLMS_OBJECT_TYPE)var_toInteger(it2); #else target->commodity.type = (DLMS_OBJECT_TYPE)var_toInteger(it2); #endif //DLMS_IGNORE_OBJECT_POINTERS //LN ret = va_getByIndex(it->Arr, 1, &it2); if (ret != 0) { return ret; } #ifndef DLMS_IGNORE_OBJECT_POINTERS if (bb_size(it2->byteArr) == 6) { if ((ret = oa_findByLN(&settings->objects, type, it2->byteArr->data, &target->commodity.target)) != 0) { return ret; } } else { target->commodity.target = NULL; } #else memset(target->commodity.logicalName, 0, 6); if (it2->byteArr != NULL && it2->byteArr->size == 6) { memcpy(target->commodity.logicalName, it2->byteArr->data, 6); } #endif //DLMS_IGNORE_OBJECT_POINTERS //attribute index ret = va_getByIndex(it->Arr, 2, &it2); if (ret != 0) { return ret; } target->commodity.attributeIndex = (unsigned char)var_toInteger(it2); //chargeTables obj_clearChargeTables(&target->chargeTables); ret = va_getByIndex(value->Arr, 2, &it); if (ret != 0) { return ret; } for (pos = 0; pos != it->Arr->size; ++pos) { ret = va_getByIndex(it->Arr, pos, &it2); if (ret != 0) { break; } ct = (gxChargeTable*)gxmalloc(sizeof(gxChargeTable)); if (ct == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } arr_push(&target->chargeTables, ct); BYTE_BUFFER_INIT(&ct->index); //index ret = va_getByIndex(it2->Arr, 0, &tmp); if (ret != 0) { break; } bb_set2(&ct->index, tmp->byteArr, 0, bb_size(tmp->byteArr)); //chargePerUnit ret = va_getByIndex(it2->Arr, 1, &tmp); if (ret != 0) { break; } ct->chargePerUnit = (short)var_toInteger(tmp); } return ret; } int cosem_setCharge(dlmsSettings* settings, gxCharge* object, unsigned char index, dlmsVARIANT* value) { int ret = 0; dlmsVARIANT tmp; if (index == 2) { object->totalAmountPaid = (short)var_toInteger(value); } else if (index == 3) { object->chargeType = (unsigned char)var_toInteger(value); } else if (index == 4) { object->priority = (unsigned char)var_toInteger(value); } else if (index == 5) { ret = setUnitCharge(settings, &object->unitChargeActive, value); } else if (index == 6) { ret = setUnitCharge(settings, &object->unitChargePassive, value); } else if (index == 7) { //Some meters are returning empty octet string here. if (value->vt == DLMS_DATA_TYPE_OCTET_STRING && value->byteArr != NULL) { var_init(&tmp); if ((ret = dlms_changeType2(value, DLMS_DATA_TYPE_DATETIME, &tmp)) != 0) { var_clear(&tmp); return ret; } time_copy(&object->unitChargeActivationTime, tmp.dateTime); var_clear(&tmp); } else { time_clear(&object->unitChargeActivationTime); } } else if (index == 8) { object->period = var_toInteger(value); } else if (index == 9) { object->chargeConfiguration = var_toInteger(value); } else if (index == 10) { if (value->vt == DLMS_DATA_TYPE_DATETIME) { object->lastCollectionTime = *value->dateTime; } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } } else if (index == 11) { object->lastCollectionAmount = var_toInteger(value); } else if (index == 12) { object->totalAmountRemaining = var_toInteger(value); } else if (index == 13) { object->proportion = (uint16_t)var_toInteger(value); } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_CHARGE #ifndef DLMS_IGNORE_CREDIT int cosem_setCredit(gxCredit* object, unsigned char index, dlmsVARIANT* value) { int ret = 0; dlmsVARIANT tmp; if (index == 2) { object->currentCreditAmount = var_toInteger(value); } else if (index == 3) { object->type = (unsigned char)var_toInteger(value); } else if (index == 4) { object->priority = (unsigned char)var_toInteger(value); } else if (index == 5) { object->warningThreshold = var_toInteger(value); } else if (index == 6) { object->limit = var_toInteger(value); } else if (index == 7) { object->creditConfiguration = var_toInteger(value); } else if (index == 8) { object->status = (unsigned char)var_toInteger(value); } else if (index == 9) { object->presetCreditAmount = var_toInteger(value); } else if (index == 10) { object->creditAvailableThreshold = var_toInteger(value); } else if (index == 11) { var_init(&tmp); ret = dlms_changeType(value->byteArr, DLMS_DATA_TYPE_DATETIME, &tmp); if (ret == 0) { time_copy(&object->period, tmp.dateTime); } var_clear(&tmp); } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_CREDIT #ifndef DLMS_IGNORE_ACCOUNT int cosem_setAccount(gxAccount* object, unsigned char index, dlmsVARIANT* value) { int ret = 0, pos; unsigned char* ba; dlmsVARIANT* it; dlmsVARIANT tmp; dlmsVARIANT* tmp2; gxCreditChargeConfiguration* ccc; gxTokenGatewayConfiguration* gwc; if (index == 2) { //payment mode ret = va_getByIndex(value->Arr, 0, &it); if (ret != 0) { return ret; } object->paymentMode = (DLMS_ACCOUNT_PAYMENT_MODE)var_toInteger(it); //account status ret = va_getByIndex(value->Arr, 1, &it); if (ret != 0) { return ret; } object->accountStatus = (DLMS_ACCOUNT_STATUS)var_toInteger(it); } else if (index == 3) { object->currentCreditInUse = (unsigned char)var_toInteger(value); } else if (index == 4) { if (value->bitArr == NULL || value->bitArr->size == 0) { return DLMS_ERROR_CODE_READ_WRITE_DENIED; } else { object->currentCreditStatus = (DLMS_ACCOUNT_CREDIT_STATUS)var_toInteger(value); } } else if (index == 5) { object->availableCredit = var_toInteger(value); } else if (index == 6) { object->amountToClear = var_toInteger(value); } else if (index == 7) { object->clearanceThreshold = var_toInteger(value); } else if (index == 8) { object->aggregatedDebt = var_toInteger(value); } else if (index == 9) { arr_clear(&object->creditReferences); for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &it); if (ret != 0) { return ret; } if (it->byteArr == NULL || it->byteArr->size != 6) { return DLMS_ERROR_CODE_INVALID_PARAMETER; } ba = (unsigned char*)gxmalloc(6); memcpy(ba, it->byteArr->data, 6); arr_push(&object->creditReferences, ba); } } else if (index == 10) { arr_clear(&object->chargeReferences); for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &it); if (ret != 0) { return ret; } if (it->byteArr == NULL || it->byteArr->size != 6) { return DLMS_ERROR_CODE_INVALID_PARAMETER; } ba = (unsigned char*)gxmalloc(6); memcpy(ba, it->byteArr->data, 6); arr_push(&object->chargeReferences, ba); } } else if (index == 11) { ccc = NULL; obj_clearCreditChargeConfigurations(&object->creditChargeConfigurations); for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &it); if (ret != 0) { break; } ccc = (gxCreditChargeConfiguration*)gxmalloc(sizeof(gxCreditChargeConfiguration)); if (ccc == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } //credit reference ret = va_getByIndex(it->Arr, 0, &tmp2); if (ret != 0) { break; } memcpy(ccc->creditReference, tmp2->byteArr->data, tmp2->byteArr->size); //charge reference ret = va_getByIndex(it->Arr, 1, &tmp2); if (ret != 0) { break; } memcpy(ccc->chargeReference, tmp2->byteArr->data, tmp2->byteArr->size); //collection configuration ret = va_getByIndex(it->Arr, 2, &tmp2); if (ret != 0) { break; } ccc->collectionConfiguration = (DLMS_CREDIT_COLLECTION_CONFIGURATION)var_toInteger(tmp2); arr_push(&object->creditChargeConfigurations, ccc); } if (ret != 0 && ccc != NULL) { gxfree(ccc); } } else if (index == 12) { obj_clearTokenGatewayConfigurations(&object->tokenGatewayConfigurations); gwc = NULL; for (pos = 0; pos != value->Arr->size; ++pos) { gwc = NULL; if ((ret = va_getByIndex(value->Arr, pos, &it)) != 0) { break; } gwc = (gxTokenGatewayConfiguration*)gxmalloc(sizeof(gxTokenGatewayConfiguration)); if (gwc == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } memset(gwc->creditReference, 0, 6); //credit reference if ((ret = va_getByIndex(it->Arr, 0, &tmp2)) != 0) { return ret; } if (tmp2->byteArr->size == 6) { memcpy(gwc->creditReference, tmp2->byteArr->data, tmp2->byteArr->size); } //token proportion if ((ret = va_getByIndex(it->Arr, 1, &tmp2)) != 0) { break; } gwc->tokenProportion = (unsigned char)var_toInteger(tmp2); arr_push(&object->tokenGatewayConfigurations, gwc); } if (ret != 0 && gwc != NULL) { gxfree(gwc); } } else if (index == 13) { var_init(&tmp); ret = dlms_changeType(value->byteArr, DLMS_DATA_TYPE_DATETIME, &tmp); if (ret == 0) { time_copy(&object->accountActivationTime, tmp.dateTime); } var_clear(&tmp); } else if (index == 14) { var_init(&tmp); ret = dlms_changeType(value->byteArr, DLMS_DATA_TYPE_DATETIME, &tmp); if (ret == 0) { time_copy(&object->accountClosureTime, tmp.dateTime); } var_clear(&tmp); } else if (index == 15) { bb_clear(&object->currency.name); //Name ret = va_getByIndex(value->Arr, 0, &it); if (ret != 0) { return ret; } if (it->strVal != NULL && it->strVal->size != 0) { bb_set2(&object->currency.name, it->strVal, 0, bb_size(it->strVal)); } //scale ret = va_getByIndex(value->Arr, 1, &it); if (ret != 0) { return ret; } object->currency.scale = (char)var_toInteger(it); //unit ret = va_getByIndex(value->Arr, 2, &it); if (ret != 0) { return ret; } object->currency.unit = (DLMS_CURRENCY)var_toInteger(it); } else if (index == 16) { object->lowCreditThreshold = var_toInteger(value); } else if (index == 17) { object->nextCreditAvailableThreshold = var_toInteger(value); } else if (index == 18) { object->maxProvision = (uint16_t)var_toInteger(value); } else if (index == 19) { object->maxProvisionPeriod = var_toInteger(value); } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_ACCOUNT #ifndef DLMS_IGNORE_IMAGE_TRANSFER int cosem_setImageTransfer(gxImageTransfer* object, unsigned char index, dlmsVARIANT* value) { int pos, ret = 0; gxImageActivateInfo* item; dlmsVARIANT* it, * tmp; if (index == 2) { object->imageBlockSize = var_toInteger(value); } else if (index == 3) { ba_clear(&object->imageTransferredBlocksStatus); if (value->bitArr != NULL) { ba_copy(&object->imageTransferredBlocksStatus, value->bitArr->data, (uint16_t)value->bitArr->size); } } else if (index == 4) { object->imageFirstNotTransferredBlockNumber = var_toInteger(value); } else if (index == 5) { object->imageTransferEnabled = var_toInteger(value) == 0 ? 0 : 1; } else if (index == 6) { object->imageTransferStatus = (DLMS_IMAGE_TRANSFER_STATUS)var_toInteger(value); } else if (index == 7) { arr_clear(&object->imageActivateInfo); item = NULL; if (value->Arr != NULL) { item = NULL; for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &it); if (ret != 0) { break; } item = (gxImageActivateInfo*)gxmalloc(sizeof(gxImageActivateInfo)); if (item == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } BYTE_BUFFER_INIT(&item->identification); BYTE_BUFFER_INIT(&item->signature); ret = va_getByIndex(it->Arr, 0, &tmp); if (ret != 0) { break; } item->size = var_toInteger(tmp); ret = va_getByIndex(it->Arr, 1, &tmp); if (ret != 0) { break; } bb_set2(&item->identification, tmp->byteArr, 0, bb_size(tmp->byteArr)); ret = va_getByIndex(it->Arr, 2, &tmp); if (ret != 0) { break; } bb_set2(&item->signature, tmp->byteArr, 0, bb_size(tmp->byteArr)); arr_push(&object->imageActivateInfo, item); } if (ret != 0 && item != NULL) { gxfree(item); } } } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_IMAGE_TRANSFER #if !(defined(DLMS_IGNORE_PROFILE_GENERIC) && defined(DLMS_IGNORE_COMPACT_DATA)) int setCaptureObjects( dlmsSettings* settings, gxArray* objects, dlmsVARIANT* value) { gxObject* obj; DLMS_OBJECT_TYPE type; dlmsVARIANT* tmp, * tmp2; gxTarget* co; int pos, ret; if ((ret = obj_clearProfileGenericCaptureObjects(objects)) != DLMS_ERROR_CODE_OK) { return ret; } arr_capacity(objects, value->Arr->size); if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } if (tmp->Arr->size != 4) { //Invalid structure format. ret = DLMS_ERROR_CODE_INVALID_PARAMETER; break; } ret = va_getByIndex(tmp->Arr, 0, &tmp2); if (ret != DLMS_ERROR_CODE_OK) { break; } type = (DLMS_OBJECT_TYPE)var_toInteger(tmp2); //Get LN. ret = va_getByIndex(tmp->Arr, 1, &tmp2); if (ret != DLMS_ERROR_CODE_OK) { break; } ret = oa_findByLN(&settings->objects, type, tmp2->byteArr->data, &obj); if (ret != DLMS_ERROR_CODE_OK) { break; } if (obj == NULL) { ret = cosem_createObject(type, &obj); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = cosem_setLogicalName(obj, tmp2->byteArr->data); if (ret != DLMS_ERROR_CODE_OK) { return ret; } //Add object to released objects list. ret = oa_push(&settings->releasedObjects, obj); if (ret != DLMS_ERROR_CODE_OK) { return ret; } } co = (gxTarget*)gxmalloc(sizeof(gxTarget)); if (co == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } ret = va_getByIndex(tmp->Arr, 2, &tmp2); if (ret != DLMS_ERROR_CODE_OK) { return ret; } co->attributeIndex = (unsigned char)var_toInteger(tmp2); ret = va_getByIndex(tmp->Arr, 3, &tmp2); if (ret != DLMS_ERROR_CODE_OK) { return ret; } co->dataIndex = (unsigned char)var_toInteger(tmp2); arr_push(objects, key_init(obj, co)); } } //Trim array. arr_capacity(objects, objects->size); return ret; } #endif //!(defined(DLMS_IGNORE_PROFILE_GENERIC) && defined(DLMS_IGNORE_CONPACT_DATA)) #ifndef DLMS_IGNORE_PROFILE_GENERIC int cosem_setProfileGeneric( dlmsSettings* settings, gxProfileGeneric* object, unsigned char index, dlmsVARIANT* value) { int ret = 0; uint16_t pos, pos2; DLMS_OBJECT_TYPE type; dlmsVARIANT* tmp, * row, * data; variantArray* va; if (index == 2) { static unsigned char UNIX_TIME[6] = { 0, 0, 1, 1, 0, 255 }; if (object->captureObjects.size == 0) { //Read capture objects first. return DLMS_ERROR_CODE_INVALID_PARAMETER; } if ((ret = obj_clearProfileGenericBuffer(&object->buffer)) == 0) { if (value->vt == DLMS_DATA_TYPE_OCTET_STRING) { uint16_t rIndex, rCount = arr_getCapacity(&object->buffer); dlmsVARIANT* row; if ((ret = cosem_checkArray(value->byteArr, &rCount)) == 0) { object->buffer.size = rCount; if (rCount != 0 && (ret = arr_getByIndex(&object->buffer, 0, (void**)&row)) == 0) { uint16_t cCount = row->Arr->size; if (cCount > object->captureObjects.size) { //Number of columns do not match. return DLMS_ERROR_CODE_INVALID_PARAMETER; } for (rIndex = 0; rIndex != rCount; ++rIndex) { if ((ret = arr_getByIndex(&object->buffer, rIndex, (void**)&row)) != 0 || (ret = cosem_checkStructure(value->byteArr, (unsigned char)cCount)) != 0) { break; } } } } } } if (value->vt == DLMS_DATA_TYPE_ARRAY) { gxtime lastDate; time_initUnix(&lastDate, 0); //Allocate array. arr_capacity(&object->buffer, value->Arr->size); for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &row); if (ret != DLMS_ERROR_CODE_OK) { return ret; } if (row->Arr->size != object->captureObjects.size) { //Number of columns do not match. return DLMS_ERROR_CODE_INVALID_PARAMETER; } for (pos2 = 0; pos2 < row->Arr->size; ++pos2) { ret = va_getByIndex(row->Arr, pos2, &data); if (ret != DLMS_ERROR_CODE_OK) { return ret; } if (data->vt == DLMS_DATA_TYPE_NONE || data->vt == DLMS_DATA_TYPE_OCTET_STRING || data->vt == DLMS_DATA_TYPE_UINT32) { gxObject* obj; gxTarget* t; gxKey* k; if ((ret = arr_getByIndex(&object->captureObjects, pos2, (void**)&k)) != 0) { return ret; } obj = (gxObject*)k->key; t = (gxTarget*)k->value; if (obj->objectType == DLMS_OBJECT_TYPE_CLOCK && t->attributeIndex == 2) { if (data->vt == DLMS_DATA_TYPE_OCTET_STRING) { dlmsVARIANT tmp3; var_init(&tmp3); var_attach(&tmp3, data->byteArr); ret = dlms_changeType(tmp3.byteArr, DLMS_DATA_TYPE_DATETIME, data); var_clear(&tmp3); if (ret != 0) { return ret; } lastDate = *data->dateTime; } //Some meters returns NULL date time to save bytes. else if (data->vt == DLMS_DATA_TYPE_NONE) { if (object->sortMethod == DLMS_SORT_METHOD_FIFO || object->sortMethod == DLMS_SORT_METHOD_SMALLEST) { time_addSeconds(&lastDate, object->capturePeriod); } else { int tm = object->capturePeriod; time_addSeconds(&lastDate, -tm); } var_setDateTime(data, &lastDate); } } else if (data->vt == DLMS_DATA_TYPE_UINT32 && obj->objectType == DLMS_OBJECT_TYPE_DATA && t->attributeIndex == 2 && memcmp(obj->logicalName, UNIX_TIME, 6) == 0) { gxtime tmp4; time_initUnix(&tmp4, data->ulVal); var_setDateTime(data, &tmp4); lastDate = *data->dateTime; } } } //Attach rows from parser. va = (variantArray*)gxmalloc(sizeof(variantArray)); va_init(va); va_attach2(va, row->Arr); arr_push(&object->buffer, va); } } if (settings->server) { object->entriesInUse = object->buffer.size; } //Trim array. arr_capacity(&object->buffer, object->buffer.size); } else if (index == 3) { object->entriesInUse = 0; ret = obj_clearProfileGenericBuffer(&object->buffer); if (ret == DLMS_ERROR_CODE_OK) { ret = setCaptureObjects(settings, &object->captureObjects, value); } } else if (index == 4) { object->capturePeriod = var_toInteger(value); } else if (index == 5) { object->sortMethod = (DLMS_SORT_METHOD)var_toInteger(value); } else if (index == 6) { if (value->vt == DLMS_DATA_TYPE_NONE) { object->sortObject = NULL; } else { if (value->Arr == NULL || value->Arr->size != 4) { //Invalid structure format. return DLMS_ERROR_CODE_INVALID_PARAMETER; } ret = va_getByIndex(value->Arr, 0, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } type = (DLMS_OBJECT_TYPE)var_toInteger(tmp); ret = va_getByIndex(value->Arr, 1, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->sortObject = NULL; ret = oa_findByLN(&settings->objects, type, tmp->byteArr->data, &object->sortObject); if (ret != DLMS_ERROR_CODE_OK) { return ret; } if (object->sortObject == NULL) { ret = cosem_createObject(type, &object->sortObject); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = cosem_setLogicalName(object->sortObject, tmp->byteArr->data); if (ret != DLMS_ERROR_CODE_OK) { return ret; } //Add object to released objects list. ret = oa_push(&settings->releasedObjects, object->sortObject); } ret = va_getByIndex(value->Arr, 2, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->sortObjectAttributeIndex = (char)var_toInteger(tmp); ret = va_getByIndex(value->Arr, 3, &tmp); if (ret != DLMS_ERROR_CODE_OK) { return ret; } object->sortObjectDataIndex = (uint16_t)var_toInteger(tmp); } } else if (index == 7) { object->entriesInUse = var_toInteger(value); } else if (index == 8) { object->profileEntries = var_toInteger(value); } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_PROFILE_GENERIC #ifndef DLMS_IGNORE_GSM_DIAGNOSTIC int cosem_setGsmDiagnostic(gxGsmDiagnostic* object, unsigned char index, dlmsVARIANT* value) { int ret = 0, pos; dlmsVARIANT tmp2; dlmsVARIANT* tmp, * it; gxAdjacentCell* ac; switch (index) { case 2: if (value->vt == DLMS_DATA_TYPE_OCTET_STRING) { if (object->operatorName != NULL) { gxfree(object->operatorName); object->operatorName = NULL; } if (value->byteArr != NULL && bb_size(value->byteArr) != 0) { object->operatorName = (char*)gxmalloc(value->byteArr->size + 1); if (object->operatorName == NULL) { return DLMS_ERROR_CODE_OUTOFMEMORY; } memcpy(object->operatorName, value->strVal->data, value->byteArr->size); object->operatorName[value->byteArr->size] = '\0'; } } else if (value->vt == DLMS_DATA_TYPE_STRING) { if (object->operatorName != NULL) { gxfree(object->operatorName); object->operatorName = NULL; } object->operatorName = NULL; if (value->strVal != NULL && bb_size(value->strVal) != 0) { object->operatorName = (char*)gxmalloc(value->strVal->size + 1); if (object->operatorName == NULL) { return DLMS_ERROR_CODE_OUTOFMEMORY; } memcpy(object->operatorName, value->strVal->data, value->strVal->size); object->operatorName[value->strVal->size] = '\0'; } } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } break; case 3: object->status = (DLMS_GSM_STATUS)var_toInteger(value); break; case 4: object->circuitSwitchStatus = (DLMS_GSM_CIRCUIT_SWITCH_STATUS)var_toInteger(value); break; case 5: object->packetSwitchStatus = (DLMS_GSM_PACKET_SWITCH_STATUS)var_toInteger(value); break; case 6: if (value != NULL && value->vt == DLMS_DATA_TYPE_STRUCTURE) { if ((ret = va_getByIndex(value->Arr, 0, &tmp)) != 0) { return ret; } object->cellInfo.cellId = (uint32_t)var_toInteger(tmp); if ((ret = va_getByIndex(value->Arr, 1, &tmp)) != 0) { return ret; } object->cellInfo.locationId = (uint16_t)var_toInteger(tmp); if ((ret = va_getByIndex(value->Arr, 2, &tmp)) != 0) { return ret; } object->cellInfo.signalQuality = (unsigned char)var_toInteger(tmp); if ((ret = va_getByIndex(value->Arr, 3, &tmp)) != 0) { return ret; } object->cellInfo.ber = (unsigned char)var_toInteger(tmp); if (object->base.version != 0) { if ((ret = va_getByIndex(value->Arr, 4, &tmp)) != 0) { return ret; } object->cellInfo.mobileCountryCode = (uint16_t)var_toInteger(tmp); if ((ret = va_getByIndex(value->Arr, 5, &tmp)) != 0) { return ret; } object->cellInfo.mobileNetworkCode = (uint16_t)var_toInteger(tmp); if ((ret = va_getByIndex(value->Arr, 6, &tmp)) != 0) { return ret; } object->cellInfo.channelNumber = tmp->ulVal; } } break; case 7: arr_clear(&object->adjacentCells); if (value != NULL && value->vt == DLMS_DATA_TYPE_ARRAY) { ac = NULL; for (pos = 0; pos != value->Arr->size; ++pos) { ac = NULL; ret = va_getByIndex(value->Arr, pos, &it); if (ret != DLMS_ERROR_CODE_OK) { break; } ret = va_getByIndex(it->Arr, 0, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } ac = (gxAdjacentCell*)gxmalloc(sizeof(gxAdjacentCell)); if (ac == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } ac->cellId = var_toInteger(tmp); ret = va_getByIndex(it->Arr, 1, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } ac->signalQuality = (unsigned char)var_toInteger(tmp); arr_push(&object->adjacentCells, ac); } if (ret != 0 && ac != NULL) { gxfree(ac); } } break; case 8: //Some meters are returning empty octet string here. if (value->vt == DLMS_DATA_TYPE_OCTET_STRING && value->byteArr != NULL) { var_init(&tmp2); ret = dlms_changeType2(value, DLMS_DATA_TYPE_DATETIME, &tmp2); if (ret != 0) { return ret; } time_copy(&object->captureTime, tmp2.dateTime); var_clear(&tmp2); } else if (value->vt == DLMS_DATA_TYPE_DATETIME) { time_copy(&object->captureTime, value->dateTime); } else { time_clear(&object->captureTime); } break; default: ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_GSM_DIAGNOSTIC #ifndef DLMS_IGNORE_TOKEN_GATEWAY int cosem_setTokenGateway(gxTokenGateway* object, unsigned char index, dlmsVARIANT* value) { int ret = DLMS_ERROR_CODE_OK, pos; dlmsVARIANT* tmp; dlmsVARIANT tmp2; dlmsVARIANT* it; switch (index) { case 2: bb_clear(&object->token); ret = bb_set2(&object->token, value->byteArr, 0, bb_size(value->byteArr)); break; case 3: time_clear(&object->time); if (value->byteArr == NULL) { time_clear(&object->time); } else { var_init(&tmp2); ret = dlms_changeType2(value, DLMS_DATA_TYPE_DATETIME, &tmp2); if (ret != 0) { return ret; } time_copy(&object->time, tmp2.dateTime); var_clear(&tmp2); } break; case 4: obj_clearByteBufferList(&object->descriptions); if (value != NULL) { gxByteBuffer* d; for (pos = 0; pos != value->Arr->size; ++pos) { if ((ret = va_getByIndex(value->Arr, pos, &it)) != 0) { return ret; } d = (gxByteBuffer*)gxmalloc(sizeof(gxByteBuffer)); if (d == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } BYTE_BUFFER_INIT(d); bb_set2(d, it->strVal, 0, it->strVal->size); arr_push(&object->descriptions, d); } } break; case 5: object->deliveryMethod = (DLMS_TOKEN_DELIVERY)var_toInteger(value); break; case 6: if ((ret = va_getByIndex(value->Arr, 0, &tmp)) != 0) { return ret; } object->status = (DLMS_TOKEN_STATUS_CODE)var_toInteger(tmp); if ((ret = va_getByIndex(value->Arr, 1, &tmp)) != 0) { return ret; } ba_clear(&object->dataValue); if (tmp->strVal != NULL && tmp->strVal->size != 0) { ba_copy(&object->dataValue, tmp->bitArr->data, tmp->bitArr->size); } break; default: ret = DLMS_ERROR_CODE_INVALID_PARAMETER; break; } return ret; } #endif //DLMS_IGNORE_TOKEN_GATEWAY #ifndef DLMS_IGNORE_COMPACT_DATA int compactData_updateTemplateDescription( dlmsSettings* settings, gxCompactData* object) { int ret; uint16_t pos; gxByteBuffer tmp; gxValueEventCollection args; gxValueEventArg e; ve_init(&e); gxKey* kv; bb_clear(&object->buffer); bb_clear(&object->templateDescription); e.action = 1; e.target = &object->base; e.index = 2; vec_init(&args); BYTE_BUFFER_INIT(&tmp); vec_push(&args, &e); if (!e.handled) { if ((ret = bb_setUInt8(&object->templateDescription, DLMS_DATA_TYPE_STRUCTURE)) != DLMS_ERROR_CODE_OK) { bb_clear(&object->buffer); return ret; } hlp_setObjectCount(object->captureObjects.size, &object->templateDescription); for (pos = 0; pos != object->captureObjects.size; ++pos) { ret = arr_getByIndex(&object->captureObjects, pos, (void**)&kv); if (ret != DLMS_ERROR_CODE_OK) { bb_clear(&object->buffer); return ret; } e.target = (gxObject*)kv->key; e.index = ((gxTarget*)kv->value)->attributeIndex; if ((ret = cosem_getValue(settings, &e)) != 0) { var_clear(&e.value); bb_clear(&object->buffer); return ret; } if (e.byteArray) { if (bb_size(e.value.byteArr) == 0) { bb_setUInt8(&object->templateDescription, 0); } else { if (e.value.byteArr->data[0] == DLMS_DATA_TYPE_ARRAY || e.value.byteArr->data[0] == DLMS_DATA_TYPE_STRUCTURE) { gxDataInfo info; dlmsVARIANT value; uint16_t count; di_init(&info); var_init(&value); e.value.byteArr->position = 1; if ((ret = hlp_getObjectCount2(e.value.byteArr, &count)) != 0 || ((gxTarget*)kv->value)->dataIndex > count) { var_clear(&e.value); bb_clear(&object->buffer); return DLMS_ERROR_CODE_OUTOFMEMORY; } //If all data is captured. if (((gxTarget*)kv->value)->dataIndex == 0) { bb_setUInt8(&object->templateDescription, e.value.byteArr->data[0]); if (e.value.byteArr->data[0] == DLMS_DATA_TYPE_ARRAY) { bb_setUInt16(&object->templateDescription, e.value.byteArr->data[1]); } else { bb_setUInt8(&object->templateDescription, e.value.byteArr->data[1]); } for (unsigned char pos = 0; pos < count; ++pos) { di_init(&info); var_clear(&value); if ((ret = dlms_getData(e.value.byteArr, &info, &value)) != 0) { var_clear(&value); var_clear(&e.value); bb_clear(&object->buffer); return ret; } if (info.type == DLMS_DATA_TYPE_STRUCTURE || info.type == DLMS_DATA_TYPE_ARRAY) { dlmsVARIANT* value2; bb_setUInt8(&object->templateDescription, info.type); bb_setUInt8(&object->templateDescription, (unsigned char)value.Arr->size); for (uint16_t pos = 0; pos < value.Arr->size; ++pos) { if ((ret = va_getByIndex(value.Arr, pos, &value2)) != 0) { var_clear(&value); var_clear(&e.value); bb_clear(&object->buffer); return ret; } bb_setUInt8(&object->templateDescription, value2->vt); } } else { bb_setUInt8(&object->templateDescription, info.type); } if (e.value.byteArr->data[0] == DLMS_DATA_TYPE_ARRAY) { break; } } } else { for (unsigned char pos = 0; pos < ((gxTarget*)kv->value)->dataIndex; ++pos) { var_clear(&value); di_init(&info); if ((ret = dlms_getData(e.value.byteArr, &info, &value)) != 0) { var_clear(&value); var_clear(&e.value); bb_clear(&object->buffer); return ret; } if (!info.complete) { return DLMS_ERROR_CODE_READ_WRITE_DENIED; } } if (info.type == DLMS_DATA_TYPE_STRUCTURE) { dlmsVARIANT* value2; bb_setUInt8(&object->templateDescription, DLMS_DATA_TYPE_STRUCTURE); bb_setUInt8(&object->templateDescription, (unsigned char)value.Arr->size); for (uint16_t pos = 0; pos < value.Arr->size; ++pos) { if ((ret = va_getByIndex(value.Arr, pos, &value2)) != 0) { var_clear(&value); var_clear(&e.value); bb_clear(&object->buffer); return ret; } bb_setUInt8(&object->templateDescription, value2->vt); } } else { bb_setUInt8(&object->templateDescription, info.type); } } var_clear(&value); } else { bb_setUInt8(&object->templateDescription, e.value.byteArr->data[0]); } } } else { if ((ret = dlms_setData(&tmp, e.value.vt, &e.value)) != 0) { var_clear(&e.value); bb_clear(&tmp); bb_clear(&object->buffer); return ret; } bb_setUInt8(&object->templateDescription, tmp.data[0]); bb_clear(&tmp); } var_clear(&e.value); ve_clear(&e); } } bb_clear(&tmp); //svr_postGet(settings, &args); vec_empty(&args); return 0; } int cosem_setCompactData( dlmsSettings* settings, gxCompactData* object, unsigned char index, dlmsVARIANT* value) { int ret = DLMS_ERROR_CODE_OK; switch (index) { case 2: bb_clear(&object->buffer); if (value->byteArr != NULL) { ret = bb_set(&object->buffer, value->byteArr->data, value->byteArr->size); } break; case 3: ret = setCaptureObjects(settings, &object->captureObjects, value); if (ret == 0 && settings->server) { ret = compactData_updateTemplateDescription(settings, object); } break; case 4: object->templateId = (unsigned char)var_toInteger(value); break; case 5: bb_clear(&object->templateDescription); if (value->byteArr != NULL) { ret = bb_set(&object->templateDescription, value->byteArr->data, value->byteArr->size); } break; case 6: object->captureMethod = (DLMS_CAPTURE_METHOD)var_toInteger(value); break; default: ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_COMPACT_DATA #ifndef DLMS_IGNORE_PARAMETER_MONITOR int cosem_setParameterMonitor( dlmsSettings* settings, gxParameterMonitor* object, unsigned char index, dlmsVARIANT* value) { int ret = 0, pos; dlmsVARIANT* tmp, * tmp3; dlmsVARIANT tmp2; DLMS_OBJECT_TYPE type; switch (index) { case 2: { #ifndef DLMS_IGNORE_OBJECT_POINTERS object->changedParameter.target = NULL; #else object->changedParameter.type = DLMS_OBJECT_TYPE_NONE; memset(object->changedParameter.logicalName, 0, 6); #endif //DLMS_IGNORE_OBJECT_POINTERS if (value->Arr != NULL) { if ((ret = va_getByIndex(value->Arr, 0, &tmp3)) == DLMS_ERROR_CODE_OK) { type = (DLMS_OBJECT_TYPE)var_toInteger(tmp3); //Get LN. if ((ret = va_getByIndex(value->Arr, 1, &tmp3)) == DLMS_ERROR_CODE_OK) { #ifndef DLMS_IGNORE_OBJECT_POINTERS if ((ret = oa_findByLN(&settings->objects, type, tmp3->byteArr->data, &object->changedParameter.target)) != 0) { return ret; } if (object->changedParameter.target == NULL) { if ((ret = cosem_createObject(type, &object->changedParameter.target)) != 0) { return ret; } oa_push(&settings->releasedObjects, object->changedParameter.target); memcpy(object->changedParameter.target->logicalName, tmp3->byteArr->data, tmp3->byteArr->size); } if ((ret = va_getByIndex(value->Arr, 2, &tmp3)) == DLMS_ERROR_CODE_OK) { object->changedParameter.attributeIndex = (unsigned char)var_toInteger(tmp3); if ((ret = va_getByIndex(value->Arr, 3, &tmp3)) == DLMS_ERROR_CODE_OK) { ret = var_copy(&object->changedParameter.value, tmp3); } } #else object->changedParameter.type = type; memcpy(object->changedParameter.logicalName, tmp3->byteArr->data, 6); if ((ret = va_getByIndex(value->Arr, 2, &tmp3)) == DLMS_ERROR_CODE_OK) { object->changedParameter.attributeIndex = (unsigned char)var_toInteger(tmp3); if ((ret = va_getByIndex(value->Arr, 3, &tmp3)) == DLMS_ERROR_CODE_OK) { ret = var_copy(&object->changedParameter.value, tmp3); } } #endif //DLMS_IGNORE_OBJECT_POINTERS } } } break; } case 3: { //Some meters are returning empty octet string here. if (value->vt == DLMS_DATA_TYPE_OCTET_STRING && value->byteArr != NULL) { ret = var_init(&tmp2); if (ret != DLMS_ERROR_CODE_OK) { return ret; } ret = dlms_changeType2(value, DLMS_DATA_TYPE_DATETIME, &tmp2); if (ret != DLMS_ERROR_CODE_OK) { return ret; } time_copy(&object->captureTime, tmp2.dateTime); var_clear(&tmp2); } else { time_clear(&object->captureTime); } } break; case 4: { obj_clearParametersList(&object->parameters); if (value->Arr != NULL) { gxTarget* it; gxObject* obj; for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &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 = (DLMS_OBJECT_TYPE)var_toInteger(tmp3); //Get LN. ret = va_getByIndex(tmp->Arr, 1, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { return ret; } obj = NULL; if ((ret = oa_findByLN(&settings->objects, type, tmp3->byteArr->data, &obj)) != 0) { return ret; } if (obj == NULL) { if ((ret = cosem_createObject(type, &obj)) != 0) { return ret; } oa_push(&settings->releasedObjects, obj); memcpy(obj->logicalName, tmp3->byteArr->data, tmp3->byteArr->size); } it = (gxTarget*)gxmalloc(sizeof(gxTarget)); if (it == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } ret = va_getByIndex(tmp->Arr, 2, &tmp3); if (ret != DLMS_ERROR_CODE_OK) { break; } it->attributeIndex = (unsigned char)var_toInteger(tmp3); arr_push(&object->parameters, key_init(obj, it)); } } break; } default: ret = DLMS_ERROR_CODE_INVALID_PARAMETER; break; } return ret; } #endif //DLMS_IGNORE_PARAMETER_MONITOR #ifndef DLMS_IGNORE_LLC_SSCS_SETUP int cosem_setLlcSscsSetup( dlmsSettings* settings, gxLlcSscsSetup* object, unsigned char index, dlmsVARIANT* value) { int ret = 0; switch (index) { case 2: object->serviceNodeAddress = (uint16_t)var_toInteger(value); break; case 3: object->baseNodeAddress = (uint16_t)var_toInteger(value); break; default: ret = DLMS_ERROR_CODE_INVALID_PARAMETER; break; } return ret; } #endif //DLMS_IGNORE_LLC_SSCS_SETUP #ifndef DLMS_IGNORE_PRIME_NB_OFDM_PLC_PHYSICAL_LAYER_COUNTERS int cosem_setPrimeNbOfdmPlcPhysicalLayerCounters( dlmsSettings* settings, gxPrimeNbOfdmPlcPhysicalLayerCounters* object, unsigned char index, dlmsVARIANT* value) { int ret = 0; switch (index) { case 2: object->crcIncorrectCount = (uint16_t)var_toInteger(value); break; case 3: object->crcFailedCount = (uint16_t)var_toInteger(value); break; case 4: object->txDropCount = (uint16_t)var_toInteger(value); break; case 5: object->rxDropCount = (uint16_t)var_toInteger(value); break; default: ret = DLMS_ERROR_CODE_INVALID_PARAMETER; break; } return ret; } #endif //DLMS_IGNORE_PRIME_NB_OFDM_PLC_PHYSICAL_LAYER_COUNTERS #ifndef DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_SETUP int cosem_setPrimeNbOfdmPlcMacSetup( dlmsSettings* settings, gxPrimeNbOfdmPlcMacSetup* object, unsigned char index, dlmsVARIANT* value) { int ret = 0; switch (index) { case 2: object->macMinSwitchSearchTime = (unsigned char)var_toInteger(value); break; case 3: object->macMaxPromotionPdu = (unsigned char)var_toInteger(value); break; case 4: object->macPromotionPduTxPeriod = (unsigned char)var_toInteger(value); break; case 5: object->macBeaconsPerFrame = (unsigned char)var_toInteger(value); break; case 6: object->macScpMaxTxAttempts = (unsigned char)var_toInteger(value); break; case 7: object->macCtlReTxTimer = (unsigned char)var_toInteger(value); break; case 8: object->macMaxCtlReTx = (unsigned char)var_toInteger(value); break; default: ret = DLMS_ERROR_CODE_INVALID_PARAMETER; break; } return ret; } #endif //DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_SETUP #ifndef DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_FUNCTIONAL_PARAMETERS int cosem_setPrimeNbOfdmPlcMacFunctionalParameters( dlmsSettings* settings, gxPrimeNbOfdmPlcMacFunctionalParameters* object, unsigned char index, dlmsVARIANT* value) { int ret = 0; switch (index) { case 2: object->lnId = (short)var_toInteger(value); break; case 3: object->lsId = (unsigned char)var_toInteger(value); break; case 4: object->sId = (unsigned char)var_toInteger(value); break; case 5: object->sna.size = 0; ret = bb_set2(&object->sna, value->byteArr, 0, bb_size(value->byteArr)); break; case 6: object->state = (DLMS_MAC_STATE)var_toInteger(value); break; case 7: object->scpLength = (short)var_toInteger(value); break; case 8: object->nodeHierarchyLevel = (unsigned char)var_toInteger(value); break; case 9: object->beaconSlotCount = (unsigned char)var_toInteger(value); break; case 10: object->beaconRxSlot = (unsigned char)var_toInteger(value); break; case 11: object->beaconTxSlot = (unsigned char)var_toInteger(value); break; case 12: object->beaconRxFrequency = (unsigned char)var_toInteger(value); break; case 13: object->beaconTxFrequency = (unsigned char)var_toInteger(value); break; case 14: object->capabilities = (DLMS_MAC_CAPABILITIES)var_toInteger(value); break; default: ret = DLMS_ERROR_CODE_INVALID_PARAMETER; break; } return ret; } #endif //DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_FUNCTIONAL_PARAMETERS #ifndef DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_COUNTERS int cosem_setPrimeNbOfdmPlcMacCounters( dlmsSettings* settings, gxPrimeNbOfdmPlcMacCounters* object, unsigned char index, dlmsVARIANT* value) { int ret = 0; switch (index) { case 2: object->txDataPktCount = var_toInteger(value); break; case 3: object->rxDataPktCount = var_toInteger(value); break; case 4: object->txCtrlPktCount = var_toInteger(value); break; case 5: object->rxCtrlPktCount = var_toInteger(value); break; case 6: object->csmaFailCount = var_toInteger(value); break; case 7: object->csmaChBusyCount = var_toInteger(value); break; default: ret = DLMS_ERROR_CODE_INVALID_PARAMETER; break; } return ret; } #endif //DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_COUNTERS #ifndef DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_NETWORK_ADMINISTRATION_DATA int cosem_setMulticastEntries(gxPrimeNbOfdmPlcMacNetworkAdministrationData* object, dlmsVARIANT* value) { int ret = 0; int pos; gxMacMulticastEntry* it; arr_clear(&object->multicastEntries); if (value->Arr != NULL) { dlmsVARIANT* tmp; dlmsVARIANT* tmp2; for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } it = (gxMacMulticastEntry*)gxmalloc(sizeof(gxMacMulticastEntry)); if ((ret = va_getByIndex(tmp->Arr, 0, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->id = (signed char)var_toInteger(tmp2); if ((ret = va_getByIndex(tmp->Arr, 1, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->members = (short)var_toInteger(tmp2); arr_push(&object->multicastEntries, it); } } return 0; } int cosem_setSwitchTable(gxPrimeNbOfdmPlcMacNetworkAdministrationData* object, dlmsVARIANT* value) { int ret = 0; int pos; arr_empty(&object->switchTable); if (value->Arr != NULL) { dlmsVARIANT* it; for (pos = 0; pos != value->Arr->size; ++pos) { if ((ret = va_getByIndex(value->Arr, pos, &it)) != DLMS_ERROR_CODE_OK) { break; } uint16_t* tmp = (uint16_t*)gxmalloc(sizeof(uint16_t)); *tmp = (uint16_t)var_toInteger(it); arr_push(&object->switchTable, tmp); } } return 0; } int cosem_setDirectTable(gxPrimeNbOfdmPlcMacNetworkAdministrationData* object, dlmsVARIANT* value) { int ret = 0; int pos; gxMacDirectTable* it; arr_clear(&object->directTable); if (value->Arr != NULL) { dlmsVARIANT* tmp; dlmsVARIANT* tmp2; for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } it = (gxMacDirectTable*)gxmalloc(sizeof(gxMacDirectTable)); if ((ret = va_getByIndex(tmp->Arr, 0, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->sourceSId = (short)var_toInteger(tmp2); if ((ret = va_getByIndex(tmp->Arr, 1, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->sourceLnId = (short)var_toInteger(tmp2); if ((ret = va_getByIndex(tmp->Arr, 2, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->sourceLcId = (short)var_toInteger(tmp2); if ((ret = va_getByIndex(tmp->Arr, 3, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->destinationSId = (short)var_toInteger(tmp2); if ((ret = va_getByIndex(tmp->Arr, 4, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->destinationLnId = (short)var_toInteger(tmp2); if ((ret = va_getByIndex(tmp->Arr, 5, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->destinationLcId = (short)var_toInteger(tmp2); if ((ret = va_getByIndex(tmp->Arr, 6, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } if ((ret = bb_get(tmp2->byteArr, it->did, sizeof(it->did))) != DLMS_ERROR_CODE_OK) { break; } arr_push(&object->directTable, it); } } return 0; } int cosem_setAvailableSwitches(gxPrimeNbOfdmPlcMacNetworkAdministrationData* object, dlmsVARIANT* value) { int ret = 0; int pos; gxMacAvailableSwitch* it; obj_clearAvailableSwitches(&object->availableSwitches); if (value->Arr != NULL) { dlmsVARIANT* tmp; dlmsVARIANT* tmp2; for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } if ((ret = va_getByIndex(tmp->Arr, 0, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it = (gxMacAvailableSwitch*)gxmalloc(sizeof(gxMacAvailableSwitch)); BYTE_BUFFER_INIT(&it->sna); bb_capacity(&it->sna, tmp2->byteArr->size); if ((ret = bb_set(&it->sna, tmp2->byteArr->data, tmp2->byteArr->size)) != DLMS_ERROR_CODE_OK) { gxfree(it); break; } if ((ret = va_getByIndex(tmp->Arr, 1, &tmp2)) != DLMS_ERROR_CODE_OK) { gxfree(it); break; } it->lsId = (short)var_toInteger(tmp2); if ((ret = va_getByIndex(tmp->Arr, 2, &tmp2)) != DLMS_ERROR_CODE_OK) { gxfree(it); break; } it->level = (signed char)var_toInteger(tmp2); if ((ret = va_getByIndex(tmp->Arr, 3, &tmp2)) != DLMS_ERROR_CODE_OK) { gxfree(it); break; } it->rxLevel = (signed char)var_toInteger(tmp2); if ((ret = va_getByIndex(tmp->Arr, 4, &tmp2)) != DLMS_ERROR_CODE_OK) { gxfree(it); break; } it->rxSnr = (signed char)var_toInteger(tmp2); arr_push(&object->availableSwitches, it); } } return 0; } int cosem_setCommunications(gxPrimeNbOfdmPlcMacNetworkAdministrationData* object, dlmsVARIANT* value) { int ret = 0; int pos; gxMacPhyCommunication* it; arr_clear(&object->communications); if (value->Arr != NULL) { dlmsVARIANT* tmp; dlmsVARIANT* tmp2; for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } it = (gxMacPhyCommunication*)gxmalloc(sizeof(gxMacPhyCommunication)); if ((ret = va_getByIndex(tmp->Arr, 0, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } if ((ret = bb_get(tmp2->byteArr, it->eui, sizeof(it->eui))) != DLMS_ERROR_CODE_OK) { break; } if ((ret = va_getByIndex(tmp->Arr, 1, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->txPower = (signed char)var_toInteger(tmp2); if ((ret = va_getByIndex(tmp->Arr, 2, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->txCoding = (signed char)var_toInteger(tmp2); if ((ret = va_getByIndex(tmp->Arr, 3, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->rxCoding = (signed char)var_toInteger(tmp2); if ((ret = va_getByIndex(tmp->Arr, 4, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->rxLvl = (signed char)var_toInteger(tmp2); if ((ret = va_getByIndex(tmp->Arr, 5, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->snr = (signed char)var_toInteger(tmp2); if ((ret = va_getByIndex(tmp->Arr, 6, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->txPowerModified = (signed char)var_toInteger(tmp2); if ((ret = va_getByIndex(tmp->Arr, 7, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->txCodingModified = (signed char)var_toInteger(tmp2); if ((ret = va_getByIndex(tmp->Arr, 8, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->rxCodingModified = (signed char)var_toInteger(tmp2); arr_push(&object->communications, it); } } return 0; } int cosem_setPrimeNbOfdmPlcMacNetworkAdministrationData( dlmsSettings* settings, gxPrimeNbOfdmPlcMacNetworkAdministrationData* object, unsigned char index, dlmsVARIANT* value) { int ret = 0; switch (index) { case 2: ret = cosem_setMulticastEntries(object, value); break; case 3: ret = cosem_setSwitchTable(object, value); break; case 4: ret = cosem_setDirectTable(object, value); break; case 5: ret = cosem_setAvailableSwitches(object, value); break; case 6: ret = cosem_setCommunications(object, value); break; default: ret = DLMS_ERROR_CODE_INVALID_PARAMETER; break; } return ret; } #endif //DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_NETWORK_ADMINISTRATION_DATA #ifndef DLMS_IGNORE_PRIME_NB_OFDM_PLC_APPLICATIONS_IDENTIFICATION int cosem_setPrimeNbOfdmPlcApplicationsIdentification( dlmsSettings* settings, gxPrimeNbOfdmPlcApplicationsIdentification* object, unsigned char index, dlmsVARIANT* value) { int ret = 0; switch (index) { case 2: { bb_clear(&object->firmwareVersion); bb_set2(&object->firmwareVersion, value->byteArr, 0, bb_size(value->byteArr)); } break; case 3: object->vendorId = (uint16_t)var_toInteger(value); break; case 4: object->productId = (uint16_t)var_toInteger(value); break; default: ret = DLMS_ERROR_CODE_INVALID_PARAMETER; break; } return ret; } #endif //DLMS_IGNORE_PRIME_NB_OFDM_PLC_APPLICATIONS_IDENTIFICATION #ifndef DLMS_IGNORE_ARBITRATOR int cosem_setArbitrator( dlmsSettings* settings, gxArbitrator* object, unsigned char index, dlmsVARIANT* value) { int pos, ret = 0; gxActionItem* it; bitArray* ba; dlmsVARIANT* tmp, * tmp2; switch (index) { case 2: { arr_clear(&object->actions); if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { it = (gxActionItem*)gxmalloc(sizeof(gxActionItem)); it->script = NULL; if ((ret = va_getByIndex(value->Arr, pos, &tmp)) != DLMS_ERROR_CODE_OK) { break; } if ((ret = va_getByIndex(tmp->Arr, 0, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } #ifndef DLMS_IGNORE_OBJECT_POINTERS if ((ret = oa_findByLN(&settings->objects, DLMS_OBJECT_TYPE_SCRIPT_TABLE, tmp2->byteArr->data, (gxObject**)&it->script)) != 0) { break; } if (it->script == NULL) { if ((ret = cosem_createObject(DLMS_OBJECT_TYPE_SCRIPT_TABLE, (gxObject**)&it->script)) != 0) { return ret; } memcpy(it->script->base.logicalName, tmp2->byteArr->data, tmp2->byteArr->size); //Add object to released objects list. ret = oa_push(&settings->releasedObjects, &it->script->base); if (ret != DLMS_ERROR_CODE_OK) { return ret; } } #else memcpy(it->scriptLogicalName, tmp2->byteArr->data, 6); #endif //DLMS_IGNORE_OBJECT_POINTERS if ((ret = va_getByIndex(tmp->Arr, 1, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->scriptSelector = (uint16_t)var_toInteger(tmp2); arr_push(&object->actions, it); } } } break; case 3: { obj_clearBitArrayList(&object->permissionsTable); if (value->Arr != NULL) { for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } ba = (bitArray*)gxmalloc(sizeof(bitArray)); ba_init(ba); if ((ba_copy(ba, tmp->bitArr->data, tmp->bitArr->size)) != 0) { break; } arr_push(&object->permissionsTable, ba); } } } break; case 4: { arr_clear(&object->weightingsTable); if (value->Arr != NULL) { dlmsVARIANT* tmp2; for (pos = 0; pos != value->Arr->size; ++pos) { ret = va_getByIndex(value->Arr, pos, &tmp); if (ret != DLMS_ERROR_CODE_OK) { break; } tmp2 = (dlmsVARIANT*)gxmalloc(sizeof(dlmsVARIANT)); var_init(tmp2); ret = var_copy(tmp2, tmp); if (ret != 0) { break; } arr_push(&object->weightingsTable, tmp2); } } } break; case 5: { obj_clearBitArrayList(&object->mostRecentRequestsTable); if (value->Arr != NULL) { bitArray* it; for (pos = 0; pos != value->Arr->size; ++pos) { if ((ret = va_getByIndex(value->Arr, pos, &tmp)) != DLMS_ERROR_CODE_OK) { break; } it = (bitArray*)gxmalloc(sizeof(bitArray)); ba_init(it); if ((ba_copy(it, tmp->bitArr->data, tmp->bitArr->size)) != 0) { break; } arr_push(&object->mostRecentRequestsTable, it); } } } break; case 6: object->lastOutcome = (unsigned char)var_toInteger(value); break; default: ret = DLMS_ERROR_CODE_INVALID_PARAMETER; break; } return ret; } #endif //DLMS_IGNORE_ARBITRATOR #ifndef DLMS_IGNORE_IEC_8802_LLC_TYPE1_SETUP int cosem_setIec8802LlcType1Setup( dlmsSettings* settings, gxIec8802LlcType1Setup* object, unsigned char index, dlmsVARIANT* value) { int ret = DLMS_ERROR_CODE_OK; switch (index) { case 2: object->maximumOctetsUiPdu = (uint16_t)var_toInteger(value); break; default: ret = DLMS_ERROR_CODE_INVALID_PARAMETER; break; } return ret; } #endif //DLMS_IGNORE_IEC_8802_LLC_TYPE1_SETUP #ifndef DLMS_IGNORE_IEC_8802_LLC_TYPE2_SETUP int cosem_setIec8802LlcType2Setup( dlmsSettings* settings, gxIec8802LlcType2Setup* object, unsigned char index, dlmsVARIANT* value) { int ret = DLMS_ERROR_CODE_OK; switch (index) { case 2: object->transmitWindowSizeK = (unsigned char)var_toInteger(value); break; case 3: object->transmitWindowSizeRW = (unsigned char)var_toInteger(value); break; case 4: object->maximumOctetsPdu = (uint16_t)var_toInteger(value); break; case 5: object->maximumNumberTransmissions = (unsigned char)var_toInteger(value); break; case 6: object->acknowledgementTimer = (uint16_t)var_toInteger(value); break; case 7: object->bitTimer = (uint16_t)var_toInteger(value); break; case 8: object->rejectTimer = (uint16_t)var_toInteger(value); break; case 9: object->busyStateTimer = (uint16_t)var_toInteger(value); break; default: ret = DLMS_ERROR_CODE_INVALID_PARAMETER; break; } return ret; } #endif //DLMS_IGNORE_IEC_8802_LLC_TYPE2_SETUP #ifndef DLMS_IGNORE_IEC_8802_LLC_TYPE3_SETUP int cosem_setIec8802LlcType3Setup( dlmsSettings* settings, gxIec8802LlcType3Setup* object, unsigned char index, dlmsVARIANT* value) { int ret = DLMS_ERROR_CODE_OK; switch (index) { case 2: object->maximumOctetsACnPdu = (uint16_t)var_toInteger(value); break; case 3: object->maximumTransmissions = (unsigned char)var_toInteger(value); break; case 4: object->acknowledgementTime = (uint16_t)var_toInteger(value); break; case 5: object->receiveLifetime = (uint16_t)var_toInteger(value); break; case 6: object->transmitLifetime = (uint16_t)var_toInteger(value); break; default: ret = DLMS_ERROR_CODE_INVALID_PARAMETER; break; } return ret; } #endif //DLMS_IGNORE_IEC_8802_LLC_TYPE3_SETUP #ifndef DLMS_IGNORE_SFSK_ACTIVE_INITIATOR int cosem_setSFSKActiveInitiator( dlmsSettings* settings, gxSFSKActiveInitiator* object, unsigned char index, dlmsVARIANT* value) { int ret = 0; dlmsVARIANT* tmp; switch (index) { case 2: if (value->vt == DLMS_DATA_TYPE_STRUCTURE) { bb_clear(&object->systemTitle); if ((ret = va_getByIndex(value->Arr, 0, &tmp)) != DLMS_ERROR_CODE_OK) { break; } if (tmp->byteArr != NULL) { if ((ret = bb_set(&object->systemTitle, tmp->byteArr->data, bb_size(tmp->byteArr))) != 0) { break; } } if ((ret = va_getByIndex(value->Arr, 1, &tmp)) != DLMS_ERROR_CODE_OK) { break; } object->macAddress = (uint16_t)var_toInteger(tmp); if ((ret = va_getByIndex(value->Arr, 2, &tmp)) != DLMS_ERROR_CODE_OK) { break; } object->lSapSelector = (unsigned char)var_toInteger(tmp); } else { bb_clear(&object->systemTitle); object->macAddress = 0; object->lSapSelector = 0; } break; default: ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_SFSK_ACTIVE_INITIATOR #ifndef DLMS_IGNORE_SFSK_MAC_COUNTERS int cosem_setFSKMacCounters( dlmsSettings* settings, gxFSKMacCounters* object, unsigned char index, dlmsVARIANT* value) { int pos, ret = DLMS_ERROR_CODE_OK; gxUint16PairUint32* it; dlmsVARIANT* tmp, * tmp2; switch (index) { case 2: { arr_clear(&object->synchronizationRegister); if (value->vt == DLMS_DATA_TYPE_ARRAY) { for (pos = 0; pos != value->Arr->size; ++pos) { if ((ret = va_getByIndex(value->Arr, pos, &tmp)) != DLMS_ERROR_CODE_OK) { break; } it = (gxUint16PairUint32*)gxmalloc(sizeof(gxUint16PairUint32)); if (it == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } if ((ret = va_getByIndex(tmp->Arr, 0, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->first = (uint16_t)var_toInteger(tmp2); if ((ret = va_getByIndex(tmp->Arr, 1, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->second = var_toInteger(tmp2); arr_push(&object->synchronizationRegister, it); } } } break; case 3: { if (value->vt == DLMS_DATA_TYPE_STRUCTURE) { if ((ret = va_getByIndex(value->Arr, 0, &tmp)) == DLMS_ERROR_CODE_OK) { object->physicalLayerDesynchronization = var_toInteger(tmp); if ((ret = va_getByIndex(value->Arr, 1, &tmp)) == DLMS_ERROR_CODE_OK) { object->timeOutNotAddressedDesynchronization = var_toInteger(tmp); if ((ret = va_getByIndex(value->Arr, 2, &tmp)) == DLMS_ERROR_CODE_OK) { object->timeOutFrameNotOkDesynchronization = var_toInteger(tmp); if ((ret = va_getByIndex(value->Arr, 3, &tmp)) == DLMS_ERROR_CODE_OK) { object->writeRequestDesynchronization = var_toInteger(tmp); if ((ret = va_getByIndex(value->Arr, 4, &tmp)) == DLMS_ERROR_CODE_OK) { object->wrongInitiatorDesynchronization = var_toInteger(tmp); } } } } } } else { object->physicalLayerDesynchronization = 0; object->timeOutNotAddressedDesynchronization = 0; object->timeOutFrameNotOkDesynchronization = 0; object->writeRequestDesynchronization = 0; object->wrongInitiatorDesynchronization = 0; } } break; case 4: { arr_clear(&object->broadcastFramesCounter); if (value->vt == DLMS_DATA_TYPE_ARRAY) { for (pos = 0; pos != value->Arr->size; ++pos) { if ((ret = va_getByIndex(value->Arr, pos, &tmp)) != DLMS_ERROR_CODE_OK) { break; } it = (gxUint16PairUint32*)gxmalloc(sizeof(gxUint16PairUint32)); if (it == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } if ((ret = va_getByIndex(tmp->Arr, 0, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->first = (uint16_t)var_toInteger(tmp2); if ((ret = va_getByIndex(tmp->Arr, 1, &tmp2)) != DLMS_ERROR_CODE_OK) { break; } it->second = var_toInteger(tmp2); arr_push(&object->broadcastFramesCounter, it); } } } break; case 5: object->repetitionsCounter = var_toInteger(value); break; case 6: object->transmissionsCounter = var_toInteger(value); break; case 7: object->crcOkFramesCounter = var_toInteger(value); break; case 8: object->crcNOkFramesCounter = var_toInteger(value); break; default: ret = DLMS_ERROR_CODE_INVALID_PARAMETER; break; } return ret; } #endif //DLMS_IGNORE_SFSK_MAC_COUNTERS #ifndef DLMS_IGNORE_SFSK_MAC_SYNCHRONIZATION_TIMEOUTS int cosem_setSFSKMacSynchronizationTimeouts( dlmsSettings* settings, gxSFSKMacSynchronizationTimeouts* object, unsigned char index, dlmsVARIANT* value) { int ret = 0; switch (index) { case 2: object->searchInitiatorTimeout = (uint16_t)var_toInteger(value); break; case 3: object->synchronizationConfirmationTimeout = (uint16_t)var_toInteger(value); break; case 4: object->timeOutNotAddressed = (uint16_t)var_toInteger(value); break; case 5: object->timeOutFrameNotOK = (uint16_t)var_toInteger(value); break; default: ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_SFSK_MAC_SYNCHRONIZATION_TIMEOUTS #ifndef DLMS_IGNORE_SFSK_PHY_MAC_SETUP int cosem_setSFSKPhyMacSetUp( dlmsSettings* settings, gxSFSKPhyMacSetUp* object, unsigned char index, dlmsVARIANT* value) { int pos, ret = 0; dlmsVARIANT* it; switch (index) { case 2: object->initiatorElectricalPhase = (DLMS_INITIATOR_ELECTRICAL_PHASE)var_toInteger(value); break; case 3: object->deltaElectricalPhase = (DLMS_DELTA_ELECTRICAL_PHASE)var_toInteger(value); break; case 4: object->maxReceivingGain = (unsigned char)var_toInteger(value); break; case 5: object->maxTransmittingGain = (unsigned char)var_toInteger(value); break; case 6: object->searchInitiatorThreshold = (unsigned char)var_toInteger(value); break; case 7: { if (value->vt == DLMS_DATA_TYPE_STRUCTURE) { if ((ret = va_getByIndex(value->Arr, 0, &it)) == DLMS_ERROR_CODE_OK) { object->markFrequency = var_toInteger(it); if ((ret = va_getByIndex(value->Arr, 1, &it)) == DLMS_ERROR_CODE_OK) { object->spaceFrequency = var_toInteger(it); } } } else { object->markFrequency = 0; object->spaceFrequency = 0; } break; } case 8: object->macAddress = (uint16_t)var_toInteger(value); break; case 9: { arr_clear(&object->macGroupAddresses); if (value->vt == DLMS_DATA_TYPE_ARRAY) { for (pos = 0; pos != value->Arr->size; ++pos) { if ((ret = va_getByIndex(value->Arr, pos, &it)) != DLMS_ERROR_CODE_OK) { break; } uint16_t* v = gxmalloc(sizeof(uint16_t)); *v = (uint16_t)var_toInteger(it); arr_push(&object->macGroupAddresses, v); } } break; } case 10: object->repeater = (DLMS_REPEATER)var_toInteger(value); break; case 11: object->repeaterStatus = value->boolVal; break; case 12: object->minDeltaCredit = (unsigned char)var_toInteger(value); break; case 13: object->initiatorMacAddress = (uint16_t)var_toInteger(value); break; case 14: object->synchronizationLocked = (unsigned char)var_toInteger(value); break; case 15: object->transmissionSpeed = (DLMS_BAUD_RATE)var_toInteger(value); break; default: ret = DLMS_ERROR_CODE_INVALID_PARAMETER; break; } return ret; } #endif //DLMS_IGNORE_SFSK_PHY_MAC_SETUP #ifndef DLMS_IGNORE_SFSK_REPORTING_SYSTEM_LIST int cosem_setSFSKReportingSystemList( dlmsSettings* settings, gxSFSKReportingSystemList* object, unsigned char index, dlmsVARIANT* value) { int pos, ret = 0; dlmsVARIANT* tmp; gxByteBuffer* it; if (index == 2) { obj_clearByteBufferList(&object->reportingSystemList); if (value->vt == DLMS_DATA_TYPE_ARRAY) { if (value->vt == DLMS_DATA_TYPE_ARRAY) { for (pos = 0; pos != value->Arr->size; ++pos) { if ((ret = va_getByIndex(value->Arr, pos, &tmp)) != DLMS_ERROR_CODE_OK) { break; } it = (gxByteBuffer*)gxmalloc(sizeof(gxByteBuffer)); BYTE_BUFFER_INIT(it); bb_set(it, tmp->byteArr->data, tmp->byteArr->size); if (it == NULL) { ret = DLMS_ERROR_CODE_OUTOFMEMORY; break; } arr_push(&object->reportingSystemList, it); } } } } else { ret = DLMS_ERROR_CODE_INVALID_PARAMETER; } return ret; } #endif //DLMS_IGNORE_SFSK_REPORTING_SYSTEM_LIST #ifdef DLMS_ITALIAN_STANDARD int updateIntervals(gxInterval* interval, gxByteBuffer* value) { int ret; unsigned char b; if ((ret = bb_getUInt8(value, &b)) != 0) { return ret; } interval[0].startHour = (unsigned char)(b >> 3); interval[0].intervalTariff = (DLMS_DEFAULT_TARIFF_BAND)((b >> 1) & 0x3); interval[0].useInterval = (b & 0x1) != 0; if ((ret = bb_getUInt8(value, &b)) != 0) { return ret; } interval[1].startHour = (unsigned char)(b >> 3); interval[1].intervalTariff = (DLMS_DEFAULT_TARIFF_BAND)((b >> 1) & 0x3); interval[1].useInterval = (b & 0x1) != 0; if ((ret = bb_getUInt8(value, &b)) != 0) { return ret; } interval[2].startHour = (unsigned char)(b >> 3); interval[2].intervalTariff = (DLMS_DEFAULT_TARIFF_BAND)((b >> 1) & 0x3); interval[2].useInterval = (b & 0x1) != 0; if ((ret = bb_getUInt8(value, &b)) != 0) { return ret; } interval[3].startHour = (unsigned char)(b >> 3); interval[3].intervalTariff = (DLMS_DEFAULT_TARIFF_BAND)((b >> 1) & 0x3); interval[3].useInterval = (b & 0x1) != 0; if ((ret = bb_getUInt8(value, &b)) != 0) { return ret; } interval[4].startHour = (unsigned char)(b >> 3); interval[4].intervalTariff = (DLMS_DEFAULT_TARIFF_BAND)((b >> 1) & 0x3); interval[4].useInterval = (b & 0x1) != 0; return 0; } int updateSeason(gxBandDescriptor* season, variantArray* value) { int ret; dlmsVARIANT* tmp; if (value->size == 5) { if ((ret = va_getByIndex(value, 0, &tmp)) != 0) { return ret; } season->dayOfMonth = tmp->bVal; if ((ret = va_getByIndex(value, 1, &tmp)) != 0) { return ret; } season->month = tmp->bVal; if ((ret = va_getByIndex(value, 2, &tmp)) != 0 || (ret = updateIntervals(season->workingDayIntervals, tmp->byteArr)) != 0 || (ret = va_getByIndex(value, 3, &tmp)) != 0 || (ret = updateIntervals(season->saturdayIntervals, tmp->byteArr)) != 0 || (ret = va_getByIndex(value, 4, &tmp)) != 0 || (ret = updateIntervals(season->holidayIntervals, tmp->byteArr)) != 0) { return ret; } } else { ret = DLMS_ERROR_CODE_UNMATCH_TYPE; } return ret; } int cosem_setTariffPlan(gxTariffPlan* object, unsigned char index, dlmsVARIANT* value) { dlmsVARIANT tmp3; dlmsVARIANT* tmp, * tmp2; int ret, pos, h, m, s; switch (index) { case 2: if (value->vt == DLMS_DATA_TYPE_OCTET_STRING) { object->calendarName = (char*)gxmalloc(value->byteArr->size); memcpy(object->calendarName, value->byteArr->data, value->byteArr->size); object->calendarName[value->byteArr->size] = 0; } else { object->calendarName = (char*)gxmalloc(value->strVal->size + 1); memcpy(object->calendarName, value->strVal->data, value->strVal->size); object->calendarName[value->strVal->size] = 0; } break; case 3: object->enabled = value->boolVal; break; case 4: { if (value->Arr->size == 4) { if ((ret = va_getByIndex(value->Arr, 0, &tmp)) != 0) { return ret; } object->plan.defaultTariffBand = tmp->bVal; if ((ret = va_getByIndex(value->Arr, 1, &tmp)) != 0) { return ret; } if ((ret = va_getByIndex(tmp->Arr, 0, &tmp2)) != 0 || (ret = updateSeason(&object->plan.winterSeason, tmp2->Arr)) != 0 || (ret = va_getByIndex(tmp->Arr, 1, &tmp2)) != 0 || (ret = updateSeason(&object->plan.summerSeason, tmp2->Arr)) != 0) { return ret; } ba_clear(&object->plan.weeklyActivation); if ((ret = va_getByIndex(value->Arr, 2, &tmp)) != 0 || (ret = ba_copy(&object->plan.weeklyActivation, tmp->bitArr->data, tmp->bitArr->size)) != 0) { return ret; } if ((ret = va_getByIndex(value->Arr, 3, &tmp)) != 0) { return ret; } arr_clear(&object->plan.specialDays); arr_capacity(&object->plan.specialDays, tmp->Arr->size); for (pos = 0; pos != tmp->Arr->size; ++pos) { if ((ret = va_getByIndex(tmp->Arr, pos, &tmp2)) != 0) { return ret; } arr_push(&object->plan.specialDays, (void*)tmp2->ulVal); } } break; } case 5: { if ((ret = va_getByIndex(value->Arr, 0, &tmp)) != 0) { return ret; } var_init(&tmp3); if ((ret = dlms_changeType2(tmp, DLMS_DATA_TYPE_TIME, &tmp3)) != 0) { return ret; } if ((tmp3.dateTime->skip & DATETIME_SKIPS_HOUR) == 0) { h = time_getHours(tmp3.dateTime); } else { h = 0; } if ((tmp3.dateTime->skip & DATETIME_SKIPS_MINUTE) == 0) { m = time_getMinutes(tmp3.dateTime); } else { m = 0; } if ((tmp3.dateTime->skip & DATETIME_SKIPS_SECOND) == 0) { s = time_getSeconds(tmp3.dateTime); } else { s = 0; } if ((ret = va_getByIndex(value->Arr, 1, &tmp2)) != 0) { return ret; } var_clear(&tmp3); if ((ret = dlms_changeType2(tmp2, DLMS_DATA_TYPE_DATE, &tmp3)) != 0) { return ret; } time_copy(&object->activationTime, tmp3.dateTime); object->activationTime.skip &= ~(DATETIME_SKIPS_HOUR | DATETIME_SKIPS_MINUTE | DATETIME_SKIPS_SECOND | DATETIME_SKIPS_MS); time_addHours(&object->activationTime, h); time_addMinutes(&object->activationTime, m); time_addSeconds(&object->activationTime, s); } break; default: return DLMS_ERROR_CODE_READ_WRITE_DENIED; } return DLMS_ERROR_CODE_OK; } #endif //DLMS_ITALIAN_STANDARD #endif //!defined(DLMS_IGNORE_MALLOC) && !defined(DLMS_COSEM_EXACT_DATA_TYPES)