Initial commit

uart_fix
Tomer27cz 2025-11-04 18:39:59 +01:00
commit 9c23deac0e
96 changed files with 89021 additions and 0 deletions

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
# Gitignore settings for ESPHome
# This is an example and may include too much for your use-case.
# You can modify this file to suit your needs.
/.esphome/
/secrets.yaml

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 Tomer27cz
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

2
README.md Normal file
View File

@ -0,0 +1,2 @@
# xt211
ESPHome component for ČEZ Sagecom XT211 AMM

View File

@ -0,0 +1,134 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef ARDUINO_IGNORE_H
#define ARDUINO_IGNORE_H
#ifdef __cplusplus
extern "C" {
#endif
//Use UTC time zone. Read more: https://www.gurux.fi/Gurux.DLMS.Objects.GXDLMSClock
//#define DLMS_USE_UTC_TIME_ZONE
/* Uncomment defines to ignore non-needed parts to make image size smaller. */
// #define DLMS_IGNORE_HDLC
// #define DLMS_IGNORE_WRAPPER
#define DLMS_IGNORE_PLC
#define DLMS_IGNORE_SERVER
#define GX_DLMS_MICROCONTROLLER
#define DLMS_IGNORE_HIGH_SHA256
#define DLMS_IGNORE_HIGH_SHA1
#define DLMS_IGNORE_HIGH_MD5
// #define DLMS_IGNORE_AES
// #define DLMS_IGNORE_HIGH_GMAC
// #define DLMS_IGNORE_DATA
// #define DLMS_IGNORE_REGISTER
// #define DLMS_IGNORE_EXTENDED_REGISTER
// #define DLMS_IGNORE_DEMAND_REGISTER
// #define DLMS_IGNORE_REGISTER_ACTIVATION
// #define DLMS_IGNORE_PROFILE_GENERIC
// #define DLMS_IGNORE_CLOCK
// #define DLMS_IGNORE_SCRIPT_TABLE
// #define DLMS_IGNORE_SCHEDULE
// #define DLMS_IGNORE_SPECIAL_DAYS_TABLE
// #define DLMS_IGNORE_ASSOCIATION_SHORT_NAME
// #define DLMS_IGNORE_ASSOCIATION_LOGICAL_NAME
// #define DLMS_IGNORE_SAP_ASSIGNMENT
// #define DLMS_IGNORE_IMAGE_TRANSFER
// #define DLMS_IGNORE_IEC_LOCAL_PORT_SETUP
// #define DLMS_IGNORE_ACTIVITY_CALENDAR
// #define DLMS_IGNORE_REGISTER_MONITOR
// #define DLMS_IGNORE_ACTION_SCHEDULE
// #define DLMS_IGNORE_IEC_HDLC_SETUP
// #define DLMS_IGNORE_IEC_TWISTED_PAIR_SETUP
// #define DLMS_IGNORE_MBUS_SLAVE_PORT_SETUP
// #define DLMS_IGNORE_UTILITY_TABLES
// #define DLMS_IGNORE_MODEM_CONFIGURATION
// #define DLMS_IGNORE_AUTO_ANSWER
// #define DLMS_IGNORE_AUTO_CONNECT
// #define DLMS_IGNORE_TCP_UDP_SETUP
// #define DLMS_IGNORE_IP4_SETUP
// #define DLMS_IGNORE_IP6_SETUP
// #define DLMS_IGNORE_MAC_ADDRESS_SETUP
// #define DLMS_IGNORE_PPP_SETUP
// #define DLMS_IGNORE_GPRS_SETUP
// #define DLMS_IGNORE_SMTP_SETUP
// #define DLMS_IGNORE_GSM_DIAGNOSTIC
// #define DLMS_IGNORE_REGISTER_TABLE
// #define DLMS_IGNORE_STATUS_MAPPING
// #define DLMS_IGNORE_SECURITY_SETUP
// #define DLMS_IGNORE_DISCONNECT_CONTROL
// #define DLMS_IGNORE_LIMITER
#define DLMS_IGNORE_MBUS_CLIENT
// #define DLMS_IGNORE_PUSH_SETUP
#define DLMS_IGNORE_PARAMETER_MONITOR
#define DLMS_IGNORE_WIRELESS_MODE_Q_CHANNEL
#define DLMS_IGNORE_MBUS_MASTER_PORT_SETUP
#define DLMS_IGNORE_ZIG_BEE_SAS_STARTUP
#define DLMS_IGNORE_ZIG_BEE_SAS_JOIN
#define DLMS_IGNORE_ZIG_BEE_SAS_APS_FRAGMENTATION
#define DLMS_IGNORE_ZIG_BEE_NETWORK_CONTROL
#define DLMS_IGNORE_DATA_PROTECTION
// #define DLMS_IGNORE_ACCOUNT
// #define DLMS_IGNORE_CREDIT
// #define DLMS_IGNORE_CHARGE
#define DLMS_IGNORE_TOKEN_GATEWAY
#define DLMS_IGNORE_COMPACT_DATA
#define DLMS_IGNORE_LLC_SSCS_SETUP
#define DLMS_IGNORE_PRIME_NB_OFDM_PLC_PHYSICAL_LAYER_COUNTERS
#define DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_SETUP
#define DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_FUNCTIONAL_PARAMETERS
#define DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_COUNTERS
#define DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_NETWORK_ADMINISTRATION_DATA
#define DLMS_IGNORE_PRIME_NB_OFDM_PLC_APPLICATIONS_IDENTIFICATION
#define DLMS_IGNORE_ARBITRATOR
#define DLMS_IGNORE_SERIALIZER
// #define DLMS_IGNORE_FLOAT32
// #define DLMS_IGNORE_FLOAT64
// #define DLMS_ITALIAN_STANDARD
//////////////////////////////////////////////////////////////////////
//Arduino client spesific settings.
//Use EPOCH time. This can be used to improve memory usage.
#define DLMS_USE_EPOCH_TIME
#define DLMS_IGNORE_NOTIFY
#define DLMS_IGNORE_SERVER
#define DLMS_IGNORE_NOTIFY
#ifdef __cplusplus
}
#endif
#endif //ARDUINO_IGNORE_H

View File

@ -0,0 +1,73 @@
import re
from esphome import pins
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import uart, binary_sensor
from esphome.const import (
CONF_ID,
CONF_BAUD_RATE,
CONF_RECEIVE_TIMEOUT,
)
DEPENDENCIES = ["uart"]
DEFAULTS_BAUD_RATE_SESSION = 9600
DEFAULTS_RECEIVE_TIMEOUT = "2000ms"
CONF_XT211_ID = "xt211_id"
CONF_OBIS_CODE = "obis_code"
CONF_DONT_PUBLISH = "dont_publish"
CONF_CLASS = "class"
CONF_PUSH_SHOW_LOG = "push_show_log"
CONF_PUSH_CUSTOM_PATTERN = "push_custom_pattern"
xt211_ns = cg.esphome_ns.namespace("xt211")
XT211 = xt211_ns.class_(
"XT211Component", cg.Component, uart.UARTDevice
)
BAUD_RATES = [300, 600, 1200, 2400, 4800, 9600, 19200]
def obis_code(value):
value = cv.string(value)
# match = re.match(r"^\d{1,3}-\d{1,3}:\d{1,3}\.\d{1,3}\.\d{1,3}$", value)
match = re.match(r"^\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}\.\d{1,3}\.\d{1,3}$", value)
if match is None:
raise cv.Invalid(f"{value} is not a valid OBIS code")
return value
CONFIG_SCHEMA = cv.All(
cv.Schema(
{
cv.GenerateID(): cv.declare_id(XT211),
cv.Optional(CONF_BAUD_RATE, default=DEFAULTS_BAUD_RATE_SESSION): cv.one_of(
*BAUD_RATES
),
cv.Optional(
CONF_RECEIVE_TIMEOUT, default=DEFAULTS_RECEIVE_TIMEOUT
): cv.positive_time_period_milliseconds,
cv.Optional(CONF_PUSH_SHOW_LOG, default=False): cv.boolean,
cv.Optional(CONF_PUSH_CUSTOM_PATTERN, default=""): cv.string,
}
)
.extend(cv.COMPONENT_SCHEMA)
.extend(uart.UART_DEVICE_SCHEMA)
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
await uart.register_uart_device(var, config)
cg.add(var.set_baud_rate(config[CONF_BAUD_RATE]))
cg.add(var.set_receive_timeout_ms(config[CONF_RECEIVE_TIMEOUT]))
cg.add(var.set_push_show_log(config[CONF_PUSH_SHOW_LOG]))
cg.add(var.set_push_custom_pattern_dsl(config[CONF_PUSH_CUSTOM_PATTERN]))
cg.add_build_flag("-Wno-error=implicit-function-declaration")
# cg.add_library("GuruxDLMS", None, "https://github.com/latonita/GuruxDLMS.c#platformio")
# cg.add_library("GuruxDLMS", None, "https://github.com/Gurux/GuruxDLMS.c#platformio")

2072
components/xt211/apdu.c Normal file

File diff suppressed because it is too large Load Diff

97
components/xt211/apdu.h Normal file
View File

@ -0,0 +1,97 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef APDU_H
#define APDU_H
#include "dlmssettings.h"
#include "bytebuffer.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef DLMS_IGNORE_CLIENT
/**
* Generates Aarq.
*/
int apdu_generateAarq(
dlmsSettings* settings,
gxByteBuffer* data);
#endif //DLMS_IGNORE_CLIENT
/**
* Parse APDU.
*/
int apdu_parsePDU(
dlmsSettings* settings,
gxByteBuffer* buff,
DLMS_ASSOCIATION_RESULT* result,
unsigned char* diagnostic,
unsigned char* command);
#ifndef DLMS_IGNORE_SERVER
/**
* Server generates AARE message.
*/
int apdu_generateAARE(
dlmsSettings* settings,
gxByteBuffer* data,
DLMS_ASSOCIATION_RESULT result,
unsigned char diagnostic,
gxByteBuffer* errorData,
gxByteBuffer* encryptedData,
unsigned char command);
#endif //DLMS_IGNORE_SERVER
/**
* Generate user information.
*
* @param settings
* DLMS settings
* @param cipher
* @param data
* Generated user information.
*/
int apdu_generateUserInformation(
dlmsSettings* settings,
gxByteBuffer* data);
int apdu_getUserInformation(
dlmsSettings* settings,
gxByteBuffer* data,
unsigned char command);
#ifdef __cplusplus
}
#endif
#endif //APDU_H

View File

@ -0,0 +1,102 @@
# import esphome.codegen as cg
# import esphome.config_validation as cv
# from esphome.components import binary_sensor
# from esphome.const import (
# DEVICE_CLASS_CONNECTIVITY,
# ENTITY_CATEGORY_DIAGNOSTIC,
# )
# from . import (
# XT211,
# xt211_ns,
# CONF_XT211_ID,
# )
#
# AUTO_LOAD = ["xt211"]
#
# CONF_TRANSMISSION = "transmission"
# CONF_SESSION = "session"
# CONF_CONNECTION = "connection"
#
# ICON_TRANSMISSION = "mdi:swap-horizontal"
# ICON_CONNECTION = "mdi:lan-connect"
# ICON_SESSION = "mdi:sync"
#
# CONFIG_SCHEMA = cv.Schema(
# {
# cv.GenerateID(CONF_XT211_ID): cv.use_id(XT211),
# cv.Optional(CONF_TRANSMISSION): binary_sensor.binary_sensor_schema(
# device_class=DEVICE_CLASS_CONNECTIVITY,
# entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
# icon=ICON_TRANSMISSION,
# ),
# cv.Optional(CONF_SESSION): binary_sensor.binary_sensor_schema(
# device_class=DEVICE_CLASS_CONNECTIVITY,
# entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
# icon=ICON_SESSION,
# ),
# cv.Optional(CONF_CONNECTION): binary_sensor.binary_sensor_schema(
# device_class=DEVICE_CLASS_CONNECTIVITY,
# entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
# icon=ICON_CONNECTION,
# ),
# }
# )
#
# async def to_code(config):
# hub = await cg.get_variable(config[CONF_XT211_ID])
#
# if conf := config.get(CONF_TRANSMISSION):
# sensor = await binary_sensor.new_binary_sensor(config[CONF_TRANSMISSION])
# cg.add(hub.set_transmission_binary_sensor(sensor))
#
# if conf := config.get(CONF_SESSION):
# sensor = await binary_sensor.new_binary_sensor(config[CONF_SESSION])
# cg.add(hub.set_session_binary_sensor(sensor))
#
# if conf := config.get(CONF_CONNECTION):
# sensor = await binary_sensor.new_binary_sensor(config[CONF_CONNECTION])
# cg.add(hub.set_connection_binary_sensor(sensor))
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import binary_sensor
from . import (
XT211,
xt211_ns,
obis_code,
CONF_XT211_ID,
CONF_OBIS_CODE,
CONF_DONT_PUBLISH,
CONF_CLASS,
)
AUTO_LOAD = ["xt211"]
XT211BinarySensor = xt211_ns.class_(
"XT211BinarySensor", binary_sensor.BinarySensor
)
CONFIG_SCHEMA = cv.All(
binary_sensor.binary_sensor_schema(
XT211BinarySensor,
).extend(
{
cv.GenerateID(CONF_XT211_ID): cv.use_id(XT211),
cv.Required(CONF_OBIS_CODE): obis_code,
cv.Optional(CONF_DONT_PUBLISH, default=False): cv.boolean,
cv.Optional(CONF_CLASS, default=1): cv.int_,
}
),
cv.has_exactly_one_key(CONF_OBIS_CODE),
)
async def to_code(config):
component = await cg.get_variable(config[CONF_XT211_ID])
var = await binary_sensor.new_binary_sensor(config)
cg.add(var.set_obis_code(config[CONF_OBIS_CODE]))
cg.add(var.set_dont_publish(config.get(CONF_DONT_PUBLISH)))
cg.add(var.set_obis_class(config[CONF_CLASS]))
cg.add(component.register_sensor(var))

344
components/xt211/bitarray.c Normal file
View File

@ -0,0 +1,344 @@
//
// --------------------------------------------------------------------------
// 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 "gxmem.h"
#if defined(_WIN32) || defined(_WIN64) || defined(__linux__)
#include <assert.h>
#endif
#if _MSC_VER > 1400
#include <crtdbg.h>
#endif
#include <string.h>
#include "errorcodes.h"
#include "bitarray.h"
#include "helpers.h"
//Returs needed amount of bytes to store bits.
uint16_t ba_getByteCount(uint16_t bitCount)
{
double d = bitCount;
if (bitCount != 0)
{
d /= 8;
if (bitCount == 0 || (bitCount % 8) != 0)
{
++d;
}
}
return (uint16_t)d;
}
//Return byte index where bit is saved.
int getByteIndex(int bitCount)
{
double d = bitCount;
d /= 8;
return (int)d;
}
//Initialize bit array.
void ba_init(bitArray* arr)
{
arr->capacity = 0;
arr->data = NULL;
#ifndef GX_DLMS_MICROCONTROLLER
arr->position = 0;
#endif //GX_DLMS_MICROCONTROLLER
arr->size = 0;
}
char ba_isAttached(bitArray* arr)
{
return (arr->capacity & 0x8000) == 0x8000;
}
uint16_t ba_getCapacity(bitArray* arr)
{
return arr->capacity & 0x7FFF;
}
uint16_t ba_size(bitArray* bb)
{
return bb != 0 ? bb->size : 0;
}
void ba_attach(
bitArray* arr,
unsigned char* value,
uint16_t count,
uint16_t capacity)
{
arr->data = value;
arr->capacity = (uint16_t)(0x8000 | capacity);
arr->size = count;
#ifndef GX_DLMS_MICROCONTROLLER
arr->position = 0;
#endif //GX_DLMS_MICROCONTROLLER
}
//Allocate new size for the array in bytes.
int ba_capacity(bitArray* arr, uint16_t capacity)
{
#ifndef DLMS_IGNORE_MALLOC
if (!ba_isAttached(arr))
{
arr->capacity = capacity;
if (capacity == 0)
{
if (arr->data != NULL)
{
gxfree(arr->data);
arr->data = NULL;
}
}
else
{
if (arr->data == NULL)
{
arr->data = (unsigned char*)gxmalloc(ba_getByteCount(arr->capacity));
if (arr->data == NULL)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
}
else
{
#ifdef gxrealloc
//If compiler supports realloc.
unsigned char* tmp = (unsigned char*)gxrealloc(arr->data, ba_getByteCount(arr->capacity));
//If not enought memory available.
if (tmp == NULL)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
arr->data = tmp;
#else
//If compiler doesn't support realloc.
unsigned char* old = arr->data;
arr->data = (unsigned char*)gxmalloc(ba_getByteCount(arr->capacity));
//If not enought memory available.
if (arr->data == NULL)
{
arr->data = old;
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
memcpy(arr->data, old, ba_getByteCount(arr->size));
gxfree(old);
#endif // gxrealloc
}
}
}
#endif //DLMS_IGNORE_MALLOC
if (ba_getCapacity(arr) < capacity)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
return 0;
}
//Push new data to the bit array.
int ba_set(bitArray* arr, unsigned char item)
{
int ret = ba_setByIndex(arr, arr->size, item);
if (ret == 0)
{
++arr->size;
}
return ret;
}
//Set bit by index.
int ba_setByIndex(bitArray* arr, uint16_t index, unsigned char item)
{
int ret;
unsigned char newItem = 0;
int byteIndex;
item = item == 0 ? 0 : 1;
if (!ba_isAttached(arr))
{
if (index >= arr->capacity)
{
if ((ret = ba_capacity(arr, arr->capacity + BIT_ARRAY_CAPACITY)) != 0)
{
return ret;
}
//If we are adding a bit to the higher than next byte.
if (index >= arr->capacity)
{
return ba_setByIndex(arr, index, item);
}
newItem = 1;
}
}
if (index >= arr->capacity)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
byteIndex = getByteIndex(index);
if (index % 8 == 0 || newItem)
{
arr->data[byteIndex] = (unsigned char)(item << 7);
}
else
{
arr->data[byteIndex] |= (item << (7 - (index % 8)));
}
return 0;
}
int ba_copy(
bitArray* target,
unsigned char* source,
uint16_t count)
{
int ret = 0;
ba_clear(target);
if (count != 0)
{
if ((ret = ba_capacity(target, count)) == 0)
{
memcpy(target->data, source, ba_getByteCount(count));
target->size = count;
#ifndef GX_DLMS_MICROCONTROLLER
target->position = 0;
#endif //GX_DLMS_MICROCONTROLLER
}
}
return ret;
}
void ba_clear(bitArray* arr)
{
#ifndef DLMS_IGNORE_MALLOC
if (!ba_isAttached(arr))
{
if (arr->data != NULL)
{
gxfree(arr->data);
arr->data = NULL;
}
arr->capacity = 0;
}
#endif //DLMS_IGNORE_MALLOC
arr->size = 0;
#ifndef GX_DLMS_MICROCONTROLLER
arr->position = 0;
#endif //GX_DLMS_MICROCONTROLLER
}
#ifndef GX_DLMS_MICROCONTROLLER
int ba_get(bitArray* arr, unsigned char* value)
{
int ret = ba_getByIndex(arr, arr->position, value);
if (ret == 0)
{
++arr->position;
}
return ret;
}
#endif //GX_DLMS_MICROCONTROLLER
int ba_getByIndex(bitArray* arr, int index, unsigned char* value)
{
char ch;
if (index >= arr->size)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
ch = arr->data[getByteIndex(index)];
*value = (ch & (1 << (7 - (index % 8)))) != 0;
return 0;
}
int ba_toInteger(bitArray* arr, uint32_t* value)
{
*value = 0;
unsigned char ch;
int pos, ret;
for (pos = 0; pos != arr->size; ++pos)
{
if ((ret = ba_getByIndex(arr, pos, &ch)) != 0)
{
return ret;
}
*value |= ch << pos;
}
return 0;
}
#ifndef DLMS_IGNORE_MALLOC
char* ba_toString(bitArray* arr)
{
unsigned char ch;
#if defined(_WIN32) || defined(_WIN64) || defined(__linux__)
int pos, ret;
#else
int pos;
#endif
char* buff = (char*)gxmalloc(arr->size + 1);
for (pos = 0; pos != arr->size; ++pos)
{
#if defined(_WIN32) || defined(_WIN64) || defined(__linux__)
ret = ba_getByIndex(arr, pos, &ch);
assert(ret == 0);
#else
ba_getByIndex(arr, pos, &ch);
#endif
buff[pos] = ch == 0 ? '0' : '1';
}
*(buff + arr->size) = 0;
return buff;
}
#endif //DLMS_IGNORE_MALLOC
int ba_toString2(
gxByteBuffer* bb,
bitArray* ba)
{
unsigned char ch;
int pos, ret = 0;
if ((ret = bb_capacity(bb, bb->size + ba->size)) == 0)
{
for (pos = 0; pos != ba->size; ++pos)
{
if ((ret = ba_getByIndex(ba, pos, &ch)) != 0 ||
(ret = bb_setInt8(bb, ch == 0 ? '0' : '1')) != 0)
{
break;
}
}
}
return ret;
}

144
components/xt211/bitarray.h Normal file
View File

@ -0,0 +1,144 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef BIT_ARRAY_H
#define BIT_ARRAY_H
#ifdef __cplusplus
extern "C" {
#endif
#include "gxignore.h"
#include "bytebuffer.h"
#define BIT_ARRAY_CAPACITY 8
typedef struct
{
unsigned char* data;
uint16_t capacity;
uint16_t size;
#ifndef GX_DLMS_MICROCONTROLLER
uint16_t position;
#endif //GX_DLMS_MICROCONTROLLER
} bitArray;
//Initialize gxByteBuffer.
void ba_init(
bitArray* arr);
//Attach bit array.
void ba_attach(
bitArray* arr,
unsigned char* value,
uint16_t count,
uint16_t capacity);
/*
* Is static buffer used.
*/
char ba_isAttached(
bitArray* arr);
//Bit array capacity.
uint16_t ba_getCapacity(
bitArray* arr);
/*
* Get size.
*/
uint16_t ba_size(bitArray* bb);
//How many bytes bit array will take.
uint16_t ba_getByteCount(
uint16_t bitCount);
//Allocate new size for the array in bits.
int ba_capacity(
bitArray* arr,
uint16_t capacity);
//Push new data to the bit array.
int ba_set(
bitArray* arr,
unsigned char item);
//Push new data to the bit array.
int ba_setByIndex(
bitArray* arr,
uint16_t index,
unsigned char item);
//Copy bit array.
int ba_copy(
bitArray* target,
unsigned char* source,
uint16_t count);
//Clear bit array.
void ba_clear(
bitArray* arr);
//Get bit value.
int ba_get(
bitArray* arr,
unsigned char* value);
//Get bit value by index.
int ba_getByIndex(
bitArray* arr,
int index,
unsigned char* value);
//Convert bit array to integer.
int ba_toInteger(
bitArray* arr,
uint32_t* value);
#ifndef DLMS_IGNORE_MALLOC
//Get bit array as a string.
char* ba_toString(
bitArray* arr);
#endif //DLMS_IGNORE_MALLOC
//Add bit array as a string.
int ba_toString2(
gxByteBuffer* bb,
bitArray* ba);
#define BIT_ATTACH(X, V, S) ba_attach(&X, V, S, 8 * sizeof(V)/sizeof(V[0]))
#ifdef __cplusplus
}
#endif
#endif //BYTE_ARRAY_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,541 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef BYTE_BUFFER_H
#define BYTE_BUFFER_H
#ifdef __cplusplus
extern "C" {
#endif
#include "gxint.h"
#include "gxignore.h"
//Arduino DOIT ESP32 uses bb_init. bb_Init is used instead.
#ifndef ESP_PLATFORM
#define BYTE_BUFFER_INIT bb_init
#else
#define BYTE_BUFFER_INIT bb_Init
#endif //DESP_PLATFORM
#define VECTOR_CAPACITY 50
typedef struct
{
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
unsigned char* data;
uint32_t capacity;
uint32_t size;
uint32_t position;
#else
unsigned char* data;
uint16_t capacity;
uint16_t size;
uint16_t position;
#endif
} gxByteBuffer;
/*
* Is static buffer used.
*/
char bb_isAttached(
gxByteBuffer* arr);
/*Get maximum buffer size.*/
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
uint32_t bb_getCapacity(
gxByteBuffer* arr);
#else
uint16_t bb_getCapacity(
gxByteBuffer* arr);
#endif
/*Returns amount of the available bytes.*/
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
uint32_t bb_available(gxByteBuffer* arr);
#else
uint16_t bb_available(gxByteBuffer* arr);
#endif
/*
* Initialize gxByteBuffer.
*/
int BYTE_BUFFER_INIT(
gxByteBuffer* bb);
/*
* Allocate new size for the array in bytes.
*/
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
int bb_capacity(
gxByteBuffer* bb,
uint32_t capacity);
#else
int bb_capacity(
gxByteBuffer* bb,
uint16_t capacity);
#endif
/*
* Get size.
*/
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
uint32_t bb_size(
gxByteBuffer* bb);
#else
uint16_t bb_size(
gxByteBuffer* bb);
#endif
/*
* Fill buffer it with zeros.
*/
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
int bb_zero(
gxByteBuffer* bb,
uint32_t index,
uint32_t count);
#else
int bb_zero(
gxByteBuffer* bb,
uint16_t index,
uint16_t count);
#endif
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
int bb_insertUInt8(
gxByteBuffer* arr,
uint32_t index,
unsigned char item);
#else
int bb_insertUInt8(
gxByteBuffer* arr,
uint16_t index,
unsigned char item);
#endif
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
int bb_allocate(
gxByteBuffer* arr,
uint32_t index,
uint32_t dataSize);
#else
int bb_allocate(
gxByteBuffer* arr,
uint16_t index,
uint16_t dataSize);
#endif
//Set new data to the gxByteBuffer.
int bb_setUInt8(
gxByteBuffer* bb,
unsigned char item);
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
int bb_setUInt8ByIndex(
gxByteBuffer* arr,
uint32_t index,
unsigned char item);
#else
int bb_setUInt8ByIndex(
gxByteBuffer* arr,
uint16_t index,
unsigned char item);
#endif
int bb_setUInt16(
gxByteBuffer* bb,
uint16_t item);
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
int bb_setUInt16ByIndex(
gxByteBuffer* arr,
uint32_t index,
uint16_t item);
#else
int bb_setUInt16ByIndex(
gxByteBuffer* arr,
uint16_t index,
uint16_t item);
#endif
int bb_setUInt32(
gxByteBuffer* bb,
uint32_t item);
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
int bb_setUInt32ByIndex(
gxByteBuffer* arr,
uint32_t index,
uint32_t item);
#else
int bb_setUInt32ByIndex(
gxByteBuffer* arr,
uint16_t index,
uint32_t item);
#endif //!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__))
int bb_setUInt64(
gxByteBuffer* bb,
uint64_t item);
#ifndef DLMS_IGNORE_FLOAT32
int bb_setFloat(
gxByteBuffer* arr,
float value);
#endif //DLMS_IGNORE_FLOAT32
#ifndef DLMS_IGNORE_FLOAT64
int bb_setDouble(
gxByteBuffer* arr,
double value);
#endif //DLMS_IGNORE_FLOAT64
int bb_setInt8(
gxByteBuffer* bb,
char item);
int bb_setInt16(
gxByteBuffer* bb,
int16_t item);
int bb_setInt32(
gxByteBuffer* bb,
int32_t item);
int bb_setInt64(
gxByteBuffer* bb,
int64_t item);
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
int bb_insert(
const unsigned char* src,
uint32_t count,
gxByteBuffer* target,
uint32_t index);
#else
int bb_insert(
const unsigned char* src,
uint16_t count,
gxByteBuffer* target,
uint16_t index);
#endif
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
int bb_set(
gxByteBuffer* bb,
const unsigned char* pSource,
uint32_t count);
#else
int bb_set(
gxByteBuffer* bb,
const unsigned char* pSource,
uint16_t count);
#endif
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
int bb_set2(
gxByteBuffer* bb,
gxByteBuffer* data,
uint32_t index,
uint32_t count);
#else
int bb_set2(
gxByteBuffer* bb,
gxByteBuffer* data,
uint16_t index,
uint16_t count);
#endif
int bb_addString(
gxByteBuffer* bb,
const char* value);
int bb_attachString(
gxByteBuffer* bb,
char* value);
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
int bb_attach(
gxByteBuffer* arr,
unsigned char* value,
uint32_t count,
uint32_t capacity);
int bb_attachString2(
gxByteBuffer* arr,
char* value,
uint32_t count,
uint32_t capacity);
#else
int bb_attach(
gxByteBuffer* arr,
unsigned char* value,
uint16_t count,
uint16_t capacity);
int bb_attachString2(
gxByteBuffer* arr,
char* value,
uint16_t count,
uint16_t capacity);
#endif
//Clean byte buffer and release allocated memory.
int bb_clear(
gxByteBuffer* bb);
//Set size and position to zero. Allocated memory is not released.
int bb_empty(
gxByteBuffer* bb);
int bb_getUInt8(
gxByteBuffer* bb,
unsigned char* value);
int bb_getUInt8ByIndex(
gxByteBuffer* bb,
uint32_t index,
unsigned char* value);
int bb_getUInt16(
gxByteBuffer* bb,
uint16_t* value);
int bb_getUInt24(
gxByteBuffer* bb,
uint32_t* value);
int bb_getUInt32(
gxByteBuffer* bb,
uint32_t* value);
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
int bb_get(
gxByteBuffer* bb,
unsigned char* value,
uint32_t count);
#else
int bb_get(
gxByteBuffer* bb,
unsigned char* value,
uint16_t count);
#endif
int bb_getInt8(
gxByteBuffer* arr,
signed char* value);
int bb_getInt16(
gxByteBuffer* bb,
int16_t* value);
int bb_getInt32(
gxByteBuffer* bb,
int32_t* value);
int bb_getInt64(
gxByteBuffer* bb,
int64_t* value);
int bb_getUInt64(
gxByteBuffer* bb,
uint64_t* value);
#ifndef DLMS_IGNORE_FLOAT32
int bb_getFloat(
gxByteBuffer* bb,
float* value);
#endif //DLMS_IGNORE_FLOAT32
#ifndef DLMS_IGNORE_FLOAT64
int bb_getDouble(
gxByteBuffer* bb,
double* value);
#endif //DLMS_IGNORE_FLOAT64
int bb_getUInt16ByIndex(
gxByteBuffer* bb,
uint32_t index,
uint16_t* value);
int bb_getUInt24ByIndex(
gxByteBuffer* bb,
uint32_t index,
uint32_t* value);
int bb_getUInt32ByIndex(
gxByteBuffer* bb,
uint32_t index,
uint32_t* value);
int bb_getUInt64ByIndex(
gxByteBuffer* bb,
uint32_t index,
uint64_t* value);
int bb_getUInt128ByIndex(
gxByteBuffer* bb,
uint32_t index,
unsigned char* value);
#ifndef DLMS_IGNORE_MALLOC
//Add hex string to byte buffer.
int bb_addHexString(
gxByteBuffer* arr,
const char* str);
#endif //DLMS_IGNORE_MALLOC
//Add hex string to byte buffer.
int bb_addHexString2(
gxByteBuffer* arr,
const char* str);
//Add hex string to byte buffer.
int bb_addLogicalName(
gxByteBuffer* arr,
const unsigned char* str);
//Get byte array as hex string.
int bb_toHexString2(
gxByteBuffer* arr,
char* buffer,
uint16_t size);
#if !(defined(DLMS_IGNORE_STRING_CONVERTER) || defined(DLMS_IGNORE_MALLOC))
//Get byte array as a string.
char* bb_toString(
gxByteBuffer* bb);
//Get byte array as hex string.
char* bb_toHexString(
gxByteBuffer* bb);
//Add double value to byte array as a string.
int bb_addDoubleAsString(
gxByteBuffer* ba,
double value);
#endif //!(defined(DLMS_IGNORE_STRING_CONVERTER) || defined(DLMS_IGNORE_MALLOC))
//Add integer value to byte array as a string.
int bb_addIntAsString(
gxByteBuffer* ba,
int value);
//Add integer value to byte array as a string.
int bb_addIntAsString2(
gxByteBuffer* ba,
int value,
unsigned char digits);
/**
* Returns data as byte array.
*
* @param bb Byte buffer as a byte array.
*/
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
int bb_subArray(
gxByteBuffer* bb,
uint32_t index,
uint32_t count,
gxByteBuffer* target);
#else
int bb_subArray(
gxByteBuffer* bb,
uint16_t index,
uint16_t count,
gxByteBuffer* target);
#endif
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
//Move data insize byte array.
int bb_move(
gxByteBuffer* ba,
uint32_t srcPos,
uint32_t destPos,
uint32_t count);
#else
//Move data insize byte array.
int bb_move(
gxByteBuffer* ba,
uint16_t srcPos,
uint16_t destPos,
uint16_t count);
#endif
/**
* Remove handled bytes. This can be used in debugging to remove handled
* bytes.
*/
int bb_trim(
gxByteBuffer* bb);
/**
* Compares, whether two given arrays are similar starting from current
* position.
*
* @param bb
* Bytebuffer to compare.
* @param arr
* Array to compare.
* @param length
* Array length.
* @return True, if arrays are similar. False, if the arrays differ.
*/
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
unsigned char bb_compare(
gxByteBuffer* bb,
unsigned char* buff,
uint32_t length);
#else
unsigned char bb_compare(
gxByteBuffer* bb,
unsigned char* buff,
uint16_t length);
#endif
//Find index of given char.
uint32_t bb_indexOf(
gxByteBuffer* bb,
char ch);
#if defined(_WIN32) || defined(_WIN64) || defined(__linux__)
//Print content of byte buffer to cout.
int bb_print(gxByteBuffer* bb);
#endif //defined(_WIN32) || defined(_WIN64) || defined(__linux__)
#define BB_ATTACH(X, V, S) bb_attach(&X, V, S, sizeof(V))
#define BB_ATTACH_STR(X, V, S) bb_attachString2(&X, V, S, sizeof(V))
#ifdef __cplusplus
}
#endif
#endif //BYTE_BUFFER_H

1072
components/xt211/ciphering.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,177 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef CHIPPERING_H
#define CHIPPERING_H
#include "gxignore.h"
#ifndef DLMS_IGNORE_HIGH_GMAC
#ifdef __cplusplus
extern "C" {
#endif
#include "bytebuffer.h"
#include "enums.h"
typedef struct
{
/**
* Used security.
*/
DLMS_SECURITY security;
DLMS_SECURITY_SUITE suite;
/**
* Is data encrypted.
*/
unsigned char encrypt;
/**
* Block cipher key.
*/
#ifndef DLMS_IGNORE_MALLOC
gxByteBuffer blockCipherKey;
#else
unsigned char blockCipherKey[32];
#endif //DLMS_IGNORE_MALLOC
/**
* Broadcast block cipher key.
*/
#ifndef DLMS_IGNORE_MALLOC
gxByteBuffer broadcastBlockCipherKey;
#else
unsigned char broadcastBlockCipherKey[32];
#endif //DLMS_IGNORE_MALLOC
/**
* System title.
*/
#ifndef DLMS_IGNORE_MALLOC
gxByteBuffer systemTitle;
#else
unsigned char systemTitle[8];
#endif //DLMS_IGNORE_MALLOC
/**
* Invocation (Frame) counter.
*/
uint32_t invocationCounter;
#ifndef DLMS_IGNORE_MALLOC
gxByteBuffer authenticationKey;
#else
unsigned char authenticationKey[32];
#endif //DLMS_IGNORE_MALLOC
//Dedicated key.
#ifndef DLMS_IGNORE_MALLOC
gxByteBuffer* dedicatedKey;
#else
unsigned char dedicatedKey[32];
#endif //DLMS_IGNORE_MALLOC
//Is data send as a broadcast or unicast.
unsigned char broacast;
} ciphering;
void cip_init(ciphering* target);
void cip_clear(ciphering* target);
/**
* Encrypt data.
*/
#ifndef DLMS_IGNORE_MALLOC
int cip_encrypt(
ciphering* settings,
DLMS_SECURITY security,
DLMS_COUNT_TYPE type,
uint32_t frameCounter,
unsigned char tag,
unsigned char* systemTitle,
gxByteBuffer* key,
gxByteBuffer* input);
#else
int cip_encrypt(
ciphering* settings,
DLMS_SECURITY security,
DLMS_COUNT_TYPE type,
uint32_t frameCounter,
unsigned char tag,
unsigned char* systemTitle,
unsigned char* key,
gxByteBuffer* input);
#endif //DLMS_IGNORE_MALLOC
/**
* Decrypt data.
*/
#ifndef DLMS_IGNORE_MALLOC
int cip_decrypt(
ciphering* settings,
unsigned char* title,
gxByteBuffer* key,
gxByteBuffer* data,
DLMS_SECURITY* security,
DLMS_SECURITY_SUITE* suite,
uint64_t* invocationCounter);
#else
int cip_decrypt(
ciphering* settings,
unsigned char* title,
unsigned char* key,
gxByteBuffer* data,
DLMS_SECURITY* security,
DLMS_SECURITY_SUITE* suite,
uint64_t* invocationCounter);
#endif //DLMS_IGNORE_MALLOC
// Encrypt data using AES RFC3394.
int cip_encryptKey(
unsigned char* kek,
//KEK size.
unsigned char size,
gxByteBuffer* data,
gxByteBuffer* output);
// Decrypt data using AES RFC3394.
//Returns DLMS_ERROR_CODE_FALSE if data is not encrypted with the key.
int cip_decryptKey(
unsigned char* kek,
//KEK size.
unsigned char size,
gxByteBuffer* data,
gxByteBuffer* output);
#ifdef __cplusplus
}
#endif
#endif //DLMS_IGNORE_HIGH_GMAC
#endif //CHIPPERING_H

2251
components/xt211/client.c Normal file

File diff suppressed because it is too large Load Diff

446
components/xt211/client.h Normal file
View File

@ -0,0 +1,446 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef CLIENT_H
#define CLIENT_H
#ifdef __cplusplus
extern "C" {
#endif
#include "gxignore.h"
#if !(defined(DLMS_IGNORE_CLIENT) && defined(DLMS_IGNORE_MALLOC))
#ifdef DLMS_DEBUG
#include "serverevents.h"
#endif //DLMS_DEBUG
#include "dlms.h"
int cl_getData(
dlmsSettings* settings,
gxByteBuffer* reply,
gxReplyData* data);
int cl_getData2(
dlmsSettings* settings,
gxByteBuffer* reply,
gxReplyData* data,
gxReplyData* notify,
unsigned char* isNotify);
// Get size of the frame.
// size: Size of received bytes on the frame.
// Returns: Zero if succeeded, or rccurred error code.
int cl_getFrameSize(dlmsSettings* settings, gxByteBuffer* data, uint32_t* size);
#ifndef DLMS_IGNORE_HDLC
int cl_snrmRequest(
dlmsSettings* settings,
message* messages);
int cl_parseUAResponse(
dlmsSettings* settings,
gxByteBuffer* data);
// Returns the number of bytes to read before the frame is complete.
// When WRAPPER is used this method can be used to check how many bytes we need to read.
// data: Received data.
// size: Size of received bytes on the frame.
// Returns: Zero if succeeded, or rccurred error code.
int cl_getRemainingFrameSize(dlmsSettings* settings, gxByteBuffer* data, uint32_t* size);
#endif //DLMS_IGNORE_HDLC
int cl_aarqRequest(
dlmsSettings* settings,
message* messages);
int cl_parseAAREResponse(
dlmsSettings* settings,
gxByteBuffer* data);
int cl_getApplicationAssociationRequest(
dlmsSettings* settings,
message* messages);
int cl_parseApplicationAssociationResponse(
dlmsSettings* settings,
gxByteBuffer* reply);
/*Read association view. Association view is not available if malloc is not used.*/
int cl_getObjectsRequest(
dlmsSettings* settings,
message* messages);
#ifndef DLMS_IGNORE_MALLOC
/*Parse association view. Association view is not available if malloc is not used.*/
int cl_parseObjects(
dlmsSettings* settings,
gxByteBuffer* data);
#endif //DLMS_IGNORE_MALLOC
//Get objects count in association view.
int cl_parseObjectCount(
gxByteBuffer* data,
uint16_t* count);
/*Parse next association view object.
This method can be used when malloc is not used or there is a limited amount of the memory in use.*/
int cl_parseNextObject(
dlmsSettings* settings,
gxByteBuffer* data,
gxObject* object);
#ifndef DLMS_IGNORE_ASSOCIATION_SHORT_NAME
int cl_readSN(
dlmsSettings* settings,
uint16_t address,
unsigned char attributeOrdinal,
gxByteBuffer* data,
message* messages);
#endif //DLMS_IGNORE_ASSOCIATION_SHORT_NAME
int cl_readLN(
dlmsSettings* settings,
const unsigned char* name,
DLMS_OBJECT_TYPE interfaceClass,
unsigned char attributeOrdinal,
gxByteBuffer* data,
message* messages);
/*This method is used to read list of objects.*/
int cl_readList(
dlmsSettings* settings,
gxArray* list,
message* messages);
int cl_read(
dlmsSettings* settings,
gxObject* object,
unsigned char attributeOrdinal,
message* messages);
int cl_getKeepAlive(
dlmsSettings* settings,
message* messages);
#ifndef DLMS_IGNORE_PROFILE_GENERIC
int cl_readRowsByEntry(
dlmsSettings* settings,
gxProfileGeneric* object,
uint32_t index,
uint32_t count,
message* messages);
int cl_readRowsByEntry2(
dlmsSettings* settings,
gxProfileGeneric* object,
uint32_t index,
uint32_t count,
uint16_t colStart,
uint16_t colEnd,
message* messages);
#ifdef DLMS_USE_EPOCH_TIME
int cl_readRowsByRange(
dlmsSettings* settings,
gxProfileGeneric* object,
uint32_t start,
uint32_t end,
message* messages);
#else
int cl_readRowsByRange(
dlmsSettings* settings,
gxProfileGeneric* object,
struct tm* start,
struct tm* end,
message* messages);
#endif //DLMS_USE_EPOCH_TIME
/////////////////////////////////////////////////////////////////////////
//Read profile generic using start and end times.
int cl_readRowsByRange2(
dlmsSettings* settings,
gxProfileGeneric* object,
gxtime* start,
gxtime* end,
message* messages);
/////////////////////////////////////////////////////////////////////////
//Read profile generic using Indonesia standard.
#ifdef DLMS_INDONESIA_STANDARD
int cl_readRowsByRange3(
dlmsSettings* settings,
gxProfileGeneric* object,
gxtime* start,
gxtime* end,
unsigned char startRegister,
unsigned char numberOfRegisters,
message* messages)
#endif //DLMS_INDONESIA_STANDARD
#endif //DLMS_IGNORE_PROFILE_GENERIC
/*This method is used to write object.*/
int cl_write(
dlmsSettings* settings,
gxObject* object,
unsigned char index,
message* messages);
/*This method is used to write list of objects.*/
int cl_writeList(
dlmsSettings* settings,
gxArray* list,
message* messages);
int cl_writeLN(
dlmsSettings* settings,
const unsigned char* name,
DLMS_OBJECT_TYPE interfaceClass,
unsigned char index,
dlmsVARIANT* data,
unsigned char byteArray,
message* messages);
int cl_writeSN(
dlmsSettings* settings,
uint16_t address,
int index,
dlmsVARIANT* data,
message* messages);
int cl_changeType(
gxByteBuffer* value,
DLMS_DATA_TYPE type,
dlmsVARIANT* newValue);
int cl_updateValue(
dlmsSettings* settings,
gxObject* object,
unsigned char attributeOrdinal,
dlmsVARIANT* value);
/**
* Update list of values.
*
* @param list
* read objects.
* @param data
* Received reply from the meter.
*/
int cl_updateValues(
dlmsSettings* settings,
gxArray* list,
gxByteBuffer* data);
int cl_receiverReady(
dlmsSettings* settings,
DLMS_DATA_REQUEST_TYPES type,
gxByteBuffer* message);
/**
* Generates a release request.
*
* @return Release request, as byte array.
*/
int cl_releaseRequest(
dlmsSettings* settings,
message* packets);
/**
* Generates a release request.
*
* @return Release request, as byte array.
*/
int cl_releaseRequest2(
dlmsSettings* settings,
message* packets,
unsigned char useProtectedRelease);
int cl_disconnectRequest(
dlmsSettings* settings,
message* messages);
/**
* Generate Method (Action) request.
*
* @param object
* Method object.
* @param index
* Method index.
* @param data
* Method data.
* @param messages DLMS action messages.
*/
int cl_method(
dlmsSettings* settings,
gxObject* object,
unsigned char index,
dlmsVARIANT* data,
message* messages);
/**
* Generate Method (Action) request.
*
* @param object
* Method object.
* @param index
* Method index.
* @param data
* Method data.
* @param bytearray
* Is data bytearray.
* @param messages DLMS action messages.
*/
int cl_method2(
dlmsSettings* settings,
gxObject* object,
unsigned char index,
unsigned char* value,
uint32_t length,
message* messages);
/**
* Generate Method (Action) request..
*
* @param name
* Method object short name or Logical Name.
* @param objectType
* Object type.
* @param index
* Method index.
* @param value
* Method data.
* @param dataType
* Data type.
* @return DLMS action message.
*/
int cl_methodLN(
dlmsSettings* settings,
const unsigned char* name,
DLMS_OBJECT_TYPE objectType,
unsigned char index,
dlmsVARIANT* data,
message* messages);
/**
* Generate Method (Action) request..
*
* @param name
* Method object short name or Logical Name.
* @param objectType
* Object type.
* @param index
* Method index.
* @param value
* byte array.
* @param length
* Length of byte array.
* @return DLMS action message.
*/
int cl_methodLN2(
dlmsSettings* settings,
unsigned char* name,
DLMS_OBJECT_TYPE objectType,
unsigned char index,
unsigned char* value,
uint32_t length,
message* messages);
#ifndef DLMS_IGNORE_ASSOCIATION_SHORT_NAME
/**
* Generate Method (Action) request.
*
* @param name
* Method object short name or Logical Name.
* @param objectType
* Object type.
* @param index
* Method index.
* @param value
* Method data.
* @param dataType
* Data type.
* @return DLMS action message.
*/
int cl_methodSN(
dlmsSettings* settings,
uint16_t address,
DLMS_OBJECT_TYPE objectType,
int index,
dlmsVARIANT* data,
message* messages);
/**
* Generate Method (Action) request.
*
* @param name
* Method object short name or Logical Name.
* @param objectType
* Object type.
* @param index
* Method index.
* @param value
* byte array.
* @param lenght
* Length of the byte array.
* @return DLMS action message.
*/
int cl_methodSN2(
dlmsSettings* settings,
uint16_t address,
DLMS_OBJECT_TYPE objectType,
int index,
unsigned char* value,
uint32_t length,
message* messages);
#endif //DLMS_IGNORE_ASSOCIATION_SHORT_NAME
/////////////////////////////////////////////////////////////////////////
// Convert physical address and logical address to server address.
// logicalAddress: Server logical address.
// physicalAddress: Server physical address.
// addressSize: Address size in bytes.
// Returns Server address.
uint16_t cl_getServerAddress(
uint16_t logicalAddress,
uint16_t physicalAddress,
unsigned char addressSize);
#ifdef __cplusplus
}
#endif
#endif //!defined(DLMS_IGNORE_CLIENT) && !defined(DLMS_IGNORE_MALLOC)
#endif //CLIENT_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,84 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef CONVERTERRS_H
#define CONVERTERRS_H
#include "gxignore.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef DLMS_IGNORE_MALLOC
#include "errorcodes.h"
#include "variant.h"
#include "gxarray.h"
#include "gxobjects.h"
#endif //DLMS_IGNORE_MALLOC
#include "enums.h"
//Get object type as string.
int obj_typeToString(
DLMS_OBJECT_TYPE type,
char* buff);
//Get object type as string.
const char* obj_typeToString2(
DLMS_OBJECT_TYPE type);
//Get object type as string.
const char* obj_typeToString2(
DLMS_OBJECT_TYPE type);
#ifndef DLMS_IGNORE_MALLOC
#ifndef DLMS_IGNORE_STRING_CONVERTER
const char* obj_getUnitAsString(
unsigned char unit);
int obj_rowsToString(
gxByteBuffer* ba,
gxArray* buffer);
//Convert object's attributes to string.
//This can be used in debugging purposes.
int obj_toString(
gxObject* object,
char** buff);
#endif //DLMS_IGNORE_STRING_CONVERTER
const char* err_toString(int err);
#endif //DLMS_IGNORE_MALLOC
#ifdef __cplusplus
}
#endif
#endif //CONVERTERRS_H

1968
components/xt211/cosem.c Normal file

File diff suppressed because it is too large Load Diff

229
components/xt211/cosem.h Normal file
View File

@ -0,0 +1,229 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef COSEM_H
#define COSEM_H
#ifdef __cplusplus
extern "C" {
#endif
#include "gxobjects.h"
#include "dlmssettings.h"
#ifndef DLMS_IGNORE_MALLOC
int cosem_createObject(
DLMS_OBJECT_TYPE type,
gxObject** object);
int cosem_createObject2(
DLMS_OBJECT_TYPE type,
const char* ln,
gxObject** object);
#endif //DLMS_IGNORE_MALLOC
int cosem_setLogicalName(
gxObject* object,
const unsigned char* value);
#ifndef DLMS_IGNORE_MALLOC
int cosem_init(
gxObject* object,
DLMS_OBJECT_TYPE type,
const char* logicalNameString);
#endif //DLMS_IGNORE_MALLOC
int cosem_init2(
gxObject* object,
DLMS_OBJECT_TYPE type,
const unsigned char* ln);
//This initialize method will also check the size of the object type and compare it with the expected size.
int cosem_init3(
gxObject* object,
const uint16_t expectedSize,
DLMS_OBJECT_TYPE type,
const unsigned char* ln);
//This initialize method will also check the size of the object type and compare it with the expected size.
int cosem_init4(
void* object,
const uint16_t expectedSize,
DLMS_OBJECT_TYPE type,
const unsigned char* ln);
int cosem_checkStructure(gxByteBuffer* bb, uint16_t expectedItemCount);
int cosem_getStructure(gxByteBuffer* bb, uint16_t* count);
int cosem_checkArray(gxByteBuffer* bb, uint16_t* count);
int cosem_checkArray2(gxByteBuffer* bb, uint16_t* count, unsigned char checkDataType);
int cosem_getUInt8(gxByteBuffer* bb, unsigned char* value);
int cosem_getUInt16(gxByteBuffer* bb, uint16_t* value);
int cosem_getUInt32(gxByteBuffer* bb, uint32_t* value);
int cosem_getInt8(gxByteBuffer* bb, signed char* value);
int cosem_getInt16(gxByteBuffer* bb, int16_t* value);
int cosem_getInt32(gxByteBuffer* bb, int32_t* value);
int cosem_getOctetString(gxByteBuffer* bb, gxByteBuffer* value);
int cosem_getString(gxByteBuffer* bb, gxByteBuffer* value);
int cosem_getOctetString2(gxByteBuffer* bb, unsigned char* value, uint16_t capacity, uint16_t* size);
int cosem_getOctetString3(gxByteBuffer* bb, gxByteBuffer* value, unsigned char exact);
int cosem_getString2(gxByteBuffer* bb, char* value, uint16_t capacity);
//Get date-time value from the octet-string.
int cosem_getDateTimeFromOctetString(gxByteBuffer* bb, gxtime* value);
//Get date-time value from the octet-string.
int cosem_getDateFromOctetString(gxByteBuffer* bb, gxtime* value);
//Get date-time value from the octet-string.
int cosem_getTimeFromOctetString(gxByteBuffer* bb, gxtime* value);
//Get date-time value from the octet-string.
int cosem_getDateTimeFromOctetString2(gxByteBuffer* bb, gxtime* value, unsigned char checkDataType);
//Get date-time value from the octet-string.
int cosem_getDateFromOctetString2(gxByteBuffer* bb, gxtime* value, unsigned char checkDataType);
//Get date-time value from the octet-string.
int cosem_getTimeFromOctetString2(gxByteBuffer* bb, gxtime* value, unsigned char checkDataType);
//Get date-time value from the byte array.
int cosem_getDateTime(gxByteBuffer* bb, gxtime* value);
//Get date value from the byte array.
int cosem_getDate(gxByteBuffer* bb, gxtime* value);
//Get time value from the byte array.
int cosem_getTime(gxByteBuffer* bb, gxtime* value);
//Get date-time value from the byte array.
int cosem_getDateTime2(gxByteBuffer* bb, gxtime* value, unsigned char checkDataType);
//Get date value from the byte array.
int cosem_getDate2(gxByteBuffer* bb, gxtime* value, unsigned char checkDataType);
//Get time value from the byte array.
int cosem_getTime2(gxByteBuffer* bb, gxtime* value, unsigned char checkDataType);
//Get get bit string from the byte array.
int cosem_getBitString(gxByteBuffer* bb, bitArray* value);
//Get get bit string from the byte array.
int cosem_getBitString2(gxByteBuffer* bb, unsigned char* value, uint16_t capacity, uint16_t* size);
//Get integer value from bit string.
int cosem_getIntegerFromBitString(gxByteBuffer* bb, uint32_t* value);
int cosem_getVariant(gxByteBuffer* bb, dlmsVARIANT* value);
int cosem_getEnum(gxByteBuffer* bb, unsigned char* value);
int cosem_getBoolean(gxByteBuffer* bb, unsigned char* value);
int cosem_getUtf8String(gxByteBuffer* bb, gxByteBuffer* value);
int cosem_getUtf8String2(gxByteBuffer* bb, char* value, uint16_t capacity, uint16_t* size);
int cosem_setDateTimeAsOctetString(gxByteBuffer* bb, gxtime* value);
int cosem_setDateAsOctetString(gxByteBuffer* bb, gxtime* value);
int cosem_setBitString(gxByteBuffer* bb, uint32_t value, uint16_t count);
int cosem_setTimeAsOctetString(gxByteBuffer* bb, gxtime* value);
int cosem_setDateTime(gxByteBuffer* bb, gxtime* value);
int cosem_setDate(gxByteBuffer* bb, gxtime* value);
int cosem_setTime(gxByteBuffer* bb, gxtime* value);
int cosem_setOctetString(gxByteBuffer* bb, gxByteBuffer* value);
int cosem_setString(gxByteBuffer* bb, const char* value, uint16_t len);
int cosem_setString2(gxByteBuffer* bb, gxByteBuffer* value);
int cosem_setOctetString2(
gxByteBuffer* bb,
const unsigned char* value,
uint16_t size);
int cosem_setUInt8(gxByteBuffer* bb, unsigned char value);
int cosem_setUInt16(gxByteBuffer* bb, uint16_t value);
int cosem_setUInt32(gxByteBuffer* bb, uint32_t value);
int cosem_setUInt64(gxByteBuffer* bb, uint64_t* value);
int cosem_setInt8(gxByteBuffer* bb, char value);
int cosem_setInt16(gxByteBuffer* bb, int16_t value);
int cosem_setInt32(gxByteBuffer* bb, int32_t value);
int cosem_setInt64(gxByteBuffer* bb, int64_t* value);
int cosem_setVariant(gxByteBuffer* bb, dlmsVARIANT* value);
int cosem_setStructure(gxByteBuffer* bb, uint16_t count);
int cosem_setArray(gxByteBuffer* bb, uint16_t count);
int cosem_setEnum(gxByteBuffer* bb, unsigned char value);
int cosem_setBoolean(gxByteBuffer* bb, unsigned char value);
#ifndef DLMS_IGNORE_PROFILE_GENERIC
int cosem_getColumns(
gxArray* captureObjects,
unsigned char selector,
dlmsVARIANT* parameters,
gxArray* columns);
#endif //DLMS_IGNORE_PROFILE_GENERIC
//Find object from settings object and create if not found.
int cosem_findObjectByLN(
dlmsSettings* settings,
DLMS_OBJECT_TYPE ot,
const unsigned char* ln,
gxObject** object);
#ifdef __cplusplus
}
#endif
#endif //COSEM_H

113
components/xt211/crc.h Normal file
View File

@ -0,0 +1,113 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef CRC_H
#define CRC_H
#include "gxignore.h"
#ifndef DLMS_IGNORE_HDLC
#if defined(USE_AVR) || defined(ARDUINO_ARCH_AVR)
//If AVR is used.
#include <avr/pgmspace.h>
#endif //#if defined(USE_AVR) || defined(ARDUINO_ARCH_AVR)
#ifdef __cplusplus
extern "C" {
#endif
//CRC table.
#ifndef USE_PROGMEM
static const uint16_t FCS16Table[] = {
#else
const uint16_t FCS16Table[] PROGMEM = {
#endif //USE_PROGMEM
0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E,
0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876,
0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD,
0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5,
0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C,
0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974,
0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB,
0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3,
0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A,
0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72,
0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9,
0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1,
0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738,
0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70,
0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7,
0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF,
0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036,
0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E,
0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5,
0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD,
0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134,
0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C,
0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3,
0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB,
0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232,
0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A,
0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1,
0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9,
0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330,
0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78
};
static uint16_t countCRC(gxByteBuffer* Buff, uint32_t index, uint32_t count)
{
uint16_t tmp;
uint16_t FCS16 = 0xFFFF;
uint16_t pos;
for (pos = 0; pos < count; ++pos)
{
#ifdef ARDUINO_ARCH_AVR
//If Arduino is used data is read from flash like this.
tmp = (FCS16 ^ Buff->data[index + pos]) & 0xFF;
FCS16 = (FCS16 >> 8) ^ pgm_read_word_near(FCS16Table + tmp);
#else
FCS16 = (FCS16 >> 8) ^ FCS16Table[(FCS16 ^ ((unsigned char*)Buff->data)[index + pos]) & 0xFF];
#endif //ARDUINO_ARCH_AVR
}
FCS16 = ~FCS16;
//CRC is in big endian byte order.
tmp = FCS16;
FCS16 = tmp >> 8;
FCS16 |= tmp << 8;
return FCS16;
}
#ifdef __cplusplus
}
#endif
#endif //DLMS_IGNORE_HDLC
#endif //CRC_H

View File

@ -0,0 +1,46 @@
//
// --------------------------------------------------------------------------
// 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 "datainfo.h"
void di_init(gxDataInfo *info)
{
info->index = 0;
info->count = 0;
info->type = DLMS_DATA_TYPE_NONE;
info->complete = 1;
#ifdef DLMS_ITALIAN_STANDARD
//Some meters require that there is a array count in data.
info->appendAA = 0;
#endif //DLMS_ITALIAN_STANDARD
}

View File

@ -0,0 +1,66 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef GXDATA_INFO_H
#define GXDATA_INFO_H
#ifdef __cplusplus
extern "C" {
#endif
#include "gxint.h"
#include "enums.h"
#include "gxignore.h"
typedef struct
{
// Last array index.
uint16_t index;
// Items count in array.
uint16_t count;
// Object data type.
DLMS_DATA_TYPE type;
// Is data parsed to the end.
unsigned char complete;
#ifdef DLMS_ITALIAN_STANDARD
//Some meters require that there is a array count in data.
unsigned char appendAA;
#endif //DLMS_ITALIAN_STANDARD
} gxDataInfo;
void di_init(gxDataInfo *info);
#ifdef __cplusplus
}
#endif
#endif //GXDATA_INFO_H

1662
components/xt211/date.c Normal file

File diff suppressed because it is too large Load Diff

380
components/xt211/date.h Normal file
View File

@ -0,0 +1,380 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef DATE_H
#define DATE_H
#ifdef __cplusplus
extern "C" {
#endif
#include "enums.h"
#include "bytebuffer.h"
#ifndef DLMS_USE_EPOCH_TIME
#include <time.h>
#endif
#ifndef DLMS_USE_EPOCH_TIME
//Get UTC offset in minutes.
void time_getUtcOffset(short* hours, short* minutes);
#endif //DLMS_USE_EPOCH_TIME
// DataType enumerates skipped fields from date time.
typedef enum
{
// Nothing is skipped from date time.
DATETIME_SKIPS_NONE = 0x0,
// Year part of date time is skipped.
DATETIME_SKIPS_YEAR = 0x1,
// Month part of date time is skipped.
DATETIME_SKIPS_MONTH = 0x2,
// Day part is skipped.
DATETIME_SKIPS_DAY = 0x4,
// Day of week part of date time is skipped.
DATETIME_SKIPS_DAYOFWEEK = 0x8,
// Hours part of date time is skipped.
DATETIME_SKIPS_HOUR = 0x10,
// Minute part of date time is skipped.
DATETIME_SKIPS_MINUTE = 0x20,
// Seconds part of date time is skipped.
DATETIME_SKIPS_SECOND = 0x40,
// Hundreds of seconds part of date time is skipped.
DATETIME_SKIPS_MS = 0x80,
//Devitation is skipped.
DATETIME_SKIPS_DEVITATION = 0x100,
//Status is skipped.
DATETIME_SKIPS_STATUS = 0x200
} DATETIME_SKIPS;
typedef struct
{
#ifdef DLMS_USE_EPOCH_TIME
uint32_t value;
#else
struct tm value;
#endif
int16_t deviation;
DATETIME_SKIPS skip : 16;
DLMS_DATE_TIME_EXTRA_INFO extraInfo : 8;
DLMS_CLOCK_STATUS status : 8;
} gxtime;
// Constructor.
void time_init(
gxtime* time,
uint16_t year,
unsigned char month,
unsigned char day,
unsigned char hour,
unsigned char minute,
unsigned char second,
uint16_t millisecond,
int16_t devitation);
#ifndef DLMS_USE_EPOCH_TIME
void time_init2(
gxtime* time,
struct tm* value);
// Constructor.
void time_init3(
gxtime* time,
int year,
int month,
int day,
int hour,
int minute,
int second,
int millisecond);
#endif //DLMS_USE_EPOCH_TIME
//Constructor from Unix time.
void time_initUnix(
gxtime* time,
uint32_t value);
void time_clear(
gxtime* time);
void time_copy(
gxtime* trg,
gxtime* src);
//Returns the approximate processor time in ms.
extern uint32_t time_elapsed(void);
/*
Get years from time.
*/
uint16_t time_getYears(
const gxtime* value);
/*
Get months from time.
*/
unsigned char time_getMonths(
const gxtime* value);
/*
Get days from time.
*/
unsigned char time_getDays(
const gxtime* value);
/*
Get hours from time.
*/
unsigned char time_getHours(
const gxtime* value);
/*
Get minutes from time.
*/
unsigned char time_getMinutes(
const gxtime* value);
/*
Get seconds from time.
*/
unsigned char time_getSeconds(
const gxtime* value);
/*
Get years from time.
*/
uint16_t time_getYears2(
uint32_t value);
/*
Get months from time.
*/
unsigned char time_getMonths2(
uint32_t value);
/*
Get days from time.
*/
unsigned char time_getDays2(
uint32_t value);
/*
Get hours from time.
*/
unsigned char time_getHours2(
uint32_t value);
/*
Get minutes from time.
*/
unsigned char time_getMinutes2(
uint32_t value);
/*
Get seconds from time.
*/
unsigned char time_getSeconds2(
uint32_t value);
/*
Adds amount of days to current time.
*/
void time_addDays(
gxtime* value,
int days);
/*
Adds amount of hours to current time.
*/
void time_addHours(
gxtime* value,
int hours);
/*
Adds amount of minutes to current time.
*/
void time_addMinutes(
gxtime* value,
int minutes);
/*
Adds amount of seconds to current time.
*/
void time_addSeconds(
gxtime* value,
int seconds);
/*
Clears date part.
*/
void time_clearDate(
gxtime* value);
/*
Clears time part.
*/
void time_clearTime(
gxtime* value);
/*
Clears hours.
*/
void time_clearHours(
gxtime* value);
/*
Clears minutes.
*/
void time_clearMinutes(
gxtime* value);
/*
Clears seconds.
*/
void time_clearSeconds(
gxtime* value);
unsigned char date_daysInMonth(
uint16_t year,
uint8_t month);
#if !defined(DLMS_IGNORE_STRING_CONVERTER) && !defined(DLMS_IGNORE_MALLOC)
//Print time to cout.
int time_print(
//Format.
const char* format,
gxtime* time);
#endif //!defined(DLMS_IGNORE_STRING_CONVERTER) && !defined(DLMS_IGNORE_MALLOC)
//Save time to char buffer.
int time_toString2(
const gxtime* time,
char* buff,
uint16_t len);
//Save time to bytebuffer.
int time_toString(
const gxtime* time,
gxByteBuffer* arr);
void time_addTime(
gxtime* time,
int hours,
int minutes,
int seconds);
/////////////////////////////////////////////////////////////////////////
// Compare times.
//
// if Return value < 0 then it indicates value1 is less than value2.
// if Return value > 0 then it indicates value2 is less than value1.
// if Return value = 0 then it indicates value1 is equal to value2.
int time_compare(
gxtime* value1,
gxtime* value2);
/////////////////////////////////////////////////////////////////////////
// Compare time and EPOCH time.
//
// if Return value < 0 then it indicates value1 is less than value2.
// if Return value > 0 then it indicates value2 is less than value1.
// if Return value = 0 then it indicates value1 is equal to value2.
int time_compare2(
gxtime* value1,
uint32_t value2);
int time_compareWithDiff(
gxtime* value1,
uint32_t value2,
short deviationDiff);
#ifndef DLMS_USE_EPOCH_TIME
//Get date-time from EPOCH time.
int time_fromUnixTime(
uint32_t epoch,
struct tm* time);
#endif //DLMS_USE_EPOCH_TIME
//Get date-time from EPOCH time.
int time_fromUnixTime2(
uint32_t epoch,
uint16_t* year,
unsigned char* month,
unsigned char* day,
unsigned char* hour,
unsigned char* minute,
unsigned char* second,
unsigned char* dayOfWeek);
//Get date-time from EPOCH time.
int time_fromUnixTime3(
const gxtime* time,
uint16_t* year,
unsigned char* month,
unsigned char* day,
unsigned char* hour,
unsigned char* minute,
unsigned char* second,
unsigned char* dayOfWeek);
#ifndef DLMS_USE_EPOCH_TIME
// Convert date time to Epoch time.
uint32_t time_toUnixTime(
struct tm* time);
#endif //DLMS_USE_EPOCH_TIME
// Convert date time to Epoch time.
uint32_t time_toUnixTime2(
gxtime* time);
//Get day of week.
unsigned char time_dayOfWeek(
uint16_t year,
unsigned char month,
unsigned char day);
//Get deviation.
int time_getDeviation(
gxtime* value1);
//Convert date time to UTC date time.
int time_toUTC(gxtime* value);
// Get next scheduled date in UTC time.
uint32_t time_getNextScheduledDate(
//Start time.
uint32_t start,
//Compared time.
gxtime* value);
#ifdef __cplusplus
}
#endif
#endif //DATE_H

6833
components/xt211/dlms.c Normal file

File diff suppressed because it is too large Load Diff

314
components/xt211/dlms.h Normal file
View File

@ -0,0 +1,314 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef DLMS_H
#define DLMS_H
#ifdef __cplusplus
extern "C" {
#endif
#include "errorcodes.h"
#include "bytebuffer.h"
#include "message.h"
#include "helpers.h"
#include "dlmssettings.h"
#include "apdu.h"
#include "variant.h"
#include "objectarray.h"
#include "replydata.h"
#include "datainfo.h"
#include "parameters.h"
//Makes sure that the basic settings are set.
int dlms_checkInit(
dlmsSettings* settings);
#ifndef DLMS_IGNORE_HDLC
//Is HDLC framing used.
unsigned char dlms_useHdlc(DLMS_INTERFACE_TYPE type);
/**
* Get PDU as HDLC frame.
*/
int dlms_getHdlcFrame(
dlmsSettings* settings,
int frame,
gxByteBuffer* data,
gxByteBuffer* reply);
#endif //DLMS_IGNORE_HDLC
#ifndef DLMS_IGNORE_PLC
int dlms_getMacHdlcFrame(
dlmsSettings* settings,
unsigned char frame,
unsigned char creditFields,
gxByteBuffer* data,
gxByteBuffer* reply);
#endif //DLMS_IGNORE_HDLC
#ifndef DLMS_IGNORE_WRAPPER
/**
* Split DLMS PDU to wrapper frames.
*
* @param settings
* DLMS settings.
* @param data
* Wrapped data.
* @return Wrapper frames.
*/
int dlms_getWrapperFrame(
dlmsSettings* settings,
DLMS_COMMAND command,
gxByteBuffer* data,
gxByteBuffer* reply);
#endif //DLMS_IGNORE_WRAPPER
#ifndef DLMS_IGNORE_HIGH_GMAC
unsigned char dlms_useDedicatedKey(dlmsSettings* settings);
#endif //DLMS_IGNORE_HIGH_GMAC
//Set data from DLMS Varuant to DLMS byte stream.
int dlms_setData(
gxByteBuffer* data,
DLMS_DATA_TYPE type,
dlmsVARIANT *value);
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
//Set data from DLMS Varuant to DLMS byte stream.
int dlms_setData2(
unsigned char *buff,
uint32_t length,
DLMS_DATA_TYPE type,
dlmsVARIANT *value);
#else
//Set data from DLMS Varuant to DLMS byte stream.
int dlms_setData2(
unsigned char *buff,
uint16_t length,
DLMS_DATA_TYPE type,
dlmsVARIANT *value);
#endif
int dlms_receiverReady(
dlmsSettings* settings,
DLMS_DATA_REQUEST_TYPES type,
gxByteBuffer* reply);
/**
* Get next logical name PDU.
*
* @param p
* LN parameters.
* @param reply
* Generated message.
*/
int dlms_getLNPdu(
gxLNParameters* p,
gxByteBuffer* reply);
//Get value from DLMS byte stream.
int dlms_getData(
gxByteBuffer* data,
gxDataInfo* info,
dlmsVARIANT *value);
#ifndef DLMS_IGNORE_ASSOCIATION_SHORT_NAME
/**
* Get next short name PDU.
* @param p SN parameters.
* @param reply Generated message.
*/
int dlms_getSNPdu(
gxSNParameters* p,
gxByteBuffer* reply);
#endif //DLMS_IGNORE_ASSOCIATION_SHORT_NAME
#ifndef DLMS_IGNORE_HDLC
//Return DLMS_ERROR_CODE_FALSE if LLC bytes are not included.
int dlms_checkLLCBytes(
dlmsSettings* settings,
gxByteBuffer* data);
int dlms_getHdlcData(
unsigned char server,
dlmsSettings* settings,
gxByteBuffer* reply,
gxReplyData* data,
unsigned char* frame,
unsigned char preEstablished,
unsigned char first);
#endif //DLMS_IGNORE_HDLC
#ifndef DLMS_IGNORE_WRAPPER
int dlms_getTcpData(
dlmsSettings* settings,
gxByteBuffer* buff,
gxReplyData* data,
gxReplyData* notify,
unsigned char* isNotify);
#endif //DLMS_IGNORE_WRAPPER
int dlms_changeType2(
dlmsVARIANT *value,
DLMS_DATA_TYPE type,
dlmsVARIANT *newValue);
int dlms_changeType(
gxByteBuffer* value,
DLMS_DATA_TYPE type,
dlmsVARIANT *newValue);
int dlms_getPdu(
dlmsSettings* settings,
gxReplyData* data,
unsigned char first);
int dlms_getData2(
dlmsSettings* settings,
gxByteBuffer* reply,
gxReplyData* data,
unsigned char first);
int dlms_getData3(
dlmsSettings* settings,
gxByteBuffer* reply,
gxReplyData* data,
gxReplyData* notify,
unsigned char first,
unsigned char* isNotify);
/**
* Get all Logical name messages. Client uses this to generate messages.
*
* @param p
* LN settings.
* @param reply
* Generated messages.
* @return Status code.
*/
int dlms_getLnMessages(
gxLNParameters *p,
message* reply);
#ifndef DLMS_IGNORE_HDLC
/**
* Add LLC bytes to generated message.
*
* @param settings
* DLMS settings.
* @param data
* Data where bytes are added.
*/
int dlms_addLLCBytes(
dlmsSettings* settings,
gxByteBuffer* data);
#endif //DLMS_IGNORE_HDLC
#ifndef DLMS_IGNORE_ASSOCIATION_SHORT_NAME
/**
* Get all Short Name messages. Client uses this to generate messages.
*
* @param p
* DLMS SN parameters.
* @param reply
* Generated messages.
* @return Status code.
*/
int dlms_getSnMessages(
gxSNParameters *p,
message* reply);
int dlms_getActionInfo(
DLMS_OBJECT_TYPE objectType,
unsigned char *value,
unsigned char *count);
#endif // DLMS_IGNORE_ASSOCIATION_SHORT_NAME
int dlms_generateChallenge(
gxByteBuffer* challenge);
/**
* Chipher text.
*
* @param auth
* Authentication level.
* @param data
* Text to chipher.
* @param secret
* Secret.
* @return Chiphered text.
*/
int dlms_secure(
dlmsSettings* settings,
int32_t ic,
gxByteBuffer* data,
gxByteBuffer* secret,
gxByteBuffer* reply);
int dlms_parseSnrmUaResponse(
dlmsSettings* settings,
gxByteBuffer* data);
// Add HDLC parameter.
int dlms_appendHdlcParameter(
gxByteBuffer* data,
uint16_t value);
//Is it possible to add more data to the PDU before it's full.
int dlms_isPduFull(
dlmsSettings* settings,
gxByteBuffer* data,
uint16_t* size);
int dlms_getMacFrame(
dlmsSettings* settings,
unsigned char frame,
unsigned char creditFields,
gxByteBuffer* data,
gxByteBuffer* reply);
/**
* This function returns true, if pre-established connection is used.
*/
unsigned char dlms_usePreEstablishedConnection(dlmsSettings* settings);
#ifdef __cplusplus
}
#endif
#endif //DLMS_H

View File

@ -0,0 +1,478 @@
//
// --------------------------------------------------------------------------
// 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 "gxmem.h"
#include "dlmssettings.h"
#if defined(_WIN32) || defined(_WIN64) || defined(__linux__)
#include <assert.h>
#include <stdio.h>
#endif
// Server sender frame sequence starting number.
static const unsigned char SERVER_START_SENDER_FRAME_SEQUENCE = 0x1E;
// Server receiver frame sequence starting number.
static const unsigned char SERVER_START_RECEIVER_FRAME_SEQUENCE = 0xFE;
// Client sender frame sequence starting number.
static const unsigned char CLIENT_START_SENDER_FRAME_SEQUENCE = 0xFE;
// Client receiver frame sequence starting number.
static const unsigned char CLIENT_START_RCEIVER_FRAME_SEQUENCE = 0xE;
//Initialize server.
void svr_init(
dlmsServerSettings* settings,
unsigned char useLogicalNameReferencing,
DLMS_INTERFACE_TYPE interfaceType,
uint16_t frameSize,
uint16_t pduSize,
unsigned char* frameBuffer,
uint16_t frameBufferSize,
unsigned char* pduBuffer,
uint16_t pduBufferSize)
{
cl_init(&settings->base, useLogicalNameReferencing, 0, 0, DLMS_AUTHENTICATION_NONE, NULL, interfaceType);
settings->base.proposedConformance |= DLMS_CONFORMANCE_GENERAL_PROTECTION;
bb_attach(&settings->receivedData, frameBuffer, 0, frameBufferSize);
reply_init(&settings->info);
bb_attach(&settings->info.data, pduBuffer, 0, pduBufferSize);
settings->base.maxInfoRX = settings->base.maxInfoTX = frameSize;
settings->base.maxServerPDUSize = pduSize;
settings->base.server = 1;
settings->initialized = 0;
trans_init(&settings->transaction);
#ifndef DLMS_IGNORE_TCP_UDP_SETUP
settings->wrapper = NULL;
#endif // DLMS_IGNORE_TCP_UDP_SETUP
#ifndef DLMS_IGNORE_IEC_HDLC_SETUP
settings->hdlc = NULL;
#endif //DLMS_IGNORE_IEC_HDLC_SETUP
#ifndef DLMS_IGNORE_IEC_LOCAL_PORT_SETUP
settings->localPortSetup = NULL;
#endif //DLMS_IGNORE_IEC_LOCAL_PORT_SETUP
#ifndef DLMS_IGNORE_CLOCK
settings->defaultClock = NULL;
#endif //DLMS_IGNORE_CLOCK
settings->dataReceived = 0;
settings->frameReceived = 0;
resetFrameSequence(&settings->base);
settings->pushClientAddress = 0;
}
//Initialize client.
void cl_init(
dlmsSettings* settings,
unsigned char useLogicalNameReferencing,
uint16_t clientAddress,
uint32_t serverAddress,
DLMS_AUTHENTICATION authentication,
const char* password,
DLMS_INTERFACE_TYPE interfaceType)
{
settings->autoIncreaseInvokeID = 0;
settings->qualityOfService = 0;
settings->protocolVersion = 0;
#ifndef DLMS_IGNORE_MALLOC
settings->preEstablishedSystemTitle = NULL;
#else
memset(settings->preEstablishedSystemTitle, 0, 8);
#endif //DLMS_IGNORE_MALLOC
settings->blockIndex = 1;
settings->clientAddress = clientAddress;
settings->serverAddress = serverAddress;
settings->dlmsVersionNumber = 6;
settings->useLogicalNameReferencing = useLogicalNameReferencing;
settings->interfaceType = interfaceType;
settings->authentication = authentication;
BYTE_BUFFER_INIT(&settings->password);
bb_addString(&settings->password, password);
memset(settings->sourceSystemTitle, 0, sizeof(settings->sourceSystemTitle));
#ifdef DLMS_IGNORE_MALLOC
memset(settings->kek, 0, sizeof(settings->kek));
#else
BYTE_BUFFER_INIT(&settings->kek);
#endif //DLMS_IGNORE_MALLOC
settings->maxServerPDUSize = 1024;
settings->maxPduSize = 0xFFFF;
settings->server = 0;
if (useLogicalNameReferencing)
{
settings->proposedConformance = (DLMS_CONFORMANCE)
(DLMS_CONFORMANCE_BLOCK_TRANSFER_WITH_ACTION |
DLMS_CONFORMANCE_BLOCK_TRANSFER_WITH_SET_OR_WRITE |
DLMS_CONFORMANCE_BLOCK_TRANSFER_WITH_GET_OR_READ |
DLMS_CONFORMANCE_SET |
DLMS_CONFORMANCE_SELECTIVE_ACCESS |
DLMS_CONFORMANCE_ACTION |
DLMS_CONFORMANCE_MULTIPLE_REFERENCES |
DLMS_CONFORMANCE_GET |
DLMS_CONFORMANCE_GENERAL_PROTECTION);
}
else
{
settings->proposedConformance = (DLMS_CONFORMANCE)(DLMS_CONFORMANCE_INFORMATION_REPORT |
DLMS_CONFORMANCE_READ | DLMS_CONFORMANCE_UN_CONFIRMED_WRITE |
DLMS_CONFORMANCE_WRITE | DLMS_CONFORMANCE_PARAMETERIZED_ACCESS |
DLMS_CONFORMANCE_MULTIPLE_REFERENCES);
}
settings->longInvokeID = 0;
settings->maxInfoTX = settings->maxInfoRX = 0x80;
settings->windowSizeTX = settings->windowSizeRX = 1;
settings->connected = DLMS_CONNECTION_STATE_NONE;
oa_init(&settings->objects);
settings->connected = DLMS_CONNECTION_STATE_NONE;
settings->customChallenges = 0;
settings->invokeID = 1;
BYTE_BUFFER_INIT(&settings->ctoSChallenge);
BYTE_BUFFER_INIT(&settings->stoCChallenge);
settings->priority = DLMS_PRIORITY_HIGH;
settings->serviceClass = DLMS_SERVICE_CLASS_CONFIRMED;
#ifndef DLMS_IGNORE_HIGH_GMAC
cip_init(&settings->cipher);
#endif //DLMS_IGNORE_HIGH_GMAC
settings->userId = -1;
resetFrameSequence(settings);
settings->serializedPdu = NULL;
oa_init(&settings->releasedObjects);
settings->expectedSecurityPolicy = 0xFF;
settings->expectedSecuritySuite = 0xFF;
settings->expectedInvocationCounter = NULL;
settings->expectedClientSystemTitle = NULL;
#ifndef DLMS_IGNORE_PLC
plc_reset(settings);
#endif //DLMS_IGNORE_PLC
oa_init(&settings->internalObjects);
}
void cl_clear(
dlmsSettings* settings)
{
settings->protocolVersion = 0;
#ifndef DLMS_IGNORE_MALLOC
if (settings->preEstablishedSystemTitle != NULL)
{
bb_clear(settings->preEstablishedSystemTitle);
gxfree(settings->preEstablishedSystemTitle);
settings->preEstablishedSystemTitle = NULL;
}
#else
memset(settings->preEstablishedSystemTitle, 0, 8);
#endif //DLMS_IGNORE_MALLOC
memset(settings->sourceSystemTitle, 0, sizeof(settings->sourceSystemTitle));
bb_clear(&settings->password);
#ifdef DLMS_IGNORE_MALLOC
memset(settings->kek, 0, sizeof(settings->kek));
#else
bb_clear(&settings->kek);
#endif //DLMS_IGNORE_MALLOC
oa_clear(&settings->objects, !settings->server);
settings->connected = DLMS_CONNECTION_STATE_NONE;
settings->customChallenges = 0;
settings->invokeID = 1;
bb_clear(&settings->ctoSChallenge);
bb_clear(&settings->stoCChallenge);
settings->priority = DLMS_PRIORITY_HIGH;
settings->serviceClass = DLMS_SERVICE_CLASS_CONFIRMED;
#ifndef DLMS_IGNORE_HIGH_GMAC
cip_clear(&settings->cipher);
#endif //DLMS_IGNORE_HIGH_GMAC
settings->maxPduSize = 0xFFFF;
settings->userId = -1;
oa_clear(&settings->releasedObjects, 1);
oa_clear(&settings->internalObjects, 0);
resetFrameSequence(settings);
settings->expectedInvocationCounter = NULL;
}
void svr_clear(
dlmsServerSettings* settings)
{
cl_clear(&settings->base);
}
#ifndef DLMS_IGNORE_PLC
void plc_reset(
dlmsSettings* settings)
{
settings->plcSettings.initialCredit = 7;
settings->plcSettings.currentCredit = 7;
settings->plcSettings.deltaCredit = 0;
//New device addresses are used.
if (settings->interfaceType == DLMS_INTERFACE_TYPE_PLC)
{
if (settings->server)
{
settings->plcSettings.macSourceAddress = DLMS_PLC_SOURCE_ADDRESS_NEW;
settings->plcSettings.macDestinationAddress = DLMS_PLC_SOURCE_ADDRESS_INITIATOR;
}
else
{
settings->plcSettings.macSourceAddress = DLMS_PLC_SOURCE_ADDRESS_INITIATOR;
settings->plcSettings.macDestinationAddress = DLMS_PLC_DESTINATION_ADDRESS_ALL_PHYSICAL;
}
settings->plcSettings.allowedTimeSlots = 10;
}
else
{
if (settings->server)
{
settings->plcSettings.macSourceAddress = DLMS_PLC_SOURCE_ADDRESS_NEW;
settings->plcSettings.macDestinationAddress = DLMS_PLC_HDLC_SOURCE_ADDRESS_INITIATOR;
}
else
{
settings->plcSettings.macSourceAddress = DLMS_PLC_HDLC_SOURCE_ADDRESS_INITIATOR;
settings->plcSettings.macDestinationAddress = DLMS_PLC_DESTINATION_ADDRESS_ALL_PHYSICAL;
}
settings->plcSettings.allowedTimeSlots = 0x14;
}
settings->plcSettings.responseProbability = 100;
}
#endif //DLMS_IGNORE_PLC
void resetBlockIndex(
dlmsSettings* settings)
{
settings->blockIndex = 1;
}
void resetFrameSequence(
dlmsSettings* settings)
{
if (settings->server)
{
settings->senderFrame = SERVER_START_SENDER_FRAME_SEQUENCE;
settings->receiverFrame = SERVER_START_RECEIVER_FRAME_SEQUENCE;
}
else
{
settings->senderFrame = CLIENT_START_SENDER_FRAME_SEQUENCE;
settings->receiverFrame = CLIENT_START_RCEIVER_FRAME_SEQUENCE;
}
}
unsigned char increaseReceiverSequence(
unsigned char value)
{
return ((value + 0x20) | 0x10 | (value & 0xE));
}
// Increase sender sequence.
//
// @param value
// Frame value.
// Increased sender frame sequence.
unsigned char increaseSendSequence(
unsigned char value)
{
return (unsigned char)((value & 0xF0) | ((value + 0x2) & 0xE));
}
#ifndef DLMS_IGNORE_HDLC_CHECK
unsigned char checkFrame(
dlmsSettings* settings,
unsigned char frame)
{
//If notify
if (frame == 0x13)
{
return 1;
}
// If U frame.
if ((frame & 0x3) == 3)
{
if (frame == 0x93)
{
unsigned char isEcho = !settings->server && frame == 0x93 &&
(settings->senderFrame == 0x10 || settings->senderFrame == 0xfe) &&
settings->receiverFrame == 0xE;
resetFrameSequence(settings);
return !isEcho;
}
if (frame == 0x73 && !settings->server)
{
return settings->senderFrame == 0xFE && settings->receiverFrame == 0xE;
}
return 1;
}
// If S -frame
if ((frame & 0x1) == 1)
{
//If echo.
if (frame == (settings->senderFrame & 0xF1))
{
return 0;
}
settings->receiverFrame = increaseReceiverSequence(settings->receiverFrame);
return 1;
}
//Handle I-frame.
unsigned char expected;
if ((settings->senderFrame & 0x1) == 0)
{
expected = increaseReceiverSequence(increaseSendSequence(settings->receiverFrame));
if (frame == expected)
{
settings->receiverFrame = frame;
return 1;
}
//If the final bit is not set.
if (frame == (expected & ~0x10) && settings->windowSizeRX != 1)
{
settings->receiverFrame = frame;
return 1;
}
//If Final bit is not set for the previous message.
if ((settings->receiverFrame & 0x10) == 0 && settings->windowSizeRX != 1)
{
expected = (unsigned char)(0x10 | increaseSendSequence(settings->receiverFrame));
if (frame == expected)
{
settings->receiverFrame = frame;
return 1;
}
//If the final bit is not set.
if (frame == (expected & ~0x10))
{
settings->receiverFrame = frame;
return 1;
}
}
}
//If answer for RR.
else
{
expected = increaseSendSequence(settings->receiverFrame);
if (frame == expected)
{
settings->receiverFrame = frame;
return 1;
}
if (frame == (expected & ~0x10))
{
settings->receiverFrame = frame;
return 1;
}
if (settings->windowSizeRX != 1)
{
//If HDLC window size is bigger than one.
if (frame == (expected | 0x10))
{
settings->receiverFrame = frame;
return 1;
}
}
}
//Pre-established connections needs this.
if ((!settings->server && settings->receiverFrame == SERVER_START_RECEIVER_FRAME_SEQUENCE) ||
(settings->server && settings->receiverFrame == CLIENT_START_RCEIVER_FRAME_SEQUENCE))
{
settings->receiverFrame = frame;
return 1;
}
#if defined(_WIN32) || defined(_WIN64) || defined(__linux__)//If Windows or Linux
printf("Invalid frame %X. Expected %X.\r\n", frame, expected);
#endif
return 0;
}
#endif //DLMS_IGNORE_HDLC_CHECK
unsigned char getNextSend(
dlmsSettings* settings, unsigned char first)
{
if (first)
{
settings->senderFrame = increaseReceiverSequence(increaseSendSequence((unsigned char)settings->senderFrame));
}
else
{
settings->senderFrame = increaseSendSequence((unsigned char)settings->senderFrame);
}
return (unsigned char)settings->senderFrame;
}
unsigned char getReceiverReady(
dlmsSettings* settings)
{
settings->senderFrame = increaseReceiverSequence((unsigned char)(settings->senderFrame | 1));
return (unsigned char)(settings->senderFrame & 0xF1);
}
unsigned char getKeepAlive(
dlmsSettings* settings)
{
settings->senderFrame = (unsigned char)(settings->senderFrame | 1);
return (unsigned char)(settings->senderFrame & 0xF1);
}
#ifndef DLMS_IGNORE_HIGH_GMAC
unsigned char isCiphered(
ciphering* cipher)
{
return cipher->security != DLMS_SECURITY_NONE;
}
#endif //DLMS_IGNORE_HIGH_GMAC
void trans_init(gxLongTransaction* trans)
{
trans->command = DLMS_COMMAND_NONE;
#ifndef DLMS_IGNORE_MALLOC
BYTE_BUFFER_INIT(&trans->data);
#endif //DLMS_IGNORE_MALLOC
vec_init(&trans->targets);
}
void trans_clear(gxLongTransaction* trans)
{
trans->command = DLMS_COMMAND_NONE;
#ifndef DLMS_IGNORE_MALLOC
bb_clear(&trans->data);
#endif //DLMS_IGNORE_MALLOC
vec_clear(&trans->targets);
}
void updateInvokeId(
dlmsServerSettings* settings,
unsigned char value)
{
if ((value & 0x80) != 0) {
settings->base.priority = DLMS_PRIORITY_HIGH;
}
else {
settings->base.priority = DLMS_PRIORITY_NORMAL;
}
if ((value & 0x40) != 0) {
settings->base.serviceClass = DLMS_SERVICE_CLASS_CONFIRMED;
}
else {
settings->base.serviceClass = DLMS_SERVICE_CLASS_UN_CONFIRMED;
}
settings->base.invokeID = (unsigned char)(value & 0xF);
}

View File

@ -0,0 +1,424 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef DLMS_SETTINGS_H
#define DLMS_SETTINGS_H
#ifdef __cplusplus
extern "C" {
#endif
#include "enums.h"
#include "variant.h"
#include "objectarray.h"
#include "message.h"
#include "gxvalueeventargs.h"
#include "replydata.h"
#include "ciphering.h"
#ifndef DLMS_IGNORE_PLC
typedef struct
{
unsigned char responseProbability;
uint16_t allowedTimeSlots;
unsigned char discoverReportInitialCredit;
unsigned char icEqualCredit;
}gxPlcRegister;
// PLC communication settings.
typedef struct
{
gxByteBuffer systemTitle;
/**
* Initial credit (IC) tells how many times the frame must be repeated.
* Maximum value is 7.
*/
unsigned char initialCredit;
/**
* The current credit (CC) initial value equal to IC and automatically
* decremented by the MAC layer after each repetition. Maximum value is 7.
*/
unsigned char currentCredit;
/**
* Delta credit (DC) is used by the system management application entity
* (SMAE) of the Client for credit management, while it has no meaning for a
* Server or a REPEATER. It represents the difference(IC-CC) of the last
* communication originated by the system identified by the DA address to
* the system identified by the SA address. Maximum value is 3.
*/
unsigned char deltaCredit;
/**
* Source MAC address.
*/
uint16_t macSourceAddress;
/**
* Destination MAC address.
*/
uint16_t macDestinationAddress;
/**
* Response probability.
*/
unsigned char responseProbability;
/**
* Allowed time slots.
*/
uint16_t allowedTimeSlots;
/**
* Server saves client system title.
*/
gxByteBuffer clientSystemTitle;
}gxPlcSettings;
#endif //DLMS_IGNORE_PLC
typedef struct
{
// Is custom challenges used. If custom challenge is used new challenge is
// not generated if it is Set. This is for debugging purposes.
unsigned char customChallenges;
// Client to server challenge.
gxByteBuffer ctoSChallenge;
// Server to Client challenge.
gxByteBuffer stoCChallenge;
unsigned char sourceSystemTitle[8];
// Invoke ID.
unsigned char invokeID;
//Long Invoke ID.
int longInvokeID;
// Priority.
DLMS_PRIORITY priority;
// Service class.
DLMS_SERVICE_CLASS serviceClass;
// Client address.
uint16_t clientAddress;
//Server address.
uint32_t serverAddress;
unsigned char useLogicalNameReferencing;
DLMS_INTERFACE_TYPE interfaceType;
DLMS_AUTHENTICATION authentication;
gxByteBuffer password;
#ifndef DLMS_IGNORE_MALLOC
gxByteBuffer kek;
#else
unsigned char kek[16];
#endif //DLMS_IGNORE_MALLOC
/**
* DLMS version number.
*/
unsigned char dlmsVersionNumber;
/**
* Max PDU size used in communicating.
*/
uint16_t maxPduSize;
/**
* Max PDU size that server uses. Client can ask anything, but server will decide.
*/
uint16_t maxServerPDUSize;
/**
* HDLC sender frame sequence number.
*/
unsigned char senderFrame;
/**
* HDLC receiver block sequence number.
*/
unsigned char receiverFrame;
/**
* Server functionality is not supported at the moment in ANSI C version.
*/
unsigned char server;
unsigned char isAuthenticationRequired;
//When connection is made client tells what kind of services it want's to use.
DLMS_CONFORMANCE proposedConformance;
// Functionality what server can offer.
DLMS_CONFORMANCE negotiatedConformance;
//Used max info TX.
uint16_t maxInfoTX;
//Used max info RX.
uint16_t maxInfoRX;
//Used max window size in TX.
unsigned char windowSizeTX;
//Used max window size in RX.
unsigned char windowSizeRX;
// Initialize PDU size that is restored after the connection is closed.
uint16_t initializePduSize;
//Initialized max info TX.
uint16_t initializeMaxInfoTX;
//Initialized max info RX.
uint16_t initializeMaxInfoRX;
//Initialized max window size in TX.
unsigned char initializeWindowSizeTX;
//Initialized max window size in RX.
unsigned char initializeWindowSizeRX;
#ifndef DLMS_IGNORE_PLC
//PLC settings.
gxPlcSettings plcSettings;
#endif //DLMS_IGNORE_PLC
//List of internal COSEM objects.
//Objects in this list are not added to assocaition view.
//Objects can be used to save internal data.
objectArray internalObjects;
//List of COSEM objects.
objectArray objects;
// Block packet index.
uint32_t blockIndex;
//Is connected to the meter.
DLMS_CONNECTION_STATE connected;
#ifndef DLMS_IGNORE_HIGH_GMAC
ciphering cipher;
#endif //DLMS_IGNORE_HIGH_GMAC
int16_t userId;
/**
* Protocol version.
*/
unsigned char protocolVersion;
unsigned char qualityOfService;
//Pre-established Application Associations system title.
#ifndef DLMS_IGNORE_MALLOC
gxByteBuffer* preEstablishedSystemTitle;
#else
unsigned char preEstablishedSystemTitle[8];
#endif //DLMS_IGNORE_MALLOC
//Client serializes data to this PDU when malloc is not used or heap size is limited.
gxByteBuffer* serializedPdu;
//Auto increase Invoke ID.
unsigned char autoIncreaseInvokeID;
//Client adds objects that are not found from the association view here so they are released when client is clear.
objectArray releasedObjects;
/////////////////////////////////////////////////////////////////////////
// Expected security suite.
// If Expected security suite is set client can't connect with other security suite.
unsigned char expectedSecuritySuite;
/////////////////////////////////////////////////////////////////////////
// Expected security policy.
// If Expected security policy is set client can't connect with other security policies.
unsigned char expectedSecurityPolicy;
/////////////////////////////////////////////////////////////////////////
// Expected Invocation(Frame) counter value.
// Expected Invocation counter is not check if value is zero.
#ifdef DLMS_COSEM_INVOCATION_COUNTER_SIZE64
uint64_t* expectedInvocationCounter;
#else
uint32_t* expectedInvocationCounter;
#endif //DLMS_COSEM_INVOCATION_COUNTER_SIZE64
/////////////////////////////////////////////////////////////////////////
// Expected client system title.
unsigned char* expectedClientSystemTitle;
} dlmsSettings;
typedef struct
{
/**
* Executed command.
*/
DLMS_COMMAND command;
/**
* Targets.
*/
gxValueEventCollection targets;
#ifndef DLMS_IGNORE_MALLOC
/**
* Extra data from PDU.
*/
gxByteBuffer data;
#endif //DLMS_IGNORE_MALLOC
} gxLongTransaction;
typedef struct
{
dlmsSettings base;
gxReplyData info;
/**
* Received data frame.
*/
gxByteBuffer receivedData;
/**
* Long get or read transaction information.
*/
gxLongTransaction transaction;
/**
* Is server initialized.
*/
unsigned char initialized;
#ifndef DLMS_IGNORE_IEC_HDLC_SETUP
gxIecHdlcSetup* hdlc;
#endif //DLMS_IGNORE_IEC_HDLC_SETUP
#ifndef DLMS_IGNORE_IEC_LOCAL_PORT_SETUP
gxLocalPortSetup* localPortSetup;
#endif //DLMS_IGNORE_IEC_LOCAL_PORT_SETUP
#ifndef DLMS_IGNORE_TCP_UDP_SETUP
gxTcpUdpSetup* wrapper;
#endif //DLMS_IGNORE_TCP_UDP_SETUP
#ifndef DLMS_IGNORE_CLOCK
gxClock* defaultClock;
#endif //DLMS_IGNORE_CLOCK
//Time when last frame was received. HDLC framing is using this.
uint32_t dataReceived;
//Time when last byte was received. HDLC framing is using this.
uint32_t frameReceived;
//Server is using push client address when sending push messages. Client address is used if PushAddress is zero.
uint16_t pushClientAddress;
#ifndef DLMS_IGNORE_IEC
/*Flag ID is used when server is operating using optical probe.*/
unsigned char flagId[3];
#endif //DLMS_IGNORE_IEC
} dlmsServerSettings;
//Initialize server.
void svr_init(
dlmsServerSettings* settings,
unsigned char useLogicalNameReferencing,
DLMS_INTERFACE_TYPE interfaceType,
//Max frame size.
uint16_t frameSize,
//Max PDU size.
uint16_t pduSize,
//Buffer where received frames are saved.
unsigned char* frameBuffer,
//Size of frame buffer.
uint16_t frameBufferSize,
//PDU Buffer.
unsigned char* pduBuffer,
//Size of PDU buffer.
uint16_t pduBufferSize);
//Initialize client.
void cl_init(
dlmsSettings* settings,
unsigned char useLogicalNameReferencing,
uint16_t clientAddress,
uint32_t serverAddress,
DLMS_AUTHENTICATION authentication,
const char* password,
DLMS_INTERFACE_TYPE interfaceType);
//Clear DLMS settings.
void cl_clear(
dlmsSettings* settings);
void svr_clear(
dlmsServerSettings* settings);
#ifndef DLMS_IGNORE_PLC
// Set default values for PLC.
void plc_reset(
dlmsSettings* settings);
#endif //DLMS_IGNORE_PLC
//Reset block index.
void resetBlockIndex(
dlmsSettings* settings);
void resetFrameSequence(
dlmsSettings* settings);
#ifndef DLMS_IGNORE_HDLC_CHECK
unsigned char checkFrame(
dlmsSettings* settings,
unsigned char frame);
#endif //DLMS_IGNORE_HDLC_CHECK
void updateInvokeId(
dlmsServerSettings* settings, unsigned char value);
// Increase receiver sequence.
//
// value: Frame value.
// Increased receiver frame sequence.
unsigned char increaseReceiverSequence(
unsigned char value);
// Increase sender sequence.
//
// value : Frame value.
// Increased sender frame sequence.
unsigned char increaseSendSequence(
unsigned char value);
unsigned char getNextSend(
dlmsSettings* settings, unsigned char first);
unsigned char getReceiverReady(
dlmsSettings* settings);
unsigned char getKeepAlive(
dlmsSettings* settings);
#ifndef DLMS_IGNORE_HIGH_GMAC
unsigned char isCiphered(
ciphering* cipher);
#endif //DLMS_IGNORE_HIGH_GMAC
void trans_init(gxLongTransaction* trans);
void trans_clear(gxLongTransaction* trans);
#ifdef __cplusplus
}
#endif
#endif //DLMS_SETTINGS_H

3419
components/xt211/enums.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,167 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef DLMS_ERROR_CODE_H
#define DLMS_ERROR_CODE_H
#ifdef __cplusplus
extern "C" {
#endif
typedef enum
{
DLMS_ERROR_TYPE_EXCEPTION_RESPONSE = 0x80000000,
DLMS_ERROR_TYPE_CONFIRMED_SERVICE_ERROR = 0x40000000,
DLMS_ERROR_TYPE_COMMUNICATION_ERROR = 0x20000000
}DLMS_ERROR_TYPE;
/////////////////////////////////////////////////////////////////////////////
// Enumerates all DLMS error codes.
// https://www.gurux.fi/Gurux.DLMS.ErrorCodes
/////////////////////////////////////////////////////////////////////////////
typedef enum
{
//Meter is not accept frame.
DLMS_ERROR_CODE_UNACCEPTABLE_FRAME = -3,
//Meter rejects send packet.
DLMS_ERROR_CODE_REJECTED = -2,
DLMS_ERROR_CODE_FALSE = -1,
//////////////////////////////////////////
//DLMS Standard error codes start here.
DLMS_ERROR_CODE_OK = 0,
//Access Error : Device reports a hardware fault
DLMS_ERROR_CODE_HARDWARE_FAULT = 1,
//Access Error : Device reports a temporary failure
DLMS_ERROR_CODE_TEMPORARY_FAILURE = 2,
// Access Error : Device reports Read-Write denied
DLMS_ERROR_CODE_READ_WRITE_DENIED = 3,
// Access Error : Device reports a undefined object
DLMS_ERROR_CODE_UNDEFINED_OBJECT = 4,
// Access Error : Device reports a inconsistent Class or Object
DLMS_ERROR_CODE_INCONSISTENT_CLASS_OR_OBJECT = 9,
// Access Error : Device reports a unavailable object
DLMS_ERROR_CODE_UNAVAILABLE_OBJECT = 11,
// Access Error : Device reports a unmatched type
DLMS_ERROR_CODE_UNMATCH_TYPE = 12,
// Access Error : Device reports scope of access violated
DLMS_ERROR_CODE_ACCESS_VIOLATED = 13,
// Access Error : Data Block Unavailable.
DLMS_ERROR_CODE_DATA_BLOCK_UNAVAILABLE = 14,
// Access Error : Long Get Or Read Aborted.
DLMS_ERROR_CODE_LONG_GET_OR_READ_ABORTED = 15,
// Access Error : No Long Get Or Read In Progress.
DLMS_ERROR_CODE_NO_LONG_GET_OR_READ_IN_PROGRESS = 16,
// Access Error : Long Set Or Write Aborted.
DLMS_ERROR_CODE_LONG_SET_OR_WRITE_ABORTED = 17,
// Access Error : No Long Set Or Write In Progress.
DLMS_ERROR_CODE_NO_LONG_SET_OR_WRITE_IN_PROGRESS = 18,
// Access Error : Data Block Number Invalid.
DLMS_ERROR_CODE_DATA_BLOCK_NUMBER_INVALID = 19,
// Access Error : Other Reason.
DLMS_ERROR_CODE_OTHER_REASON = 250,
//DLMS Standard error codes end here.
//////////////////////////////////////////
//Unknown error.
DLMS_ERROR_CODE_UNKNOWN,
//Data send failed.
DLMS_ERROR_CODE_SEND_FAILED,
//Data receive failed.
DLMS_ERROR_CODE_RECEIVE_FAILED,
DLMS_ERROR_CODE_NOT_IMPLEMENTED,
//Secure connection is not supported.
DLMS_ERROR_CODE_DLMS_SECURITY_NOT_IMPLEMENTED,
//Invalid DLMS command.
DLMS_ERROR_CODE_INVALID_COMMAND,
//Invalid Block number.
DLMS_ERROR_CODE_INVALID_BLOCK_NUMBER,
//Invalid parameter.
DLMS_ERROR_CODE_INVALID_PARAMETER,
//Server is not initialized.
DLMS_ERROR_CODE_NOT_INITIALIZED,
//Not enough memory available.
DLMS_ERROR_CODE_OUTOFMEMORY,
//Packet is not a reply for a send packet.
DLMS_ERROR_CODE_NOT_REPLY,
//Invalid Logical Name
DLMS_ERROR_CODE_INVALID_LOGICAL_NAME,
//Client HDLC Address is not set.
DLMS_ERROR_CODE_INVALID_CLIENT_ADDRESS,
//Server HDLC Address is not set.
DLMS_ERROR_CODE_INVALID_SERVER_ADDRESS,
//Not a HDLC frame.
DLMS_ERROR_CODE_INVALID_DATA_FORMAT,
//Invalid DLMS version number.
DLMS_ERROR_CODE_INVALID_VERSION_NUMBER,
//Client addresses do not match
DLMS_ERROR_CODE_CLIENT_ADDRESS_NO_NOT_MATCH,
//Server addresses do not match
DLMS_ERROR_CODE_SERVER_ADDRESS_NO_NOT_MATCH,
//CRC do not match.
DLMS_ERROR_CODE_WRONG_CRC,
//Invalid response
DLMS_ERROR_CODE_INVALID_RESPONSE,
//Invalid Tag.
DLMS_ERROR_CODE_INVALID_TAG,
//Encoding failed. Not enough data.
DLMS_ERROR_CODE_ENCODING_FAILED,
DLMS_ERROR_CODE_REJECTED_PERMAMENT,
DLMS_ERROR_CODE_REJECTED_TRANSIENT,
DLMS_ERROR_CODE_NO_REASON_GIVEN,
DLMS_ERROR_CODE_APPLICATION_CONTEXT_NAME_NOT_SUPPORTED,
DLMS_ERROR_CODE_AUTHENTICATION_MECHANISM_NAME_NOT_RECOGNISED,
DLMS_ERROR_CODE_AUTHENTICATION_MECHANISM_NAME_REQUIRED,
DLMS_ERROR_CODE_AUTHENTICATION_FAILURE,
DLMS_ERROR_CODE_AUTHENTICATION_REQUIRED,
//Invalid frame number.
DLMS_ERROR_CODE_INVALID_FRAME_NUMBER,
DLMS_ERROR_CODE_INVALID_DATE_TIME,
DLMS_ERROR_CODE_INVALID_INVOKE_ID,
//Invocation counter value is too small.
DLMS_ERROR_CODE_INVOCATION_COUNTER_TOO_SMALL,
//Client try to connect with wrong security.
DLMS_ERROR_CODE_INVALID_DECIPHERING_ERROR,
//Client try to connect with wrong security suite.
DLMS_ERROR_CODE_INVALID_SECURITY_SUITE,
//Serialization load failed.
DLMS_ERROR_CODE_SERIALIZATION_LOAD_FAILURE,
//Serialization save failed.
DLMS_ERROR_CODE_SERIALIZATION_SAVE_FAILURE,
//Serialization count failed.
DLMS_ERROR_CODE_SERIALIZATION_COUNT_FAILURE
}DLMS_ERROR_CODE;
#ifdef __cplusplus
}
#endif
#endif //DLMS_ERROR_CODE_H

603
components/xt211/gxaes.c Normal file
View File

@ -0,0 +1,603 @@
//
// --------------------------------------------------------------------------
// Gurux Ltd
//
//
//
// Filename: $HeadURL$
//
// Version: $Revision$,
// $Date$
// $Author$
//
// Copyright (c) Gurux Ltd
//
//---------------------------------------------------------------------------
//
// DESCRIPTION
//
// This file is a part of Gurux Device Framework.
//
// Gurux Device Framework is Open Source software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; version 2 of the License.
// Gurux Device Framework is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// This code is licensed under the GNU General Public License v2.
// Full text may be retrieved at http://www.gnu.org/licenses/gpl-2.0.txt
//---------------------------------------------------------------------------
#include "gxignore.h"
#ifndef DLMS_IGNORE_AES
#include <string.h> // CBC mode, for memset
#include <stdint.h>
#include "gxaes.h"
#if defined(USE_AVR) || defined(ARDUINO_ARCH_AVR)
//If AVR is used.
#include <avr/pgmspace.h>
#endif //#if defined(USE_AVR) || defined(ARDUINO_ARCH_AVR)
#define Nb 4
#define BLOCKLEN 16 //Block length in bytes AES is 128b block only
#if defined(AES256) && (AES256 == 1)
#define Nk 8
#define KEYLEN 32
#define Nr 14
#define keyExpSize 240
#elif defined(AES192) && (AES192 == 1)
#define Nk 6
#define KEYLEN 24
#define Nr 12
#define keyExpSize 208
#else
#define Nk 4 // The number of 32 bit words in a key.
#define KEYLEN 16 // Key length in bytes
#define Nr 10 // The number of rounds in AES Cipher.
#define keyExpSize 176
#endif
#ifndef MULTIPLY_AS_A_FUNCTION
#define MULTIPLY_AS_A_FUNCTION 0
#endif
// state - array holding the intermediate results during decryption.
typedef unsigned char state_t[4][4];
static state_t* state;
// The array that stores the round keys.
static unsigned char RoundKey[keyExpSize];
// The Key input to the AES Program
static const unsigned char* Key;
#if defined(CBC) && CBC
// Initial Vector used only for CBC mode
static unsigned char* Iv;
#endif
#ifndef USE_PROGMEM
static const unsigned char __SBOX[256] = {
#else
static const unsigned char __SBOX[256] PROGMEM = {
#endif //#if defined(_WIN32) || defined(_WIN64)
//0 1 2 3 4 5 6 7 8 9 A B C D E F
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 };
#ifndef USE_PROGMEM
static const unsigned char __RS_BOX[256] = {
#else
static const unsigned char __RS_BOX[256] PROGMEM = {
#endif //#if defined(_WIN32) || defined(_WIN64)
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d };
// The round constant word array, Rcon[i], contains the values given by
// x to th e power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8)
#ifndef USE_PROGMEM
static const unsigned char __R_CON[11] = {
#else
static const unsigned char __R_CON[11] PROGMEM = {
#endif //#if defined(_WIN32) || defined(_WIN64)
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };
#if 0
#ifndef USE_PROGMEM
static const unsigned char __R_CON[256] = {
#else
static const unsigned char __R_CON[256] PROGMEM = {
#endif //#if defined(_WIN32) || defined(_WIN64)
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39,
0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,
0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef,
0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc,
0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b,
0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3,
0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94,
0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20,
0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35,
0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f,
0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04,
0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63,
0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d };
#endif
static unsigned char getSBoxValue(unsigned char offset)
{
#ifdef ARDUINO_ARCH_AVR
//If Arduino is used data is read from flash like this.
return pgm_read_byte_near(__SBOX + offset);
#else
return __SBOX[offset];
#endif //ARDUINO_ARCH_AVR
}
static unsigned char getSBoxInvert(unsigned char offset)
{
#ifdef ARDUINO_ARCH_AVR
//If Arduino is used data is read from flash like this.
return pgm_read_byte_near(__RS_BOX + offset);
#else
return __RS_BOX[offset];
#endif //ARDUINO_ARCH_AVR
}
static unsigned char getRCon(unsigned char offset)
{
#ifdef ARDUINO_ARCH_AVR
//If Arduino is used data is read from flash like this.
return pgm_read_byte_near(__R_CON + offset);
#else
return __R_CON[offset];
#endif //ARDUINO_ARCH_AVR
}
// This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states.
static void KeyExpansion(void)
{
unsigned char k;
uint32_t i;
// Used for the column/row operations
unsigned char tempa[4];
// The first round key is the key itself.
for (i = 0; i < Nk; ++i)
{
RoundKey[(i * 4) + 0] = Key[(i * 4) + 0];
RoundKey[(i * 4) + 1] = Key[(i * 4) + 1];
RoundKey[(i * 4) + 2] = Key[(i * 4) + 2];
RoundKey[(i * 4) + 3] = Key[(i * 4) + 3];
}
// All other round keys are found from the previous round keys.
//i == Nk
for (; i < Nb * (Nr + 1); ++i)
{
{
tempa[0] = RoundKey[(i - 1) * 4 + 0];
tempa[1] = RoundKey[(i - 1) * 4 + 1];
tempa[2] = RoundKey[(i - 1) * 4 + 2];
tempa[3] = RoundKey[(i - 1) * 4 + 3];
}
if (i % Nk == 0)
{
// This function shifts the 4 bytes in a word to the left once.
// [a0,a1,a2,a3] becomes [a1,a2,a3,a0]
// Function RotWord()
{
k = tempa[0];
tempa[0] = tempa[1];
tempa[1] = tempa[2];
tempa[2] = tempa[3];
tempa[3] = k;
}
// SubWord() is a function that takes a four-byte input word and
// applies the S-box to each of the four bytes to produce an output word.
// Function Subword()
{
tempa[0] = getSBoxValue(tempa[0]);
tempa[1] = getSBoxValue(tempa[1]);
tempa[2] = getSBoxValue(tempa[2]);
tempa[3] = getSBoxValue(tempa[3]);
}
tempa[0] = (unsigned char)(tempa[0] ^ getRCon((unsigned char)(i / Nk)));
}
#if defined(AES256) && (AES256 == 1)
if (i % Nk == 4)
{
// Function Subword()
{
tempa[0] = getSBoxValue(tempa[0]);
tempa[1] = getSBoxValue(tempa[1]);
tempa[2] = getSBoxValue(tempa[2]);
tempa[3] = getSBoxValue(tempa[3]);
}
}
#endif
RoundKey[i * 4 + 0] = RoundKey[(i - Nk) * 4 + 0] ^ tempa[0];
RoundKey[i * 4 + 1] = RoundKey[(i - Nk) * 4 + 1] ^ tempa[1];
RoundKey[i * 4 + 2] = RoundKey[(i - Nk) * 4 + 2] ^ tempa[2];
RoundKey[i * 4 + 3] = RoundKey[(i - Nk) * 4 + 3] ^ tempa[3];
}
}
// This function adds the round key to state.
// The round key is added to the state by an XOR function.
static void AddRoundKey(unsigned char round)
{
unsigned char i, j;
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 4; ++j)
{
(*state)[i][j] ^= RoundKey[round * Nb * 4 + i * Nb + j];
}
}
}
// The SubBytes Function Substitutes the values in the
// state matrix with values in an S-box.
static void SubBytes(void)
{
unsigned char i, j;
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 4; ++j)
{
(*state)[j][i] = getSBoxValue((*state)[j][i]);
}
}
}
// The ShiftRows() function shifts the rows in the state to the left.
// Each row is shifted with different offset.
// Offset = Row number. So the first row is not shifted.
static void ShiftRows(void)
{
unsigned char temp;
// Rotate first row 1 columns to left
temp = (*state)[0][1];
(*state)[0][1] = (*state)[1][1];
(*state)[1][1] = (*state)[2][1];
(*state)[2][1] = (*state)[3][1];
(*state)[3][1] = temp;
// Rotate second row 2 columns to left
temp = (*state)[0][2];
(*state)[0][2] = (*state)[2][2];
(*state)[2][2] = temp;
temp = (*state)[1][2];
(*state)[1][2] = (*state)[3][2];
(*state)[3][2] = temp;
// Rotate third row 3 columns to left
temp = (*state)[0][3];
(*state)[0][3] = (*state)[3][3];
(*state)[3][3] = (*state)[2][3];
(*state)[2][3] = (*state)[1][3];
(*state)[1][3] = temp;
}
static unsigned char xtime(unsigned char x)
{
return (unsigned char)((x << 1) ^ (((x >> 7) & 1) * 0x1b));
}
// MixColumns function mixes the columns of the state matrix
static void MixColumns(void)
{
unsigned char i;
unsigned char Tmp, Tm, t;
for (i = 0; i < 4; ++i)
{
t = (*state)[i][0];
Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3];
Tm = (*state)[i][0] ^ (*state)[i][1]; Tm = xtime(Tm); (*state)[i][0] ^= Tm ^ Tmp;
Tm = (*state)[i][1] ^ (*state)[i][2]; Tm = xtime(Tm); (*state)[i][1] ^= Tm ^ Tmp;
Tm = (*state)[i][2] ^ (*state)[i][3]; Tm = xtime(Tm); (*state)[i][2] ^= Tm ^ Tmp;
Tm = (*state)[i][3] ^ t; Tm = xtime(Tm); (*state)[i][3] ^= Tm ^ Tmp;
}
}
// Multiply is used to multiply numbers in the field GF(2^8)
#if MULTIPLY_AS_A_FUNCTION
static unsigned char Multiply(unsigned char x, unsigned char y)
{
return (((y & 1) * x) ^
((y >> 1 & 1) * xtime(x)) ^
((y >> 2 & 1) * xtime(xtime(x))) ^
((y >> 3 & 1) * xtime(xtime(xtime(x)))) ^
((y >> 4 & 1) * xtime(xtime(xtime(xtime(x))))));
}
#else
#define Multiply(x, y) \
( ((y & 1) * x) ^ \
((y>>1 & 1) * xtime(x)) ^ \
((y>>2 & 1) * xtime(xtime(x))) ^ \
((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ \
((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))) \
#endif
// MixColumns function mixes the columns of the state matrix.
// The method used to multiply may be difficult to understand for the inexperienced.
// Please use the references to gain more information.
static void InvMixColumns(void)
{
int i;
unsigned char a, b, c, d;
for (i = 0; i < 4; ++i)
{
a = (*state)[i][0];
b = (*state)[i][1];
c = (*state)[i][2];
d = (*state)[i][3];
(*state)[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09);
(*state)[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d);
(*state)[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b);
(*state)[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e);
}
}
// The SubBytes Function Substitutes the values in the
// state matrix with values in an S-box.
static void InvSubBytes(void)
{
unsigned char i, j;
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 4; ++j)
{
(*state)[j][i] = getSBoxInvert((*state)[j][i]);
}
}
}
static void InvShiftRows(void)
{
unsigned char temp;
// Rotate first row 1 columns to right
temp = (*state)[3][1];
(*state)[3][1] = (*state)[2][1];
(*state)[2][1] = (*state)[1][1];
(*state)[1][1] = (*state)[0][1];
(*state)[0][1] = temp;
// Rotate second row 2 columns to right
temp = (*state)[0][2];
(*state)[0][2] = (*state)[2][2];
(*state)[2][2] = temp;
temp = (*state)[1][2];
(*state)[1][2] = (*state)[3][2];
(*state)[3][2] = temp;
// Rotate third row 3 columns to right
temp = (*state)[0][3];
(*state)[0][3] = (*state)[1][3];
(*state)[1][3] = (*state)[2][3];
(*state)[2][3] = (*state)[3][3];
(*state)[3][3] = temp;
}
// Cipher is the main function that encrypts the PlainText.
static void Cipher(void)
{
unsigned char round = 0;
// Add the First round key to the state before starting the rounds.
AddRoundKey(0);
// There will be Nr rounds.
// The first Nr-1 rounds are identical.
// These Nr-1 rounds are executed in the loop below.
for (round = 1; round < Nr; ++round)
{
SubBytes();
ShiftRows();
MixColumns();
AddRoundKey(round);
}
// The last round is given below.
// The MixColumns function is not here in the last round.
SubBytes();
ShiftRows();
AddRoundKey(Nr);
}
static void InvCipher(void)
{
unsigned char round = 0;
// Add the First round key to the state before starting the rounds.
AddRoundKey(Nr);
// There will be Nr rounds.
// The first Nr-1 rounds are identical.
// These Nr-1 rounds are executed in the loop below.
for (round = (Nr - 1); round > 0; --round)
{
InvShiftRows();
InvSubBytes();
AddRoundKey(round);
InvMixColumns();
}
// The last round is given below.
// The MixColumns function is not here in the last round.
InvShiftRows();
InvSubBytes();
AddRoundKey(0);
}
/*****************************************************************************/
/* Public functions: */
/*****************************************************************************/
#if defined(ECB) && (ECB == 1)
void gxaes_ecb_encrypt(const unsigned char* input, const unsigned char* key, unsigned char* output, const size_t length)
{
// Copy input to output, and work in-memory on output
memcpy(output, input, length);
state = (state_t*)output;
Key = key;
KeyExpansion();
// The next function call encrypts the PlainText with the Key using AES algorithm.
Cipher();
}
void gxaes_ecb_decrypt(const unsigned char* input, const unsigned char* key, unsigned char *output, const size_t length)
{
// Copy input to output, and work in-memory on output
memcpy(output, input, length);
state = (state_t*)output;
// The KeyExpansion routine must be called before encryption.
Key = key;
KeyExpansion();
InvCipher();
}
#endif // #if defined(ECB) && (ECB == 1)
#if defined(CBC) && (CBC == 1)
static void XorWithIv(unsigned char* buf)
{
unsigned char i;
for (i = 0; i < BLOCKLEN; ++i) //WAS for(i = 0; i < KEYLEN; ++i) but the block in AES is always 128bit so 16 bytes!
{
buf[i] ^= Iv[i];
}
}
void gxaes_cbc_encrypt(unsigned char* output, unsigned char* input, uint32_t length, const unsigned char* key, const unsigned char* iv)
{
uintptr_t i;
unsigned char extra = length % BLOCKLEN; /* Remaining bytes in the last non-full block */
// Skip the key expansion if key is passed as 0
if (0 != key)
{
Key = key;
KeyExpansion();
}
if (iv != 0)
{
Iv = (unsigned char*)iv;
}
for (i = 0; i < length; i += BLOCKLEN)
{
XorWithIv(input);
memcpy(output, input, BLOCKLEN);
state = (state_t*)output;
Cipher();
Iv = output;
input += BLOCKLEN;
output += BLOCKLEN;
//printf("Step %d - %d", i/16, i);
}
if (extra)
{
memcpy(output, input, extra);
state = (state_t*)output;
Cipher();
}
}
void gxaes_cbc_decrypt(unsigned char* output, unsigned char* input, uint32_t length, const unsigned char* key, const unsigned char* iv)
{
uintptr_t i;
unsigned char extra = length % BLOCKLEN; /* Remaining bytes in the last non-full block */
// Skip the key expansion if key is passed as 0
if (0 != key)
{
Key = key;
KeyExpansion();
}
// If iv is passed as 0, we continue to encrypt without re-setting the Iv
if (iv != 0)
{
Iv = (unsigned char*)iv;
}
for (i = 0; i < length; i += BLOCKLEN)
{
memcpy(output, input, BLOCKLEN);
state = (state_t*)output;
InvCipher();
XorWithIv(output);
Iv = input;
input += BLOCKLEN;
output += BLOCKLEN;
}
if (extra)
{
memcpy(output, input, extra);
state = (state_t*)output;
InvCipher();
}
}
#endif // #if defined(CBC) && (CBC == 1)
#endif //DLMS_IGNORE_AES

73
components/xt211/gxaes.h Normal file
View File

@ -0,0 +1,73 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef GXAES1
#define GXAES1
#include "gxignore.h"
#ifndef DLMS_IGNORE_AES
#ifdef __cplusplus
extern "C" {
#endif
#ifndef CBC
#define CBC 1
#endif
#ifndef ECB
#define ECB 1
#endif
#define AES128 1
//#define AES192 1
//#define AES256 1
#if defined(ECB) && (ECB == 1)
void gxaes_ecb_encrypt(const unsigned char* input, const unsigned char* key, unsigned char *output, const size_t length);
void gxaes_ecb_decrypt(const unsigned char* input, const unsigned char* key, unsigned char *output, const size_t length);
#endif // #if defined(ECB) && (ECB == !)
#if defined(CBC) && (CBC == 1)
void gxaes_cbc_encrypt(unsigned char* output, unsigned char* input, uint32_t length, const unsigned char* key, const unsigned char* iv);
void gxaes_cbc_decrypt(unsigned char* output, unsigned char* input, uint32_t length, const unsigned char* key, const unsigned char* iv);
#endif // #if defined(CBC) && (CBC == 1)
#ifdef __cplusplus
}
#endif
#endif //DLMS_IGNORE_AES
#endif //GXAES1

460
components/xt211/gxarray.c Normal file
View File

@ -0,0 +1,460 @@
//
// --------------------------------------------------------------------------
// 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 "gxmem.h"
#if _MSC_VER > 1400
#include <crtdbg.h>
#endif
#include <string.h>
#include "errorcodes.h"
#include "gxarray.h"
#include "bytebuffer.h"
#include "gxkey.h"
//Initialize gxArray.
void arr_init(gxArray* arr)
{
arr->capacity = 0;
arr->data = NULL;
arr->size = 0;
#ifndef DLMS_IGNORE_MALLOC
arr->position = 0;
#endif //DLMS_IGNORE_MALLOC
}
char arr_isAttached(gxArray* arr)
{
return (arr->capacity & 0x8000) == 0x8000;
}
uint16_t arr_getCapacity(gxArray* arr)
{
return arr->capacity & 0x7FFF;
}
void arr_attach(
gxArray* arr,
void* value,
uint16_t count,
uint16_t capacity)
{
arr->data = value;
arr->capacity = (uint16_t)(0x8000 | capacity);
arr->size = count;
#ifndef DLMS_IGNORE_MALLOC
arr->position = 0;
#endif //DLMS_IGNORE_MALLOC
}
//Allocate new size for the array in bytes.
int arr_capacity(gxArray* arr, int capacity)
{
#ifndef DLMS_IGNORE_MALLOC
if (!arr_isAttached(arr))
{
if (capacity == 0)
{
if (arr->data != NULL)
{
gxfree(arr->data);
arr->data = NULL;
}
}
else
{
if (arr->data == NULL)
{
arr->data = (void**)gxmalloc(capacity * sizeof(void*));
if (arr->data == NULL)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
}
else
{
#ifdef gxrealloc
void* tmp = (void**)gxrealloc(arr->data, capacity * sizeof(void*));
//If not enought memory available.
if (tmp == NULL)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
arr->data = tmp;
#else
//If compiler doesn't support realloc.
void* old = arr->data;
arr->data = (void**)gxmalloc(capacity * sizeof(void*));
//If not enought memory available.
if (arr->data == NULL)
{
arr->data = old;
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
memcpy(arr->data, old, sizeof(void*) * arr->size);
gxfree(old);
#endif // gxrealloc
}
}
arr->capacity = (uint16_t)capacity;
}
#endif //DLMS_IGNORE_MALLOC
if (arr_getCapacity(arr) < capacity)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
return 0;
}
#ifndef DLMS_IGNORE_MALLOC
int arr_push(gxArray* arr, void* item)
{
if (arr->size >= arr->capacity)
{
int ret = arr_capacity(arr, arr->capacity + GXARRAY_CAPACITY);
if (ret != 0)
{
return ret;
}
}
arr->data[arr->size] = item;
++arr->size;
return 0;
}
#endif //DLMS_IGNORE_MALLOC
void arr_clear(
gxArray* arr)
{
#ifndef DLMS_IGNORE_MALLOC
int pos;
if (arr->size != 0)
{
for (pos = 0; pos != arr->size; ++pos)
{
gxfree(arr->data[pos]);
}
}
if (!arr_isAttached(arr) && arr->capacity != 0)
{
gxfree(arr->data);
arr->data = NULL;
arr->capacity = 0;
}
if (!arr_isAttached(arr))
{
arr->size = 0;
}
#else
arr->size = 0;
#endif //DLMS_IGNORE_MALLOC
#ifndef DLMS_IGNORE_MALLOC
arr->position = 0;
#endif //DLMS_IGNORE_MALLOC
}
void arr_empty(
gxArray* arr)
{
#ifndef DLMS_IGNORE_MALLOC
if (arr->size != 0)
{
gxfree(arr->data);
arr->data = NULL;
}
arr->capacity = 0;
if (!arr_isAttached(arr))
{
arr->size = 0;
}
#else
arr->size = 0;
#endif //DLMS_IGNORE_MALLOC
#ifndef DLMS_IGNORE_MALLOC
arr->position = 0;
#endif //DLMS_IGNORE_MALLOC
}
#ifndef DLMS_IGNORE_MALLOC
int arr_get(gxArray* arr, void** value)
{
if (arr->position >= arr->size)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
*value = arr->data[arr->position];
++arr->position;
return 0;
}
#endif //DLMS_IGNORE_MALLOC
#ifndef DLMS_IGNORE_MALLOC
int arr_getByIndex(gxArray* arr, uint16_t index, void** value)
{
if (arr == NULL || value == NULL)
{
return DLMS_ERROR_CODE_INVALID_PARAMETER;
}
if (index >= arr->size)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
*value = arr->data[index];
return 0;
}
int arr_getByIndex3(gxArray* arr, uint16_t index, void** value, unsigned char checkSize)
{
if (arr == NULL || value == NULL)
{
return DLMS_ERROR_CODE_INVALID_PARAMETER;
}
if (index >= arr->size)
{
if (checkSize || index >= arr->capacity)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
}
*value = arr->data[index];
return 0;
}
#else
int arr_getByIndex(gxArray* arr, uint16_t index, void** value, uint16_t itemSize)
{
if (arr == NULL || value == NULL)
{
return DLMS_ERROR_CODE_INVALID_PARAMETER;
}
if (index >= arr->size)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
*value = (void*)((unsigned char*)arr->data + (index * itemSize));
return 0;
}
int arr_getByIndex3(gxArray* arr, uint16_t index, void** value, uint16_t itemSize, unsigned char checkSize)
{
if (arr == NULL || value == NULL)
{
return DLMS_ERROR_CODE_INVALID_PARAMETER;
}
if (index >= arr->size)
{
if (checkSize || index >= arr->capacity)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
}
*value = (void*)((unsigned char*)arr->data + (index * itemSize));
return 0;
}
#endif //DLMS_IGNORE_MALLOC
int arr_getByIndex2(gxArray* arr, uint16_t index, void** value, uint16_t itemSize)
{
#ifndef DLMS_IGNORE_MALLOC
return arr_getByIndex(arr, index, value);
#else
return arr_getByIndex(arr, index, value, itemSize);
#endif //DLMS_IGNORE_MALLOC
}
int arr_getByIndex4(gxArray* arr, uint16_t index, void** value, uint16_t itemSize, unsigned char checkSize)
{
#ifndef DLMS_IGNORE_MALLOC
return arr_getByIndex3(arr, index, value, checkSize);
#else
return arr_getByIndex3(arr, index, value, itemSize, checkSize);
#endif //DLMS_IGNORE_MALLOC
}
int arr_getByIndexRef(gxArray* arr, uint16_t index, void** value)
{
if (arr == NULL || value == NULL)
{
return DLMS_ERROR_CODE_INVALID_PARAMETER;
}
if (index >= arr->size)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
*value = (void*)((gxArray**)arr->data)[index];
return 0;
}
int arr_setByIndexRef(gxArray* arr, void* value)
{
if (!(arr->size < arr_getCapacity(arr)))
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
((gxArray**)arr->data)[arr->size] = value;
++arr->size;
return 0;
}
void arr_clearKeyValuePair(gxArray* arr)
{
#ifndef DLMS_IGNORE_MALLOC
gxKey* k;
int pos;
if (arr->capacity != 0)
{
for (pos = 0; pos != arr->size; ++pos)
{
k = (gxKey*)arr->data[pos];
gxfree(k->key);
gxfree(k->value);
gxfree(k);
}
gxfree(arr->data);
arr->data = NULL;
arr->capacity = 0;
arr->size = 0;
arr->position = 0;
}
#else
arr_clear(arr);
#endif //DLMS_IGNORE_MALLOC
}
void arr_clearStrings(gxArray* arr)
{
#ifndef DLMS_IGNORE_MALLOC
gxByteBuffer* it;
int pos;
if (arr->capacity != 0)
{
for (pos = 0; pos != arr->size; ++pos)
{
it = (gxByteBuffer*)arr->data[pos];
gxfree(it->data);
gxfree(it);
}
gxfree(arr->data);
arr->data = NULL;
arr->capacity = 0;
arr->size = 0;
arr->position = 0;
}
#else
arr_clear(arr);
#endif //DLMS_IGNORE_MALLOC
}
#ifndef DLMS_IGNORE_MALLOC
int arr_removeByIndex(gxArray* arr, uint16_t index, void** value)
{
int pos;
if (index >= arr->size)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
if (value != NULL)
{
*value = arr->data[index];
}
for (pos = index; pos != arr->size; ++pos)
{
arr->data[pos] = arr->data[pos + 1];
}
--arr->size;
return 0;
}
#else
int arr_removeByIndex(
gxArray* arr,
uint16_t index,
uint16_t itemSize)
{
int ret;
uint16_t pos;
void* prev = NULL;
void* item = NULL;
if ((ret = arr_getByIndex(arr, index, &prev, itemSize)) == 0)
{
for (pos = index + 1; pos < arr->size; ++pos)
{
if ((ret = arr_getByIndex(arr, pos, &item, itemSize)) == 0)
{
memcpy(prev, item, itemSize);
prev = item;
}
}
--arr->size;
}
return 0;
}
#endif //DLMS_IGNORE_MALLOC
#ifndef DLMS_IGNORE_MALLOC
int arr_swap(gxArray* arr, uint16_t index1, uint16_t index2)
{
void* tmp;
if (!(index1 < arr->size || index2 < arr->size))
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
tmp = arr->data[index1];
arr->data[index1] = arr->data[index2];
arr->data[index2] = tmp;
return 0;
}
#else
int arr_swap(
gxArray* arr,
uint16_t index1,
uint16_t index2,
uint16_t itemSize,
void* tmp)
{
int ret;
void* prev = NULL;
void* item = NULL;
if ((ret = arr_getByIndex(arr, index1, &prev, itemSize)) == 0 &&
(ret = arr_getByIndex(arr, index2, &item, itemSize)) == 0)
{
memcpy(tmp, prev, itemSize);
memcpy(prev, item, itemSize);
memcpy(item, tmp, itemSize);
}
return 0;
}
#endif //DLMS_IGNORE_MALLOC

165
components/xt211/gxarray.h Normal file
View File

@ -0,0 +1,165 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef GXARRAY_H
#define GXARRAY_H
#ifdef __cplusplus
extern "C" {
#endif
#include <string.h> /* memset */
#include "gxint.h"
#define GXARRAY_CAPACITY 10
typedef struct
{
#ifndef DLMS_IGNORE_MALLOC
void** data;
#else
void* data;
#endif //DLMS_IGNORE_MALLOC
uint16_t capacity;
uint16_t size;
#ifndef DLMS_IGNORE_MALLOC
int position;
#endif //DLMS_IGNORE_MALLOC
} gxArray;
//Initialize gxArray.
void arr_init(gxArray* arr);
void arr_attach(
gxArray* arr,
void* value,
uint16_t count,
uint16_t capacity);
/*
* Is static buffer used.
*/
char arr_isAttached(
gxArray* arr);
/*Get maximum buffer size.*/
uint16_t arr_getCapacity(
gxArray* arr);
//Allocate new size for the array in bytes.
int arr_capacity(gxArray* arr, int capacity);
#ifndef DLMS_IGNORE_MALLOC
//Push new data to the gxArray.
int arr_push(gxArray* arr, void* item);
#endif //DLMS_IGNORE_MALLOC
//Clear array. All items are automatically free.
void arr_clear(gxArray* arr);
//Empty array but is not free items.
void arr_empty(
gxArray* arr);
//Clear key value pair array. All items are automatically free.
void arr_clearKeyValuePair(gxArray* arr);
//Clear string array.
void arr_clearStrings(gxArray* arr);
#ifndef DLMS_IGNORE_MALLOC
int arr_get(gxArray* arr, void** value);
int arr_getByIndex(
gxArray* arr,
uint16_t index,
void** value);
int arr_getByIndex3(
gxArray* arr,
uint16_t index,
void** value,
unsigned char checkSize);
int arr_removeByIndex(
gxArray* arr,
uint16_t index,
void** value);
//Swap two array items.
int arr_swap(gxArray* arr, uint16_t index1, uint16_t index2);
#else
int arr_getByIndex(
gxArray* arr,
uint16_t index,
void** value,
uint16_t itemSize);
int arr_getByIndex3(
gxArray* arr,
uint16_t index,
void** value,
uint16_t itemSize,
unsigned char checkSize);
int arr_removeByIndex(
gxArray* arr,
uint16_t index,
uint16_t itemSize);
//Swap two array items.
int arr_swap(
gxArray* arr,
uint16_t index1,
uint16_t index2,
uint16_t itemSize,
void* tmp);
//This method is used to access array where items are saved with pointer.
//Example: registerAssignment.
int arr_getByIndexRef(gxArray* arr, uint16_t index, void** value);
int arr_setByIndexRef(gxArray* arr, void* value);
#endif //DLMS_IGNORE_MALLOC
int arr_getByIndex2(gxArray* arr, uint16_t index, void** value, uint16_t itemSize);
int arr_getByIndex4(gxArray* arr, uint16_t index, void** value, uint16_t itemSize, unsigned char checkSize);
#define ARR_ATTACH(X, V, S) arr_attach(&X, V, S, sizeof(V)/sizeof(V[0]))
#ifdef __cplusplus
}
#endif
#endif //GXARRAY_H

148
components/xt211/gxdefine.h Normal file
View File

@ -0,0 +1,148 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef GXDEFINE_H
#define GXDEFINE_H
#ifdef __cplusplus
extern "C" {
#endif
//Define max user name length.
#define MAX_USER_NAME_LENGTH 20
//Define max destination length.
#define MAX_DESTINATION_LENGTH 20
//Define max SAP logical device name length.
#define MAX_SAP_LOGICAL_DEVICE_NAME_LENGTH 20
//Define max season profile name length.
#define MAX_SEASON_PROFILE_NAME_LENGTH 20
//Define max season profile name length.
#define MAX_SEASON_PROFILE_NAME_LENGTH 20
//Define max season profile week name length.
#define MAX_SEASON_PROFILE_WEEK_NAME_LENGTH 20
//Define max week profile name length.
#define MAX_SEASON_WEEK_PROFILE_NAME_LENGTH 20
//Define max IP4 setup IP option data length.
#define MAX_IP4_SETUP_IP_OPTION_DATA_LENGTH 20
//Define max SAP item name length.
#define MAX_SAP_ITEM_NAME_LENGTH 20
//Define max modem initialization string length.
#define MAX_MODEM_INITIALIZATION_STRING_LENGTH 20
//Define max modem profile string length.
#define MAX_MODEM_PROFILE_STRING_LENGTH 20
//Define max certificate serial number length.
#define MAX_CERTIFICATE_SERIAL_NUMBER_LENGTH 20
//Define max certificate issuer length.
#define MAX_CERTIFICATE_ISSUER_LENGTH 40
//Define max certificate subject length.
#define MAX_CERTIFICATE_SUBJECT_LENGTH 20
//Define max function name length.
#define MAX_FUNCTION_NAME_LENGTH 10
//Define max function target length.
#define MAX_FUNCTION_TARGET_LENGTH 10
//Define max certificate subject alt length.
#define MAX_CERTIFICATE_SUBJECT_ALT_LENGTH 40
//Define max certificate subject alt length.
#define MAX_CAPTURE_DEFINITION_ELEMENT_LENGTH 100
//Define max certificate subject alt length.
#define MAX_CHARGE_TABLE_INDEX_LENGTH 100
//Define max certificate subject alt length.
#define MAX_TOKEN_GATEWAY_DESCRIPTION_LENGTH 20
//Define max image identification length.
#define MAX_IMAGE_IDENTIFICATION_LENGTH 20
//Define image signature length.
#define MAX_IMAGE_SIGNATURE_LENGTH 20
//Define max push setup target length.
#define MAX_PUSH_SETUP_TARGET_LENGTH 20
//Define max currency name length.
#define MAX_CURRENCY_NAME_LENGTH 20
//Define max client PDU size.
#define MAX_CLIENT_PDU_SIZE 200
//Define max capture object buffer size.
#define MAX_CAPTURE_OBJECT_BUFFER_SIZE 100
//Define max challenge size.
#define MAX_CHALLENGE_SIZE 64
//Define max register activation mask name length.
#define MAX_REGISTER_ACTIVATION_MASK_NAME_LENGTH 10
//Define max reporting system item name length.
#define MAX_REPORTING_SYSTEM_ITEM_LENGTH 20
//Define max SAP item count. This is used when data is serialized.
#define MAX_SAP_ITEM_SERIALIZE_COUNT 5
//Define key size for G3 MAC key table.
#define MAX_G3_MAC_KEY_TABLE_KEY_SIZE 16
//Define neighbour table gain item size for G3 MAC Setup object.
#define MAX_G3_MAC_NEIGHBOUR_TABLE_GAIN_ITEM_SIZE 6
//Define neighbour table gain size for G3 MAC Setup object.
#define MAX_G3_MAC_NEIGHBOUR_TABLE_GAIN_SIZE 5
//Define neighbour table tone map item size in bytes for G3 MAC Setup object.
#define MAX_G3_MAC_NEIGHBOUR_TABLE_TONE_MAP_ITEM_SIZE 3
//Define neighbour table tone map size for G3 MAC Setup object.
#define MAX_G3_MAC_NEIGHBOUR_TABLE_TONE_MAP_SIZE 5
#ifdef __cplusplus
}
#endif
#endif //GXDEFINE_H

6947
components/xt211/gxget.c Normal file

File diff suppressed because it is too large Load Diff

296
components/xt211/gxget.h Normal file
View File

@ -0,0 +1,296 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef COSEM_GET_H
#define COSEM_GET_H
#ifdef __cplusplus
extern "C" {
#endif
#include "gxobjects.h"
#include "dlmssettings.h"
int cosem_getData(
gxValueEventArg* e);
int cosem_getRegister(
gxValueEventArg* e);
#ifndef DLMS_IGNORE_CLOCK
int cosem_getClock(
gxValueEventArg* e);
//Update Daylight Saving time flag if DST is used.
void clock_updateDST(
gxClock* object,
gxtime* value);
//Convert UTC date time to meter date time.
int clock_utcToMeterTime(
gxClock* object,
gxtime* value);
#endif // DLMS_IGNORE_CLOCK
int cosem_getActionSchedule(
gxValueEventArg* e);
int cosem_getActivityCalendar(
gxValueEventArg* e);
int cosem_getAssociationLogicalName(
dlmsSettings* settings,
gxValueEventArg* e);
#ifndef DLMS_IGNORE_ASSOCIATION_SHORT_NAME
int cosem_getAssociationShortName(
dlmsSettings* settings,
gxValueEventArg* e);
#endif //DLMS_IGNORE_ASSOCIATION_SHORT_NAME
int cosem_getAutoAnswer(
gxValueEventArg* e);
int cosem_getAutoConnect(
gxValueEventArg* e);
int cosem_getDemandRegister(
gxValueEventArg* e);
int cosem_getMacAddressSetup(
gxValueEventArg* e);
int cosem_getExtendedRegister(
gxValueEventArg* e);
int cosem_getGprsSetup(
gxValueEventArg* e);
int cosem_getSecuritySetup(
gxValueEventArg* e);
int cosem_getIecHdlcSetup(
gxValueEventArg* e);
int cosem_getIecLocalPortSetup(
gxValueEventArg* e);
int cosem_getIP4Setup(
gxValueEventArg* e);
int cosem_getProfileGeneric(
dlmsSettings* settings,
gxValueEventArg* e);
int cosem_getMbusSlavePortSetup(
gxValueEventArg* e);
int cosem_getDisconnectControl(
gxValueEventArg* e);
int cosem_getLimiter(
gxValueEventArg* e);
int cosem_getmMbusClient(
gxValueEventArg* e);
int cosem_getModemConfiguration(
dlmsSettings* settings,
gxValueEventArg* e);
int cosem_getPppSetup(
gxValueEventArg* e);
int cosem_getRegisterActivation(
dlmsSettings* settings,
gxValueEventArg* e);
int cosem_getRegisterMonitor(
gxValueEventArg* e);
int cosem_getSapAssignment(
gxValueEventArg* e);
int cosem_getSchedule(
gxValueEventArg* e);
int cosem_getScriptTable(
gxValueEventArg* e);
int cosem_getSpecialDaysTable(
gxValueEventArg* e);
int cosem_getTcpUdpSetup(
gxValueEventArg* e);
int cosem_getMbusMasterPortSetup(
gxValueEventArg* e);
int cosem_getMessageHandler(
gxValueEventArg* e);
int cosem_getPushSetup(
gxValueEventArg* e);
int cosem_getValue(
dlmsSettings* settings,
gxValueEventArg* e);
#ifndef DLMS_IGNORE_G3_PLC_MAC_SETUP
int cosem_getG3PlcMacSetupNeighbourTables(
gxArray* tables,
uint16_t address,
uint16_t count,
gxValueEventArg* e);
int cosem_getG3PlcMacSetupPosTables(
gxArray* tables,
uint16_t address,
uint16_t count,
gxValueEventArg* e);
#endif //DLMS_IGNORE_G3_PLC_MAC_SETUP
#ifndef DLMS_IGNORE_MALLOC
int cosem_getRow(
gxArray* table,
int index,
gxArray* captureObjects,
gxArray* columns,
gxByteBuffer* data);
#endif //DLMS_IGNORE_MALLOC
int cosem_getTariffPlan(
gxValueEventArg* e);
#ifndef DLMS_IGNORE_GSM_DIAGNOSTIC
int cosem_getGsmDiagnostic(
gxValueEventArg* e);
#endif //DLMS_IGNORE_GSM_DIAGNOSTIC
#ifndef DLMS_IGNORE_PARAMETER_MONITOR
int cosem_getParameterMonitor(
gxValueEventArg* e);
#endif //DLMS_IGNORE_PARAMETER_MONITOR
#ifndef DLMS_IGNORE_COMPACT_DATA
//Convert compact data buffer to array of values.
int compactData_getValues(
dlmsSettings* settings,
gxByteBuffer* templateDescription,
gxByteBuffer* buffer,
variantArray* values);
#endif //DLMS_IGNORE_COMPACT_DATA
#ifndef DLMS_IGNORE_LLC_SSCS_SETUP
int cosem_getLlcSscsSetup(
gxValueEventArg* e);
#endif //DLMS_IGNORE_LLC_SSCS_SETUP
#ifndef DLMS_IGNORE_PRIME_NB_OFDM_PLC_PHYSICAL_LAYER_COUNTERS
int cosem_getPrimeNbOfdmPlcPhysicalLayerCounters(
gxValueEventArg* e);
#endif //DLMS_IGNORE_PRIME_NB_OFDM_PLC_PHYSICAL_LAYER_COUNTERS
#ifndef DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_SETUP
int cosem_getPrimeNbOfdmPlcMacSetup(
gxValueEventArg* e);
#endif //DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_SETUP
#ifndef DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_FUNCTIONAL_PARAMETERS
int cosem_getPrimeNbOfdmPlcMacFunctionalParameters(
gxValueEventArg* e);
#endif //DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_FUNCTIONAL_PARAMETERS
#ifndef DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_COUNTERS
int cosem_getPrimeNbOfdmPlcMacCounters(
gxValueEventArg* e);
#endif //DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_COUNTERS
#ifndef DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_NETWORK_ADMINISTRATION_DATA
int cosem_getPrimeNbOfdmPlcMacNetworkAdministrationData(
gxValueEventArg* e);
#endif //DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_NETWORK_ADMINISTRATION_DATA
#ifndef DLMS_IGNORE_PRIME_NB_OFDM_PLC_APPLICATIONS_IDENTIFICATION
int cosem_getPrimeNbOfdmPlcApplicationsIdentification(
gxValueEventArg* e);
#endif //DLMS_IGNORE_PRIME_NB_OFDM_PLC_APPLICATIONS_IDENTIFICATION
#ifndef DLMS_IGNORE_ARBITRATOR
int cosem_getArbitrator(
gxValueEventArg* e);
#endif //DLMS_IGNORE_ARBITRATOR
#ifndef DLMS_IGNORE_IEC_8802_LLC_TYPE1_SETUP
int cosem_getIec8802LlcType1Setup(
gxValueEventArg* e);
#endif //DLMS_IGNORE_IEC_8802_LLC_TYPE1_SETUP
#ifndef DLMS_IGNORE_IEC_8802_LLC_TYPE2_SETUP
int cosem_getIec8802LlcType2Setup(
gxValueEventArg* e);
#endif //DLMS_IGNORE_IEC_8802_LLC_TYPE2_SETUP
#ifndef DLMS_IGNORE_IEC_8802_LLC_TYPE3_SETUP
int cosem_getIec8802LlcType3Setup(
gxValueEventArg* e);
#endif //DLMS_IGNORE_IEC_8802_LLC_TYPE3_SETUP
#ifndef DLMS_IGNORE_SFSK_ACTIVE_INITIATOR
int cosem_getSFSKActiveInitiator(
gxValueEventArg* e);
#endif //DLMS_IGNORE_SFSK_ACTIVE_INITIATOR
#ifndef DLMS_IGNORE_SFSK_MAC_COUNTERS
int cosem_getFSKMacCounters(
gxValueEventArg* e);
#endif //DLMS_IGNORE_SFSK_MAC_COUNTERS
#ifndef DLMS_IGNORE_SFSK_MAC_SYNCHRONIZATION_TIMEOUTS
int cosem_getSFSKMacSynchronizationTimeouts(
gxValueEventArg* e);
#endif //DLMS_IGNORE_SFSK_MAC_SYNCHRONIZATION_TIMEOUTS
#ifndef DLMS_IGNORE_SFSK_PHY_MAC_SETUP
int cosem_getSFSKPhyMacSetUp(
gxValueEventArg* e);
#endif //DLMS_IGNORE_SFSK_PHY_MAC_SETUP
#ifndef DLMS_IGNORE_SFSK_REPORTING_SYSTEM_LIST
int cosem_getSFSKReportingSystemList(
gxValueEventArg* e);
#endif //DLMS_IGNORE_SFSK_REPORTING_SYSTEM_LIST
#ifdef DLMS_ITALIAN_STANDARD
//Convert compact data buffer to array of values.
//Some Italy meters require that there is a array count in data.
//This is against compact data structure defined in DLMS standard.
int compactData_getValues2(
dlmsSettings* settings,
gxByteBuffer* templateDescription,
gxByteBuffer* buffer,
variantArray* values,
unsigned char appendAA);
#endif //DLMS_ITALIAN_STANDARD
#ifdef __cplusplus
}
#endif
#endif //COSEM_GET_H

252
components/xt211/gxignore.h Normal file
View File

@ -0,0 +1,252 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef GXIGNORE_H
#define GXIGNORE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Uncomment defines to ignore non-needed parts to make image size smaller. */
// #define DLMS_IGNORE_HDLC
// #define DLMS_IGNORE_WRAPPER
// #define DLMS_IGNORE_PLC
// #define DLMS_IGNORE_IEC
// #define DLMS_IGNORE_NOTIFY
// #define DLMS_IGNORE_SERVER
// #define DLMS_IGNORE_CLIENT
// #define GX_DLMS_MICROCONTROLLER
// #define DLMS_IGNORE_HIGH_SHA256
// #define DLMS_IGNORE_HIGH_SHA1
// #define DLMS_IGNORE_HIGH_MD5
// #define DLMS_IGNORE_AES
// #define DLMS_IGNORE_HIGH_GMAC
// #define DLMS_IGNORE_DATA
// #define DLMS_IGNORE_REGISTER
// #define DLMS_IGNORE_EXTENDED_REGISTER
// #define DLMS_IGNORE_DEMAND_REGISTER
// #define DLMS_IGNORE_REGISTER_ACTIVATION
// #define DLMS_IGNORE_PROFILE_GENERIC
// #define DLMS_IGNORE_CLOCK
// #define DLMS_IGNORE_SCRIPT_TABLE
// #define DLMS_IGNORE_SCHEDULE
// #define DLMS_IGNORE_SPECIAL_DAYS_TABLE
// #define DLMS_IGNORE_ASSOCIATION_SHORT_NAME
// #define DLMS_IGNORE_ASSOCIATION_LOGICAL_NAME
// #define DLMS_IGNORE_SAP_ASSIGNMENT
// #define DLMS_IGNORE_IMAGE_TRANSFER
// #define DLMS_IGNORE_IEC_LOCAL_PORT_SETUP
// #define DLMS_IGNORE_ACTIVITY_CALENDAR
// #define DLMS_IGNORE_REGISTER_MONITOR
// #define DLMS_IGNORE_ACTION_SCHEDULE
// #define DLMS_IGNORE_IEC_HDLC_SETUP
// #define DLMS_IGNORE_IEC_TWISTED_PAIR_SETUP
// #define DLMS_IGNORE_MBUS_SLAVE_PORT_SETUP
// #define DLMS_IGNORE_UTILITY_TABLES
// #define DLMS_IGNORE_MODEM_CONFIGURATION
// #define DLMS_IGNORE_AUTO_ANSWER
// #define DLMS_IGNORE_AUTO_CONNECT
// #define DLMS_IGNORE_TCP_UDP_SETUP
// #define DLMS_IGNORE_IP4_SETUP
// #define DLMS_IGNORE_IP6_SETUP
// #define DLMS_IGNORE_MAC_ADDRESS_SETUP
// #define DLMS_IGNORE_PPP_SETUP
// #define DLMS_IGNORE_GPRS_SETUP
// #define DLMS_IGNORE_SMTP_SETUP
// #define DLMS_IGNORE_GSM_DIAGNOSTIC
// #define DLMS_IGNORE_REGISTER_TABLE
// #define DLMS_IGNORE_STATUS_MAPPING
// #define DLMS_IGNORE_SECURITY_SETUP
// #define DLMS_IGNORE_DISCONNECT_CONTROL
// #define DLMS_IGNORE_LIMITER
// #define DLMS_IGNORE_MBUS_CLIENT
// #define DLMS_IGNORE_PUSH_SETUP
// #define DLMS_IGNORE_PARAMETER_MONITOR
// #define DLMS_IGNORE_WIRELESS_MODE_Q_CHANNEL
// #define DLMS_IGNORE_MBUS_MASTER_PORT_SETUP
// #define DLMS_IGNORE_ZIG_BEE_SAS_STARTUP
// #define DLMS_IGNORE_ZIG_BEE_SAS_JOIN
// #define DLMS_IGNORE_ZIG_BEE_SAS_APS_FRAGMENTATION
// #define DLMS_IGNORE_ZIG_BEE_NETWORK_CONTROL
// #define DLMS_IGNORE_DATA_PROTECTION
// #define DLMS_IGNORE_ACCOUNT
// #define DLMS_IGNORE_CREDIT
// #define DLMS_IGNORE_CHARGE
// #define DLMS_IGNORE_TOKEN_GATEWAY
// #define DLMS_IGNORE_COMPACT_DATA
// #define DLMS_IGNORE_LLC_SSCS_SETUP
// #define DLMS_IGNORE_PRIME_NB_OFDM_PLC_PHYSICAL_LAYER_COUNTERS
// #define DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_SETUP
// #define DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_FUNCTIONAL_PARAMETERS
// #define DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_COUNTERS
// #define DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_NETWORK_ADMINISTRATION_DATA
// #define DLMS_IGNORE_PRIME_NB_OFDM_PLC_APPLICATIONS_IDENTIFICATION
// #define DLMS_IGNORE_ARBITRATOR
// #define DLMS_IGNORE_G3_PLC_MAC_LAYER_COUNTERS
// #define DLMS_IGNORE_G3_PLC_MAC_SETUP
// #define DLMS_IGNORE_G3_PLC_6LO_WPAN
// #define DLMS_IGNORE_FUNCTION_CONTROL
// #define DLMS_IGNORE_ARRAY_MANAGER
// #define DLMS_IGNORE_MALLOC
// #define DLMS_USE_CUSTOM_MALLOC
// #define DLMS_IGNORE_OBJECT_POINTERS
// #define DLMS_IGNORE_FLOAT32
// #define DLMS_IGNORE_FLOAT64
//Use EPOCH time. This can be used to improve memory usage.
// #define DLMS_USE_EPOCH_TIME
//Use UTC time zone. Read more: https://www.gurux.fi/Gurux.DLMS.Objects.GXDLMSClock
// #define DLMS_USE_UTC_TIME_ZONE
// #define DLMS_IGNORE_SET
// #define DLMS_IGNORE_ACTION
// String converters are not used.
// #define DLMS_IGNORE_STRING_CONVERTER
//Framework send debug information that can be used in debugging.
// #define DLMS_DEBUG
//Defined if AVR is used.
// #define USE_AVR
//Defined if program memory (flash) is used instead of SRAM.
// #define USE_PROGMEM
// COSEM objects are using DLMS standard data types.
// Using exact data types will save memory, but reading failes if meter returns wrong data type,
// ex. Int8 when data type should be UInt8.
// #define DLMS_COSEM_EXACT_DATA_TYPES
// If innovation counter size is UInt64 and not default UInt32.
// #define DLMS_COSEM_INVOCATION_COUNTER_SIZE64
// Use 32 bit max size bytebuffer instead of 16 bit.
// This might be used in client side if a lot of data is read from the meter.
// #define GX_DLMS_BYTE_BUFFER_SIZE_32
//Serializer is not used.
//DLMS_IGNORE_SERIALIZER
//Serializer is used instead of file system.
//#define GX_DLMS_SERIALIZER
//GENERAL_CIPHERING is not used.
//#define DLMS_IGNORE_GENERAL_CIPHERING
/**
* Ignore HDLC Control field check.
Some meters are sending invalid control field.
Note! It's not recommended to use this.
*/
//#define DLMS_IGNORE_HDLC_CHECK
// #define DLMS_ITALIAN_STANDARD
// #define DLMS_INDONESIA_STANDARD
#ifdef ARDUINO
/////////////////////////////////////////////////////////////////////////////
//If Arduino is used.
#include "ArduinoIgnore.h"
/////////////////////////////////////////////////////////////////////////////
#endif //ARDUINO
#ifdef ARDUINO_ARCH_AVR
/////////////////////////////////////////////////////////////////////////////
//If Arduino is used.
#include "ArduinoIgnore.h"
#define DLMS_IGNORE_IP6_SETUP
#define DLMS_USE_EPOCH_TIME
#define DLMS_IGNORE_NOTIFY
#define GX_DLMS_MICROCONTROLLER
#define DLMS_IGNORE_HIGH_SHA256
#define DLMS_IGNORE_HIGH_SHA1
#define DLMS_IGNORE_HIGH_MD5
#define USE_PROGMEM
/////////////////////////////////////////////////////////////////////////////
#endif //ARDUINO_ARCH_AVR
#ifdef ARDUINO_ARCH_ESP32
/////////////////////////////////////////////////////////////////////////////
//If Arduino ESP32 is used.
#include "ArduinoIgnore.h"
#define DLMS_IGNORE_IP6_SETUP
#define DLMS_USE_EPOCH_TIME
#define DLMS_IGNORE_NOTIFY
#define GX_DLMS_MICROCONTROLLER
#define DLMS_IGNORE_HIGH_SHA256
#define DLMS_IGNORE_HIGH_SHA1
#define DLMS_IGNORE_HIGH_MD5
/////////////////////////////////////////////////////////////////////////////
#endif //ARDUINO_ARCH_ESP32
#ifdef ARDUINO_ARCH_ESP8266
/////////////////////////////////////////////////////////////////////////////
//If Arduino ESP is used.
#include "ArduinoIgnore.h"
#ifndef ESP_PLATFORM
#define ESP_PLATFORM
#endif
#define DLMS_IGNORE_IP6_SETUP
#define DLMS_USE_EPOCH_TIME
#define DLMS_IGNORE_NOTIFY
#define GX_DLMS_MICROCONTROLLER
#define DLMS_IGNORE_HIGH_SHA256
#define DLMS_IGNORE_HIGH_SHA1
#define DLMS_IGNORE_HIGH_MD5
/////////////////////////////////////////////////////////////////////////////
#endif //ARDUINO_ARCH_ESP8266
#ifdef USE_ESP32_FRAMEWORK_ESP_IDF
#include "ArduinoIgnore.h"
#ifndef ESP_PLATFORM
#define ESP_PLATFORM
#endif
#define DLMS_IGNORE_IP6_SETUP
#define DLMS_USE_EPOCH_TIME
#define DLMS_IGNORE_NOTIFY
#define DLMS_IGNORE_FUNCTION_CONTROL
#define GX_DLMS_MICROCONTROLLER
#define DLMS_IGNORE_HIGH_SHA256
#define DLMS_IGNORE_HIGH_SHA1
#define DLMS_IGNORE_HIGH_MD5
#endif
#ifdef __cplusplus
}
#endif
#endif //GXIGNORE_H

65
components/xt211/gxint.h Normal file
View File

@ -0,0 +1,65 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef GXINT_H
#define GXINT_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#if !(defined uint16_t) && !(defined _UINT16_T_DECLARED)
#define uint16_t unsigned short
#endif //!(defined uint16_t) && !(defined _UINT16_T_DECLARED)
#if !(defined uint32_t) && !(defined _UINT32_T_DECLARED)
#define uint32_t unsigned long
#endif //!(defined uint32_t) && !(defined _UINT32_T_DECLARED)
#if !(defined uint64_t) && !(defined _UINT64_T_DECLARED)
#define uint64_t unsigned long long
#endif //#!(defined uint64_t) && !(defined _UINT64_T_DECLARED)
#if !(defined int16_t) && !(defined _INT16_T_DECLARED)
#define int16_t short
#endif //!(defined int16_t) && !(defined _INT16_T_DECLARED)
#if !(defined int32_t) && !(defined _INT32_T_DECLARED)
#define int32_t long
#endif //!(defined int32_t) && !(defined _INT32_T_DECLARED)
#if !(defined int64_t) && !(defined _INT64_T_DECLARED)
#define int64_t long long
#endif //!(defined int64_t) && !(defined _INT64_T_DECLARED)
#ifdef __cplusplus
}
#endif
#endif //GXINT_H

57
components/xt211/gxkey.c Normal file
View File

@ -0,0 +1,57 @@
//
// --------------------------------------------------------------------------
// 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 "gxmem.h"
#include "gxkey.h"
#ifndef DLMS_IGNORE_MALLOC
gxKey* key_init(void* key, void* value)
{
gxKey* obj = (gxKey*) gxmalloc(sizeof(gxKey));
if (obj != NULL)
{
obj->key = key;
obj->value = value;
}
return obj;
}
gxKey2* key_init2(unsigned char key, void* value)
{
gxKey2* obj = (gxKey2*)gxmalloc(sizeof(gxKey2));
if (obj != NULL)
{
obj->key = key;
obj->value = value;
}
return obj;
}
#endif //DLMS_IGNORE_MALLOC

60
components/xt211/gxkey.h Normal file
View File

@ -0,0 +1,60 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef GXKEY_H
#define GXKEY_H
#include "gxignore.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef DLMS_IGNORE_MALLOC
typedef struct {
void *key;
void *value;
} gxKey;
typedef struct {
unsigned char key;
void *value;
} gxKey2;
//Make key.
gxKey* key_init(void* key, void* value);
gxKey2* key_init2(unsigned char key, void* value);
#endif //DLMS_IGNORE_MALLOC
#ifdef __cplusplus
}
#endif
#endif //GXKEY_H

68
components/xt211/gxmem.h Normal file
View File

@ -0,0 +1,68 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef GX_MEM
#define GX_MEM
#include "gxignore.h"
#if !defined(DLMS_USE_CUSTOM_MALLOC) && !defined(DLMS_IGNORE_MALLOC)
#ifdef __cplusplus
extern "C" {
#endif
#include <stdlib.h> // malloc and free needs this or error is generated.
#if _MSC_VER > 1400
#include <crtdbg.h>
#endif
#ifndef gxfree
#define gxfree(p) free(p)
#endif
#ifndef gxmalloc
#define gxmalloc(s) malloc(s)
#endif
#ifndef gxcalloc
#define gxcalloc(p, s) calloc(p, s)
#endif
#ifndef gxrealloc
#define gxrealloc(p, s) realloc(p, s)
#endif
#ifdef __cplusplus
}
#endif
#endif //!defined(DLMS_USE_CUSTOM_MALLOC) && !defined(DLMS_IGNORE_MALLOC)
#endif //GX_MEM

2162
components/xt211/gxobjects.c Normal file

File diff suppressed because it is too large Load Diff

4299
components/xt211/gxobjects.h Normal file

File diff suppressed because it is too large Load Diff

472
components/xt211/gxset.c Normal file
View File

@ -0,0 +1,472 @@
//
// --------------------------------------------------------------------------
// 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(_WIN32) || defined(_WIN64) || defined(__linux__)
#include <assert.h>
#endif
#include "gxmem.h"
#if _MSC_VER > 1400
#include <crtdbg.h>
#endif
#include "gxset.h"
#include "cosem.h"
int cosem_setValue(dlmsSettings* settings, gxValueEventArg* e)
{
int ret = DLMS_ERROR_CODE_OK;
if (e->index == 1)
{
#if defined(DLMS_IGNORE_MALLOC) || defined(DLMS_COSEM_EXACT_DATA_TYPES)
ret = cosem_getOctetString2(e->value.byteArr, e->target->logicalName, 6, NULL);
#else
if (e->value.byteArr == NULL || e->value.byteArr->size - e->value.byteArr->position != 6)
{
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
}
else
{
ret = bb_get(e->value.byteArr, e->target->logicalName, 6);
}
#endif //DLMS_IGNORE_MALLOC
return ret;
}
switch (e->target->objectType)
{
#ifndef DLMS_IGNORE_DATA
case DLMS_OBJECT_TYPE_DATA:
ret = cosem_setData(e);
break;
#endif //DLMS_IGNORE_DATA
#ifndef DLMS_IGNORE_REGISTER
case DLMS_OBJECT_TYPE_REGISTER:
ret = cosem_setRegister((gxRegister*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_REGISTER
#ifndef DLMS_IGNORE_CLOCK
case DLMS_OBJECT_TYPE_CLOCK:
ret = cosem_setClock(settings, (gxClock*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_CLOCK
#ifndef DLMS_IGNORE_ACTION_SCHEDULE
case DLMS_OBJECT_TYPE_ACTION_SCHEDULE:
ret = cosem_setActionSchedule(settings, (gxActionSchedule*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_ACTION_SCHEDULE
#ifndef DLMS_IGNORE_ACTIVITY_CALENDAR
case DLMS_OBJECT_TYPE_ACTIVITY_CALENDAR:
ret = cosem_setActivityCalendar(settings, (gxActivityCalendar*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_ACTIVITY_CALENDAR
#ifndef DLMS_IGNORE_ASSOCIATION_LOGICAL_NAME
case DLMS_OBJECT_TYPE_ASSOCIATION_LOGICAL_NAME:
ret = cosem_setAssociationLogicalName(settings, (gxAssociationLogicalName*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_ASSOCIATION_LOGICAL_NAME
#ifndef DLMS_IGNORE_ASSOCIATION_SHORT_NAME
case DLMS_OBJECT_TYPE_ASSOCIATION_SHORT_NAME:
ret = cosem_setAssociationShortName(settings, (gxAssociationShortName*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_ASSOCIATION_SHORT_NAME
#ifndef DLMS_IGNORE_AUTO_ANSWER
case DLMS_OBJECT_TYPE_AUTO_ANSWER:
ret = cosem_setAutoAnswer((gxAutoAnswer*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_AUTO_ANSWER
#ifndef DLMS_IGNORE_AUTO_CONNECT
case DLMS_OBJECT_TYPE_AUTO_CONNECT:
ret = cosem_setAutoConnect((gxAutoConnect*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_AUTO_CONNECT
#ifndef DLMS_IGNORE_DEMAND_REGISTER
case DLMS_OBJECT_TYPE_DEMAND_REGISTER:
ret = cosem_setDemandRegister((gxDemandRegister*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_DEMAND_REGISTER
#ifndef DLMS_IGNORE_MAC_ADDRESS_SETUP
case DLMS_OBJECT_TYPE_MAC_ADDRESS_SETUP:
ret = cosem_setMacAddressSetup((gxMacAddressSetup*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_MAC_ADDRESS_SETUP
#ifndef DLMS_IGNORE_EXTENDED_REGISTER
case DLMS_OBJECT_TYPE_EXTENDED_REGISTER:
ret = cosem_setExtendedRegister((gxExtendedRegister*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_EXTENDED_REGISTER
#ifndef DLMS_IGNORE_GPRS_SETUP
case DLMS_OBJECT_TYPE_GPRS_SETUP:
ret = cosem_setGprsSetup((gxGPRSSetup*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_GPRS_SETUP
#ifndef DLMS_IGNORE_SECURITY_SETUP
case DLMS_OBJECT_TYPE_SECURITY_SETUP:
ret = cosem_setSecuritySetup(settings, (gxSecuritySetup*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_SECURITY_SETUP
#ifndef DLMS_IGNORE_IEC_HDLC_SETUP
case DLMS_OBJECT_TYPE_IEC_HDLC_SETUP:
ret = cosem_setIecHdlcSetup((gxIecHdlcSetup*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_IEC_HDLC_SETUP
#ifndef DLMS_IGNORE_IEC_LOCAL_PORT_SETUP
case DLMS_OBJECT_TYPE_IEC_LOCAL_PORT_SETUP:
ret = cosem_setIecLocalPortSetup((gxLocalPortSetup*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_IEC_LOCAL_PORT_SETUP
#ifndef DLMS_IGNORE_IEC_TWISTED_PAIR_SETUP
case DLMS_OBJECT_TYPE_IEC_TWISTED_PAIR_SETUP:
ret = cosem_setIecTwistedPairSetup((gxIecTwistedPairSetup*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_IEC_TWISTED_PAIR_SETUP
#ifndef DLMS_IGNORE_IP4_SETUP
case DLMS_OBJECT_TYPE_IP4_SETUP:
ret = cosem_setIP4Setup(settings, (gxIp4Setup*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_IP4_SETUP
#ifndef DLMS_IGNORE_IP6_SETUP
case DLMS_OBJECT_TYPE_IP6_SETUP:
ret = cosem_setIP6Setup(settings, (gxIp6Setup*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_IP6_SETUP
#ifndef DLMS_IGNORE_MBUS_SLAVE_PORT_SETUP
case DLMS_OBJECT_TYPE_MBUS_SLAVE_PORT_SETUP:
ret = cosem_setMbusSlavePortSetup((gxMbusSlavePortSetup*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_MBUS_SLAVE_PORT_SETUP
#ifndef DLMS_IGNORE_IMAGE_TRANSFER
case DLMS_OBJECT_TYPE_IMAGE_TRANSFER:
ret = cosem_setImageTransfer((gxImageTransfer*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_IMAGE_TRANSFER
#ifndef DLMS_IGNORE_DISCONNECT_CONTROL
case DLMS_OBJECT_TYPE_DISCONNECT_CONTROL:
ret = cosem_setDisconnectControl((gxDisconnectControl*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_DISCONNECT_CONTROL
#ifndef DLMS_IGNORE_LIMITER
case DLMS_OBJECT_TYPE_LIMITER:
ret = cosem_setLimiter(settings, (gxLimiter*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_LIMITER
#ifndef DLMS_IGNORE_MBUS_CLIENT
case DLMS_OBJECT_TYPE_MBUS_CLIENT:
ret = cosem_setmMbusClient(settings, (gxMBusClient*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_MBUS_CLIENT
#ifndef DLMS_IGNORE_MODEM_CONFIGURATION
case DLMS_OBJECT_TYPE_MODEM_CONFIGURATION:
ret = cosem_setModemConfiguration((gxModemConfiguration*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_MODEM_CONFIGURATION
#ifndef DLMS_IGNORE_PPP_SETUP
case DLMS_OBJECT_TYPE_PPP_SETUP:
ret = cosem_setPppSetup(settings, (gxPppSetup*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_PPP_SETUP
#ifndef DLMS_IGNORE_PROFILE_GENERIC
case DLMS_OBJECT_TYPE_PROFILE_GENERIC:
ret = cosem_setProfileGeneric(settings, (gxProfileGeneric*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_PROFILE_GENERIC
#ifndef DLMS_IGNORE_REGISTER_ACTIVATION
case DLMS_OBJECT_TYPE_REGISTER_ACTIVATION:
ret = cosem_setRegisterActivation(settings, e);
break;
#endif //DLMS_IGNORE_REGISTER_ACTIVATION
#ifndef DLMS_IGNORE_REGISTER_MONITOR
case DLMS_OBJECT_TYPE_REGISTER_MONITOR:
ret = cosem_setRegisterMonitor(settings, (gxRegisterMonitor*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_REGISTER_MONITOR
#ifndef DLMS_IGNORE_REGISTER_TABLE
case DLMS_OBJECT_TYPE_REGISTER_TABLE:
ret = cosem_setRegistertable((gxRegisterTable*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_REGISTER_TABLE
#ifndef DLMS_IGNORE_ZIG_BEE_SAS_STARTUP
case DLMS_OBJECT_TYPE_ZIG_BEE_SAS_STARTUP:
//TODO:
#if defined(_WIN32) || defined(_WIN64) || defined(__linux__)
assert(0);
#endif
break;
#endif //DLMS_IGNORE_ZIG_BEE_SAS_STARTUP
#ifndef DLMS_IGNORE_ZIG_BEE_SAS_JOIN
case DLMS_OBJECT_TYPE_ZIG_BEE_SAS_JOIN:
//TODO:
#if defined(_WIN32) || defined(_WIN64) || defined(__linux__)
assert(0);
#endif
break;
#endif //DLMS_IGNORE_ZIG_BEE_SAS_JOIN
#ifndef DLMS_IGNORE_ZIG_BEE_SAS_APS_FRAGMENTATION
case DLMS_OBJECT_TYPE_ZIG_BEE_SAS_APS_FRAGMENTATION:
//TODO:
#if defined(_WIN32) || defined(_WIN64) || defined(__linux__)
assert(0);
#endif
break;
#endif //DLMS_IGNORE_ZIG_BEE_SAS_APS_FRAGMENTATION
#ifndef DLMS_IGNORE_ZIG_BEE_NETWORK_CONTROL
case DLMS_OBJECT_TYPE_ZIG_BEE_NETWORK_CONTROL:
//TODO:
#if defined(_WIN32) || defined(_WIN64) || defined(__linux__)
assert(0);
#endif
break;
#endif //DLMS_IGNORE_ZIG_BEE_NETWORK_CONTROL
#ifndef DLMS_IGNORE_SAP_ASSIGNMENT
case DLMS_OBJECT_TYPE_SAP_ASSIGNMENT:
ret = cosem_setSapAssignment((gxSapAssignment*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_SAP_ASSIGNMENT
#ifndef DLMS_IGNORE_SCHEDULE
case DLMS_OBJECT_TYPE_SCHEDULE:
ret = cosem_setSchedule(settings, (gxSchedule*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_SCHEDULE
#ifndef DLMS_IGNORE_SCRIPT_TABLE
case DLMS_OBJECT_TYPE_SCRIPT_TABLE:
ret = cosem_setScriptTable(settings, (gxScriptTable*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_SCRIPT_TABLE
#ifndef DLMS_IGNORE_SPECIAL_DAYS_TABLE
case DLMS_OBJECT_TYPE_SPECIAL_DAYS_TABLE:
ret = cosem_setSpecialDaysTable((gxSpecialDaysTable*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_SPECIAL_DAYS_TABLE
#ifndef DLMS_IGNORE_STATUS_MAPPING
case DLMS_OBJECT_TYPE_STATUS_MAPPING:
//TODO:
#if defined(_WIN32) || defined(_WIN64) || defined(__linux__)
assert(0);
#endif
break;
#endif //DLMS_IGNORE_STATUS_MAPPING
#ifndef DLMS_IGNORE_TCP_UDP_SETUP
case DLMS_OBJECT_TYPE_TCP_UDP_SETUP:
ret = cosem_setTcpUdpSetup(settings, (gxTcpUdpSetup*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_TCP_UDP_SETUP
#ifndef DLMS_IGNORE_MBUS_DIAGNOSTIC
case DLMS_OBJECT_TYPE_MBUS_DIAGNOSTIC:
ret = cosem_setMbusDiagnostic((gxMbusDiagnostic*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_MBUS_DIAGNOSTIC
#ifndef DLMS_IGNORE_MBUS_PORT_SETUP
case DLMS_OBJECT_TYPE_MBUS_PORT_SETUP:
ret = cosem_setMbusPortSetup((gxMBusPortSetup*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_MBUS_PORT_SETUP
#ifndef DLMS_IGNORE_G3_PLC_MAC_LAYER_COUNTERS
case DLMS_OBJECT_TYPE_G3_PLC_MAC_LAYER_COUNTERS:
ret = cosem_setG3PlcMacLayerCounters((gxG3PlcMacLayerCounters*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_G3_PLC_MAC_LAYER_COUNTERS
#ifndef DLMS_IGNORE_G3_PLC_MAC_SETUP
case DLMS_OBJECT_TYPE_G3_PLC_MAC_SETUP:
ret = cosem_setG3PlcMacSetup((gxG3PlcMacSetup*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_G3_PLC_MAC_SETUP
#ifndef DLMS_IGNORE_G3_PLC_6LO_WPAN
case DLMS_OBJECT_TYPE_G3_PLC_6LO_WPAN:
ret = cosem_setG3Plc6LoWPAN((gxG3Plc6LoWPAN*)e->target,
e->index, &e->value);
break;
#endif //DLMS_IGNORE_G3_PLC_6LO_WPAN
#ifndef DLMS_IGNORE_FUNCTION_CONTROL
case DLMS_OBJECT_TYPE_FUNCTION_CONTROL:
ret = cosem_setFunctionControl(settings,
(gxFunctionControl*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_FUNCTION_CONTROL
#ifndef DLMS_IGNORE_ARRAY_MANAGER
case DLMS_OBJECT_TYPE_ARRAY_MANAGER:
ret = cosem_setArrayManager(settings,
(gxArrayManager*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_ARRAY_MANAGER
#ifndef DLMS_IGNORE_UTILITY_TABLES
case DLMS_OBJECT_TYPE_UTILITY_TABLES:
ret = cosem_setUtilityTables((gxUtilityTables*)e->target,
e->index, &e->value);
break;
#endif //DLMS_IGNORE_UTILITY_TABLES
#ifndef DLMS_IGNORE_MBUS_MASTER_PORT_SETUP
case DLMS_OBJECT_TYPE_MBUS_MASTER_PORT_SETUP:
ret = cosem_setMbusMasterPortSetup((gxMBusMasterPortSetup*)e->target,
e->index, &e->value);
break;
#endif //DLMS_IGNORE_MBUS_MASTER_PORT_SETUP
#ifndef DLMS_IGNORE_PUSH_SETUP
case DLMS_OBJECT_TYPE_PUSH_SETUP:
ret = cosem_setPushSetup(settings, (gxPushSetup*)e->target,
e->index, &e->value);
break;
#endif //DLMS_IGNORE_PUSH_SETUP
#ifndef DLMS_IGNORE_DATA_PROTECTION
case DLMS_OBJECT_TYPE_DATA_PROTECTION:
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
#if defined(_WIN32) || defined(_WIN64) || defined(__linux__)
assert(0);
#endif
break;
#endif //DLMS_IGNORE_DATA_PROTECTION
#ifndef DLMS_IGNORE_ACCOUNT
case DLMS_OBJECT_TYPE_ACCOUNT:
ret = cosem_setAccount((gxAccount*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_ACCOUNT
#ifndef DLMS_IGNORE_CREDIT
case DLMS_OBJECT_TYPE_CREDIT:
ret = cosem_setCredit((gxCredit*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_CREDIT
#ifndef DLMS_IGNORE_CHARGE
case DLMS_OBJECT_TYPE_CHARGE:
ret = cosem_setCharge(settings, (gxCharge*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_CHARGE
#ifndef DLMS_IGNORE_TOKEN_GATEWAY
case DLMS_OBJECT_TYPE_TOKEN_GATEWAY:
ret = cosem_setTokenGateway((gxTokenGateway*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_TOKEN_GATEWAY
#ifndef DLMS_IGNORE_GSM_DIAGNOSTIC
case DLMS_OBJECT_TYPE_GSM_DIAGNOSTIC:
ret = cosem_setGsmDiagnostic((gxGsmDiagnostic*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_GSM_DIAGNOSTIC
#ifndef DLMS_IGNORE_COMPACT_DATA
case DLMS_OBJECT_TYPE_COMPACT_DATA:
ret = cosem_setCompactData(settings, (gxCompactData*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_COMPACT_DATA
#ifndef DLMS_IGNORE_PARAMETER_MONITOR
case DLMS_OBJECT_TYPE_PARAMETER_MONITOR:
ret = cosem_setParameterMonitor(settings, (gxParameterMonitor*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_PARAMETER_MONITOR
#ifndef DLMS_IGNORE_LLC_SSCS_SETUP
case DLMS_OBJECT_TYPE_LLC_SSCS_SETUP:
ret = cosem_setLlcSscsSetup(settings, (gxLlcSscsSetup*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_LLC_SSCS_SETUP
#ifndef DLMS_IGNORE_PRIME_NB_OFDM_PLC_PHYSICAL_LAYER_COUNTERS
case DLMS_OBJECT_TYPE_PRIME_NB_OFDM_PLC_PHYSICAL_LAYER_COUNTERS:
ret = cosem_setPrimeNbOfdmPlcPhysicalLayerCounters(settings, (gxPrimeNbOfdmPlcPhysicalLayerCounters*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_PRIME_NB_OFDM_PLC_PHYSICAL_LAYER_COUNTERS
#ifndef DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_SETUP
case DLMS_OBJECT_TYPE_PRIME_NB_OFDM_PLC_MAC_SETUP:
ret = cosem_setPrimeNbOfdmPlcMacSetup(settings, (gxPrimeNbOfdmPlcMacSetup*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_SETUP
#ifndef DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_FUNCTIONAL_PARAMETERS
case DLMS_OBJECT_TYPE_PRIME_NB_OFDM_PLC_MAC_FUNCTIONAL_PARAMETERS:
ret = cosem_setPrimeNbOfdmPlcMacFunctionalParameters(settings, (gxPrimeNbOfdmPlcMacFunctionalParameters*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_FUNCTIONAL_PARAMETERS
#ifndef DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_COUNTERS
case DLMS_OBJECT_TYPE_PRIME_NB_OFDM_PLC_MAC_COUNTERS:
ret = cosem_setPrimeNbOfdmPlcMacCounters(settings, (gxPrimeNbOfdmPlcMacCounters*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_COUNTERS
#ifndef DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_NETWORK_ADMINISTRATION_DATA
case DLMS_OBJECT_TYPE_PRIME_NB_OFDM_PLC_MAC_NETWORK_ADMINISTRATION_DATA:
ret = cosem_setPrimeNbOfdmPlcMacNetworkAdministrationData(settings, (gxPrimeNbOfdmPlcMacNetworkAdministrationData*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_NETWORK_ADMINISTRATION_DATA
#ifndef DLMS_IGNORE_PRIME_NB_OFDM_PLC_APPLICATIONS_IDENTIFICATION
case DLMS_OBJECT_TYPE_PRIME_NB_OFDM_PLC_APPLICATIONS_IDENTIFICATION:
ret = cosem_setPrimeNbOfdmPlcApplicationsIdentification(settings, (gxPrimeNbOfdmPlcApplicationsIdentification*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_PRIME_NB_OFDM_PLC_APPLICATIONS_IDENTIFICATION
#ifndef DLMS_IGNORE_ARBITRATOR
case DLMS_OBJECT_TYPE_ARBITRATOR:
ret = cosem_setArbitrator(settings, (gxArbitrator*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_ARBITRATOR
#ifndef DLMS_IGNORE_IEC_8802_LLC_TYPE1_SETUP
case DLMS_OBJECT_TYPE_IEC_8802_LLC_TYPE1_SETUP:
ret = cosem_setIec8802LlcType1Setup(settings, (gxIec8802LlcType1Setup*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_IEC_8802_LLC_TYPE1_SETUP
#ifndef DLMS_IGNORE_IEC_8802_LLC_TYPE2_SETUP
case DLMS_OBJECT_TYPE_IEC_8802_LLC_TYPE2_SETUP:
ret = cosem_setIec8802LlcType2Setup(settings, (gxIec8802LlcType2Setup*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_IEC_8802_LLC_TYPE2_SETUP
#ifndef DLMS_IGNORE_IEC_8802_LLC_TYPE3_SETUP
case DLMS_OBJECT_TYPE_IEC_8802_LLC_TYPE3_SETUP:
ret = cosem_setIec8802LlcType3Setup(settings, (gxIec8802LlcType3Setup*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_IEC_8802_LLC_TYPE3_SETUP
#ifndef DLMS_IGNORE_SFSK_ACTIVE_INITIATOR
case DLMS_OBJECT_TYPE_SFSK_ACTIVE_INITIATOR:
ret = cosem_setSFSKActiveInitiator(settings, (gxSFSKActiveInitiator*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_SFSK_ACTIVE_INITIATOR
#ifndef DLMS_IGNORE_SFSK_MAC_COUNTERS
case DLMS_OBJECT_TYPE_SFSK_MAC_COUNTERS:
ret = cosem_setFSKMacCounters(settings, (gxFSKMacCounters*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_SFSK_MAC_COUNTERS
#ifndef DLMS_IGNORE_SFSK_MAC_SYNCHRONIZATION_TIMEOUTS
case DLMS_OBJECT_TYPE_SFSK_MAC_SYNCHRONIZATION_TIMEOUTS:
ret = cosem_setSFSKMacSynchronizationTimeouts(settings, (gxSFSKMacSynchronizationTimeouts*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_SFSK_MAC_SYNCHRONIZATION_TIMEOUTS
#ifndef DLMS_IGNORE_SFSK_PHY_MAC_SETUP
case DLMS_OBJECT_TYPE_SFSK_PHY_MAC_SETUP:
ret = cosem_setSFSKPhyMacSetUp(settings, (gxSFSKPhyMacSetUp*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_SFSK_PHY_MAC_SETUP
#ifndef DLMS_IGNORE_SFSK_REPORTING_SYSTEM_LIST
case DLMS_OBJECT_TYPE_SFSK_REPORTING_SYSTEM_LIST:
ret = cosem_setSFSKReportingSystemList(settings, (gxSFSKReportingSystemList*)e->target, e->index, &e->value);
break;
#endif //DLMS_IGNORE_SFSK_REPORTING_SYSTEM_LIST
#ifdef DLMS_ITALIAN_STANDARD
case DLMS_OBJECT_TYPE_TARIFF_PLAN:
ret = cosem_setTariffPlan((gxTariffPlan*)e->target, e->index, &e->value);
break;
#endif //DLMS_ITALIAN_STANDARD
default:
//Unknown type.
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
}
return ret;
}

57
components/xt211/gxset.h Normal file
View File

@ -0,0 +1,57 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef COSEM_SET_H
#define COSEM_SET_H
#ifdef __cplusplus
extern "C" {
#endif
#if defined(DLMS_IGNORE_MALLOC) || defined(DLMS_COSEM_EXACT_DATA_TYPES)
#include "gxsetignoremalloc.h"
#else
#include "gxsetmalloc.h"
#endif //DLMS_IGNORE_MALLOC
#include "gxobjects.h"
#include "dlmssettings.h"
int cosem_setValue(dlmsSettings* settings, gxValueEventArg *e);
/////////////////////////////////////////////////////////////////////////
// The season profile is sorted according to start date
// (in increasing order).
int cosem_orderSeasonProfile(gxArray* profile);
#ifdef __cplusplus
}
#endif
#endif//COSEM_SET_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,396 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef COSEM_SET_MALLOC_H
#define COSEM_SET_MALLOC_H
#include "gxignore.h"
#if !defined(DLMS_IGNORE_MALLOC) && !defined(DLMS_COSEM_EXACT_DATA_TYPES)
#ifdef __cplusplus
extern "C" {
#endif
#include "gxobjects.h"
#include "dlmssettings.h"
#ifndef DLMS_IGNORE_DATA
int cosem_setData(gxValueEventArg* e);
#endif //DLMS_IGNORE_DATA
#ifndef DLMS_IGNORE_REGISTER
int cosem_setRegister(gxRegister* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_REGISTER
#ifndef DLMS_IGNORE_CLOCK
int cosem_setClock(dlmsSettings* settings, gxClock* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_CLOCK
#ifndef DLMS_IGNORE_ACTION_SCHEDULE
int cosem_setActionSchedule(dlmsSettings* settings, gxActionSchedule* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_ACTION_SCHEDULE
#ifndef DLMS_IGNORE_ACTIVITY_CALENDAR
int cosem_setActivityCalendar(dlmsSettings* settings, gxActivityCalendar* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_ACTIVITY_CALENDAR
#ifndef DLMS_IGNORE_ASSOCIATION_LOGICAL_NAME
int cosem_parseLNObjects(dlmsSettings* settings, gxByteBuffer* data, objectArray* objects);
int cosem_setAssociationLogicalName(dlmsSettings* settings, gxAssociationLogicalName* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_ASSOCIATION_LOGICAL_NAME
#ifndef DLMS_IGNORE_ASSOCIATION_SHORT_NAME
int cosem_parseSNObjects(dlmsSettings* settings, gxByteBuffer* data, objectArray* objects);
int cosem_setAssociationShortName(dlmsSettings* settings, gxAssociationShortName* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_ASSOCIATION_SHORT_NAME
#ifndef DLMS_IGNORE_AUTO_ANSWER
int cosem_setAutoAnswer(gxAutoAnswer* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_AUTO_ANSWER
#ifndef DLMS_IGNORE_AUTO_CONNECT
int cosem_setAutoConnect(gxAutoConnect* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_AUTO_CONNECT
#ifndef DLMS_IGNORE_DEMAND_REGISTER
int cosem_setDemandRegister(gxDemandRegister* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_DEMAND_REGISTER
#ifndef DLMS_IGNORE_MAC_ADDRESS_SETUP
int cosem_setMacAddressSetup(gxMacAddressSetup* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_MAC_ADDRESS_SETUP
#ifndef DLMS_IGNORE_EXTENDED_REGISTER
int cosem_setExtendedRegister(gxExtendedRegister* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_EXTENDED_REGISTER
#ifndef DLMS_IGNORE_GPRS_SETUP
int cosem_setGprsSetup(gxGPRSSetup* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_GPRS_SETUP
#ifndef DLMS_IGNORE_SECURITY_SETUP
int cosem_setSecuritySetup(dlmsSettings* settings, gxSecuritySetup* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_SECURITY_SETUP
#ifndef DLMS_IGNORE_IEC_HDLC_SETUP
int cosem_setIecHdlcSetup(gxIecHdlcSetup* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_IEC_HDLC_SETUP
#ifndef DLMS_IGNORE_IEC_LOCAL_PORT_SETUP
int cosem_setIecLocalPortSetup(gxLocalPortSetup* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_IEC_LOCAL_PORT_SETUP
#ifndef DLMS_IGNORE_IP4_SETUP
int cosem_setIP4Setup(dlmsSettings* settings, gxIp4Setup* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_IP4_SETUP
#ifndef DLMS_IGNORE_PROFILE_GENERIC
int cosem_setProfileGeneric(dlmsSettings* settings, gxProfileGeneric* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_PROFILE_GENERIC
#ifndef DLMS_IGNORE_UTILITY_TABLES
int cosem_setUtilityTables(gxUtilityTables* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_UTILITY_TABLES
#ifndef DLMS_IGNORE_MBUS_SLAVE_PORT_SETUP
int cosem_setMbusSlavePortSetup(gxMbusSlavePortSetup* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_MBUS_SLAVE_PORT_SETUP
#ifndef DLMS_IGNORE_DISCONNECT_CONTROL
int cosem_setDisconnectControl(gxDisconnectControl* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_DISCONNECT_CONTROL
#ifndef DLMS_IGNORE_LIMITER
int cosem_setLimiter(dlmsSettings* settings, gxLimiter* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_LIMITER
#ifndef DLMS_IGNORE_MBUS_CLIENT
int cosem_setmMbusClient(dlmsSettings* settings, gxMBusClient* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_MBUS_CLIENT
#ifndef DLMS_IGNORE_MODEM_CONFIGURATION
int cosem_setModemConfiguration(gxModemConfiguration* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_MODEM_CONFIGURATION
#ifndef DLMS_IGNORE_PPP_SETUP
int cosem_setPppSetup(dlmsSettings* settings, gxPppSetup* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_PPP_SETUP
#ifndef DLMS_IGNORE_REGISTER_ACTIVATION
int cosem_setRegisterActivation(dlmsSettings* settings, gxValueEventArg* e);
#endif //DLMS_IGNORE_REGISTER_ACTIVATION
#ifndef DLMS_IGNORE_REGISTER_MONITOR
int cosem_setRegisterMonitor(dlmsSettings* settings, gxRegisterMonitor* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_REGISTER_MONITOR
#ifndef DLMS_IGNORE_SAP_ASSIGNMENT
int cosem_setSapAssignment(gxSapAssignment* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_SAP_ASSIGNMENT
#ifndef DLMS_IGNORE_SCHEDULE
int cosem_setSchedule(dlmsSettings* settings, gxSchedule* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_SCHEDULE
#ifndef DLMS_IGNORE_SCRIPT_TABLE
int cosem_setScriptTable(dlmsSettings* settings, gxScriptTable* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_SCRIPT_TABLE
#ifndef DLMS_IGNORE_SPECIAL_DAYS_TABLE
int cosem_setSpecialDaysTable(gxSpecialDaysTable* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_SPECIAL_DAYS_TABLE
#ifndef DLMS_IGNORE_TCP_UDP_SETUP
int cosem_setTcpUdpSetup(dlmsSettings* settings, gxTcpUdpSetup* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_TCP_UDP_SETUP
#ifndef DLMS_IGNORE_MBUS_DIAGNOSTIC
int cosem_setMbusDiagnostic(gxMbusDiagnostic* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_MBUS_DIAGNOSTIC
#ifndef DLMS_IGNORE_MBUS_PORT_SETUP
int cosem_setMbusPortSetup(gxMBusPortSetup* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_MBUS_PORT_SETUP
#ifndef DLMS_IGNORE_MBUS_MASTER_PORT_SETUP
int cosem_setMbusMasterPortSetup(gxMBusMasterPortSetup* object, unsigned char index, dlmsVARIANT* value);
#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);
#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);
#endif //DLMS_IGNORE_G3_PLC_MAC_SETUP
#ifndef DLMS_IGNORE_G3_PLC_6LO_WPAN
int cosem_setG3Plc6LoWPAN(gxG3Plc6LoWPAN* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_G3_PLC_6LO_WPAN
#ifndef DLMS_IGNORE_FUNCTION_CONTROL
int cosem_setFunctionControl(
dlmsSettings* settings,
gxFunctionControl* object,
unsigned char index,
dlmsVARIANT* value);
#endif //DLMS_IGNORE_FUNCTION_CONTROL
#ifndef DLMS_IGNORE_ARRAY_MANAGER
int cosem_setArrayManager(dlmsSettings* settings, gxArrayManager* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_ARRAY_MANAGER
#ifndef DLMS_IGNORE_PUSH_SETUP
int cosem_setPushSetup(dlmsSettings* settings, gxPushSetup* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_PUSH_SETUP
#ifndef DLMS_IGNORE_GSM_DIAGNOSTIC
int cosem_setGsmDiagnostic(gxGsmDiagnostic* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_GSM_DIAGNOSTIC
#ifndef DLMS_IGNORE_COMPACT_DATA
int compactData_updateTemplateDescription(
dlmsSettings* settings,
gxCompactData* object);
#endif //DLMS_IGNORE_COMPACT_DATA
#ifndef DLMS_IGNORE_IEC_TWISTED_PAIR_SETUP
int cosem_setIecTwistedPairSetup(gxIecTwistedPairSetup* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_IEC_TWISTED_PAIR_SETUP
#ifndef DLMS_IGNORE_IP6_SETUP
int cosem_setIP6Setup(dlmsSettings* settings, gxIp6Setup* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_IP6_SETUP
#ifndef DLMS_IGNORE_IMAGE_TRANSFER
int cosem_setImageTransfer(gxImageTransfer* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_IMAGE_TRANSFER
#ifndef DLMS_IGNORE_REGISTER_TABLE
int cosem_setRegistertable(gxRegisterTable* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_REGISTER_TABLE
#ifndef DLMS_IGNORE_ACCOUNT
int cosem_setAccount(gxAccount* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_ACCOUNT
#ifndef DLMS_IGNORE_CREDIT
int cosem_setCredit(gxCredit* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_CREDIT
#ifndef DLMS_IGNORE_CHARGE
int cosem_setCharge(dlmsSettings* settings, gxCharge* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_CHARGE
#ifndef DLMS_IGNORE_TOKEN_GATEWAY
int cosem_setTokenGateway(gxTokenGateway* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_TOKEN_GATEWAY
#ifndef DLMS_IGNORE_COMPACT_DATA
int cosem_setCompactData(
dlmsSettings* settings,
gxCompactData* object,
unsigned char index,
dlmsVARIANT* value);
#endif //DLMS_IGNORE_COMPACT_DATA
#ifndef DLMS_IGNORE_PARAMETER_MONITOR
int cosem_setParameterMonitor(
dlmsSettings* settings,
gxParameterMonitor* object,
unsigned char index,
dlmsVARIANT* value);
#endif //DLMS_IGNORE_PARAMETER_MONITOR
#ifndef DLMS_IGNORE_LLC_SSCS_SETUP
int cosem_setLlcSscsSetup(
dlmsSettings* settings,
gxLlcSscsSetup* object,
unsigned char index,
dlmsVARIANT* value);
#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);
#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);
#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);
#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);
#endif //DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_COUNTERS
#ifndef DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_NETWORK_ADMINISTRATION_DATA
int cosem_setPrimeNbOfdmPlcMacNetworkAdministrationData(
dlmsSettings* settings,
gxPrimeNbOfdmPlcMacNetworkAdministrationData* object,
unsigned char index,
dlmsVARIANT* value);
#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);
#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);
#endif //DLMS_IGNORE_ARBITRATOR
#ifndef DLMS_IGNORE_IEC_8802_LLC_TYPE1_SETUP
int cosem_setIec8802LlcType1Setup(
dlmsSettings* settings,
gxIec8802LlcType1Setup* object,
unsigned char index,
dlmsVARIANT* value);
#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);
#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);
#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);
#endif //DLMS_IGNORE_SFSK_ACTIVE_INITIATOR
#ifndef DLMS_IGNORE_SFSK_MAC_COUNTERS
int cosem_setFSKMacCounters(
dlmsSettings* settings,
gxFSKMacCounters* object,
unsigned char index,
dlmsVARIANT* value);
#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);
#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);
#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);
#endif //DLMS_IGNORE_SFSK_REPORTING_SYSTEM_LIST
#ifdef __cplusplus
}
#endif
#endif //!defined(DLMS_IGNORE_MALLOC) && !defined(DLMS_COSEM_EXACT_DATA_TYPES)
#endif//COSEM_SET_MALLOC_H

View File

@ -0,0 +1,178 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef VALUE_EVENT_ARG_H
#define VALUE_EVENT_ARG_H
#ifdef __cplusplus
extern "C" {
#endif
#include "gxignore.h"
#include "gxobjects.h"
#include "errorcodes.h"
typedef struct
{
/**
* CGXDLMSVariant value.
*/
dlmsVARIANT value;
#if !defined(DLMS_IGNORE_MALLOC) && !defined(DLMS_COSEM_EXACT_DATA_TYPES)
/**
* Data type of the value.
*/
DLMS_DATA_TYPE dataType;
#endif //!defined(DLMS_IGNORE_MALLOC) && !defined(DLMS_COSEM_EXACT_DATA_TYPES)
/**
* Is request handled.
*/
unsigned char handled;
/**
* Target DLMS object
*/
gxObject* target;
/**
* Attribute index.
*/
unsigned char index;
/**
* Optional selector.
*/
unsigned char selector;
/**
* Optional parameters.
*/
dlmsVARIANT parameters;
/**
* Occurred error.
*/
DLMS_ERROR_CODE error;
/**
* Is action. This is reserved for internal use.
*/
unsigned char action;
/**
* Is value added as byte array.
*/
unsigned char byteArray;
/**
* Is value max PDU size skipped.
*/
unsigned char skipMaxPduSize;
/**
* Transaction begin index.
*/
uint32_t transactionStartIndex;
/**
* Transaction end index.
*/
uint32_t transactionEndIndex;
//It this transaction.
uint16_t transaction;
} gxValueEventArg;
/**
* Initialize value event arg.
*/
void ve_init(
gxValueEventArg* ve);
/**
* Clear value event arg.
*/
void ve_clear(
gxValueEventArg* ve);
typedef struct
{
#ifdef DLMS_IGNORE_MALLOC
gxValueEventArg* data;
#else
gxValueEventArg** data;
#endif //DLMS_IGNORE_MALLOC
unsigned char capacity;
unsigned char size;
unsigned char position;
} gxValueEventCollection;
//Initialize value event collection.
void vec_init(
gxValueEventCollection* arr);
#ifdef DLMS_IGNORE_MALLOC
//Attach value event collection.
void vec_attach(
gxValueEventCollection* arr,
gxValueEventArg* value,
unsigned char count,
unsigned char capacity);
#endif //DLMS_IGNORE_MALLOC
/*
* Is static buffer used.
*/
char vec_isAttached(
gxValueEventCollection* arr);
//Bit array capacity.
unsigned char vec_getCapacity(
gxValueEventCollection* arr);
#ifndef DLMS_IGNORE_MALLOC
//Push new data to the value event collection.
int vec_push(
gxValueEventCollection* arr,
gxValueEventArg* item);
#endif //DLMS_IGNORE_MALLOC
//empty array, but items are not free.
void vec_empty(
gxValueEventCollection* arr);
//Clear array. All items are automatically free.
void vec_clear(
gxValueEventCollection* arr);
int vec_getByIndex(
gxValueEventCollection* arr,
int index,
gxValueEventArg** value);
#ifdef __cplusplus
}
#endif
#endif //VALUE_EVENT_ARG_H

1187
components/xt211/helpers.c Normal file

File diff suppressed because it is too large Load Diff

274
components/xt211/helpers.h Normal file
View File

@ -0,0 +1,274 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef GXHELPERS_H
#define GXHELPERS_H
#ifdef __cplusplus
extern "C" {
#endif
#include "gxignore.h"
#ifdef USE_AVR
//If AVR is used.
#include <avr/pgmspace.h>
#endif //USE_AVR
#include "bytebuffer.h"
#include "variant.h"
static const unsigned char EMPTY_SYSTEM_TITLE[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
static const unsigned char EMPTY_LN[6] = { 0, 0, 0, 0, 0, 0 };
static const unsigned char DEFAULT_ASSOCIATION[6] = { 0, 0, 40, 0, 0, 255 };
static const unsigned char EMPTY_KEY[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
//Get error message directly from EEPROM to save RAM.
#if defined(ARDUINO) || defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266)
//If AVR is used.
#ifdef IDF_VER//espressif is using the different folder.
#include <pgmspace.h>
#else
#include <avr/pgmspace.h>
#endif//ESP_PLATFORM
#define GET_STR_FROM_EEPROM(x) PSTR(x)
#else
#define GET_STR_FROM_EEPROM(x) (const char*)x
#endif//defined(ARDUINO) || defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266)
//Get UInt32.
#define GETU32(pt) (((uint32_t)(pt)[0] << 24) | \
((uint32_t)(pt)[1] << 16) | \
((uint32_t)(pt)[2] << 8) | \
((uint32_t)(pt)[3]))
//Set Int32 as Big Endian value.
#define PUT32(ct, st) { \
(ct)[0] = (unsigned char)((st) >> 24); \
(ct)[1] = (unsigned char)((st) >> 16); \
(ct)[2] = (unsigned char)((st) >> 8); \
(ct)[3] = (unsigned char)(st); }
//Check byte order.
unsigned char hlp_isBigEndian(void);
//Convert ASCII value to numeric unsigned char value.
unsigned char hlp_getValue(char c);
const char* hlp_getErrorMessage(int error);
//Returns items count. Use hlp_getObjectCount22.
int hlp_getObjectCount(gxByteBuffer* buff);
//Returns items count.
int hlp_getObjectCount2(
gxByteBuffer* buff,
uint16_t* count);
//Get count size in bytes.
unsigned char hlp_getObjectCountSizeInBytes(uint32_t count);
// Set count of items.
int hlp_setObjectCount(
uint32_t count,
gxByteBuffer* buff);
#ifndef DLMS_IGNORE_MALLOC
/**
* Convert byte array to hex string. This method use malloc to allocate enough memory.
*/
char* hlp_bytesToHex(const unsigned char* pBytes, int count);
#endif //DLMS_IGNORE_MALLOC
/**
* Convert byte array to hex string.
*/
int hlp_bytesToHex2(const unsigned char* bytes, uint16_t count, char* buff, uint16_t size);
#ifndef DLMS_IGNORE_MALLOC
/**
* Convert hex string to byte array. This method use malloc to allocate enough memory.
*/
int hlp_hexToBytes(
const char* str,
unsigned char** arr,
uint16_t* count);
#endif //DLMS_IGNORE_MALLOC
/**
* Convert hex string to byte array.
*/
int hlp_hexToBytes2(
const char* str,
unsigned char* arr,
uint16_t* count);
#if !defined(DLMS_IGNORE_MALLOC)
//Set logical name from string.
int hlp_setLogicalName(unsigned char ln[6], const char* name);
#endif //!defined(DLMS_IGNORE_MALLOC)
#if !defined(DLMS_IGNORE_STRING_CONVERTER) && !defined(DLMS_IGNORE_MALLOC)
void hlp_trace(unsigned char* data, int index, int count, unsigned char send);
//Get Logical Name from string.
int hlp_parseLogicalName(gxByteBuffer* value, unsigned char ln[6]);
//Set logical name from string.
int hlp_setLogicalName2(dlmsVARIANT* ln, const char* name);
int hlp_appendLogicalName(gxByteBuffer* bb, const unsigned char value[6]);
//Print logical name to cout.
int hlp_printLogicalName(
//Format.
const char* format,
//Logical name.
const unsigned char value[6]);
#endif //!defined(DLMS_IGNORE_STRING_CONVERTER) && !defined(DLMS_IGNORE_MALLOC)
int hlp_getLogicalNameToString(const unsigned char value[6], char* ln);
void hlp_replace(gxByteBuffer* str, char oldCh, char newCh);
double hlp_getScaler(int scaler);
/**
* Get data type in bytes.
*
* @param type
* Data type.
* @return Size of data type in bytes.
*/
int hlp_getDataTypeSize(DLMS_DATA_TYPE type);
/**
* Convert integer to string.
*
* @param str
* Parsed string.
* @param strsize
* String size.
* @param value
* Integer value.
* @param isSigned
* Is value signed number.
* @param digits
* number of digits in string.
* @return Length of the string or -1 if error has occurred.
*/
int hlp_intToString(
char* str,
int bufsize,
int32_t value,
unsigned char isSigned,
unsigned char digits);
/**
* Convert integer to string.
*
* @param str
* Parsed string.
* @param strsize
* String size.
* @param value
* Integer value.
* @param digits
* number of digits in string.
* @return Length of the string or -1 if error has occurred.
*/
int hlp_uint64ToString(
char* str,
int bufsize,
uint64_t value,
unsigned char digits);
/**
* Convert string to integer.
*
* @param str
* Parsed string.
* @return Value of string as integer.
*/
int32_t hlp_stringToInt(
const char* str);
/**
* Convert integer to string.
*
* @param str
* Parsed string.
* @param strsize
* String size.
* @param value
* Integer value.
* @param isSigned
* Is value signed number.
* @return Length of the string or -1 if error has occurred.
*/
int hlp_int64ToString(
char* str,
int bufsize,
int64_t value,
unsigned char isSigned);
/**
* Convert string to integer64.
*
* @param str
* Parsed string.
* @return Value of string as integer.
*/
int64_t hlp_stringToInt64(
const char* str);
/**
* Random generator using Linear-feedback shift register.
* https://en.wikipedia.org/wiki/Linear-feedback_shift_register
*
* @return Random number.
*/
unsigned char hlp_rand(void);
//Add bits from byte array to bit array.
int hlp_add(
bitArray* arr,
gxByteBuffer* bytes,
uint16_t count);
//Swap bits. Reserved for internal use.
unsigned char hlp_swapBits(unsigned char value);
#ifdef __cplusplus
}
#endif
#endif //GXHELPERS_H

View File

@ -0,0 +1,100 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef LN_PARAMETERS_H
#define LN_PARAMETERS_H
#ifdef __cplusplus
extern "C" {
#endif
#include "dlmssettings.h"
#include "bytebuffer.h"
#include "enums.h"
/**
* LN Parameters
*/
typedef struct
{
/**
* DLMS settings.
*/
dlmsSettings *settings;
/**
* DLMS command.
*/
DLMS_COMMAND command;
/**
* Request type.
*/
int requestType;
/**
* Attribute descriptor.
*/
gxByteBuffer attributeDescriptor;
/**
* Data.
*/
gxByteBuffer m_Data;
/**
* Send date and time. This is used in Data notification messages.
*/
#ifdef DLMS_USE_EPOCH_TIME
uint32_t time;
#else
struct tm time;
#endif //DLMS_USE_EPOCH_TIME
/**
* Reply status.
*/
int status;
/**
* Are there more data to send or more data to receive.
*/
unsigned char multipleBlocks;
/**
* Is this last block in send.
*/
unsigned char lastBlock;
/**
* Block index.
*/
int blockIndex;
} lnParameters;
#ifdef __cplusplus
}
#endif
#endif //LN_PARAMETERS_H

143
components/xt211/message.c Normal file
View File

@ -0,0 +1,143 @@
//
// --------------------------------------------------------------------------
// Gurux Ltd
//
//
//
// Filename: $HeadURL$
//
// Version: $Revision$,
// $Date$
// $Author$
//
// Copyright (c) Gurux Ltd
//
//---------------------------------------------------------------------------
//
// DESCRIPTION
//
// This file is a part of Gurux Device Framework.
//
// Gurux Device Framework is Open Source software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; version 2 of the License.
// Gurux Device Framework is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// This code is licensed under the GNU General Public License v2.
// Full text may be retrieved at http://www.gnu.org/licenses/gpl-2.0.txt
//---------------------------------------------------------------------------
#include "gxignore.h"
#ifndef DLMS_IGNORE_MALLOC
#include "gxmem.h"
#endif //DLMS_IGNORE_MALLOC
#if _MSC_VER > 1400
#include <crtdbg.h>
#endif
#include <string.h>
#include "message.h"
#include "errorcodes.h"
#ifndef DLMS_IGNORE_MALLOC
//Initialize gxByteBuffer.
void mes_init(message* mes)
{
mes->capacity = MESSAGE_CAPACITY;
mes->data = (gxByteBuffer**)gxmalloc(mes->capacity * sizeof(gxByteBuffer*));
mes->size = 0;
mes->attached = 0;
}
#endif //DLMS_IGNORE_MALLOC
void mes_attach(message* mes, gxByteBuffer** data, unsigned char capacity)
{
mes->capacity = capacity;
mes->data = data;
mes->size = 0;
#ifndef DLMS_IGNORE_MALLOC
mes->attached = 1;
#endif //DLMS_IGNORE_MALLOC
}
#ifndef DLMS_IGNORE_MALLOC
//Push new message.
int mes_push(message* mes, gxByteBuffer* item)
{
if (mes->size == mes->capacity)
{
if (mes->attached)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
mes->capacity += MESSAGE_CAPACITY;
if (mes->data == NULL)
{
mes->data = (gxByteBuffer**)gxmalloc(mes->capacity * sizeof(gxByteBuffer*));
if (mes->data == NULL)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
}
else
{
#ifdef gxrealloc
//If compiler supports realloc.
mes->data = (gxByteBuffer**)gxrealloc(mes->data, mes->capacity * sizeof(gxByteBuffer*));
if (mes->data == NULL)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
#else
//If compiler doesn't support realloc.
gxByteBuffer** old = mes->data;
mes->data = (gxByteBuffer**)gxmalloc(mes->capacity * sizeof(gxByteBuffer*));
//If not enought memory available.
if (mes->data == NULL)
{
mes->data = old;
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
memcpy(mes->data, old, sizeof(gxByteBuffer*) * mes->size);
gxfree(old);
#endif // gxrealloc
}
}
mes->data[mes->size] = item;
++mes->size;
return 0;
}
#endif //DLMS_IGNORE_MALLOC
void mes_clear(message* mes)
{
int pos;
#ifdef DLMS_IGNORE_MALLOC
for (pos = 0; pos != mes->capacity; ++pos)
{
mes->data[pos]->size = mes->data[pos]->position = 0;
}
#else
if (!mes->attached)
{
if (mes->size != 0)
{
for (pos = 0; pos != mes->size; ++pos)
{
gxfree(mes->data[pos]->data);
gxfree(mes->data[pos]);
}
}
if (mes->data != NULL)
{
gxfree(mes->data);
mes->data = NULL;
}
mes->capacity = 0;
}
#endif //DLMS_IGNORE_MALLOC
mes->size = 0;
}

View File

@ -0,0 +1,73 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef MESSAGE_H
#define MESSAGE_H
#include "gxignore.h"
#include "bytebuffer.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MESSAGE_CAPACITY 2
typedef struct
{
gxByteBuffer** data;
unsigned char capacity;
unsigned char size;
#ifndef DLMS_IGNORE_MALLOC
unsigned char attached;
#endif //DLMS_IGNORE_MALLOC
} message;
#ifndef DLMS_IGNORE_MALLOC
//Initialize gxByteBuffer.
void mes_init(message* mes);
//Push new message.
int mes_push(
message* mes,
gxByteBuffer* item);
#endif //DLMS_IGNORE_MALLOC
void mes_attach(message* mes, gxByteBuffer** data, unsigned char capacity);
//Clear message list.
void mes_clear(
message* mes);
#ifdef __cplusplus
}
#endif
#endif //MESSAGE_H

View File

@ -0,0 +1,12 @@
#include "object_locker.h"
namespace esphome {
namespace xt211 {
std::vector<void *> AnyObjectLocker::locked_objects_(5);
Mutex AnyObjectLocker::lock_;
// unlock() function removed
}; // namespace xt211
}; // namespace esphome

View File

@ -0,0 +1,32 @@
#pragma once
#include "esphome/core/log.h"
#include "esphome/core/helpers.h"
#include <algorithm>
#include <vector>
namespace esphome {
namespace xt211 {
class AnyObjectLocker {
public:
static bool try_lock(void *obj) {
if (!lock_.try_lock()) {
return false;
}
bool result = false;
if (std::find(locked_objects_.begin(), locked_objects_.end(), obj) == locked_objects_.end()) {
locked_objects_.push_back(obj);
result = true;
}
lock_.unlock();
return result;
}
// unlock() function removed to enforce read-only/no-session-release
private:
static std::vector<void *> locked_objects_;
static Mutex lock_;
};
}; // namespace xt211
}; // namespace esphome

View File

@ -0,0 +1,446 @@
//
// --------------------------------------------------------------------------
// 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 "gxmem.h"
#if _MSC_VER > 1400
#include <crtdbg.h>
#endif
#if defined(_WIN64) || defined(_WIN32) || defined(__linux__)
#include <stdio.h>
#endif //defined(_WIN64) || defined(_WIN32) || defined(__linux__)
#include <string.h>
#include "objectarray.h"
#include "helpers.h"
#if defined(_WIN64) || defined(_WIN32) || defined(__linux__)
#include <stdio.h>
#include "helpers.h"
#endif //defined(_WIN64) || defined(_WIN32) || defined(__linux__)
//Initialize objectArray.
void oa_init(objectArray* arr)
{
arr->capacity = 0;
arr->data = NULL;
#if !(defined(GX_DLMS_MICROCONTROLLER) || defined(DLMS_IGNORE_MALLOC))
arr->position = 0;
#endif //!(defined(GX_DLMS_MICROCONTROLLER) || defined(DLMS_IGNORE_MALLOC))
arr->size = 0;
}
char oa_isAttached(objectArray* arr)
{
return (arr->capacity & 0x8000) == 0x8000;
}
uint16_t oa_getCapacity(objectArray* arr)
{
return arr->capacity & 0x7FFF;
}
//Allocate new size for the array in bytes.
int oa_capacity(objectArray* arr, const uint16_t capacity)
{
#ifndef DLMS_IGNORE_MALLOC
if (!oa_isAttached(arr))
{
arr->capacity = capacity;
if (arr->data == NULL)
{
arr->data = (gxObject**)gxmalloc(arr->capacity * sizeof(gxObject*));
}
else
{
#ifdef gxrealloc
//If compiler supports realloc.
arr->data = (gxObject**)gxrealloc(arr->data, arr->capacity * sizeof(gxObject*));
#else
//If compiler doesn't support realloc.
gxObject** old = arr->data;
arr->data = (gxObject**)gxmalloc(arr->capacity * sizeof(gxObject*));
//If not enought memory available.
if (arr->data == NULL)
{
arr->data = old;
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
memcpy(arr->data, old, sizeof(gxObject*) * arr->size);
gxfree(old);
#endif // gxrealloc
}
}
#endif //DLMS_IGNORE_MALLOC
if (oa_getCapacity(arr) < capacity)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
return 0;
}
//Attach object to objectArray.
void oa_attach(objectArray* arr, gxObject** item, uint16_t count)
{
arr->capacity = 0x8000 + count;
arr->size = count;
#if !(defined(GX_DLMS_MICROCONTROLLER) || defined(DLMS_IGNORE_MALLOC))
arr->position = 0;
#endif //!(defined(GX_DLMS_MICROCONTROLLER) || defined(DLMS_IGNORE_MALLOC))
arr->data = item;
}
int oa_verify(objectArray* arr)
{
uint16_t pos;
int ret;
gxObject* it;
for (pos = 0; pos != arr->size; ++pos)
{
if ((ret = oa_getByIndex(arr, pos, &it)) != 0)
{
return ret;
}
if (it->objectType == 0)
{
#if defined(_WIN64) || defined(_WIN32) || defined(__linux__)
if (pos > 0)
{
char ln[25];
if ((ret = oa_getByIndex(arr, pos - 1, &it)) != 0 ||
(ret = hlp_getLogicalNameToString(it->logicalName, ln)) != 0)
{
return ret;
}
printf("Last initialized object:%s\n", ln);
}
#endif
//If init2 is not called.
return DLMS_ERROR_CODE_INVALID_PARAMETER;
}
}
return DLMS_ERROR_CODE_OK;
}
#ifndef DLMS_IGNORE_MALLOC
//Push new data to the objectArray.
int oa_push(objectArray* arr, gxObject* item)
{
if (!oa_isAttached(arr) && arr->size >= arr->capacity)
{
arr->capacity += OBJECT_ARRAY_CAPACITY;
if (arr->data == NULL)
{
arr->data = (gxObject**)gxmalloc(arr->capacity * sizeof(gxObject*));
}
else
{
#ifdef gxrealloc
//If compiler supports realloc.
arr->data = (gxObject**)gxrealloc(arr->data, arr->capacity * sizeof(gxObject*));
#else
//If compiler doesn't support realloc.
gxObject** old = arr->data;
arr->data = (gxObject**)gxmalloc(arr->capacity * sizeof(gxObject*));
//If not enought memory available.
if (arr->data == NULL)
{
arr->data = old;
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
memcpy(arr->data, old, sizeof(gxObject*) * arr->size);
gxfree(old);
#endif // gxrealloc
}
}
if (oa_getCapacity(arr) <= arr->size)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
arr->data[arr->size] = item;
++arr->size;
return DLMS_ERROR_CODE_OK;
}
#endif //DLMS_IGNORE_MALLOC
void oa_copy(objectArray* target, objectArray* source)
{
int pos;
oa_empty(target);
oa_capacity(target, source->size);
for (pos = 0; pos != source->size; ++pos)
{
target->data[pos] = source->data[pos];
}
target->size = source->size;
}
void oa_move(objectArray* target, objectArray* source)
{
int pos;
oa_empty(target);
oa_capacity(target, source->size);
for (pos = 0; pos != source->size; ++pos)
{
target->data[pos] = source->data[pos];
}
target->size = source->size;
source->size = 0;
#if !(defined(GX_DLMS_MICROCONTROLLER) || defined(DLMS_IGNORE_MALLOC))
source->position = 0;
#endif //!(defined(GX_DLMS_MICROCONTROLLER) || defined(DLMS_IGNORE_MALLOC))
}
void oa_clear2(
objectArray* arr,
uint16_t index,
uint16_t count)
{
uint16_t pos;
if (arr->data != NULL)
{
//Clear objects first.
for (pos = 0; pos != count; ++pos)
{
obj_clear(arr->data[index + pos]);
}
#ifndef DLMS_IGNORE_MALLOC
for (pos = 0; pos != count; ++pos)
{
gxfree(arr->data[index + pos]);
}
#endif //DLMS_IGNORE_MALLOC
}
arr->size = index;
#if !(defined(GX_DLMS_MICROCONTROLLER) || defined(DLMS_IGNORE_MALLOC))
arr->position = 0;
#endif //!(defined(GX_DLMS_MICROCONTROLLER) || defined(DLMS_IGNORE_MALLOC))
}
void oa_clear(objectArray* arr, unsigned char releaseObjects)
{
#ifndef DLMS_IGNORE_MALLOC
uint16_t pos;
if (arr->data != NULL)
{
//Clear objects first.
for (pos = 0; pos != arr->size; ++pos)
{
obj_clear(arr->data[pos]);
}
if (releaseObjects)
{
for (pos = 0; pos != arr->size; ++pos)
{
gxfree(arr->data[pos]);
}
}
if (!oa_isAttached(arr))
{
gxfree(arr->data);
arr->data = NULL;
arr->capacity = 0;
}
}
#endif //DLMS_IGNORE_MALLOC
arr->size = 0;
#if !(defined(GX_DLMS_MICROCONTROLLER) || defined(DLMS_IGNORE_MALLOC))
arr->position = 0;
#endif //!(defined(GX_DLMS_MICROCONTROLLER) || defined(DLMS_IGNORE_MALLOC))
}
void oa_empty(objectArray* arr)
{
#ifndef DLMS_IGNORE_MALLOC
if (!oa_isAttached(arr))
{
if (arr->data != NULL)
{
gxfree(arr->data);
arr->data = NULL;
}
arr->capacity = 0;
}
#endif //DLMS_IGNORE_MALLOC
arr->size = 0;
#if !(defined(GX_DLMS_MICROCONTROLLER) || defined(DLMS_IGNORE_MALLOC))
arr->position = 0;
#endif //!(defined(GX_DLMS_MICROCONTROLLER) || defined(DLMS_IGNORE_MALLOC))
}
//Get item from object array by index.
int oa_getByIndex(
const objectArray* arr,
uint16_t index,
gxObject** item)
{
if (index >= arr->size)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
*item = (gxObject*)arr->data[index];
return DLMS_ERROR_CODE_OK;
}
#ifndef DLMS_IGNORE_ASSOCIATION_SHORT_NAME
int oa_findBySN(
objectArray* objects,
uint16_t sn,
gxObject** object)
{
uint16_t pos;
int ret = DLMS_ERROR_CODE_OK;
gxObject* obj = NULL;
*object = NULL;
for (pos = 0; pos != objects->size; ++pos)
{
ret = oa_getByIndex(objects, pos, &obj);
if (ret != DLMS_ERROR_CODE_OK)
{
return ret;
}
if (obj->shortName == sn)
{
*object = obj;
return 0;
}
}
return ret;
}
#endif //DLMS_IGNORE_ASSOCIATION_SHORT_NAME
int oa_findByLN(
objectArray* objects,
DLMS_OBJECT_TYPE type,
const unsigned char* ln,
gxObject** object)
{
uint16_t pos;
int ret = DLMS_ERROR_CODE_OK;
gxObject* obj = NULL;
*object = NULL;
if (ln == NULL)
{
return DLMS_ERROR_CODE_INVALID_PARAMETER;
}
for (pos = 0; pos != objects->size; ++pos)
{
if ((ret = oa_getByIndex(objects, pos, &obj)) != DLMS_ERROR_CODE_OK)
{
break;
}
if ((obj->objectType == type || DLMS_OBJECT_TYPE_NONE == type) && memcmp(obj->logicalName, ln, 6) == 0)
{
*object = obj;
break;
}
}
return ret;
}
int oa_getObjects(objectArray* src, DLMS_OBJECT_TYPE type, objectArray* objects)
{
uint16_t pos;
int ret = DLMS_ERROR_CODE_OK;
gxObject* obj = NULL;
if (src == NULL || objects == NULL)
{
return DLMS_ERROR_CODE_INVALID_PARAMETER;
}
for (pos = 0; pos != src->size; ++pos)
{
ret = oa_getByIndex(src, pos, &obj);
if (ret != DLMS_ERROR_CODE_OK)
{
return ret;
}
if (obj->objectType == type || type == DLMS_OBJECT_TYPE_NONE)
{
#ifdef DLMS_IGNORE_MALLOC
if (objects->data == NULL || !(objects->size < oa_getCapacity(objects)))
{
return DLMS_ERROR_CODE_INVALID_PARAMETER;
}
objects->data[objects->size] = obj;
++objects->size;
#else
oa_push(objects, obj);
#endif //DLMS_IGNORE_MALLOC
}
}
//Trim array.
oa_capacity(objects, objects->size);
return ret;
}
int oa_getObjects2(
objectArray* src,
DLMS_OBJECT_TYPE* types,
unsigned char typeCount,
objectArray* objects)
{
uint16_t pos, pos2;
int ret = DLMS_ERROR_CODE_OK;
gxObject* obj = NULL;
oa_empty(objects);
if (src == NULL || objects == NULL || types == NULL)
{
return DLMS_ERROR_CODE_INVALID_PARAMETER;
}
for (pos = 0; pos != src->size; ++pos)
{
ret = oa_getByIndex(src, pos, &obj);
if (ret != DLMS_ERROR_CODE_OK)
{
return ret;
}
for (pos2 = 0; pos2 != typeCount; ++pos2)
{
if (types[pos2] == obj->objectType)
{
#ifdef DLMS_IGNORE_MALLOC
if (!(objects->size < oa_getCapacity(objects)))
{
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
break;
}
memcpy(&objects->data[objects->size], obj, sizeof(gxObject));
++objects->size;
#else
oa_push(objects, obj);
#endif //DLMS_IGNORE_MALLOC
break;
}
}
}
//Trim array.
oa_capacity(objects, objects->size);
return ret;
}

View File

@ -0,0 +1,141 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef OBJECTARRAY_H
#define OBJECTARRAY_H
#ifdef __cplusplus
extern "C" {
#endif
#include "gxignore.h"
#include "gxobjects.h"
#define OBJECT_ARRAY_CAPACITY 10
//Initialize variantArray.
void oa_init(
objectArray* arr);
//Attach objects to objectArray.
void oa_attach(
objectArray * arr,
gxObject** item,
uint16_t count);
//Verify that all objects are called init2. This is used for developing purposes.
int oa_verify(
objectArray * arr);
char oa_isAttached(objectArray* arr);
uint16_t oa_getCapacity(objectArray* arr);
//Allocate new size for the array in bytes.
int oa_capacity(
objectArray* arr,
const uint16_t capacity);
#ifndef DLMS_IGNORE_MALLOC
//Push new data to the variantArray.
int oa_push(
objectArray * arr,
gxObject* item);
#endif //DLMS_IGNORE_MALLOC
//Copy content of object array.
void oa_copy(
objectArray *target,
objectArray* source);
//Move content of object array.
void oa_move(
objectArray* target,
objectArray* source);
//Clear object array. Clear will free objects as well.
void oa_clear2(
objectArray* arr,
uint16_t index,
uint16_t count);
//Clear object array. Clear will free objects as well.
void oa_clear(
objectArray* arr,
unsigned char releaseObjects);
//Empty object array. Empty do not free objects.
void oa_empty(
objectArray* arr);
//Get item from object array by index.
int oa_getByIndex(
const objectArray* arr,
uint16_t index,
gxObject** item);
#ifndef DLMS_IGNORE_ASSOCIATION_SHORT_NAME
//Find object using Short Name.
int oa_findBySN(
objectArray* objects,
uint16_t sn,
gxObject** object);
#endif //DLMS_IGNORE_ASSOCIATION_SHORT_NAME
//Find object using Logical Name.
int oa_findByLN(
objectArray* objects,
DLMS_OBJECT_TYPE type,
const unsigned char* ln,
gxObject** object);
//Get object by object type.
int oa_getObjects(
objectArray* src,
DLMS_OBJECT_TYPE type,
objectArray* objects);
//Get object by array of object type.
int oa_getObjects2(
objectArray* src,
DLMS_OBJECT_TYPE* types,
unsigned char typeCount,
objectArray* objects);
#define OA_ATTACH(X, V) oa_attach(&X, (gxObject**) V, sizeof(V)/sizeof(V[0]))
#ifdef __cplusplus
}
#endif
#endif //OBJECTARRAY_H

View File

@ -0,0 +1,90 @@
//
// --------------------------------------------------------------------------
// 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 "parameters.h"
#ifndef DLMS_IGNORE_ASSOCIATION_SHORT_NAME
void params_initSN(
gxSNParameters *target,
dlmsSettings *settings,
DLMS_COMMAND command,
int count,
unsigned char commandType,
gxByteBuffer* attributeDescriptor,
gxByteBuffer* data,
DLMS_COMMAND encryptedCommand)
{
target->settings = settings;
target->blockIndex = (uint16_t)settings->blockIndex;
target->command = command;
target->encryptedCommand = encryptedCommand;
target->count = count;
target->requestType = commandType;
target->attributeDescriptor = attributeDescriptor;
target->data = data;
target->multipleBlocks = 0;
target->time = 0;
target->lastBlock = 1;
#ifdef DLMS_IGNORE_MALLOC
target->serializedPdu = settings->serializedPdu;
#endif //DLMS_IGNORE_MALLOC
}
#endif // DLMS_IGNORE_ASSOCIATION_SHORT_NAME
void params_initLN(
gxLNParameters *target,
dlmsSettings* settings,
unsigned char invokeId,
DLMS_COMMAND command,
unsigned char commandType,
gxByteBuffer* attributeDescriptor,
gxByteBuffer* data,
unsigned char status,
DLMS_COMMAND encryptedCommand,
unsigned char multipleBlocks,
unsigned char lastBlock)
{
target->invokeId = invokeId;
target->settings = settings;
target->blockIndex = settings->blockIndex;
target->command = command;
target->encryptedCommand = encryptedCommand;
target->requestType = commandType;
target->attributeDescriptor = attributeDescriptor;
target->data = data;
target->time = 0;
target->status = status;
target->multipleBlocks = multipleBlocks;
target->lastBlock = lastBlock;
//Serialize data to this PDU.
target->serializedPdu = settings->serializedPdu;
}

View File

@ -0,0 +1,194 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef PARAMETERS_H
#define PARAMETERS_H
#ifdef __cplusplus
extern "C" {
#endif
#include "gxignore.h"
#include "dlmssettings.h"
#ifndef DLMS_IGNORE_ASSOCIATION_SHORT_NAME
/**
* SN Parameters
*/
typedef struct
{
/**
* DLMS settings.
*/
dlmsSettings *settings;
/**
* DLMS command.
*/
DLMS_COMMAND command;
/**
* Encrypted DLMS command.
*/
DLMS_COMMAND encryptedCommand;
/**
* Request type.
*/
unsigned char requestType;
/**
* Attribute descriptor.
*/
gxByteBuffer* attributeDescriptor;
/**
* Data.
*/
gxByteBuffer* data;
/**
* Send date and time. This is used in Data notification messages.
*/
#ifdef DLMS_USE_EPOCH_TIME
uint32_t time;
#else
struct tm* time;
#endif //DLMS_USE_EPOCH_TIME
/**
* Item Count.
*/
int count;
/**
* Are there more data to send or more data to receive.
*/
unsigned char multipleBlocks;
/**
* Is this last block.
*/
unsigned char lastBlock;
/**
* Block index.
*/
uint16_t blockIndex;
//Serialize data to this PDU.
#ifdef DLMS_IGNORE_MALLOC
gxByteBuffer* serializedPdu;
#endif //DLMS_IGNORE_MALLOC
} gxSNParameters;
void params_initSN(
gxSNParameters *target,
dlmsSettings *settings,
DLMS_COMMAND command,
int count,
unsigned char commandType,
gxByteBuffer* attributeDescriptor,
gxByteBuffer* data,
DLMS_COMMAND encryptedCommand);
#endif //DLMS_IGNORE_ASSOCIATION_SHORT_NAME
/**
* LN Parameters
*/
typedef struct
{
/**
* DLMS settings.
*/
dlmsSettings *settings;
/**
* DLMS command.
*/
DLMS_COMMAND command;
/**
* Encrypted DLMS command.
*/
DLMS_COMMAND encryptedCommand;
/**
* Request type.
*/
unsigned char requestType;
/**
* Attribute descriptor.
*/
gxByteBuffer* attributeDescriptor;
/**
* Data.
*/
gxByteBuffer* data;
/**
* Send date and time. This is used in Data notification messages.
*/
#ifdef DLMS_USE_EPOCH_TIME
uint32_t time;
#else
struct tm* time;
#endif // DLMS_USE_EPOCH_TIME
/**
* Reply status.
*/
unsigned char status;
/**
* Are there more data to send or more data to receive.
*/
unsigned char multipleBlocks;
/**
* Is this last block in send.
*/
unsigned char lastBlock;
/**
* Block index.
*/
uint32_t blockIndex;
/**
* Received invoke ID.
*/
unsigned char invokeId;
//Serialize data to this PDU.
gxByteBuffer* serializedPdu;
} gxLNParameters;
void params_initLN(
gxLNParameters *target,
dlmsSettings* settings,
unsigned char invokeId,
DLMS_COMMAND command,
unsigned char commandType,
gxByteBuffer* attributeDescriptor,
gxByteBuffer* data,
unsigned char status,
DLMS_COMMAND encryptedCommand,
unsigned char multipleBlocks,
unsigned char lastBlock);
#ifdef __cplusplus
}
#endif
#endif //PARAMETERS_H

View File

@ -0,0 +1,116 @@
//
// --------------------------------------------------------------------------
// 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 <string.h> /* memset */
#include "gxmem.h"
#if _MSC_VER > 1400
#include <crtdbg.h>
#endif
#include "replydata.h"
/**
* @return Is more data available.
*/
unsigned char reply_isMoreData(gxReplyData* reply)
{
return reply->moreData != DLMS_DATA_REQUEST_TYPES_NONE;
}
/**
* Initialize reply structure.
*/
void reply_init(gxReplyData* reply)
{
reply->invokeId = 0;
reply->commandType = 0;
reply->moreData = DLMS_DATA_REQUEST_TYPES_NONE;
reply->encryptedCommand = reply->command = DLMS_COMMAND_NONE;
BYTE_BUFFER_INIT(&reply->data);
reply->complete = 0;
var_init(&reply->dataValue);
reply->totalCount = 0;
reply->readPosition = 0;
reply->packetLength = 0;
reply->peek = 0;
reply->ignoreValue = 0;
reply->dataType = DLMS_DATA_TYPE_NONE;
reply->cipherIndex = 0;
#ifdef DLMS_USE_EPOCH_TIME
reply->time = 0;
#else
memset(&reply->time, 0, sizeof(struct tm));
#endif // DLMS_USE_EPOCH_TIME
reply->preEstablished = 0;
reply->blockNumber = 0;
reply->blockNumberAck = 0;
reply->streaming = 0;
reply->windowSize = 0;
reply->serverAddress = 0;
reply->clientAddress = 0;
}
void reply_clear2(gxReplyData* reply, unsigned char clearData)
{
reply->invokeId = 0;
reply->moreData = DLMS_DATA_REQUEST_TYPES_NONE;
reply->encryptedCommand = reply->command = DLMS_COMMAND_NONE;
if (clearData)
{
bb_clear(&reply->data);
reply->preEstablished = 0;
}
reply->complete = 0;
var_clear(&reply->dataValue);
reply->totalCount = 0;
reply->readPosition = 0;
reply->packetLength = 0;
reply->peek = 0;
reply->ignoreValue = 0;
reply->dataType = DLMS_DATA_TYPE_NONE;
reply->cipherIndex = 0;
#ifdef DLMS_USE_EPOCH_TIME
reply->time = 0;
#else
memset(&reply->time, 0, sizeof(struct tm));
#endif // DLMS_USE_EPOCH_TIME
reply->blockNumber = 0;
reply->blockNumberAck = 0;
reply->streaming = 0;
reply->windowSize = 0;
reply->serverAddress = 0;
reply->clientAddress = 0;
}
void reply_clear(gxReplyData* reply)
{
reply_clear2(reply, 1);
}

View File

@ -0,0 +1,158 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef GXREPLYDATA_H
#define GXREPLYDATA_H
#ifdef __cplusplus
extern "C" {
#endif
#include "variant.h"
typedef struct
{
/**
* Is more data available.
*/
DLMS_DATA_REQUEST_TYPES moreData;
/**
* Received command.
*/
DLMS_COMMAND command;
/**
* Encrypted command.
*/
DLMS_COMMAND encryptedCommand;
unsigned char commandType;
/**
* Received data.
*/
gxByteBuffer data;
/**
* Is frame complete.
*/
unsigned char complete;
/**
* Read value.
*/
dlmsVARIANT dataValue;
/**
* Expected count of element in the array.
*/
uint16_t totalCount;
#if defined(GX_DLMS_BYTE_BUFFER_SIZE_32) || (!defined(GX_DLMS_MICROCONTROLLER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
/**
* Last read position. This is used in peek to solve how far data is read.
*/
uint32_t readPosition;
/**
* Packet length.
*/
uint32_t packetLength;
#else
/**
* Last read position. This is used in peek to solve how far data is read.
*/
uint16_t readPosition;
/**
* Packet length.
*/
uint16_t packetLength;
#endif
/**
* Try Get value.
*/
unsigned char peek;
/**
* Value is not try to parse. This is used in data collector.
*/
unsigned char ignoreValue;
DLMS_DATA_TYPE dataType;
/**
* Cipher index is position where data is decrypted.
*/
uint16_t cipherIndex;
/**
* Data notification date time.
*/
#ifdef DLMS_USE_EPOCH_TIME
uint32_t time;
#else
struct tm time;
#endif // DLMS_USE_EPOCH_TIME
/**
* Pre-established connection.
*/
unsigned char preEstablished;
unsigned char invokeId;
//GBT block number.
uint16_t blockNumber;
//GBT block number ACK.
uint16_t blockNumberAck;
//GBT is streaming used.
unsigned streaming;
//GBT window size
unsigned windowSize;
//Server address.
uint16_t serverAddress;
//Client address.
uint16_t clientAddress;
} gxReplyData;
unsigned char reply_isMoreData(gxReplyData* reply);
/**
* Initialize reply structure.
*/
void reply_init(gxReplyData* reply);
void reply_clear(gxReplyData* reply);
void reply_clear2(gxReplyData* reply, unsigned char clearData);
#ifdef __cplusplus
}
#endif
#endif //GXREPLYDATA_H

View File

@ -0,0 +1,41 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import sensor
from . import (
XT211,
xt211_ns,
obis_code,
CONF_XT211_ID,
CONF_OBIS_CODE,
CONF_DONT_PUBLISH,
CONF_CLASS,
)
XT211Sensor = xt211_ns.class_("XT211Sensor", sensor.Sensor)
CONF_MULTIPLIER = "multiplier"
CONFIG_SCHEMA = cv.All(
sensor.sensor_schema(
XT211Sensor,
).extend(
{
cv.GenerateID(CONF_XT211_ID): cv.use_id(XT211),
cv.Required(CONF_OBIS_CODE): obis_code,
cv.Optional(CONF_DONT_PUBLISH, default=False): cv.boolean,
cv.Optional(CONF_MULTIPLIER, default=1.0): cv.float_,
cv.Optional(CONF_CLASS, default=3): cv.int_,
}
),
cv.has_exactly_one_key(CONF_OBIS_CODE),
)
async def to_code(config):
component = await cg.get_variable(config[CONF_XT211_ID])
var = await sensor.new_sensor(config)
cg.add(var.set_obis_code(config[CONF_OBIS_CODE]))
cg.add(var.set_dont_publish(config.get(CONF_DONT_PUBLISH)))
cg.add(var.set_multiplier(config[CONF_MULTIPLIER]))
cg.add(var.set_obis_class(config[CONF_CLASS]))
cg.add(component.register_sensor(var))

5108
components/xt211/server.c Normal file

File diff suppressed because it is too large Load Diff

157
components/xt211/server.h Normal file
View File

@ -0,0 +1,157 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef SERVER_H
#define SERVER_H
#include "gxignore.h"
#ifndef DLMS_IGNORE_SERVER
#ifdef __cplusplus
extern "C" {
#endif
#include "serverevents.h"
#include "dlms.h"
typedef struct
{
/*Received data from the client.*/
unsigned char* data;
/*Data size.*/
uint16_t dataSize;
/*Server reply for the client.*/
gxByteBuffer* reply;
/*Is GBT streaming in progress.*/
DLMS_DATA_REQUEST_TYPES moreData;
/*GBT Message count to send.*/
unsigned char gbtCount;
/*HDLC window count to send.*/
unsigned char hdlcWindowCount;
/*Received command.*/
DLMS_COMMAND command;
#ifndef DLMS_IGNORE_IEC
/*Baudrate is changed when optical probe is used.*/
uint16_t newBaudRate;
#endif //DLMS_IGNORE_IEC
}gxServerReply;
int sr_initialize(
gxServerReply* sr,
unsigned char* data,
uint16_t dataSize,
gxByteBuffer* reply);
int svr_initialize(
dlmsServerSettings* settings);
/*Server handles received bytes from the client.*/
int svr_handleRequest(
dlmsServerSettings* settings,
gxByteBuffer* data,
gxByteBuffer* reply);
/*Server handles received bytes from the client.*/
int svr_handleRequest2(
dlmsServerSettings* settings,
unsigned char* buff,
uint16_t size,
gxByteBuffer* reply);
/*Server handles received byte from the client.*/
int svr_handleRequest3(
dlmsServerSettings* settings,
unsigned char data,
gxByteBuffer* reply);
/*Server handles received bytes from the client.*/
int svr_handleRequest4(
dlmsServerSettings* settings,
gxServerReply* sr);
void svr_reset(
dlmsServerSettings* settings);
/*
Run the background processes.
*/
int svr_run(
dlmsServerSettings* settings,
//Current EPOCH time.
uint32_t time,
//Next EPOCH execution time.
uint32_t* next);
#ifndef DLMS_IGNORE_REGISTER_MONITOR
/*
The server verifies that value of monitored object don't cross the thresholds.
Selected script is invoked if value is passed.
*/
int svr_monitor(dlmsServerSettings* settings, gxRegisterMonitor* object);
/*
The server verifies that values of monitored objects don't cross the thresholds.
Selected script is invoked if value is passed.
*/
int svr_monitorAll(dlmsServerSettings* settings);
#endif //DLMS_IGNORE_REGISTER_MONITOR
#ifndef DLMS_IGNORE_LIMITER
/*
The server verifies that value of monitored object don't cross the thresholds.
Selected script is invoked if value is passed.
*/
int svr_limiter(dlmsServerSettings* settings, gxLimiter* object, uint32_t now);
/*
The server verifies that values of monitored objects don't cross the thresholds.
Selected script is invoked if value is passed.
*/
int svr_limiterAll(dlmsServerSettings* settings, uint32_t now);
#endif //DLMS_IGNORE_LIMITER
#ifndef DLMS_IGNORE_ASSOCIATION_SHORT_NAME
/**
* Update short names.
*/
int svr_updateShortNames(
dlmsServerSettings* settings,
unsigned char force);
#endif //DLMS_IGNORE_ASSOCIATION_SHORT_NAME
//Check is client changing the settings with action.
//This can be used to check is meter data changed.
//Return value is saved atribute index or zero if nothing hasn't change.
uint32_t svr_isChangedWithAction(DLMS_OBJECT_TYPE objectType, unsigned char methodIndex);
#ifdef __cplusplus
}
#endif
#endif //DLMS_IGNORE_SERVER
#endif //SERVER_H

View File

@ -0,0 +1,67 @@
//
// --------------------------------------------------------------------------
// 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 "serverevents.h"
#ifdef DLMS_DEBUG
#include <stdio.h>
#endif //DLMS_DEBUG
void svr_notifyTrace(const char* str, int err)
{
#ifdef DLMS_DEBUG
if (err != 0)
{
char tmp[20];
sprintf(tmp, " Error: %d", err);
svr_trace(str, tmp);
}
else
{
svr_trace(str, " succeeded.");
}
#endif// DLMS_DEBUG
}
void svr_notifyTrace2(const char* str, const short ot, const unsigned char* ln, int err)
{
#ifdef DLMS_DEBUG
if (err != 0)
{
char tmp[20];
sprintf(tmp, " %d:%d.%d.%d.%d.%d.%d Error: %d", ot, ln[0], ln[1], ln[2], ln[3], ln[4], ln[5], err);
svr_trace(str, tmp);
}
else
{
svr_trace(str, " succeeded.");
}
#endif// DLMS_DEBUG
}

View File

@ -0,0 +1,227 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef SERVER_EVENTS_H
#define SERVER_EVENTS_H
#include "gxignore.h"
#if !defined(DLMS_IGNORE_SERVER) || defined(DLMS_DEBUG)
#include "dlmssettings.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef DLMS_IGNORE_SERVER
/**
* Check is data sent to this server.
*
* @param serverAddress
* Server address.
* @param clientAddress
* Client address.
* @return True, if data is sent to this server.
*/
extern unsigned char svr_isTarget(
dlmsSettings* settings,
uint32_t serverAddress,
uint32_t clientAddress);
/**
* Get attribute access level.
*/
extern DLMS_ACCESS_MODE svr_getAttributeAccess(
dlmsSettings* settings,
gxObject* obj,
unsigned char index);
/**
* Get method access level.
*/
extern DLMS_METHOD_ACCESS_MODE svr_getMethodAccess(
dlmsSettings* settings,
gxObject* obj,
unsigned char index);
/**
* called when client makes connection to the server.
*/
extern int svr_connected(
dlmsServerSettings* settings);
/**
* Client has try to made invalid connection. Password is incorrect.
*
* @param connectionInfo
* Connection information.
*/
extern int svr_invalidConnection(
dlmsServerSettings* settings);
/**
* called when client clses connection to the server.
*/
extern int svr_disconnected(
dlmsServerSettings* settings);
extern void svr_preGet(
dlmsSettings* settings,
gxValueEventCollection* args);
extern void svr_postGet(
dlmsSettings* settings,
gxValueEventCollection* args);
/**
* Read selected item(s).
*
* @param args
* Handled read requests.
*/
extern void svr_preRead(
dlmsSettings* settings,
gxValueEventCollection* args);
/**
* Write selected item(s).
*
* @param args
* Handled write requests.
*/
extern void svr_preWrite(
dlmsSettings* settings,
gxValueEventCollection* args);
/**
* Action is occurred.
*
* @param args
* Handled action requests.
*/
extern void svr_preAction(
dlmsSettings* settings,
gxValueEventCollection* args);
/**
* Read selected item(s).
*
* @param args
* Handled read requests.
*/
extern void svr_postRead(
dlmsSettings* settings,
gxValueEventCollection* args);
/**
* Write selected item(s).
*
* @param args
* Handled write requests.
*/
extern void svr_postWrite(
dlmsSettings* settings,
gxValueEventCollection* args);
/**
* Action is occurred.
*
* @param args
* Handled action requests.
*/
extern void svr_postAction(
dlmsSettings* settings,
gxValueEventCollection* args);
/**
* Check whether the authentication and password are correct.
*
* @param authentication
* Authentication level.
* @param password
* Password.
* @return Source diagnostic.
*/
extern DLMS_SOURCE_DIAGNOSTIC svr_validateAuthentication(
dlmsServerSettings* settings,
DLMS_AUTHENTICATION authentication,
gxByteBuffer* password);
/**
* Find object.
*
* @param objectType
* Object type.
* @param sn
* Short Name. In Logical name referencing this is not used.
* @param ln
* Logical Name. In Short Name referencing this is not used.
* @return Found object or NULL if object is not found.
*/
extern int svr_findObject(
dlmsSettings* settings,
DLMS_OBJECT_TYPE objectType,
int sn,
unsigned char* ln,
gxValueEventArg* e);
/**
* This is reserved for future use.
*
* @param args
* Handled data type requests.
*/
extern void svr_getDataType(
dlmsSettings* settings,
gxValueEventCollection* args);
#endif //DLMS_IGNORE_SERVER
#ifdef DLMS_DEBUG
/**
* Trace that can be used in debugging.
*
* str: Method info.
* Data: optional data.
*/
extern void svr_trace(
const char* str,
const char* data);
#endif //DLMS_DEBUG
//Server uses notify trace if DLMS_DEBUG is defined.
void svr_notifyTrace(const char* str, int err);
//Server uses notify trace if DLMS_DEBUG is defined.
void svr_notifyTrace2(const char* str, const short ot, const unsigned char* ln, int err);
#ifdef __cplusplus
}
#endif
#endif //DLMS_IGNORE_SERVER
#endif //SERVER_EVENTS_H

View File

@ -0,0 +1,98 @@
//
// --------------------------------------------------------------------------
// Gurux Ltd
//
//
//
// Filename: $HeadURL$
//
// Version: $Revision$,
// $Date$
// $Author$
//
// Copyright (c) Gurux Ltd
//
//---------------------------------------------------------------------------
//
// DESCRIPTION
//
// This file is a part of Gurux Device Framework.
//
// Gurux Device Framework is Open Source software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; version 2 of the License.
// Gurux Device Framework is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// This code is licensed under the GNU General Public License v2.
// Full text may be retrieved at http://www.gnu.org/licenses/gpl-2.0.txt
//---------------------------------------------------------------------------
#include "gxignore.h"
#ifndef SN_PARAMETERS_H
#define SN_PARAMETERS_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef DLMS_IGNORE_ASSOCIATION_SHORT_NAME
#include "dlmssettings.h"
#include "bytebuffer.h"
#include "enums.h"
typedef struct
{
/**
* DLMS settings.
*/
dlmsSettings *settings;
/**
* DLMS command.
*/
DLMS_COMMAND command;
/**
* Request type.
*/
int requestType;
/**
* Attribute descriptor.
*/
gxByteBuffer attributeDescriptor;
/**
* Data.
*/
gxByteBuffer data;
/**
* Send date and time. This is used in Data notification messages.
*/
#ifdef DLMS_USE_EPOCH_TIME
uint32_t time;
#else
struct tm time;
#endif // DLMS_USE_EPOCH_TIME
/**
* Item Count.
*/
int count;
/**
* Are there more data to send or more data to receive.
*/
unsigned char multipleBlocks;
/**
* Block index.
*/
int blockIndex;
} snParameters;
#endif //DLMS_IGNORE_ASSOCIATION_SHORT_NAME
#ifdef __cplusplus
}
#endif
#endif //SN_PARAMETERS_H

View File

@ -0,0 +1,43 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import text_sensor
from . import (
XT211,
xt211_ns,
obis_code,
CONF_XT211_ID,
CONF_OBIS_CODE,
CONF_DONT_PUBLISH,
CONF_CLASS,
)
AUTO_LOAD = ["xt211"]
XT211TextSensor = xt211_ns.class_(
"XT211TextSensor", text_sensor.TextSensor
)
CONFIG_SCHEMA = cv.All(
text_sensor.text_sensor_schema(
XT211TextSensor,
).extend(
{
cv.GenerateID(CONF_XT211_ID): cv.use_id(XT211),
cv.Required(CONF_OBIS_CODE): obis_code,
cv.Optional(CONF_DONT_PUBLISH, default=False): cv.boolean,
cv.Optional(CONF_CLASS, default=1): cv.int_,
}
),
cv.has_exactly_one_key(CONF_OBIS_CODE),
)
async def to_code(config):
component = await cg.get_variable(config[CONF_XT211_ID])
var = await text_sensor.new_text_sensor(config)
cg.add(var.set_obis_code(config[CONF_OBIS_CODE]))
cg.add(var.set_dont_publish(config.get(CONF_DONT_PUBLISH)))
cg.add(var.set_obis_class(config[CONF_CLASS]))
cg.add(component.register_sensor(var))

View File

@ -0,0 +1,48 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef CHIPPERINGENUMS_H
#define CHIPPERINGENUMS_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef DLMS_IGNORE_HIGH_GMAC
#endif //DLMS_IGNORE_HIGH_GMAC
#ifdef __cplusplus
}
#endif
#endif //CHIPPERINGENUMS_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,70 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef COSEM_INVOKE_H
#define COSEM_INVOKE_H
//#ifdef __cplusplus
//extern "C" {
//#endif
#include "gxignore.h"
#ifndef DLMS_IGNORE_SERVER
#include "gxobjects.h"
#include "dlmssettings.h"
int cosem_invoke(
dlmsServerSettings* settings,
gxValueEventArg* e);
#ifndef DLMS_IGNORE_COMPACT_DATA
/*
* Copies the values of the objects to capture into the buffer by reading
* capture objects.
*/
int cosem_captureCompactData(
dlmsSettings* settings,
gxCompactData* object);
#endif //DLMS_IGNORE_COMPACT_DATA
#ifndef DLMS_IGNORE_SCRIPT_TABLE
int invoke_ScriptTable(
dlmsServerSettings* settings,
gxValueEventArg* e);
#endif //DLMS_IGNORE_SCRIPT_TABLE
//#ifdef __cplusplus
//}
//#endif
#endif //DLMS_IGNORE_SERVER
#endif //COSEM_INVOKE_H

View File

@ -0,0 +1,264 @@
//
// --------------------------------------------------------------------------
// Gurux Ltd
//
//
//
// Filename: $HeadURL$
//
// Version: $Revision$,
// $Date$
// $Author$
//
// Copyright (c) Gurux Ltd
//
//---------------------------------------------------------------------------
//
// DESCRIPTION
//
// This file is a part of Gurux Device Framework.
//
// Gurux Device Framework is Open Source software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; version 2 of the License.
// Gurux Device Framework is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// This code is licensed under the GNU General Public License v2.
// Full text may be retrieved at http://www.gnu.org/licenses/gpl-2.0.txt
//---------------------------------------------------------------------------
#include "gxignore.h"
#ifndef DLMS_IGNORE_HIGH_MD5
#include <string.h>
#include "gxmd5.h"
unsigned int gxmd5_F(unsigned int x, unsigned int y, unsigned int z)
{
return (x & y) | (~x & z);
}
unsigned int gxmd5_G(unsigned int x, unsigned int y, unsigned int z)
{
return (x & z) | (y & ~z);
}
unsigned int gxmd5_H(unsigned int x, unsigned int y, unsigned int z)
{
return x ^ y ^ z;
}
unsigned int gxmd5_I(uint32_t x, uint32_t y, uint32_t z)
{
return y ^ (x | ~z);
}
unsigned int gxmd5_rotate_left(unsigned int x, int n)
{
return (x << n) | (x >> (32 - n));
}
void gxmd5_FF(uint32_t* a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac)
{
*a = gxmd5_rotate_left(*a + gxmd5_F(b, c, d) + x + ac, s) + b;
}
void gxmd5_GG(uint32_t* a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac) {
*a = gxmd5_rotate_left(*a + gxmd5_G(b, c, d) + x + ac, s) + b;
}
void gxmd5_HH(uint32_t* a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac) {
*a = gxmd5_rotate_left(*a + gxmd5_H(b, c, d) + x + ac, s) + b;
}
void gxmd5_II(uint32_t* a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac) {
*a = gxmd5_rotate_left(*a + gxmd5_I(b, c, d) + x + ac, s) + b;
}
void gxmd5_decode(uint32_t* output, unsigned char* input, unsigned int len)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
{
output[i] = (input[j]) | (((uint32_t)input[j + 1]) << 8) |
(((uint32_t)input[j + 2]) << 16) | (((uint32_t)input[j + 3]) << 24);
}
}
void gxmd5_encode(unsigned char* output, uint32_t* input, unsigned int len)
{
unsigned int i, pos = 0;
for (i = 0; i != len; ++i)
{
output[pos] = input[i] & 0xff;
++pos;
output[pos] = (input[i] >> 8) & 0xff;
++pos;
output[pos] = (input[i] >> 16) & 0xff;
++pos;
output[pos] = (input[i] >> 24) & 0xff;
++pos;
}
}
void gxmd5_transform(unsigned char* block, uint32_t* state)
{
uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
gxmd5_decode(x, block, 64);
/* Round 1 */
gxmd5_FF(&a, b, c, d, x[0], S11, 0xd76aa478);
gxmd5_FF(&d, a, b, c, x[1], S12, 0xe8c7b756);
gxmd5_FF(&c, d, a, b, x[2], S13, 0x242070db);
gxmd5_FF(&b, c, d, a, x[3], S14, 0xc1bdceee);
gxmd5_FF(&a, b, c, d, x[4], S11, 0xf57c0faf);
gxmd5_FF(&d, a, b, c, x[5], S12, 0x4787c62a);
gxmd5_FF(&c, d, a, b, x[6], S13, 0xa8304613);
gxmd5_FF(&b, c, d, a, x[7], S14, 0xfd469501);
gxmd5_FF(&a, b, c, d, x[8], S11, 0x698098d8);
gxmd5_FF(&d, a, b, c, x[9], S12, 0x8b44f7af);
gxmd5_FF(&c, d, a, b, x[10], S13, 0xffff5bb1);
gxmd5_FF(&b, c, d, a, x[11], S14, 0x895cd7be);
gxmd5_FF(&a, b, c, d, x[12], S11, 0x6b901122);
gxmd5_FF(&d, a, b, c, x[13], S12, 0xfd987193);
gxmd5_FF(&c, d, a, b, x[14], S13, 0xa679438e);
gxmd5_FF(&b, c, d, a, x[15], S14, 0x49b40821);
/* Round 2 */
gxmd5_GG(&a, b, c, d, x[1], S21, 0xf61e2562);
gxmd5_GG(&d, a, b, c, x[6], S22, 0xc040b340);
gxmd5_GG(&c, d, a, b, x[11], S23, 0x265e5a51);
gxmd5_GG(&b, c, d, a, x[0], S24, 0xe9b6c7aa);
gxmd5_GG(&a, b, c, d, x[5], S21, 0xd62f105d);
gxmd5_GG(&d, a, b, c, x[10], S22, 0x2441453);
gxmd5_GG(&c, d, a, b, x[15], S23, 0xd8a1e681);
gxmd5_GG(&b, c, d, a, x[4], S24, 0xe7d3fbc8);
gxmd5_GG(&a, b, c, d, x[9], S21, 0x21e1cde6);
gxmd5_GG(&d, a, b, c, x[14], S22, 0xc33707d6);
gxmd5_GG(&c, d, a, b, x[3], S23, 0xf4d50d87);
gxmd5_GG(&b, c, d, a, x[8], S24, 0x455a14ed);
gxmd5_GG(&a, b, c, d, x[13], S21, 0xa9e3e905);
gxmd5_GG(&d, a, b, c, x[2], S22, 0xfcefa3f8);
gxmd5_GG(&c, d, a, b, x[7], S23, 0x676f02d9);
gxmd5_GG(&b, c, d, a, x[12], S24, 0x8d2a4c8a);
/* Round 3 */
gxmd5_HH(&a, b, c, d, x[5], S31, 0xfffa3942);
gxmd5_HH(&d, a, b, c, x[8], S32, 0x8771f681);
gxmd5_HH(&c, d, a, b, x[11], S33, 0x6d9d6122);
gxmd5_HH(&b, c, d, a, x[14], S34, 0xfde5380c);
gxmd5_HH(&a, b, c, d, x[1], S31, 0xa4beea44);
gxmd5_HH(&d, a, b, c, x[4], S32, 0x4bdecfa9);
gxmd5_HH(&c, d, a, b, x[7], S33, 0xf6bb4b60);
gxmd5_HH(&b, c, d, a, x[10], S34, 0xbebfbc70);
gxmd5_HH(&a, b, c, d, x[13], S31, 0x289b7ec6);
gxmd5_HH(&d, a, b, c, x[0], S32, 0xeaa127fa);
gxmd5_HH(&c, d, a, b, x[3], S33, 0xd4ef3085);
gxmd5_HH(&b, c, d, a, x[6], S34, 0x4881d05);
gxmd5_HH(&a, b, c, d, x[9], S31, 0xd9d4d039);
gxmd5_HH(&d, a, b, c, x[12], S32, 0xe6db99e5);
gxmd5_HH(&c, d, a, b, x[15], S33, 0x1fa27cf8);
gxmd5_HH(&b, c, d, a, x[2], S34, 0xc4ac5665);
/* Round 4 */
gxmd5_II(&a, b, c, d, x[0], S41, 0xf4292244);
gxmd5_II(&d, a, b, c, x[7], S42, 0x432aff97);
gxmd5_II(&c, d, a, b, x[14], S43, 0xab9423a7);
gxmd5_II(&b, c, d, a, x[5], S44, 0xfc93a039);
gxmd5_II(&a, b, c, d, x[12], S41, 0x655b59c3);
gxmd5_II(&d, a, b, c, x[3], S42, 0x8f0ccc92);
gxmd5_II(&c, d, a, b, x[10], S43, 0xffeff47d);
gxmd5_II(&b, c, d, a, x[1], S44, 0x85845dd1);
gxmd5_II(&a, b, c, d, x[8], S41, 0x6fa87e4f);
gxmd5_II(&d, a, b, c, x[15], S42, 0xfe2ce6e0);
gxmd5_II(&c, d, a, b, x[6], S43, 0xa3014314);
gxmd5_II(&b, c, d, a, x[13], S44, 0x4e0811a1);
gxmd5_II(&a, b, c, d, x[4], S41, 0xf7537e82);
gxmd5_II(&d, a, b, c, x[11], S42, 0xbd3af235);
gxmd5_II(&c, d, a, b, x[2], S43, 0x2ad7d2bb);
gxmd5_II(&b, c, d, a, x[9], S44, 0xeb86d391);
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
}
int gxmd5_update(unsigned char* data, uint32_t len, unsigned char* buffer, uint32_t* count, uint32_t* state)
{
unsigned int i;
// Number of bytes.
unsigned int index = count[0] / 8 % 64;
// Update number of bits
if ((count[0] += (len << 3)) < (len << 3))
{
count[1]++;
}
count[1] += (len >> 29);
// number of bytes we need to fill in buffer
unsigned int firstpart = 64 - index;
// transform as many times as possible.
if (len >= firstpart)
{
memcpy(&buffer[index], data, firstpart);
gxmd5_transform(buffer, state);
// Transform block
for (i = firstpart; i + 64 <= len; i += 64)
{
gxmd5_transform(data + i, state);
}
index = 0;
}
else
{
i = 0;
}
memcpy(&buffer[index], &data[i], len - i);
return 0;
}
int gxmd5_encrypt(gxByteBuffer* data, gxByteBuffer* digest)
{
// Bytes that didn't fit in last 64 byte chunk
unsigned char buffer[64];
// Number of bits (lo, hi)
uint32_t count[2] = { 0, 0 };
// Digest
uint32_t state[4] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 };
bb_capacity(digest, 16);
gxmd5_update(data->data, data->size, buffer, count, state);
static unsigned char padding[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
// Save number of bits
unsigned char bits[8];
gxmd5_encode(bits, count, 2);
// Pad out to 56 mod 64.
unsigned int index = count[0] / 8 % 64;
unsigned int padLen = (index < 56) ? (56 - index) : (120 - index);
gxmd5_update(padding, padLen, buffer, count, state);
// Append length (before padding)
gxmd5_update(bits, 8, buffer, count, state);
// Store state in digest
gxmd5_encode(digest->data, state, 4);
digest->size = 16;
return 0;
}
#endif //DLMS_IGNORE_HIGH_MD5

View File

@ -0,0 +1,73 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef GXMD5_H
#define GXMD5_H
#ifdef __cplusplus
extern "C" {
#endif
//If MD5 is not used.
#include "gxignore.h"
#ifndef DLMS_IGNORE_HIGH_MD5
#include "bytebuffer.h"
// Constants .
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
int gxmd5_encrypt(gxByteBuffer* data, gxByteBuffer* crypted);
#endif //DLMS_IGNORE_HIGH_MD5
#ifdef __cplusplus
}
#endif
#endif //GXMD5_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,179 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef GXSERIALIZER_H
#define GXSERIALIZER_H
#include "gxignore.h"
#ifndef DLMS_IGNORE_SERIALIZER
#include "gxobjects.h"
#include "dlmssettings.h"
#include <stdlib.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
#if !(!defined(GX_DLMS_SERIALIZER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__)))
/*Return EEPROM or Flash size.*/
extern uint32_t SERIALIZER_SIZE();
//Read bytes from.
extern int SERIALIZER_LOAD(uint32_t index, uint32_t count, void* value);
//Write byte
extern int SERIALIZER_SAVE(uint32_t index, uint32_t count, const void* value);
#endif //#if !defined(GX_DLMS_SERIALIZER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__))
//This attribute is not serialized.
#define IGNORE_ATTRIBUTE(OBJECT, INDEX) {OBJECT, INDEX, 0}
//This attribute is not serialized by object type.
#define IGNORE_ATTRIBUTE_BY_TYPE(TYPE, INDEX) {0, INDEX, TYPE}
#define ___COSEM_ATTRIBUTES(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16,...) _16
//Visual Studio reguires this.
#define ___EXPAND(x) x
#define ___COUNT_ATTRIBUTES(...) ___EXPAND(___COSEM_ATTRIBUTES(__VA_ARGS__,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0))
#define GET_ALL_ATTRIBUTES() -1
#define GET_ATTRIBUTE1(A) 1 << (A - 1)
#define GET_ATTRIBUTE2(A, B) GET_ATTRIBUTE1(A) | GET_ATTRIBUTE1(B)
#define GET_ATTRIBUTE3(A, B, C) GET_ATTRIBUTE2(A, B) | GET_ATTRIBUTE1(C)
#define GET_ATTRIBUTE4(A, B, C, D) GET_ATTRIBUTE3(A, B, C) | GET_ATTRIBUTE1(D)
#define GET_ATTRIBUTE5(A, B, C, D, E) GET_ATTRIBUTE4(A, B, C, D) | GET_ATTRIBUTE1(E)
#define GET_ATTRIBUTE6(A, B, C, D, E, F) GET_ATTRIBUTE5(A, B, C, D, E) | GET_ATTRIBUTE1(F)
#define GET_ATTRIBUTE7(A, B, C, D, E, F, G) GET_ATTRIBUTE6(A, B, C, D, E, F) | GET_ATTRIBUTE1(G)
#define GET_ATTRIBUTE8(A, B, C, D, E, F, G, H) GET_ATTRIBUTE7(A, B, C, D, E, F, G) | GET_ATTRIBUTE1(H)
#define GET_ATTRIBUTE9(A, B, C, D, E, F, G, H, I) GET_ATTRIBUTE8(A, B, C, D, E, F, G, H) | GET_ATTRIBUTE1(I)
#define GET_ATTRIBUTE10(A, B, C, D, E, F, G, H, I, J)GET_ATTRIBUTE9(A, B, C, D, E, F, G, H, I) | GET_ATTRIBUTE1(J)
#define GET_ATTRIBUTE11(A, B, C, D, E, F, G, H, I, J, K) GET_ATTRIBUTE10(A, B, C, D, E, F, G, H, I, J) | GET_ATTRIBUTE1(K)
#define GET_ATTRIBUTE12(A, B, C, D, E, F, G, H, I, J, K, L) GET_ATTRIBUTE11(A, B, C, D, E, F, G, H, I, J, K) | GET_ATTRIBUTE1(L)
#define GET_ATTRIBUTE13(A, B, C, D, E, F, G, H, I, J, K, L, M) GET_ATTRIBUTE12(A, B, C, D, E, F, G, H, I, J, K, L) | GET_ATTRIBUTE1(M)
#define GET_ATTRIBUTE14(A, B, C, D, E, F, G, H, I, J, K, L, M, N) GET_ATTRIBUTE13(A, B, C, D, E, F, G, H, I, J, K, L, M) | GET_ATTRIBUTE1(N)
#define GET_ATTRIBUTE15(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) GET_ATTRIBUTE14(A, B, C, D, E, F, G, H, I, J, K, L, M, N) | GET_ATTRIBUTE1(O)
#define GET_ATTRIBUTE16(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) GET_ATTRIBUTE15(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) | GET_ATTRIBUTE1(P)
#define CONC(A, B) CONC_(A, B)
#define CONC_(A, B) A##B
#define GET_ATTRIBUTE(...) CONC(GET_ATTRIBUTE, ___COUNT_ATTRIBUTES(__VA_ARGS__))(__VA_ARGS__)
#define GET_ATTRIBUTE_EXCEPT(...) (uint16_t)~(GET_ATTRIBUTE(__VA_ARGS__))
#define GET_ATTRIBUTE_ALL() 0xFFFF
typedef struct
{
/*Target to ignore*/
gxObject* target;
/*Bit enumerated attribute list from attributes that are not serialized.*/
uint16_t attributes;
/*Object type to ignore*/
uint16_t objectType;
} gxSerializerIgnore;
typedef struct
{
//List of attributes that are not serialized.
gxSerializerIgnore* ignoredAttributes;
//Count of ignored objects.
uint16_t count;
#if !defined(GX_DLMS_SERIALIZER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__))
FILE* stream;
#else
//Serialization position is used to save serialization index.
uint32_t position;
//Index of where changed data starts. This is used for debugging.
uint32_t updateStart;
//Index of where changed data ends. This is used for debugging.
uint32_t updateEnd;
#endif //!defined(GX_DLMS_SERIALIZER) && (defined(_WIN32) || defined(_WIN64) || defined(__linux__))
#ifdef DLMS_IGNORE_MALLOC
//Only this object is saved if it is set.
gxObject* savedObject;
//Only attributes saved when savedObject is used.
uint32_t savedAttributes;
//This is for internal use.
//Whether to save the object. This is needed if only changed object is used.
gxObject* currentObject;
//This is for internal use.
uint16_t currentIndex;
#endif //DLMS_IGNORE_MALLOC
} gxSerializerSettings;
void ser_init(gxSerializerSettings* settings);
//Serialize object to bytebuffer.
int ser_saveObject(
gxSerializerSettings* serializeSettings,
gxObject* object);
//Serialize objects to flash.
int ser_saveObjects(
gxSerializerSettings* serializeSettings,
gxObject** objects,
uint16_t count);
//Serialize objects to flash.
int ser_saveObjects2(
gxSerializerSettings* serializeSettings,
objectArray* objects);
//Serialize object from flash.
int ser_loadObject(
dlmsSettings* settings,
gxSerializerSettings* serializeSettings,
gxObject* object);
//Serialize objects from the flash.
int ser_loadObjects(
dlmsSettings* settings,
gxSerializerSettings* serializeSettings,
gxObject** object,
uint16_t count);
//Serialize objects from the flash.
int ser_loadObjects2(
dlmsSettings* settings,
gxSerializerSettings* serializeSettings,
objectArray* object);
//Get data size in bytes.
int ser_getDataSize(
gxSerializerSettings* serializeSettings,
void* size);
#ifdef __cplusplus
}
#endif
#endif //DLMS_IGNORE_SERIALIZER
#endif //GXSERIALIZER_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,388 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef COSEM_SET_IGNORE_MALLOC_H
#define COSEM_SET_IGNORE_MALLOC_H
#include "gxignore.h"
#if defined(DLMS_IGNORE_MALLOC) || defined(DLMS_COSEM_EXACT_DATA_TYPES)
#ifdef __cplusplus
extern "C" {
#endif
#include "gxobjects.h"
#include "dlmssettings.h"
#ifndef DLMS_IGNORE_DATA
int cosem_setData(gxValueEventArg* e);
#endif //DLMS_IGNORE_DATA
#ifndef DLMS_IGNORE_REGISTER
int cosem_setRegister(gxRegister* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_REGISTER
#ifndef DLMS_IGNORE_CLOCK
int cosem_setClock(dlmsSettings* settings, gxClock* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_CLOCK
#ifndef DLMS_IGNORE_ACTION_SCHEDULE
int cosem_setActionSchedule(dlmsSettings* settings, gxActionSchedule* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_ACTION_SCHEDULE
#ifndef DLMS_IGNORE_ACTIVITY_CALENDAR
int cosem_setActivityCalendar(dlmsSettings* settings, gxActivityCalendar* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_ACTIVITY_CALENDAR
#ifndef DLMS_IGNORE_ASSOCIATION_LOGICAL_NAME
int cosem_parseLNObjects(dlmsSettings* settings, gxByteBuffer* data, objectArray* objects);
int cosem_setAssociationLogicalName(dlmsSettings* settings, gxAssociationLogicalName* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_ASSOCIATION_LOGICAL_NAME
#ifndef DLMS_IGNORE_ASSOCIATION_SHORT_NAME
int cosem_parseSNObjects(dlmsSettings* settings, gxByteBuffer* data, objectArray* objects);
int cosem_setAssociationShortName(dlmsSettings* settings, gxAssociationShortName* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_ASSOCIATION_SHORT_NAME
#ifndef DLMS_IGNORE_AUTO_ANSWER
int cosem_setAutoAnswer(gxAutoAnswer* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_AUTO_ANSWER
#ifndef DLMS_IGNORE_AUTO_CONNECT
int cosem_setAutoConnect(gxAutoConnect* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_AUTO_CONNECT
#ifndef DLMS_IGNORE_DEMAND_REGISTER
int cosem_setDemandRegister(gxDemandRegister* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_DEMAND_REGISTER
#ifndef DLMS_IGNORE_MAC_ADDRESS_SETUP
int cosem_setMacAddressSetup(gxMacAddressSetup* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_MAC_ADDRESS_SETUP
#ifndef DLMS_IGNORE_EXTENDED_REGISTER
int cosem_setExtendedRegister(gxExtendedRegister* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_EXTENDED_REGISTER
#ifndef DLMS_IGNORE_GPRS_SETUP
int cosem_setGprsSetup(gxGPRSSetup* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_GPRS_SETUP
#ifndef DLMS_IGNORE_SECURITY_SETUP
int cosem_setSecuritySetup(dlmsSettings* settings, gxSecuritySetup* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_SECURITY_SETUP
#ifndef DLMS_IGNORE_IEC_HDLC_SETUP
int cosem_setIecHdlcSetup(gxIecHdlcSetup* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_IEC_HDLC_SETUP
#ifndef DLMS_IGNORE_IEC_LOCAL_PORT_SETUP
int cosem_setIecLocalPortSetup(gxLocalPortSetup* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_IEC_LOCAL_PORT_SETUP
#ifndef DLMS_IGNORE_IP4_SETUP
int cosem_setIP4Setup(dlmsSettings* settings, gxIp4Setup* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_IP4_SETUP
#ifndef DLMS_IGNORE_PROFILE_GENERIC
int cosem_setProfileGeneric(dlmsSettings* settings, gxProfileGeneric* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_PROFILE_GENERIC
#ifndef DLMS_IGNORE_UTILITY_TABLES
int cosem_setUtilityTables(gxUtilityTables* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_UTILITY_TABLES
#ifndef DLMS_IGNORE_MBUS_SLAVE_PORT_SETUP
int cosem_setMbusSlavePortSetup(gxMbusSlavePortSetup* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_MBUS_SLAVE_PORT_SETUP
#ifndef DLMS_IGNORE_DISCONNECT_CONTROL
int cosem_setDisconnectControl(gxDisconnectControl* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_DISCONNECT_CONTROL
#ifndef DLMS_IGNORE_LIMITER
int cosem_setLimiter(dlmsSettings* settings, gxLimiter* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_LIMITER
#ifndef DLMS_IGNORE_MBUS_CLIENT
int cosem_setmMbusClient(dlmsSettings* settings, gxMBusClient* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_MBUS_CLIENT
#ifndef DLMS_IGNORE_MODEM_CONFIGURATION
int cosem_setModemConfiguration(gxModemConfiguration* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_MODEM_CONFIGURATION
#ifndef DLMS_IGNORE_PPP_SETUP
int cosem_setPppSetup(dlmsSettings* settings, gxPppSetup* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_PPP_SETUP
#ifndef DLMS_IGNORE_REGISTER_ACTIVATION
int cosem_setRegisterActivation(dlmsSettings* settings, gxValueEventArg* e);
#endif //DLMS_IGNORE_REGISTER_ACTIVATION
#ifndef DLMS_IGNORE_REGISTER_MONITOR
int cosem_setRegisterMonitor(dlmsSettings* settings, gxRegisterMonitor* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_REGISTER_MONITOR
#ifndef DLMS_IGNORE_SAP_ASSIGNMENT
int cosem_setSapAssignment(gxSapAssignment* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_SAP_ASSIGNMENT
#ifndef DLMS_IGNORE_SCHEDULE
int cosem_setSchedule(dlmsSettings* settings, gxSchedule* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_SCHEDULE
#ifndef DLMS_IGNORE_SCRIPT_TABLE
int cosem_setScriptTable(dlmsSettings* settings, gxScriptTable* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_SCRIPT_TABLE
#ifndef DLMS_IGNORE_SPECIAL_DAYS_TABLE
int cosem_setSpecialDaysTable(gxSpecialDaysTable* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_SPECIAL_DAYS_TABLE
#ifndef DLMS_IGNORE_TCP_UDP_SETUP
int cosem_setTcpUdpSetup(dlmsSettings* settings, gxTcpUdpSetup* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_TCP_UDP_SETUP
#ifndef DLMS_IGNORE_MBUS_DIAGNOSTIC
int cosem_setMbusDiagnostic(gxMbusDiagnostic* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_MBUS_DIAGNOSTIC
#ifndef DLMS_IGNORE_MBUS_PORT_SETUP
int cosem_setMbusPortSetup(gxMBusPortSetup* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_MBUS_PORT_SETUP
#ifndef DLMS_IGNORE_MBUS_MASTER_PORT_SETUP
int cosem_setMbusMasterPortSetup(gxMBusMasterPortSetup* object, unsigned char index, dlmsVARIANT *value);
#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);
#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);
#endif //DLMS_IGNORE_G3_PLC_MAC_SETUP
#ifndef DLMS_IGNORE_G3_PLC_6LO_WPAN
int cosem_setG3Plc6LoWPAN(gxG3Plc6LoWPAN* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_G3_PLC_6LO_WPAN
#ifndef DLMS_IGNORE_FUNCTION_CONTROL
int cosem_setFunctionControl(
dlmsSettings* settings,
gxFunctionControl* object,
unsigned char index,
dlmsVARIANT* value);
#endif //DLMS_IGNORE_FUNCTION_CONTROL
#ifndef DLMS_IGNORE_ARRAY_MANAGER
int cosem_setArrayManager(dlmsSettings* settings, gxArrayManager* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_ARRAY_MANAGER
#ifndef DLMS_IGNORE_PUSH_SETUP
int cosem_setPushSetup(dlmsSettings* settings, gxPushSetup* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_PUSH_SETUP
#ifndef DLMS_IGNORE_GSM_DIAGNOSTIC
int cosem_setGsmDiagnostic(gxGsmDiagnostic* object, unsigned char index, dlmsVARIANT *value);
#endif //DLMS_IGNORE_GSM_DIAGNOSTIC
#ifndef DLMS_IGNORE_COMPACT_DATA
int compactData_updateTemplateDescription(
dlmsSettings* settings,
gxCompactData* object);
#endif //DLMS_IGNORE_COMPACT_DATA
#ifndef DLMS_IGNORE_IEC_TWISTED_PAIR_SETUP
int cosem_setIecTwistedPairSetup(gxIecTwistedPairSetup* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_IEC_TWISTED_PAIR_SETUP
#ifndef DLMS_IGNORE_IP6_SETUP
int cosem_setIP6Setup(dlmsSettings* settings, gxIp6Setup* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_IP6_SETUP
#ifndef DLMS_IGNORE_IMAGE_TRANSFER
int cosem_setImageTransfer(gxImageTransfer* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_IMAGE_TRANSFER
#ifndef DLMS_IGNORE_REGISTER_TABLE
int cosem_setRegistertable(gxRegisterTable* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_REGISTER_TABLE
#ifndef DLMS_IGNORE_ACCOUNT
int cosem_setAccount(gxAccount* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_ACCOUNT
#ifndef DLMS_IGNORE_CREDIT
int cosem_setCredit(gxCredit* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_CREDIT
#ifndef DLMS_IGNORE_CHARGE
int cosem_setCharge(dlmsSettings* settings, gxCharge* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_CHARGE
#ifndef DLMS_IGNORE_TOKEN_GATEWAY
int cosem_setTokenGateway(gxTokenGateway* object, unsigned char index, dlmsVARIANT* value);
#endif //DLMS_IGNORE_TOKEN_GATEWAY
#ifndef DLMS_IGNORE_COMPACT_DATA
int cosem_setCompactData(
dlmsSettings* settings,
gxCompactData* object,
unsigned char index,
dlmsVARIANT* value);
#endif //DLMS_IGNORE_COMPACT_DATA
#ifndef DLMS_IGNORE_PARAMETER_MONITOR
int cosem_setParameterMonitor(
dlmsSettings* settings,
gxParameterMonitor* object,
unsigned char index,
dlmsVARIANT* value);
#endif //DLMS_IGNORE_PARAMETER_MONITOR
#ifndef DLMS_IGNORE_LLC_SSCS_SETUP
int cosem_setLlcSscsSetup(
dlmsSettings* settings,
gxLlcSscsSetup* object,
unsigned char index,
dlmsVARIANT* value);
#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);
#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);
#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);
#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);
#endif //DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_COUNTERS
#ifndef DLMS_IGNORE_PRIME_NB_OFDM_PLC_MAC_NETWORK_ADMINISTRATION_DATA
int cosem_setPrimeNbOfdmPlcMacNetworkAdministrationData(
dlmsSettings* settings,
gxPrimeNbOfdmPlcMacNetworkAdministrationData* object,
unsigned char index,
dlmsVARIANT* value);
#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);
#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);
#endif //DLMS_IGNORE_ARBITRATOR
#ifndef DLMS_IGNORE_IEC_8802_LLC_TYPE1_SETUP
int cosem_setIec8802LlcType1Setup(
dlmsSettings* settings,
gxIec8802LlcType1Setup* object,
unsigned char index,
dlmsVARIANT* value);
#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);
#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);
#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);
#endif //DLMS_IGNORE_SFSK_ACTIVE_INITIATOR
#ifndef DLMS_IGNORE_SFSK_MAC_COUNTERS
int cosem_setFSKMacCounters(
dlmsSettings* settings,
gxFSKMacCounters* object,
unsigned char index,
dlmsVARIANT* value);
#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);
#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);
#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);
#endif //DLMS_IGNORE_SFSK_REPORTING_SYSTEM_LIST
#ifdef __cplusplus
}
#endif
#endif //defined(DLMS_IGNORE_MALLOC) || defined(DLMS_COSEM_EXACT_DATA_TYPES)
#endif//COSEM_SET_IGNORE_MALLOC_H

View File

@ -0,0 +1,209 @@
//
// --------------------------------------------------------------------------
// Gurux Ltd
//
//
//
// Filename: $HeadURL$
//
// Version: $Revision$,
// $Date$
// $Author$
//
// Copyright (c) Gurux Ltd
//
//---------------------------------------------------------------------------
//
// DESCRIPTION
//
// This file is a part of Gurux Device Framework.
//
// Gurux Device Framework is Open Source software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; version 2 of the License.
// Gurux Device Framework is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// This code is licensed under the GNU General Public License v2.
// Full text may be retrieved at http://www.gnu.org/licenses/gpl-2.0.txt
//---------------------------------------------------------------------------
#include "gxignore.h"
#ifndef DLMS_IGNORE_HIGH_SHA1
#include <string.h>
#include "gxsha1.h"
#define SHA1_ROL(value, bits) (((value) << (bits)) | (((value) & 0xffffffff) >> (32 - (bits))))
#define SHA1_BLK(i) (block[i&15] = SHA1_ROL(block[(i+13)&15] ^ block[(i+8)&15] ^ block[(i+2)&15] ^ block[i&15],1))
#define SHA1_R0(v,w,x,y,z,i) z += ((w & (x ^ y)) ^ y) + block[i] + 0x5a827999 + SHA1_ROL(v,5); w=SHA1_ROL(w,30);
#define SHA1_R1(v,w,x,y,z,i) z += ((w & (x ^ y)) ^ y) + SHA1_BLK(i) + 0x5a827999 + SHA1_ROL(v,5); w=SHA1_ROL(w,30);
#define SHA1_R2(v,w,x,y,z,i) z += (w ^ x ^ y) + SHA1_BLK(i) + 0x6ed9eba1 + SHA1_ROL(v,5); w=SHA1_ROL(w,30);
#define SHA1_R3(v,w,x,y,z,i) z += (((w | x) & y) | ( w & x)) + SHA1_BLK(i) + 0x8f1bbcdc + SHA1_ROL(v,5); w=SHA1_ROL(w,30);
#define SHA1_R4(v,w,x,y,z,i) z += (w ^ x ^ y) + SHA1_BLK(i) + 0xca62c1d6 + SHA1_ROL(v,5); w=SHA1_ROL(w,30);
/*
* Hash block is a single 512-bit block.
*/
void gxsha1_transform(uint32_t* block, uint32_t* digest, uint32_t* transforms)
{
uint32_t a = digest[0];
uint32_t b = digest[1];
uint32_t c = digest[2];
uint32_t d = digest[3];
uint32_t e = digest[4];
SHA1_R0(a, b, c, d, e, 0);
SHA1_R0(e, a, b, c, d, 1);
SHA1_R0(d, e, a, b, c, 2);
SHA1_R0(c, d, e, a, b, 3);
SHA1_R0(b, c, d, e, a, 4);
SHA1_R0(a, b, c, d, e, 5);
SHA1_R0(e, a, b, c, d, 6);
SHA1_R0(d, e, a, b, c, 7);
SHA1_R0(c, d, e, a, b, 8);
SHA1_R0(b, c, d, e, a, 9);
SHA1_R0(a, b, c, d, e, 10);
SHA1_R0(e, a, b, c, d, 11);
SHA1_R0(d, e, a, b, c, 12);
SHA1_R0(c, d, e, a, b, 13);
SHA1_R0(b, c, d, e, a, 14);
SHA1_R0(a, b, c, d, e, 15);
SHA1_R1(e, a, b, c, d, 16);
SHA1_R1(d, e, a, b, c, 17);
SHA1_R1(c, d, e, a, b, 18);
SHA1_R1(b, c, d, e, a, 19);
SHA1_R2(a, b, c, d, e, 20);
SHA1_R2(e, a, b, c, d, 21);
SHA1_R2(d, e, a, b, c, 22);
SHA1_R2(c, d, e, a, b, 23);
SHA1_R2(b, c, d, e, a, 24);
SHA1_R2(a, b, c, d, e, 25);
SHA1_R2(e, a, b, c, d, 26);
SHA1_R2(d, e, a, b, c, 27);
SHA1_R2(c, d, e, a, b, 28);
SHA1_R2(b, c, d, e, a, 29);
SHA1_R2(a, b, c, d, e, 30);
SHA1_R2(e, a, b, c, d, 31);
SHA1_R2(d, e, a, b, c, 32);
SHA1_R2(c, d, e, a, b, 33);
SHA1_R2(b, c, d, e, a, 34);
SHA1_R2(a, b, c, d, e, 35);
SHA1_R2(e, a, b, c, d, 36);
SHA1_R2(d, e, a, b, c, 37);
SHA1_R2(c, d, e, a, b, 38);
SHA1_R2(b, c, d, e, a, 39);
SHA1_R3(a, b, c, d, e, 40);
SHA1_R3(e, a, b, c, d, 41);
SHA1_R3(d, e, a, b, c, 42);
SHA1_R3(c, d, e, a, b, 43);
SHA1_R3(b, c, d, e, a, 44);
SHA1_R3(a, b, c, d, e, 45);
SHA1_R3(e, a, b, c, d, 46);
SHA1_R3(d, e, a, b, c, 47);
SHA1_R3(c, d, e, a, b, 48);
SHA1_R3(b, c, d, e, a, 49);
SHA1_R3(a, b, c, d, e, 50);
SHA1_R3(e, a, b, c, d, 51);
SHA1_R3(d, e, a, b, c, 52);
SHA1_R3(c, d, e, a, b, 53);
SHA1_R3(b, c, d, e, a, 54);
SHA1_R3(a, b, c, d, e, 55);
SHA1_R3(e, a, b, c, d, 56);
SHA1_R3(d, e, a, b, c, 57);
SHA1_R3(c, d, e, a, b, 58);
SHA1_R3(b, c, d, e, a, 59);
SHA1_R4(a, b, c, d, e, 60);
SHA1_R4(e, a, b, c, d, 61);
SHA1_R4(d, e, a, b, c, 62);
SHA1_R4(c, d, e, a, b, 63);
SHA1_R4(b, c, d, e, a, 64);
SHA1_R4(a, b, c, d, e, 65);
SHA1_R4(e, a, b, c, d, 66);
SHA1_R4(d, e, a, b, c, 67);
SHA1_R4(c, d, e, a, b, 68);
SHA1_R4(b, c, d, e, a, 69);
SHA1_R4(a, b, c, d, e, 70);
SHA1_R4(e, a, b, c, d, 71);
SHA1_R4(d, e, a, b, c, 72);
SHA1_R4(c, d, e, a, b, 73);
SHA1_R4(b, c, d, e, a, 74);
SHA1_R4(a, b, c, d, e, 75);
SHA1_R4(e, a, b, c, d, 76);
SHA1_R4(d, e, a, b, c, 77);
SHA1_R4(c, d, e, a, b, 78);
SHA1_R4(b, c, d, e, a, 79);
digest[0] += a;
digest[1] += b;
digest[2] += c;
digest[3] += d;
digest[4] += e;
++* transforms;
}
void gxsha1_update(gxByteBuffer* data, uint32_t* digest, uint32_t* transforms)
{
unsigned int pos;
uint32_t block[16];
while (data->size - data->position > 64)
{
for (pos = 0; pos != 16; ++pos)
{
bb_getUInt32(data, &block[pos]);
}
gxsha1_transform(block, digest, transforms);
}
}
int gxsha1_final(gxByteBuffer* data, uint32_t* digest, uint32_t* transforms, gxByteBuffer* reply)
{
int pos;
bb_capacity(reply, (uint16_t) *transforms * 64);
bb_set(reply, data->data, data->size);
/* Total number of hashed bits */
uint64_t total_bits = (*transforms * 64 + data->size) * 8;
/* Padding */
bb_setUInt8(reply, 0x80);
uint32_t orig_size = reply->size;
bb_zero(reply, reply->size, 64 - reply->size);
uint32_t block[16];
for (pos = 0; pos != 16; ++pos)
{
bb_getUInt32(reply, &block[pos]);
}
if (orig_size > 64 - 8)
{
gxsha1_transform(block, digest, transforms);
for (pos = 0; pos < 16 - 2; ++pos)
{
block[pos] = 0;
}
}
/* Append total_bits, split this uint64 into two uint32 */
block[16 - 1] = (uint32_t)total_bits;
block[16 - 2] = (uint32_t)(total_bits >> 32);
gxsha1_transform(block, digest, transforms);
bb_capacity(reply, 20);
reply->position = reply->size = 0;
for (pos = 0; pos < 5; ++pos)
{
bb_setUInt32(reply, digest[pos]);
}
return 0;
}
int gxsha1_encrypt(gxByteBuffer* data, gxByteBuffer* result)
{
uint32_t digest[5] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 };
uint32_t transforms = 0;
gxsha1_update(data, digest, &transforms);
return gxsha1_final(data, digest, &transforms, result);
}
#endif //DLMS_IGNORE_HIGH_SHA1

View File

@ -0,0 +1,52 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef GXSHA1
#define GXSHA1
#ifdef __cplusplus
extern "C" {
#endif
#include "gxignore.h"
#ifndef DLMS_IGNORE_HIGH_SHA1
#include "bytebuffer.h"
int gxsha1_encrypt(gxByteBuffer* data, gxByteBuffer* digest);
#endif //DLMS_IGNORE_HIGH_SHA1
#ifdef __cplusplus
}
#endif
#endif //GXSHA_256

View File

@ -0,0 +1,180 @@
//
// --------------------------------------------------------------------------
// Gurux Ltd
//
//
//
// Filename: $HeadURL$
//
// Version: $Revision$,
// $Date$
// $Author$
//
// Copyright (c) Gurux Ltd
//
//---------------------------------------------------------------------------
//
// DESCRIPTION
//
// This file is a part of Gurux Device Framework.
//
// Gurux Device Framework is Open Source software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; version 2 of the License.
// Gurux Device Framework is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// This code is licensed under the GNU General Public License v2.
// Full text may be retrieved at http://www.gnu.org/licenses/gpl-2.0.txt
//---------------------------------------------------------------------------
#include "gxignore.h"
#ifndef DLMS_IGNORE_HIGH_SHA256
#include <string.h>
#include "gxsha256.h"
const uint32_t sha256_k[64] =
{ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 };
#define SHA2_SHFR(x, n) (x >> n)
#define SHA2_ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
#define SHA2_ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
#define SHA2_CH(x, y, z) ((x & y) ^ (~x & z))
#define SHA2_MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
#define SHA256_F1(x) (SHA2_ROTR(x, 2) ^ SHA2_ROTR(x, 13) ^ SHA2_ROTR(x, 22))
#define SHA256_F2(x) (SHA2_ROTR(x, 6) ^ SHA2_ROTR(x, 11) ^ SHA2_ROTR(x, 25))
#define SHA256_F3(x) (SHA2_ROTR(x, 7) ^ SHA2_ROTR(x, 18) ^ SHA2_SHFR(x, 3))
#define SHA256_F4(x) (SHA2_ROTR(x, 17) ^ SHA2_ROTR(x, 19) ^ SHA2_SHFR(x, 10))
#define SHA2_UNPACK32(x, str) \
{ \
*((str) + 3) = (unsigned char) ((x) ); \
*((str) + 2) = (unsigned char) ((x) >> 8); \
*((str) + 1) = (unsigned char) ((x) >> 16); \
*((str) + 0) = (unsigned char) ((x) >> 24); \
}
#define SHA2_PACK32(str, x) \
{ \
*(x) = ((uint32_t) *((str) + 3) ) \
| ((uint32_t) *((str) + 2) << 8) \
| ((uint32_t) *((str) + 1) << 16) \
| ((uint32_t) *((str) + 0) << 24); \
}
void gxsha256_transform(uint32_t *h, const unsigned char *message, unsigned int block_nb)
{
uint32_t w[64];
uint32_t wv[8];
uint32_t t1, t2;
const unsigned char *sub_block;
unsigned int i;
int j;
for (i = 0; i < block_nb; i++)
{
sub_block = message + (i << 6);
for (j = 0; j < 16; j++)
{
SHA2_PACK32(&sub_block[j << 2], &w[j]);
}
for (j = 16; j < 64; j++)
{
w[j] = SHA256_F4(w[j - 2]) + w[j - 7] + SHA256_F3(w[j - 15]) + w[j - 16];
}
for (j = 0; j < 8; j++)
{
wv[j] = h[j];
}
for (j = 0; j < 64; j++) {
t1 = wv[7] + SHA256_F2(wv[4]) + SHA2_CH(wv[4], wv[5], wv[6])
+ sha256_k[j] + w[j];
t2 = SHA256_F1(wv[0]) + SHA2_MAJ(wv[0], wv[1], wv[2]);
wv[7] = wv[6];
wv[6] = wv[5];
wv[5] = wv[4];
wv[4] = wv[3] + t1;
wv[3] = wv[2];
wv[2] = wv[1];
wv[1] = wv[0];
wv[0] = t1 + t2;
}
for (j = 0; j < 8; j++)
{
h[j] += wv[j];
}
}
}
int gxsha256_update(uint32_t *h, unsigned char *block, gxByteBuffer* data, unsigned int *len, unsigned int *totalLen)
{
unsigned int block_nb;
unsigned int new_len, rem_len, tmp_len;
const unsigned char *shifted_message;
tmp_len = 64 - (data->size - data->position);
rem_len = data->size < tmp_len ? data->size : tmp_len;
memcpy(&block[data->position], data->data, rem_len);
if (data->size - data->position < 64)
{
data->position = data->size;
return 0;
}
new_len = *len - rem_len;
block_nb = new_len / 64;
shifted_message = data->data + rem_len;
gxsha256_transform(h, block, 1);
gxsha256_transform(h, shifted_message, block_nb);
rem_len = new_len % 64;
memcpy(block, &shifted_message[block_nb << 6], rem_len);
*len = rem_len;
*totalLen += (block_nb + 1) << 6;
return 0;
}
int gxsha256_final(uint32_t *h, unsigned char *block, unsigned char *digest, unsigned int len, unsigned int totalLen)
{
unsigned int block_nb;
unsigned int pm_len;
uint32_t len_b;
int i;
block_nb = (1 + ((64 - 9) < (len % 64)));
len_b = (totalLen + len) << 3;
pm_len = block_nb << 6;
memset(block + len, 0, pm_len - len);
block[len] = 0x80;
SHA2_UNPACK32(len_b, block + pm_len - 4);
gxsha256_transform(h, block, block_nb);
for (i = 0; i < 8; i++)
{
SHA2_UNPACK32(h[i], &digest[i << 2]);
}
return 0;
}
int gxsha256_encrypt(gxByteBuffer* data, gxByteBuffer* digest)
{
unsigned int len = data->size, totalLen = 0;
uint32_t h[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
unsigned char block[128];
bb_capacity(digest, 32);
digest->size = 32;
gxsha256_update((uint32_t*)&h, block, data, &len, &totalLen);
return gxsha256_final(h, block, digest->data, len, totalLen);
}
#endif //DLMS_IGNORE_HIGH_SHA256

View File

@ -0,0 +1,52 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef GXSHA_256
#define GXSHA_256
#include "gxignore.h"
#ifndef DLMS_IGNORE_HIGH_SHA256
#ifdef __cplusplus
extern "C" {
#endif
#include "bytebuffer.h"
int gxsha256_encrypt(gxByteBuffer* data, gxByteBuffer* digest);
#ifdef __cplusplus
}
#endif
#endif //DLMS_IGNORE_HIGH_SHA256
#endif //GXSHA_256

View File

@ -0,0 +1,233 @@
//
// --------------------------------------------------------------------------
// 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 "gxmem.h"
#if _MSC_VER > 1400
#include <crtdbg.h>
#endif
#include "gxvalueeventargs.h"
#include "objectarray.h"
void vec_init(gxValueEventCollection* arr)
{
arr->capacity = 0;
arr->data = NULL;
arr->position = 0;
arr->size = 0;
}
char vec_isAttached(gxValueEventCollection* arr)
{
return (arr->capacity & 0x80) == 0x80;
}
unsigned char vec_getCapacity(gxValueEventCollection* arr)
{
return arr->capacity & 0x7F;
}
#ifdef DLMS_IGNORE_MALLOC
void vec_attach(
gxValueEventCollection* arr,
gxValueEventArg* value,
unsigned char count,
unsigned char capacity)
{
arr->data = value;
arr->capacity = (uint16_t)(0x80 | capacity);
arr->size = count;
arr->position = 0;
}
#endif //DLMS_IGNORE_MALLOC
//Allocate new size for the array in bytes.
int vec_capacity(gxValueEventCollection* arr, unsigned char capacity)
{
#ifndef DLMS_IGNORE_MALLOC
if (!vec_isAttached(arr))
{
arr->capacity = capacity;
if (arr->data == NULL)
{
arr->data = (gxValueEventArg * *)gxmalloc(arr->capacity * sizeof(gxValueEventArg*));
}
else
{
#ifdef gxrealloc
//If compiler supports realloc.
arr->data = (gxValueEventArg * *)gxrealloc(arr->data, arr->capacity * sizeof(gxValueEventArg*));
#else
//If compiler doesn't supports realloc.
gxValueEventArg ** old = arr->data;
arr->data = (gxValueEventArg * *)gxmalloc(arr->capacity * sizeof(gxValueEventArg*));
//If not enought memory available.
if (arr->data == NULL)
{
arr->data = old;
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
memcpy(arr->data, old, sizeof(gxValueEventArg*) * arr->size);
gxfree(old);
#endif //gxrealloc
}
}
#endif //DLMS_IGNORE_MALLOC
if (vec_getCapacity(arr) < capacity)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
return 0;
}
#ifndef DLMS_IGNORE_MALLOC
//Push new data to the gxValueEventCollection.
int vec_push(gxValueEventCollection * arr, gxValueEventArg* item)
{
int ret = 0;
if (!vec_isAttached(arr))
{
if (arr->size >= vec_getCapacity(arr))
{
if ((ret = vec_capacity(arr, arr->capacity + 2)) != 0)
{
return ret;
}
}
}
if (vec_getCapacity(arr) <= arr->size)
{
ret = DLMS_ERROR_CODE_OUTOFMEMORY;
}
else
{
arr->data[arr->size] = item;
++arr->size;
}
return ret;
}
#endif //DLMS_IGNORE_MALLOC
void vec_empty(
gxValueEventCollection* arr)
{
#ifndef DLMS_IGNORE_MALLOC
if (!vec_isAttached(arr))
{
if (arr->size != 0)
{
gxfree(arr->data);
arr->data = NULL;
}
arr->capacity = 0;
}
#endif //DLMS_IGNORE_MALLOC
arr->size = 0;
arr->position = 0;
}
void vec_clear(
gxValueEventCollection* arr)
{
#ifndef DLMS_IGNORE_MALLOC
if (!vec_isAttached(arr))
{
int pos;
if (arr->size != 0)
{
for (pos = 0; pos != arr->size; ++pos)
{
ve_clear(arr->data[pos]);
gxfree(arr->data[pos]);
}
gxfree(arr->data);
arr->data = NULL;
}
arr->capacity = 0;
}
#endif //DLMS_IGNORE_MALLOC
arr->size = 0;
arr->position = 0;
}
int vec_getByIndex(gxValueEventCollection* arr, int index, gxValueEventArg** value)
{
if (index >= arr->size)
{
return DLMS_ERROR_CODE_OUTOFMEMORY;
}
#ifdef DLMS_IGNORE_MALLOC
*value = &arr->data[index];
#else
* value = arr->data[index];
#endif //DLMS_IGNORE_MALLOC
return 0;
}
void ve_init(gxValueEventArg * ve)
{
var_init(&ve->value);
ve->handled = 0;
ve->target = NULL;
ve->index = 0;
#if !defined(DLMS_IGNORE_MALLOC) && !defined(DLMS_COSEM_EXACT_DATA_TYPES)
ve->dataType = DLMS_DATA_TYPE_NONE;
#endif //!defined(DLMS_IGNORE_MALLOC) && !defined(DLMS_COSEM_EXACT_DATA_TYPES)
ve->selector = 0;
var_init(&ve->parameters);
ve->error = DLMS_ERROR_CODE_OK;
ve->action = 0;
ve->byteArray = 0;
ve->skipMaxPduSize = 0;
ve->transactionStartIndex = 0;
ve->transactionEndIndex = 0;
ve->transaction = 0;
}
void ve_clear(gxValueEventArg * ve)
{
var_clear(&ve->value);
ve->handled = 0;
ve->target = NULL;
ve->index = 0;
#if !defined(DLMS_IGNORE_MALLOC) && !defined(DLMS_COSEM_EXACT_DATA_TYPES)
ve->dataType = DLMS_DATA_TYPE_NONE;
#endif //!defined(DLMS_IGNORE_MALLOC) && !defined(DLMS_COSEM_EXACT_DATA_TYPES)
ve->selector = 0;
var_clear(&ve->parameters);
ve->error = DLMS_ERROR_CODE_OK;
ve->action = 0;
ve->byteArray = 0;
ve->skipMaxPduSize = 0;
ve->transactionStartIndex = 0;
ve->transactionEndIndex = 0;
ve->transaction = 0;
}

View File

@ -0,0 +1,514 @@
//
// --------------------------------------------------------------------------
// 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(_WIN32) || defined(_WIN64) || defined(__linux__)
#include <assert.h>
#endif
#include "gxmem.h"
#if _MSC_VER > 1400
#include <crtdbg.h>
#endif
#include "notify.h"
#include "cosem.h"
#include "gxset.h"
#include "serverevents.h"
int notify_getData(
dlmsSettings* settings,
gxByteBuffer* reply,
gxReplyData* data)
{
return dlms_getData2(settings, reply, data, 0);
}
int notify_addData(
dlmsSettings* settings,
gxObject* obj,
unsigned char index,
gxByteBuffer* buff)
{
int ret;
gxValueEventArg e;
ve_init(&e);
e.target = obj;
e.index = index;
#ifdef DLMS_IGNORE_MALLOC
e.value.byteArr = buff;
e.value.vt = DLMS_DATA_TYPE_OCTET_STRING;
#endif //DLMS_IGNORE_MALLOC
if ((ret = cosem_getValue(settings, &e)) != 0)
{
return ret;
}
if (e.byteArray)
{
if (!bb_isAttached(buff))
{
bb_set(buff, e.value.byteArr->data, e.value.byteArr->size);
var_clear(&e.value);
}
return 0;
}
ret = dlms_setData(buff, e.value.vt, &e.value);
var_clear(&e.value);
return ret;
}
int notify_generateDataNotificationMessages2(
dlmsSettings* settings,
#ifdef DLMS_USE_EPOCH_TIME
uint32_t time,
#else
struct tm* time,
#endif //DLMS_USE_EPOCH_TIME
gxByteBuffer* data,
message* messages)
{
int ret;
if (settings->useLogicalNameReferencing)
{
gxLNParameters p;
params_initLN(&p, settings, 0, DLMS_COMMAND_DATA_NOTIFICATION, 0, data, NULL, 0xff, DLMS_COMMAND_NONE, 0, 0);
p.time = time;
ret = dlms_getLnMessages(&p, messages);
}
else
{
#if !defined(DLMS_IGNORE_ASSOCIATION_SHORT_NAME) && !defined(DLMS_IGNORE_MALLOC)
gxSNParameters p;
params_initSN(&p, settings, DLMS_COMMAND_DATA_NOTIFICATION, 1, 0, data, NULL, DLMS_COMMAND_NONE);
ret = dlms_getSnMessages(&p, messages);
#else
ret = DLMS_ERROR_CODE_INVALID_PARAMETER;
#endif //!defined(DLMS_IGNORE_ASSOCIATION_SHORT_NAME) && !defined(DLMS_IGNORE_MALLOC)
}
return ret;
}
int notify_generateDataNotificationMessages(
dlmsSettings* settings,
#ifdef DLMS_USE_EPOCH_TIME
uint32_t date,
#else
struct tm* date,
#endif //DLMS_USE_EPOCH_TIME
gxArray* objects,
message* messages)
{
int ret = 0;
uint16_t pos;
gxListItem* it;
gxByteBuffer buff;
BYTE_BUFFER_INIT(&buff);
bb_setUInt8(&buff, DLMS_DATA_TYPE_STRUCTURE);
hlp_setObjectCount(objects->size, &buff);
for (pos = 0; pos != objects->size; ++pos)
{
#ifdef DLMS_IGNORE_MALLOC
if ((ret = arr_getByIndex(objects, pos, (void**)&it, sizeof(gxListItem))) != 0)
{
break;
}
#else
if ((ret = arr_getByIndex(objects, pos, (void**)&it)) != 0)
{
break;
}
#endif //DLMS_IGNORE_MALLOC
if ((ret = notify_addData(settings, it->key, it->value, &buff)) != 0)
{
break;
}
}
if (ret == 0)
{
return notify_generateDataNotificationMessages2(settings, date, &buff, messages);
}
bb_clear(&buff);
return ret;
}
//Sends Event Notification Request.
int notify_generateEventNotificationMessages(
dlmsSettings* settings,
#ifdef DLMS_USE_EPOCH_TIME
uint32_t time,
#else
struct tm* time,
#endif //DLMS_USE_EPOCH_TIME
gxListItem* item,
variantArray* data,
gxByteBuffer* pdu,
message* messages)
{
int ret;
uint16_t pos;
dlmsVARIANT* it;
if ((ret = bb_setUInt16(pdu, item->key->objectType)) != 0 ||
(ret = bb_set(pdu, item->key->logicalName, 6)) != 0 ||
(ret = bb_setUInt8(pdu, item->value)) != 0)
{
return ret;
}
if (data == NULL)
{
if ((ret = notify_addData(settings, item->key, item->value, pdu)) != 0)
{
return ret;
}
}
else
{
if ((ret = bb_setUInt8(pdu, DLMS_DATA_TYPE_ARRAY)) == 0 &&
(ret = hlp_setObjectCount(data->size, pdu)) == 0)
{
for (pos = 0; pos != data->size; ++pos)
{
if ((ret = va_getByIndex(data, pos, &it)) != 0 ||
(ret = dlms_setData(pdu, it->vt, it)) != 0)
{
break;
}
}
}
}
if (ret == 0)
{
gxLNParameters p;
params_initLN(&p, settings, 0, DLMS_COMMAND_EVENT_NOTIFICATION, 0, pdu, NULL, 0xff, DLMS_COMMAND_NONE, 0, 0);
p.time = time;
ret = dlms_getLnMessages(&p, messages);
}
return ret;
}
//Sends Event Notification Request.
int notify_generateEventNotificationMessages2(
dlmsSettings* settings,
#ifdef DLMS_USE_EPOCH_TIME
uint32_t time,
#else
struct tm* time,
#endif //DLMS_USE_EPOCH_TIME
gxListItem* item,
gxByteBuffer* data,
gxByteBuffer* pdu,
message* messages)
{
int ret;
if ((ret = bb_setUInt16(pdu, item->key->objectType)) != 0 ||
(ret = bb_set(pdu, item->key->logicalName, 6)) != 0 ||
(ret = bb_setUInt8(pdu, item->value)) != 0)
{
return ret;
}
ret = bb_set2(pdu, data, data->position, bb_available(data));
if (ret == 0)
{
gxLNParameters p;
params_initLN(&p, settings, 0, DLMS_COMMAND_EVENT_NOTIFICATION, 0, pdu, NULL, 0xff, DLMS_COMMAND_NONE, 0, 0);
p.time = time;
ret = dlms_getLnMessages(&p, messages);
}
return ret;
}
#ifndef DLMS_IGNORE_PUSH_SETUP
int notify_generatePushSetupMessages(
dlmsSettings* settings,
#ifdef DLMS_USE_EPOCH_TIME
uint32_t date,
#else
struct tm* date,
#endif //DLMS_USE_EPOCH_TIME
gxPushSetup* push,
message* messages)
{
int ret = 0;
uint16_t pos;
gxByteBuffer pdu;
gxValueEventCollection args;
#ifdef DLMS_IGNORE_MALLOC
gxTarget* it;
pdu = *settings->serializedPdu;
gxValueEventArg p[1];
ve_init(&p[0]);
p[0].action = 1;
vec_attach(&args, p, 1, 1);
#else
gxValueEventArg e;
gxKey* it;
BYTE_BUFFER_INIT(&pdu);
ve_init(&e);
vec_init(&args);
vec_push(&args, &e);
#endif //DLMS_IGNORE_MALLOC
if (push == NULL || messages == NULL)
{
return DLMS_ERROR_CODE_INVALID_PARAMETER;
}
mes_clear(messages);
if ((ret = bb_setUInt8(&pdu, DLMS_DATA_TYPE_STRUCTURE)) == 0 &&
(ret = hlp_setObjectCount(push->pushObjectList.size, &pdu)) == 0)
{
for (pos = 0; pos != push->pushObjectList.size; ++pos)
{
#ifdef DLMS_IGNORE_MALLOC
if ((ret = arr_getByIndex(&push->pushObjectList, pos, (void**)&it, sizeof(gxTarget))) != 0)
{
break;
}
#else
if ((ret = arr_getByIndex(&push->pushObjectList, pos, (void**)&it)) != 0)
{
break;
}
#endif //DLMS_IGNORE_MALLOC
#ifdef DLMS_IGNORE_MALLOC
p[0].target = it->target;
p[0].index = it->attributeIndex;
svr_preRead(settings, &args);
if (p[0].error != 0)
{
break;
}
if ((ret = notify_addData(settings, it->target, it->attributeIndex, &pdu)) != 0)
{
break;
}
#else
e.target = (gxObject*)it->key;
e.index = ((gxTarget*)it->value)->attributeIndex;
#ifndef DLMS_IGNORE_SERVER
svr_preRead(settings, &args);
#endif
if (e.error != 0)
{
break;
}
if (e.value.vt != DLMS_DATA_TYPE_NONE)
{
ret = dlms_setData(&pdu, e.value.vt, &e.value);
var_clear(&e.value);
}
else
{
if ((ret = notify_addData(settings, (gxObject*)it->key, ((gxTarget*)it->value)->attributeIndex, &pdu)) != 0)
{
break;
}
}
#endif //DLMS_IGNORE_MALLOC
#ifndef DLMS_IGNORE_SERVER
svr_postRead(settings, &args);
#endif //DLMS_IGNORE_SERVER
#ifdef DLMS_IGNORE_MALLOC
ve_clear(&p[0]);
if (p[0].error != 0)
{
break;
}
#else
ve_clear(&e);
if (e.error != 0)
{
break;
}
#endif //DLMS_IGNORE_MALLOC
}
}
vec_empty(&args);
if (ret == 0)
{
#ifdef DLMS_IGNORE_MALLOC
//Update size and position
settings->serializedPdu->position = pdu.position;
settings->serializedPdu->size = pdu.size;
#endif //DLMS_IGNORE_MALLOC
ret = notify_generateDataNotificationMessages2(settings, date, &pdu, messages);
}
#ifndef DLMS_IGNORE_MALLOC
bb_clear(&pdu);
#endif //DLMS_IGNORE_MALLOC
return ret;
}
int notify_parsePush(
dlmsSettings* settings,
variantArray* data,
gxArray* items)
{
gxListItem* k;
gxObject* obj;
unsigned char index;
int classID, ret;
uint16_t pos;
gxValueEventArg e;
dlmsVARIANT* it, * list, * tmp;
if ((ret = va_getByIndex(data, 0, &list)) != 0)
{
return ret;
}
for (pos = 0; pos != list->Arr->size; ++pos)
{
if ((ret = va_getByIndex(list->Arr, pos, &it)) != 0)
{
return ret;
}
if ((ret = va_getByIndex(it->Arr, 0, &tmp)) != 0)
{
return ret;
}
classID = var_toInteger(tmp) & 0xFFFF;
if (classID > 0)
{
if ((ret = va_getByIndex(it->Arr, 1, &tmp)) != 0)
{
return ret;
}
if ((ret = oa_findByLN(&settings->objects, (DLMS_OBJECT_TYPE)classID, tmp->byteArr->data, &obj)) != 0)
{
return ret;
}
if (obj == NULL)
{
#ifdef DLMS_IGNORE_MALLOC
return DLMS_ERROR_CODE_OUTOFMEMORY;
#else
if ((ret = cosem_createObject((DLMS_OBJECT_TYPE)classID, &obj)) != 0)
{
return ret;
}
memcpy(obj->logicalName, tmp->byteArr, 6);
oa_push(&settings->objects, obj);
//Add object to released objects list.
ret = oa_push(&settings->releasedObjects, obj);
#endif //DLMS_IGNORE_MALLOC
}
#ifdef DLMS_IGNORE_MALLOC
return DLMS_ERROR_CODE_OUTOFMEMORY;
#else
if ((ret = va_getByIndex(it->Arr, 2, &tmp)) != 0)
{
return ret;
}
index = (unsigned char)var_toInteger(tmp);
#if defined(_WIN64) || defined(__LP64__) || defined(_LP64)
arr_push(items, key_init(obj, (void*)(uint64_t)index));
#else
arr_push(items, key_init(obj, (void*)(uint32_t)index));
#endif //DLMS_IGNORE_MALLOC
#endif //DLMS_IGNORE_MALLOC
}
}
ve_init(&e);
for (pos = 0; pos != items->size; ++pos)
{
#ifdef DLMS_IGNORE_MALLOC
if ((ret = arr_getByIndex(items, pos, (void**)&k, sizeof(gxListItem))) != 0)
{
break;
}
#else
if ((ret = arr_getByIndex(items, pos, (void**)&k)) != 0)
{
break;
}
#endif //DLMS_IGNORE_MALLOC
obj = (gxObject*)k->key;
if ((ret = va_getByIndex(data, pos, &it)) != 0)
{
return ret;
}
index = k->value;
e.target = obj;
e.index = index;
e.value = *it;
if ((ret = cosem_setValue(settings, &e)) != 0)
{
return ret;
}
}
return ret;
}
#if !defined(DLMS_IGNORE_MALLOC) && !defined(DLMS_COSEM_EXACT_DATA_TYPES)
int notify_getPushValues(
dlmsSettings* settings,
gxPushSetup* pushSetup,
variantArray* data,
gxArray* items)
{
gxObject* tmp;
gxKey* k;
int ret = 0;
uint16_t pos;
gxValueEventArg e;
dlmsVARIANT* it;
for (pos = 0; pos != pushSetup->pushObjectList.size; ++pos)
{
if ((ret = arr_getByIndex(&pushSetup->pushObjectList, pos, (void**)&k)) != 0)
{
break;
}
if ((ret = cosem_createObject(((gxObject*)k->key)->objectType, &tmp)) != 0)
{
break;
}
memcpy(tmp->logicalName, ((gxObject*)k->key)->logicalName, 6);
if ((ret = va_getByIndex(data, pos, &it)) != 0)
{
return ret;
}
e.target = (gxObject*)tmp;
e.index = ((gxTarget*)k->value)->attributeIndex;
e.value = *it;
if ((ret = cosem_setValue(settings, &e)) != 0)
{
break;
}
arr_push(items, key_init(e.target, co_init(e.index, 0)));
}
return ret;
}
#endif //!defined(DLMS_IGNORE_MALLOC) && !defined(DLMS_COSEM_EXACT_DATA_TYPES)
#endif //DLMS_IGNORE_PUSH_SETUP

View File

@ -0,0 +1,188 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef NOTIFY_H
#define NOTIFY_H
#include "gxignore.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "dlms.h"
#include "gxget.h"
#include "gxkey.h"
/**
* Removes the HDLC frame from the packet, and returns COSEM data only.
*
* @param reply
* The received data from the device.
* @param data
* Information from the received data.
* @return Is frame complete.
*/
int notify_getData(
dlmsSettings* settings,
gxByteBuffer* reply,
gxReplyData *data);
/**
* Add value of COSEM object to byte buffer. AddData method can be used with
* GetDataNotificationMessage -method. DLMS specification do not specify the
* structure of Data-Notification body. So each manufacture can sent
* different data.
*
* @param obj
* COSEM object.
* @param index
* Attribute index.
* @param buff
* Byte buffer.
*/
int notify_addData(
dlmsSettings* settings,
gxObject* obj,
unsigned char index,
gxByteBuffer* buff);
/**
* Generates data notification message.
*
* @param date
* Date time. Set to null or Date(0) if not used
* @param data
* Notification body.
* @return Generated data notification message(s).
*/
int notify_generateDataNotificationMessages2(
dlmsSettings* settings,
#ifdef DLMS_USE_EPOCH_TIME
uint32_t time,
#else
struct tm* time,
#endif //DLMS_USE_EPOCH_TIME
gxByteBuffer* data,
message* messages);
/**
* Generates data notification message.
*
* @param date
* Date time. Set To Min or Max if not added.
* @param objects
* List of objects and attribute indexes to notify.
* @return Generated data notification message(s).
*/
int notify_generateDataNotificationMessages(
dlmsSettings* settings,
#ifdef DLMS_USE_EPOCH_TIME
uint32_t date,
#else
struct tm* date,
#endif //DLMS_USE_EPOCH_TIME
gxArray* objects,
message* messages);
#ifndef DLMS_IGNORE_PUSH_SETUP
/**
* Generates push setup message.
*
* @param date
* Date time. Set to null or Date(0) if not used.
* @param push
* Target Push object.
* @return Generated data notification message(s).
*/
int notify_generatePushSetupMessages(
dlmsSettings* settings,
#ifdef DLMS_USE_EPOCH_TIME
uint32_t date,
#else
struct tm* date,
#endif //DLMS_USE_EPOCH_TIME
gxPushSetup* push,
message* messages);
/**
* Returns collection of push objects. If this method is used Push object
* must be set for first object on push object list.
*
* @param data
* Received value.
* @return Array of objects and called indexes.
*/
int notify_parsePush(
dlmsSettings* settings,
variantArray* data,
gxArray* items);
#if !defined(DLMS_IGNORE_MALLOC) && !defined(DLMS_COSEM_EXACT_DATA_TYPES)
int notify_getPushValues(
dlmsSettings* settings,
gxPushSetup* pushSetup,
variantArray* data,
gxArray* items);
#endif //!defined(DLMS_IGNORE_MALLOC) && !defined(DLMS_COSEM_EXACT_DATA_TYPES)
//Sends Event Notification Request.
int notify_generateEventNotificationMessages2(
dlmsSettings* settings,
#ifdef DLMS_USE_EPOCH_TIME
uint32_t time,
#else
struct tm* time,
#endif //DLMS_USE_EPOCH_TIME
gxListItem* item,
gxByteBuffer* data,
gxByteBuffer* pdu,
message* messages);
//Sends Event Notification Request.
int notify_generateEventNotificationMessages(
dlmsSettings* settings,
#ifdef DLMS_USE_EPOCH_TIME
uint32_t time,
#else
struct tm* time,
#endif //DLMS_USE_EPOCH_TIME
gxListItem* item,
variantArray* data,
gxByteBuffer* pdu,
message* messages);
#endif //DLMS_IGNORE_PUSH_SETUP
#ifdef __cplusplus
}
#endif
#endif //NOTIFY_H

2615
components/xt211/variant.c Normal file

File diff suppressed because it is too large Load Diff

534
components/xt211/variant.h Normal file
View File

@ -0,0 +1,534 @@
//
// --------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
#ifndef VARIANT_H
#define VARIANT_H
#ifdef __cplusplus
extern "C" {
#endif
#include "gxignore.h"
#include "date.h"
#include "enums.h"
#include "errorcodes.h"
#include "bytebuffer.h"
#include "bitarray.h"
#if _MSC_VER > 1400
#pragma warning(disable : 4201)
#endif
#if defined(_WIN32) || defined(_WIN64) || defined(__linux__)
#include <assert.h>
#endif
#define GX_SWAP_UINT16(a)(((a & 0xFF) << 8) | ((a & 0xFF00) >> 8))
#define GX_SWAP_UINT32(a)(GX_SWAP_UINT16(a & 0xFFFF) << 16) | (GX_SWAP_UINT16(a >> 16) )
#define VARIANT_ARRAY_CAPACITY 10
#if defined(_WIN32) || defined(_WIN64) || defined(__linux__)
#define VERIFY(X, TYPE) (assert(X.vt == TYPE))
#else
#define VERIFY(X, TYPE)
#endif
#define V_VT(X) ((X)->vt)
#define GX_UNION(X, Y, Z) V_VT(X)=Z;(X)->Y
#ifdef DLMS_IGNORE_MALLOC
#define GX_UNION2(X, Y, Z, S, C) (X)->size=S;(X)->capacity=C;V_VT(X)=Z;(X)->Y
#endif //DLMS_IGNORE_MALLOC
#define GX_UINT8(X) GX_UNION(&X, bVal, DLMS_DATA_TYPE_UINT8)
#define GX_UINT16(X) GX_UNION(&X, uiVal, DLMS_DATA_TYPE_UINT16)
#define GX_UINT32(X) GX_UNION(&X, ulVal, DLMS_DATA_TYPE_UINT32)
#define GX_UINT64(X) GX_UNION(&X, ullVal, DLMS_DATA_TYPE_UINT64)
#define GX_INT8(X) GX_UNION(&X, cVal, DLMS_DATA_TYPE_INT8)
#define GX_INT16(X) GX_UNION(&X, iVal, DLMS_DATA_TYPE_INT16)
#define GX_INT32(X) GX_UNION(&X, lVal, DLMS_DATA_TYPE_INT32)
#define GX_INT64(X) GX_UNION(&X, llVal, DLMS_DATA_TYPE_INT64)
#define GX_FLOAT(X) GX_UNION(&X, fltVal, DLMS_DATA_TYPE_FLOAT32)
#define GX_DOUBLE(X) GX_UNION(&X, dblVal, DLMS_DATA_TYPE_FLOAT64)
#define GX_BOOL(X) GX_UNION(&X, bVal, DLMS_DATA_TYPE_BOOLEAN)
#ifdef DLMS_IGNORE_MALLOC
#define GX_DATETIME(X) X.size = 12; GX_UNION(&X, pVal, (DLMS_DATA_TYPE)(DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_DATETIME))
#else
#define GX_DATETIME(X) GX_UNION(&X, pVal, (DLMS_DATA_TYPE)(DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_DATETIME))
#endif //DLMS_IGNORE_MALLOC
#define GX_DATE(X) GX_UNION(&X, pVal, (DLMS_DATA_TYPE)(DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_DATE))
#define GX_TIME(X) GX_UNION(&X, pVal, (DLMS_DATA_TYPE)(DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_TIME))
#define GX_UINT8_BYREF(X, VALUE_) GX_UNION(&X, pbVal = &VALUE_, (DLMS_DATA_TYPE)(DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_UINT8))
#define GX_UINT16_BYREF(X, VALUE_) GX_UNION(&X, puiVal = &VALUE_, (DLMS_DATA_TYPE)(DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_UINT16))
#define GX_UINT32_BYREF(X, VALUE_) GX_UNION(&X, pulVal = &VALUE_, (DLMS_DATA_TYPE)(DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_UINT32))
#define GX_UINT64_BYREF(X, VALUE_) GX_UNION(&X, pullVal = &VALUE_, (DLMS_DATA_TYPE)(DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_UINT64))
#define GX_INT8_BYREF(X, VALUE_) GX_UNION(&X, pcVal = &VALUE_, (DLMS_DATA_TYPE)(DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_INT8))
#define GX_INT16_BYREF(X, VALUE_) GX_UNION(&X, piVal = &VALUE_, (DLMS_DATA_TYPE)(DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_INT16))
#define GX_INT32_BYREF(X, VALUE_) GX_UNION(&X, plVal = &VALUE_, (DLMS_DATA_TYPE)(DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_INT32))
#define GX_INT64_BYREF(X, VALUE_) GX_UNION(&X, pllVal = &VALUE_, (DLMS_DATA_TYPE)(DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_INT64))
#define GX_FLOAT_BYREF(X, VALUE_) GX_UNION(&X, pfltVal = &VALUE_, (DLMS_DATA_TYPE)(DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_FLOAT32))
#define GX_DOUBLE_BYREF(X, VALUE_) GX_UNION(&X, pdblVal = &VALUE_, (DLMS_DATA_TYPE)(DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_FLOAT64))
#ifdef DLMS_IGNORE_MALLOC
#define GX_OCTET_STRING(X, VALUE_, SIZE_) GX_UNION2(&X, pVal = VALUE_, (DLMS_DATA_TYPE) (DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_OCTET_STRING), SIZE_, sizeof(VALUE_))
#define GX_BIT_STRING(X, VALUE_, SIZE_) GX_UNION2(&X, pVal = VALUE_, (DLMS_DATA_TYPE) (DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_BIT_STRING), SIZE_, 8 * sizeof(VALUE_)/sizeof(VALUE_[0]))
#define GX_STRING(X, VALUE_, SIZE_) GX_UNION2(&X, pVal = VALUE_, (DLMS_DATA_TYPE)(DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_STRING), SIZE_, sizeof(VALUE_))
#define GX_ARRAY(X, VALUE_) GX_UNION2(&X, pVal = &VALUE_, (DLMS_DATA_TYPE)(DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_ARRAY), 0, 0)
#define GX_STRUCT(X, VALUE_) GX_UNION2(&X, pVal = &VALUE_, (DLMS_DATA_TYPE)(DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_STRUCTURE), 0, 0)
#endif //DLMS_IGNORE_MALLOC
#define GX_BOOL_BYREF(X, VALUE_) GX_UNION(&X, pcVal = &VALUE_, (DLMS_DATA_TYPE)(DLMS_DATA_TYPE_BYREF | DLMS_DATA_TYPE_BOOLEAN))
/*Get UInt8 value from variant.*/
#define GX_GET_UINT8(X) (X.vt & DLMS_DATA_TYPE_BYREF) == 0 ? X.bVal : *X.pbVal
/*Get UInt16 value from variant.*/
#define GX_GET_UINT16(X) (X.vt & DLMS_DATA_TYPE_BYREF) == 0 ? X.uiVal : *X.puiVal
/*Get UInt32 value from variant.*/
#define GX_GET_UINT32(X) (X.vt & DLMS_DATA_TYPE_BYREF) == 0 ? X.culVal : *X.pulVal
/*Get UInt64 value from variant.*/
#define GX_GET_UINT64(X) (X.vt & DLMS_DATA_TYPE_BYREF) == 0 ? X.cullVal : *X.pullVal
/*Get Int8 value from variant.*/
#define GX_GET_INT8(X) (X.vt & DLMS_DATA_TYPE_BYREF) == 0 ? X.cVal : *X.pcVal
/*Get Int16 value from variant.*/
#define GX_GET_INT16(X)(X.vt & DLMS_DATA_TYPE_BYREF) == 0 ? X.iVal : *X.piVal
/*Get Int32 value from variant.*/
#define GX_GET_INT32(X)(X.vt & DLMS_DATA_TYPE_BYREF) == 0 ? X.lVal : *X.plVal
/*Get Int64 value from variant.*/
#define GX_GET_INT64(X)(X.vt & DLMS_DATA_TYPE_BYREF) == 0 ? X.llVal : *X.pllVal
/*Get float value from variant.*/
#define GX_GET_FLOAT(X) (X.vt & DLMS_DATA_TYPE_BYREF) == 0 ? X.fltVal : *X.pfltVal
/*Get double value from variant.*/
#define GX_GET_DOUBLE(X) (X.vt & DLMS_DATA_TYPE_BYREF) == 0 ? X.dblVal : *X.pdblVal
/*Get boolean value from variant.*/
#define GX_GET_BOOL(X) (X.vt & DLMS_DATA_TYPE_BYREF) == 0 ? (X.bVal != 0) : (*X.pbVal != 0)
typedef struct
{
#ifdef DLMS_IGNORE_MALLOC
void* data;
#else
void** data;
#endif //DLMS_IGNORE_MALLOC
uint16_t capacity;
uint16_t size;
} variantArray;
typedef struct tagdlmsVARIANT
{
DLMS_DATA_TYPE vt;
union
{
unsigned char bVal;
signed char cVal;
int16_t iVal;
int32_t lVal;
int64_t llVal;
#ifndef DLMS_IGNORE_FLOAT32
float fltVal;
#endif //DLMS_IGNORE_FLOAT32
#ifndef DLMS_IGNORE_FLOAT64
double dblVal;
#endif //DLMS_IGNORE_FLOAT64
unsigned char boolVal;
uint16_t uiVal;
uint32_t ulVal;
uint64_t ullVal;
#ifndef DLMS_IGNORE_MALLOC
gxtime* dateTime;
gxByteBuffer* strVal;
gxByteBuffer* strUtfVal;
bitArray* bitArr;
#endif //DLMS_IGNORE_MALLOC
variantArray* Arr;
gxByteBuffer* byteArr;
unsigned char* pbVal;
signed char* pcVal;
short* piVal;
int32_t* plVal;
int64_t* pllVal;
#ifndef DLMS_IGNORE_FLOAT32
float* pfltVal;
#endif //DLMS_IGNORE_FLOAT32
#ifndef DLMS_IGNORE_FLOAT64
double* pdblVal;
#endif //DLMS_IGNORE_FLOAT64
unsigned char* pboolVal;
uint16_t* puiVal;
uint32_t* pulVal;
uint64_t* pullVal;
void* pVal;
};
#ifdef DLMS_IGNORE_MALLOC
uint16_t size;
uint16_t capacity;
#endif //DLMS_IGNORE_MALLOC
} dlmsVARIANT;
#ifdef DLMS_IGNORE_MALLOC
typedef dlmsVARIANT* dlmsVARIANT_PTR;
#else
typedef dlmsVARIANT* dlmsVARIANT_PTR;
#endif //DLMS_IGNORE_MALLOC
//Initialize variantArray.
void va_init(
variantArray* arr);
#ifdef DLMS_IGNORE_MALLOC
void va_attach(
variantArray* trg,
dlmsVARIANT* src,
uint16_t size,
uint16_t capacity);
#endif //DLMS_IGNORE_MALLOC
void va_attach2(
variantArray* trg,
variantArray* src);
//Is variant array attached.
char va_isAttached(variantArray* arr);
//Get variant array capacity.
uint16_t va_size(
variantArray* arr);
//Get variant array capacity.
uint16_t va_getCapacity(
variantArray* arr);
//Allocate new size for the array in bytes.
int va_capacity(
variantArray* arr,
uint16_t capacity);
//Push new data to the variantArray.
int va_push(
variantArray* arr,
dlmsVARIANT* item);
void va_clear(
variantArray* arr);
//Set byte value to variant.
int var_setUInt8(
dlmsVARIANT* data,
unsigned char value);
//Set UInt16 value to variant.
int var_setUInt16(
dlmsVARIANT* data,
uint16_t value);
//Set UInt32 value to variant.
int var_setUInt32(dlmsVARIANT
* data,
uint32_t value);
//Set UInt64 value to variant.
int var_setUInt64(
dlmsVARIANT* data,
uint64_t value);
//Set signed byte value to variant.
int var_setInt8(
dlmsVARIANT* data,
char value);
//Set Int16 value to variant.
int var_setInt16(
dlmsVARIANT* data,
short value);
//Set Int32 value to variant.
int var_setInt32(
dlmsVARIANT* data,
int32_t value);
//Set Int64 value to variant.
int var_setInt64(
dlmsVARIANT* data,
int64_t value);
#ifndef DLMS_IGNORE_FLOAT64
int var_setDouble(
dlmsVARIANT* data,
double value);
#endif //DLMS_IGNORE_FLOAT64
#ifndef DLMS_IGNORE_MALLOC
int var_setDateTime(
dlmsVARIANT* target,
gxtime* value);
int var_setDate(
dlmsVARIANT* target,
gxtime* value);
int var_setTime(
dlmsVARIANT* target,
gxtime* value);
#endif //DLMS_IGNORE_MALLOC
int var_setBoolean(
dlmsVARIANT* target,
char value);
int var_getDateTime(
dlmsVARIANT* target,
gxtime* value);
int var_getDateTime2(
gxtime* dateTime,
gxByteBuffer* ba);
int var_getDate(
gxtime* date,
gxByteBuffer* ba);
int var_getTime(
gxtime* date,
gxByteBuffer* ba);
int var_setDateTimeAsOctetString(
dlmsVARIANT* target,
gxtime* value);
int var_setDateAsOctetString(
dlmsVARIANT* target,
gxtime* value);
int var_setTimeAsOctetString(
dlmsVARIANT* target,
gxtime* value);
//Get byte value from variant.
int var_getUInt8(
dlmsVARIANT* data,
unsigned char* value);
//Get UInt16 value from variant.
int var_getUInt16(
dlmsVARIANT* data,
uint16_t* value);
//Get UInt32 value from variant.
int var_getUInt32(
dlmsVARIANT* data,
uint32_t* value);
//Get UInt64 value from variant.
int var_getUInt64(
dlmsVARIANT* data,
uint64_t* value);
//Get signed byte value from variant.
int var_getInt8(
dlmsVARIANT* data,
char* value);
//Get Int16 value from variant.
int var_getInt16(
dlmsVARIANT* data,
short* value);
//Get Int32 value from variant.
int var_getInt32(
dlmsVARIANT* data,
int32_t* value);
//Get Int64 value from variant.
int var_getInt64(
dlmsVARIANT* data,
int64_t* value);
#ifndef DLMS_IGNORE_MALLOC
int var_addBytes(
dlmsVARIANT* data,
const unsigned char* value,
uint16_t count);
#endif //DLMS_IGNORE_MALLOC
#ifndef DLMS_IGNORE_MALLOC
int var_setString(
dlmsVARIANT* data,
const char* value,
uint16_t count);
#endif //DLMS_IGNORE_MALLOC
#ifndef DLMS_IGNORE_MALLOC
void var_attach(
dlmsVARIANT* target,
gxByteBuffer* source);
#endif //DLMS_IGNORE_MALLOC
int var_addOctetString(
dlmsVARIANT* data,
gxByteBuffer* ba);
int var_setEnum(dlmsVARIANT* data,
unsigned char value);
int var_addByteArray(
dlmsVARIANT* data,
gxByteBuffer* ba,
uint16_t index,
uint16_t count);
//Initialize variant.
int var_init(
dlmsVARIANT* data);
#ifndef DLMS_IGNORE_MALLOC
//attach static array.
void var_attachArray(
dlmsVARIANT* data,
const variantArray* arr,
const uint16_t count);
#endif //DLMS_IGNORE_MALLOC
#ifndef DLMS_IGNORE_MALLOC
//attach static structure.
void var_attachStructure(
dlmsVARIANT* data,
const dlmsVARIANT** arr,
const uint16_t count);
#endif //DLMS_IGNORE_MALLOC
//copy variant.
int var_copy(
dlmsVARIANT* value,
dlmsVARIANT* copy);
//Clear variant.
int var_clear(
dlmsVARIANT* data);
//Get bytes from variant value.
int var_getBytes(
dlmsVARIANT* data,
gxByteBuffer* ba);
//Get bytes from variant value.
int var_getBytes2(
dlmsVARIANT* data,
DLMS_DATA_TYPE type,
gxByteBuffer* ba);
//Get bytes from variant value without data type.
int var_getBytes3(
dlmsVARIANT* data,
DLMS_DATA_TYPE type,
gxByteBuffer* ba,
unsigned char addType);
//Get size in bytes.
int var_getSize(
DLMS_DATA_TYPE vt);
//Convert variant value to integer.
int var_toInteger(
dlmsVARIANT* data);
//Get item from variant array by index.
int va_getByIndex(
variantArray* arr,
int index,
dlmsVARIANT_PTR* item);
#ifndef DLMS_IGNORE_MALLOC
//copy variant array.
int va_copyArray(
variantArray* target,
variantArray* source);
//Add given value to the array N times.
int va_addValue(
variantArray* target,
dlmsVARIANT* value,
uint16_t count);
#endif //DLMS_IGNORE_MALLOC
#ifndef DLMS_IGNORE_MALLOC
int var_changeType(
dlmsVARIANT* value,
DLMS_DATA_TYPE newType);
#endif //DLMS_IGNORE_MALLOC
#ifndef DLMS_IGNORE_MALLOC
//Convert variant to string.
//Note! toString do not clear existing byte array.
int var_toString(
dlmsVARIANT* item,
gxByteBuffer* value);
//Convert variant array to string.
//Note! toString do not clear existing byte array.
int va_toString(
variantArray* items,
gxByteBuffer* ba);
#endif //DLMS_IGNORE_MALLOC
//Convert variant to double.
double var_toDouble(
dlmsVARIANT* target);
#ifdef DLMS_IGNORE_MALLOC
//Attach value by ref.
int var_byRef(
dlmsVARIANT* target,
DLMS_DATA_TYPE type,
void* value);
#endif //DLMS_IGNORE_MALLOC
#ifndef GX_DLMS_MICROCONTROLLER
//Print content of the variant to cout.
int var_print(
//Format.
const char* format,
dlmsVARIANT* target);
//Print content of the variant array to cout.
int va_print(
variantArray* target);
#endif //GX_DLMS_MICROCONTROLLER
#define VA_ATTACH(X, V, S) va_attach(&X, V, S, sizeof(V)/sizeof(V[0]))
#ifdef __cplusplus
}
#endif
#endif //VARIANT_H

494
components/xt211/xt211.cpp Normal file
View File

@ -0,0 +1,494 @@
#include "xt211.h"
#include "xt211_axdr_parser.h"
#include "esphome/core/application.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#include <sstream>
namespace esphome {
namespace xt211 {
static const char *TAG0 = "xt211_";
#define TAG (this->tag_.c_str())
static constexpr uint8_t
BOOT_WAIT_S = 10;
void XT211Component::setup() {
ESP_LOGD(TAG, "setup (PUSH mode only)");
this->buffers_.init(DEFAULT_IN_BUF_SIZE_PUSH);
#ifdef USE_ESP32
iuart_ = make_unique<XT211Uart>(*static_cast<uart::IDFUARTComponent *>(this->parent_));
#endif
#if USE_ESP8266
iuart_ = make_unique<XT211Uart>(*static_cast<uart::ESP8266UartComponent *>(this->parent_));
#endif
this->set_baud_rate_(this->baud_rate_);
CosemObjectFoundCallback fn = [this](auto... args) { (void) this->set_sensor_value(args...); };
this->axdr_parser_ = new AxdrStreamParser(&this->buffers_.in, fn, this->push_show_log_);
// default patterns
this->axdr_parser_->register_pattern_dsl("T1", "TC,TO,TS,TV");
this->axdr_parser_->register_pattern_dsl("T2", "TO,TV,TSU");
this->axdr_parser_->register_pattern_dsl("T3", "TV,TC,TSU,TO");
this->axdr_parser_->register_pattern_dsl("U.ZPA", "F,C,O,A,TV");
// user-provided pattern
if (this->push_custom_pattern_dsl_.length() > 0) {
this->axdr_parser_->register_pattern_dsl("CUSTOM", this->push_custom_pattern_dsl_, 0);
}
bool locked = false;
for (int i = 0; i < 3; i++)
if (this->try_lock_uart_session_()) {
locked = true;
break;
}
if (!locked) {
ESP_LOGE(TAG, "Failed to lock UART session. Aborting setup.");
this->mark_failed();
return;
}
this->set_timeout(BOOT_WAIT_S * 1000, [this]() {
ESP_LOGD(TAG, "Boot timeout, component is ready to use");
this->clear_rx_buffers_();
this->set_next_state_(State::IDLE);
});
}
void XT211Component::dump_config() {
ESP_LOGCONFIG(TAG, "XT211 (PUSH Mode Read-Only):");
ESP_LOGCONFIG(TAG, " Receive Timeout: %ums", this->receive_timeout_ms_);
ESP_LOGCONFIG(TAG, " Mode: PUSH Data Reception");
ESP_LOGCONFIG(TAG, " Sensors:");
for (const auto &sensors: sensors_) {
auto &s = sensors.second;
ESP_LOGCONFIG(TAG, " OBIS code: %s, Name: %s", s->get_obis_code().c_str(), s->get_sensor_name().c_str());
}
}
void XT211Component::register_sensor(XT211SensorBase *sensor) {
this->sensors_.insert({sensor->get_obis_code(), sensor});
}
void XT211Component::abort_mission_() {
ESP_LOGV(TAG, "Push mode error, returning to listening");
this->clear_rx_buffers_();
this->set_next_state_(State::IDLE);
}
void XT211Component::report_failure(bool failure) {
if (!failure) {
this->stats_.failures_ = 0;
return;
}
this->stats_.failures_++;
ESP_LOGE(TAG, "Failure reported. Count: %u", this->stats_.failures_);
}
void XT211Component::loop() {
if (!this->is_ready() || this->state_ == State::NOT_INITIALIZED)
return;
switch (this->state_) {
case State::IDLE: {
this->update_last_rx_time_();
this->indicate_transmission(false);
this->indicate_session(false);
// Push mode listening logic
if (this->available() > 0) {
// Set up for receiving push data
memset(this->buffers_.in.data, 0, buffers_.in.capacity);
this->buffers_.in.size = 0;
// read what we can then move forward to avoid buffer overflow
this->receive_frame_raw_();
ESP_LOGV(TAG, "Push mode: incoming data detected");
this->stats_.connections_tried_++;
this->loop_state_.session_started_ms = millis();
this->indicate_transmission(true);
this->set_next_state_(State::COMMS_RX);
}
}
break;
case State::WAIT:
if (this->check_wait_timeout_()) {
this->set_next_state_(this->wait_.next_state);
this->update_last_rx_time_();
}
break;
case State::COMMS_RX: {
this->handle_comms_rx_();
}
break;
case State::MISSION_FAILED: {
this->set_next_state_(State::IDLE);
this->report_failure(true);
this->stats_dump();
}
break;
case State::PUSH_DATA_PROCESS: {
this->handle_push_data_process_();
}
break;
case State::PUBLISH: {
this->handle_publish_();
}
break;
default:
// Should not happen
ESP_LOGW(TAG, "Unhandled state: %s", state_to_string(this->state_));
this->set_next_state_(State::IDLE);
break;
}
}
void XT211Component::handle_comms_rx_() {
this->log_state_();
if (this->check_rx_timeout_()) {
ESP_LOGI(TAG, "Push data reception completed (timeout reached)");
this->indicate_connection(false);
this->indicate_transmission(false);
// check if we received any data at all
this->indicate_connection(true);
if (this->buffers_.in.size > 0) {
ESP_LOGV(TAG, "Push mode RX data avail, len=%d", this->buffers_.in.size);
this->set_next_state_(State::PUSH_DATA_PROCESS);
} else {
ESP_LOGV(TAG, "Push mode RX timeout, no data, idling");
this->set_next_state_(State::IDLE);
}
return;
}
received_frame_size_ = this->receive_frame_raw_();
// keep reading until timeout
}
void XT211Component::handle_push_data_process_() {
this->log_state_();
ESP_LOGD(TAG, "Processing received push data");
this->loop_state_.sensor_iter = this->sensors_.begin();
this->set_next_state_(State::PUBLISH);
this->process_push_data();
this->clear_rx_buffers_();
}
void XT211Component::handle_publish_() {
this->log_state_();
ESP_LOGD(TAG, "Publishing data");
this->update_last_rx_time_();
if (this->loop_state_.sensor_iter != this->sensors_.end()) {
if (this->loop_state_.sensor_iter->second->shall_we_publish()) {
this->loop_state_.sensor_iter->second->publish();
}
this->loop_state_.sensor_iter++;
} else {
this->stats_dump();
if (this->crc_errors_per_session_sensor_ != nullptr) {
this->crc_errors_per_session_sensor_->publish_state(this->stats_.crc_errors_per_session());
}
this->report_failure(false);
this->set_next_state_(State::IDLE);
ESP_LOGD(TAG, "Total time: %u ms", millis() - this->loop_state_.session_started_ms);
}
}
// This is the entry point for PollingComponent, which is now unused.
void XT211Component::update() {}
void XT211Component::set_next_state_delayed_(uint32_t ms, State next_state) {
if (ms == 0) {
set_next_state_(next_state);
} else {
ESP_LOGV(TAG, "Short delay for %u ms", ms);
set_next_state_(State::WAIT);
wait_.start_time = millis();
wait_.delay_ms = ms;
wait_.next_state = next_state;
}
}
void XT211Component::PushBuffers::init(size_t default_in_buf_size) {
BYTE_BUFFER_INIT(&in);
bb_capacity(&in, default_in_buf_size);
this->reset();
}
void XT211Component::PushBuffers::reset() {
in.size = 0;
in.position = 0;
}
void XT211Component::PushBuffers::check_and_grow_input(uint16_t
more_data) {
const uint16_t GROW_EPSILON = 20;
if (in.size + more_data > in.capacity) {
ESP_LOGVV(TAG0,
"Growing input buffer from %d to %d", in.capacity, in.size + more_data + GROW_EPSILON);
bb_capacity(&in, in
.size + more_data + GROW_EPSILON);
}
}
void XT211Component::process_push_data() {
ESP_LOGD(TAG, "Processing PUSH data frame with AXDR parser");
// Ensure we parse from the beginning of the collected frame
this->buffers_.in.position = 0;
const auto total_size = this->buffers_.in.size;
ESP_LOGD(TAG, "PUSH frame size: %u bytes", static_cast<unsigned>(total_size));
size_t total_objects = 0;
size_t iterations = 0;
while (this->buffers_.in.position < this->buffers_.in.size) {
auto before = this->buffers_.in.position;
auto parsed_now = this->axdr_parser_->parse();
auto after = this->buffers_.in.position;
iterations++;
if (parsed_now == 0 && after == before) {
// No progress, avoid potential infinite loop on malformed frames
ESP_LOGW(TAG, "AXDR parser made no progress at pos=%u/%u, aborting", static_cast<unsigned>(after),
static_cast<unsigned>(this->buffers_.in.size));
break;
}
total_objects += parsed_now;
ESP_LOGV(TAG, "AXDR iteration %u: parsed=%u, pos=%u/%u, objects_total=%u", static_cast<unsigned>(iterations),
static_cast<unsigned>(parsed_now), static_cast<unsigned>(after),
static_cast<unsigned>(this->buffers_.in.size), static_cast<unsigned>(total_objects));
}
ESP_LOGD(TAG, "PUSH data parsing complete: %u objects, bytes consumed %u/%u", static_cast<unsigned>(total_objects),
static_cast<unsigned>(this->buffers_.in.position), static_cast<unsigned>(total_size));
}
int XT211Component::set_sensor_value(uint16_t class_id, const uint8_t *obis_code, DLMS_DATA_TYPE value_type,
const uint8_t *value_buffer_ptr, uint8_t value_length, const int8_t *scaler,
const uint8_t *unit) {
static char obis_buf[32];
auto er = hlp_getLogicalNameToString(obis_code, obis_buf);
std::string obis_str(obis_buf);
auto range = this->sensors_.equal_range(obis_str);
int found_count = 0;
for (auto it = range.first; it != range.second; ++it) {
XT211SensorBase *sensor = it->second;
if (!sensor->shall_we_publish()) {
continue;
}
ESP_LOGD(TAG, "Found sensor for OBIS code %s: '%s' ", obis_buf, sensor->get_sensor_name().c_str());
found_count++;
#ifdef USE_SENSOR
if (sensor->get_type() == SensorType::SENSOR) {
float val = dlms_data_as_float(value_type, value_buffer_ptr, value_length);
if (scaler != nullptr) {
float scale = pow(10, *scaler);
val *= scale;
}
static_cast<XT211Sensor *>(sensor)->set_value(val);
}
#endif
#ifdef USE_TEXT_SENSOR
if (sensor->get_type() == SensorType::TEXT_SENSOR) {
auto val = dlms_data_as_string(value_type, value_buffer_ptr, value_length);
static_cast<XT211TextSensor *>(sensor)->set_value(val.c_str());
}
#endif
#ifdef USE_BINARY_SENSOR
if (sensor->get_type() == SensorType::BINARY_SENSOR) {
bool val = dlms_data_as_float(value_type, value_buffer_ptr, value_length) != 0.0f;
static_cast<XT211BinarySensor *>(sensor)->set_value(val);
}
#endif
}
if (found_count == 0) {
ESP_LOGVV(TAG, "No sensor found for OBIS code: '%s'", (char *) obis_buf);
} else {
ESP_LOGVV(TAG, "Updated %d sensors for OBIS code: '%s'", found_count, (char *) obis_buf);
}
return DLMS_ERROR_CODE_OK;
}
void XT211Component::indicate_transmission(bool transmission_on) {
#ifdef USE_BINARY_SENSOR
if (this->transmission_binary_sensor_) {
this->transmission_binary_sensor_->publish_state(transmission_on);
}
#endif
}
void XT211Component::indicate_session(bool session_on) {
#ifdef USE_BINARY_SENSOR
if (this->session_binary_sensor_) {
this->session_binary_sensor_->publish_state(session_on);
}
#endif
}
void XT211Component::indicate_connection(bool connection_on) {
#ifdef USE_BINARY_SENSOR
if (this->connection_binary_sensor_) {
this->connection_binary_sensor_->publish_state(connection_on);
}
#endif
}
size_t XT211Component::receive_frame_(FrameStopFunction stop_fn) {
const uint32_t read_time_limit_ms = 45;
size_t ret_val;
auto count_available = this->available();
if (count_available <= 0)
return 0;
uint32_t read_start = millis();
uint8_t * p;
// ESP_LOGVV(TAG, "avail RX: %d", count_available);
buffers_.check_and_grow_input(count_available);
while (count_available-- > 0) {
if (millis() - read_start > read_time_limit_ms) {
return 0;
}
p = &this->buffers_.in.data[this->buffers_.in.size];
if (!iuart_->read_one_byte(p)) {
return 0;
}
this->buffers_.in.size++;
if (stop_fn(this->buffers_.in.data, this->buffers_.in.size)) {
ESP_LOGVV(TAG, "RX: %s", format_hex_pretty(this->buffers_.in.data, this->buffers_.in.size).c_str());
ret_val = this->buffers_.in.size;
this->update_last_rx_time_();
return ret_val;
}
yield();
App.feed_wdt();
}
return 0;
}
size_t XT211Component::receive_frame_raw_() {
auto frame_end_check_timeout = [](uint8_t *b, size_t s) {
return false; // never stop by content, only by timeout
};
return receive_frame_(frame_end_check_timeout);
}
void XT211Component::clear_rx_buffers_() {
int available = this->available();
if (available > 0) {
ESP_LOGVV(TAG, "Cleaning garbage from UART input buffer: %d bytes", available);
}
int len;
while (available > 0) {
len = std::min(available, (int) buffers_.in.capacity);
this->read_array(this->buffers_.in.data, len);
available -= len;
}
memset(this->buffers_.in.data, 0, buffers_.in.capacity);
this->buffers_.in.size = 0;
this->buffers_.in.position = 0;
}
const char *XT211Component::state_to_string(State state) {
switch (state) {
case State::NOT_INITIALIZED:
return "NOT_INITIALIZED";
case State::IDLE:
return "IDLE";
case State::WAIT:
return "WAIT";
case State::COMMS_RX:
return "COMMS_RX";
case State::MISSION_FAILED:
return "MISSION_FAILED";
case State::PUBLISH:
return "PUBLISH";
case State::PUSH_DATA_PROCESS:
return "PUSH_DATA_PROCESS";
default:
return "UNKNOWN";
}
}
void XT211Component::log_state_(State *next_state) {
if (this->state_ != this->last_reported_state_) {
if (next_state == nullptr) {
ESP_LOGV(TAG, "State::%s", state_to_string(this->state_));
} else {
ESP_LOGV(TAG, "State::%s -> %s", state_to_string(this->state_), state_to_string(*next_state));
}
this->last_reported_state_ = this->state_;
}
}
void XT211Component::stats_dump() {
ESP_LOGV(TAG, "============================================");
ESP_LOGV(TAG, "Data collection and publishing finished.");
ESP_LOGV(TAG, "Total number of sessions ............. %u", this->stats_.connections_tried_);
ESP_LOGV(TAG, "Total number of invalid frames ....... %u", this->stats_.invalid_frames_);
ESP_LOGV(TAG, "Total number of CRC errors ........... %u", this->stats_.crc_errors_);
ESP_LOGV(TAG, "Total number of CRC errors recovered . %u", this->stats_.crc_errors_recovered_);
ESP_LOGV(TAG, "CRC errors per session ............... %f", this->stats_.crc_errors_per_session());
ESP_LOGV(TAG, "Number of failures ................... %u", this->stats_.failures_);
ESP_LOGV(TAG, "============================================");
}
bool XT211Component::try_lock_uart_session_() {
if (AnyObjectLocker::try_lock(this->parent_)) {
ESP_LOGV(TAG, "UART bus %p locked by %s", this->parent_, this->tag_.c_str());
return true;
}
ESP_LOGV(TAG, "UART bus %p busy", this->parent_);
return false;
}
void XT211Component::set_baud_rate_(uint32_t baud_rate) {
if (this->iuart_ != nullptr) {
this->iuart_->update_baudrate(baud_rate);
}
}
uint8_t XT211Component::next_obj_id_ = 0;
std::string XT211Component::generateTag() { return str_sprintf("%s%03d", TAG0, ++next_obj_id_); }
} // namespace xt211
} // namespace esphome

206
components/xt211/xt211.h Normal file
View File

@ -0,0 +1,206 @@
#pragma once
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/uart/uart.h"
#include "esphome/core/component.h"
#ifdef USE_BINARY_SENSOR
#include "esphome/components/binary_sensor/binary_sensor.h"
#endif
#include <cstdint>
#include <list>
#include <map>
#include <memory>
#include <string>
#include "xt211_sensor.h"
#include "xt211_uart.h"
#include "object_locker.h"
#include "client.h"
#include "converters.h"
#include "cosem.h"
#include "dlmssettings.h"
namespace esphome {
namespace xt211 {
static const size_t DEFAULT_IN_BUF_SIZE_PUSH = 2048;
using SensorMap = std::multimap<std::string, XT211SensorBase *>;
using FrameStopFunction = std::function<
bool(uint8_t
*buf,
size_t size
)>;
class AxdrStreamParser;
class XT211Component : public PollingComponent, public uart::UARTDevice {
public:
XT211Component() : tag_(generateTag()) {};
void setup() override;
void dump_config() override;
void loop() override;
void update() override; // Kept for PollingComponent, but will be empty
float get_setup_priority() const override { return setup_priority::DATA; };
void set_baud_rate(uint32_t baud_rate) { this->baud_rate_ = baud_rate; };
void set_receive_timeout_ms(uint32_t timeout) { this->receive_timeout_ms_ = timeout; };
void register_sensor(XT211SensorBase *sensor);
void set_reboot_after_failure(uint16_t number_of_failures) { this->failures_before_reboot_ = number_of_failures; }
// PUSH mode is now default, these are for configuring it
void set_push_show_log(bool show_log) { this->push_show_log_ = show_log; }
void set_push_custom_pattern_dsl(const std::string &dsl) { this->push_custom_pattern_dsl_ = dsl; }
bool has_error{true};
#ifdef USE_BINARY_SENSOR
SUB_BINARY_SENSOR(transmission)
SUB_BINARY_SENSOR(session)
SUB_BINARY_SENSOR(connection)
#endif
#ifdef USE_TEXT_SENSOR
SUB_TEXT_SENSOR(last_scan)
#endif
protected:
bool push_show_log_{false};
std::string push_custom_pattern_dsl_{""};
uint32_t receive_timeout_ms_{2000};
std::unique_ptr <XT211Uart> iuart_;
SensorMap sensors_;
sensor::Sensor *crc_errors_per_session_sensor_{};
enum class State : uint8_t {
NOT_INITIALIZED,
IDLE,
WAIT,
COMMS_RX,
MISSION_FAILED,
PUSH_DATA_PROCESS, // Process received push data
PUBLISH,
} state_{State::NOT_INITIALIZED};
State last_reported_state_{State::NOT_INITIALIZED};
struct {
uint32_t start_time{0};
uint32_t delay_ms{0};
State next_state{State::IDLE};
} wait_;
bool is_idling() const { return this->state_ == State::WAIT || this->state_ == State::IDLE; };
void set_next_state_(State next_state) { state_ = next_state; };
void set_next_state_delayed_(uint32_t ms, State next_state);
void process_push_data();
// State handler methods extracted from loop()
void handle_comms_rx_();
void handle_push_data_process_();
void handle_publish_();
int set_sensor_value(uint16_t class_id, const uint8_t *obis_code, DLMS_DATA_TYPE value_type,
const uint8_t *value_buffer_ptr, uint8_t value_length, const int8_t *scaler,
const uint8_t *unit);
void indicate_transmission(bool transmission_on);
void indicate_session(bool session_on);
void indicate_connection(bool connection_on);
AxdrStreamParser *axdr_parser_{nullptr};
size_t received_frame_size_{0};
uint32_t baud_rate_{9600};
uint32_t last_rx_time_{0};
struct LoopState {
uint32_t session_started_ms{0}; // start of session
SensorMap::iterator sensor_iter{nullptr}; // publishing sensor values
} loop_state_;
struct PushBuffers {
gxByteBuffer in;
void init(size_t default_in_buf_size);
void reset();
void check_and_grow_input(uint16_t more_data);
} buffers_;
protected:
void clear_rx_buffers_();
void set_baud_rate_(uint32_t baud_rate);
size_t receive_frame_(FrameStopFunction stop_fn);
size_t receive_frame_raw_();
inline void update_last_rx_time_() { this->last_rx_time_ = millis(); }
bool check_wait_timeout_() { return millis() - wait_.start_time >= wait_.delay_ms; }
bool check_rx_timeout_() { return millis() - this->last_rx_time_ >= receive_timeout_ms_; }
void report_failure(bool failure);
void abort_mission_();
const char *state_to_string(State state);
void log_state_(State *next_state = nullptr);
struct Stats {
uint32_t connections_tried_{0};
uint32_t crc_errors_{0};
uint32_t crc_errors_recovered_{0};
uint32_t invalid_frames_{0};
uint8_t failures_{0};
float crc_errors_per_session() const { return (float) crc_errors_ / connections_tried_; }
} stats_;
void stats_dump();
uint8_t failures_before_reboot_{0};
bool try_lock_uart_session_();
// unlock_uart_session_() has been removed
public:
private:
static uint8_t next_obj_id_;
std::string tag_;
static std::string generateTag();
};
} // namespace xt211
} // namespace esphome

View File

@ -0,0 +1,877 @@
#include "xt211_axdr_parser.h"
#include "esphome/core/log.h"
#include "esphome/core/helpers.h"
#include <cstring>
#include <sstream>
#include <iomanip>
namespace esphome {
namespace xt211 {
constexpr const char *TAG = "xt211.axdr";
const char *dlms_error_to_string(int error) {
switch (error) {
case DLMS_ERROR_CODE_OK:
return "DLMS_ERROR_CODE_OK";
case DLMS_ERROR_CODE_HARDWARE_FAULT:
return "DLMS_ERROR_CODE_HARDWARE_FAULT";
case DLMS_ERROR_CODE_TEMPORARY_FAILURE:
return "DLMS_ERROR_CODE_TEMPORARY_FAILURE";
case DLMS_ERROR_CODE_READ_WRITE_DENIED:
return "DLMS_ERROR_CODE_READ_WRITE_DENIED";
case DLMS_ERROR_CODE_UNDEFINED_OBJECT:
return "DLMS_ERROR_CODE_UNDEFINED_OBJECT";
case DLMS_ERROR_CODE_ACCESS_VIOLATED:
return "DLMS_ERROR_CODE_ACCESS_VIOLATED";
default:
return "";
}
}
const char *dlms_data_type_to_string(DLMS_DATA_TYPE vt) {
switch (vt) {
case DLMS_DATA_TYPE_NONE:
return "DLMS_DATA_TYPE_NONE";
case DLMS_DATA_TYPE_BOOLEAN:
return "DLMS_DATA_TYPE_BOOLEAN";
case DLMS_DATA_TYPE_BIT_STRING:
return "DLMS_DATA_TYPE_BIT_STRING";
case DLMS_DATA_TYPE_INT32:
return "DLMS_DATA_TYPE_INT32";
case DLMS_DATA_TYPE_UINT32:
return "DLMS_DATA_TYPE_UINT32";
case DLMS_DATA_TYPE_OCTET_STRING:
return "DLMS_DATA_TYPE_OCTET_STRING";
case DLMS_DATA_TYPE_STRING:
return "DLMS_DATA_TYPE_STRING";
case DLMS_DATA_TYPE_BINARY_CODED_DESIMAL:
return "DLMS_DATA_TYPE_BINARY_CODED_DESIMAL";
case DLMS_DATA_TYPE_STRING_UTF8:
return "DLMS_DATA_TYPE_STRING_UTF8";
case DLMS_DATA_TYPE_INT8:
return "DLMS_DATA_TYPE_INT8";
case DLMS_DATA_TYPE_INT16:
return "DLMS_DATA_TYPE_INT16";
case DLMS_DATA_TYPE_UINT8:
return "DLMS_DATA_TYPE_UINT8";
case DLMS_DATA_TYPE_UINT16:
return "DLMS_DATA_TYPE_UINT16";
case DLMS_DATA_TYPE_INT64:
return "DLMS_DATA_TYPE_INT64";
case DLMS_DATA_TYPE_UINT64:
return "DLMS_DATA_TYPE_UINT64";
case DLMS_DATA_TYPE_ENUM:
return "DLMS_DATA_TYPE_ENUM";
case DLMS_DATA_TYPE_FLOAT32:
return "DLMS_DATA_TYPE_FLOAT32";
case DLMS_DATA_TYPE_FLOAT64:
return "DLMS_DATA_TYPE_FLOAT64";
case DLMS_DATA_TYPE_DATETIME:
return "DLMS_DATA_TYPE_DATETIME";
case DLMS_DATA_TYPE_DATE:
return "DLMS_DATA_TYPE_DATE";
case DLMS_DATA_TYPE_TIME:
return "DLMS_DATA_TYPE_TIME";
case DLMS_DATA_TYPE_ARRAY:
return "DLMS_DATA_TYPE_ARRAY";
case DLMS_DATA_TYPE_STRUCTURE:
return "DLMS_DATA_TYPE_STRUCTURE";
case DLMS_DATA_TYPE_COMPACT_ARRAY:
return "DLMS_DATA_TYPE_COMPACT_ARRAY";
case DLMS_DATA_TYPE_BYREF:
return "DLMS_DATA_TYPE_BYREF";
default:
return "DMS_DATA_TYPE UNKNOWN";
}
}
bool hlp_isValueDataType(DLMS_DATA_TYPE type) {
switch (type) {
// Complex/Container types - NOT value types
case DLMS_DATA_TYPE_ARRAY:
case DLMS_DATA_TYPE_STRUCTURE:
case DLMS_DATA_TYPE_COMPACT_ARRAY:
return false;
// All other types are value types
case DLMS_DATA_TYPE_NONE:
case DLMS_DATA_TYPE_BOOLEAN:
case DLMS_DATA_TYPE_BIT_STRING:
case DLMS_DATA_TYPE_INT32:
case DLMS_DATA_TYPE_UINT32:
case DLMS_DATA_TYPE_OCTET_STRING:
case DLMS_DATA_TYPE_STRING:
case DLMS_DATA_TYPE_BINARY_CODED_DESIMAL:
case DLMS_DATA_TYPE_STRING_UTF8:
case DLMS_DATA_TYPE_INT8:
case DLMS_DATA_TYPE_INT16:
case DLMS_DATA_TYPE_UINT8:
case DLMS_DATA_TYPE_UINT16:
case DLMS_DATA_TYPE_INT64:
case DLMS_DATA_TYPE_UINT64:
case DLMS_DATA_TYPE_ENUM:
case DLMS_DATA_TYPE_FLOAT32:
case DLMS_DATA_TYPE_FLOAT64:
case DLMS_DATA_TYPE_DATETIME:
case DLMS_DATA_TYPE_DATE:
case DLMS_DATA_TYPE_TIME:
return true;
default:
return false;
}
}
float dlms_data_as_float(DLMS_DATA_TYPE value_type, const uint8_t *value_buffer_ptr, uint8_t value_length) {
if (value_buffer_ptr == nullptr || value_length == 0)
return 0.0f;
auto be16 = [](const uint8_t *p) -> uint16_t { return (uint16_t) ((p[0] << 8) | p[1]); };
auto be32 = [](const uint8_t *p) -> uint32_t {
return ((uint32_t) p[0] << 24) | ((uint32_t) p[1] << 16) | ((uint32_t) p[2] << 8) | (uint32_t) p[3];
};
auto be64 = [](const uint8_t *p) -> uint64_t {
uint64_t v = 0;
for (int i = 0; i < 8; i++)
v = (v << 8) | p[i];
return v;
};
switch (value_type) {
case DLMS_DATA_TYPE_BOOLEAN:
case DLMS_DATA_TYPE_ENUM:
case DLMS_DATA_TYPE_UINT8:
return static_cast<float>(value_buffer_ptr[0]);
case DLMS_DATA_TYPE_INT8:
return static_cast<float>(static_cast<int8_t>(value_buffer_ptr[0]));
case DLMS_DATA_TYPE_UINT16:
if (value_length >= 2)
return static_cast<float>(be16(value_buffer_ptr));
return 0.0f;
case DLMS_DATA_TYPE_INT16:
if (value_length >= 2) {
int16_t v = static_cast<int16_t>(be16(value_buffer_ptr));
return static_cast<float>(v);
}
return 0.0f;
case DLMS_DATA_TYPE_UINT32:
if (value_length >= 4)
return static_cast<float>(be32(value_buffer_ptr));
return 0.0f;
case DLMS_DATA_TYPE_INT32:
if (value_length >= 4) {
int32_t v = static_cast<int32_t>(be32(value_buffer_ptr));
return static_cast<float>(v);
}
return 0.0f;
case DLMS_DATA_TYPE_UINT64:
if (value_length >= 8)
return static_cast<float>(be64(value_buffer_ptr));
return 0.0f;
case DLMS_DATA_TYPE_INT64:
if (value_length >= 8) {
uint64_t u = be64(value_buffer_ptr);
int64_t v = static_cast<int64_t>(u);
return static_cast<float>(v);
}
return 0.0f;
case DLMS_DATA_TYPE_FLOAT32:
if (value_length >= 4) {
uint32_t u = be32(value_buffer_ptr);
float f{};
std::memcpy(&f, &u, sizeof(f));
return f;
}
return 0.0f;
case DLMS_DATA_TYPE_FLOAT64:
if (value_length >= 8) {
uint8_t b[8];
for (int i = 0; i < 8; i++)
b[i] = value_buffer_ptr[i];
double d{};
std::memcpy(&d, b, sizeof(d));
return static_cast<float>(d);
}
return 0.0f;
default:
return 0.0f;
}
}
std::string dlms_data_as_string(DLMS_DATA_TYPE value_type, const uint8_t *value_buffer_ptr, uint8_t value_length) {
if (value_buffer_ptr == nullptr && value_length == 0)
return std::string();
auto hex_of = [](const uint8_t *p, uint8_t len) -> std::string {
std::ostringstream ss;
ss << std::hex << std::setfill('0');
for (uint8_t i = 0; i < len; i++) {
ss << std::setw(2) << static_cast<int>(p[i]);
if (i + 1 < len)
ss << ""; // compact
}
return ss.str();
};
switch (value_type) {
case DLMS_DATA_TYPE_OCTET_STRING:
case DLMS_DATA_TYPE_STRING:
case DLMS_DATA_TYPE_STRING_UTF8: {
return std::string(reinterpret_cast<const char *>(value_buffer_ptr),
reinterpret_cast<const char *>(value_buffer_ptr) + value_length);
}
case DLMS_DATA_TYPE_BIT_STRING:
case DLMS_DATA_TYPE_BINARY_CODED_DESIMAL:
return hex_of(value_buffer_ptr, value_length);
case DLMS_DATA_TYPE_BOOLEAN:
case DLMS_DATA_TYPE_ENUM:
case DLMS_DATA_TYPE_UINT8: {
return std::to_string(static_cast<unsigned>(value_buffer_ptr ? value_buffer_ptr[0] : 0));
}
case DLMS_DATA_TYPE_INT8: {
return std::to_string(static_cast<int>(static_cast<int8_t>(value_buffer_ptr ? value_buffer_ptr[0] : 0)));
}
case DLMS_DATA_TYPE_UINT16: {
if (value_length >= 2) {
uint16_t v = (uint16_t) ((value_buffer_ptr[0] << 8) | value_buffer_ptr[1]);
return std::to_string(v);
}
return std::string();
}
case DLMS_DATA_TYPE_INT16: {
if (value_length >= 2) {
int16_t v = (int16_t) ((value_buffer_ptr[0] << 8) | value_buffer_ptr[1]);
return std::to_string(v);
}
return std::string();
}
case DLMS_DATA_TYPE_UINT32: {
if (value_length >= 4) {
uint32_t v = ((uint32_t) value_buffer_ptr[0] << 24) | ((uint32_t) value_buffer_ptr[1] << 16) |
((uint32_t) value_buffer_ptr[2] << 8) | (uint32_t) value_buffer_ptr[3];
return std::to_string(v);
}
return std::string();
}
case DLMS_DATA_TYPE_INT32: {
if (value_length >= 4) {
int32_t v = ((int32_t) value_buffer_ptr[0] << 24) | ((int32_t) value_buffer_ptr[1] << 16) |
((int32_t) value_buffer_ptr[2] << 8) | (int32_t) value_buffer_ptr[3];
return std::to_string(v);
}
return std::string();
}
case DLMS_DATA_TYPE_UINT64: {
if (value_length >= 8) {
uint64_t v = 0;
for (int i = 0; i < 8; i++)
v = (v << 8) | value_buffer_ptr[i];
return std::to_string(v);
}
return std::string();
}
case DLMS_DATA_TYPE_INT64: {
if (value_length >= 8) {
uint64_t u = 0;
for (int i = 0; i < 8; i++)
u = (u << 8) | value_buffer_ptr[i];
int64_t v = static_cast<int64_t>(u);
return std::to_string(v);
}
return std::string();
}
case DLMS_DATA_TYPE_FLOAT32:
case DLMS_DATA_TYPE_FLOAT64: {
float f = dlms_data_as_float(value_type, value_buffer_ptr, value_length);
// Use minimal formatting
std::ostringstream ss;
ss << f;
return ss.str();
}
case DLMS_DATA_TYPE_DATETIME:
case DLMS_DATA_TYPE_DATE:
case DLMS_DATA_TYPE_TIME:
// For now, return hex. Higher-level layers may decode properly.
return hex_of(value_buffer_ptr, value_length);
case DLMS_DATA_TYPE_NONE:
default:
return std::string();
}
}
void AxdrPatternRegistry::add_pattern(const AxdrDescriptorPattern &p) {
auto it = std::upper_bound(
patterns_.begin(), patterns_.end(), p,
[](const AxdrDescriptorPattern &a, const AxdrDescriptorPattern &b) { return a.priority < b.priority; });
patterns_.insert(it, p);
}
uint8_t AxdrStreamParser::peek_byte_() {
if (this->buffer_->position + 1 > this->buffer_->size) {
return 0xFF;
}
return this->buffer_->data[this->buffer_->position];
}
uint8_t AxdrStreamParser::read_byte_() {
if (this->buffer_->position + 1 > this->buffer_->size) {
return 0xFF;
}
return this->buffer_->data[this->buffer_->position++];
}
uint16_t AxdrStreamParser::read_u16_() {
if (this->buffer_->position + 2 > this->buffer_->size) {
return 0xFFFF;
}
uint16_t value =
(this->buffer_->data[this->buffer_->position] << 8) | this->buffer_->data[this->buffer_->position + 1];
this->buffer_->position += 2;
return value;
}
uint32_t AxdrStreamParser::read_u32_() {
if (this->buffer_->position + 4 > this->buffer_->size) {
return 0xFFFFFFFF;
}
uint32_t value =
(this->buffer_->data[this->buffer_->position] << 24) | (this->buffer_->data[this->buffer_->position + 1] << 16) |
(this->buffer_->data[this->buffer_->position + 2] << 8) | this->buffer_->data[this->buffer_->position + 3];
this->buffer_->position += 4;
return value;
}
bool AxdrStreamParser::test_if_date_time_12b_() {
if (this->buffer_->position + 12 > this->buffer_->size) {
return 0;
}
const uint8_t *buf = this->buffer_->data + this->buffer_->position;
if (!buf)
return false;
// Year
uint16_t year = (buf[0] << 8) | buf[1];
if (!(year == 0x0000 || (year >= 1970 && year <= 2100)))
return false;
// Month
uint8_t month = buf[2];
if (!(month == 0xFF || (month >= 1 && month <= 12)))
return false;
// Day of month
uint8_t day = buf[3];
if (!(day == 0xFF || (day >= 1 && day <= 31)))
return false;
// Day of week
uint8_t dow = buf[4];
if (!(dow == 0xFF || (dow >= 1 && dow <= 7)))
return false;
// Hour
uint8_t hour = buf[5];
if (!(hour == 0xFF || hour <= 23))
return false;
// Minute
uint8_t minute = buf[6];
if (!(minute == 0xFF || minute <= 59))
return false;
// Second
uint8_t second = buf[7];
if (!(second == 0xFF || second <= 59))
return false;
// Hundredths of second
uint8_t ms = buf[8];
if (!(ms == 0xFF || ms <= 99))
return false;
// some makers mix up the order
// Deviation (timezone offset, signed, 2 bytes)
uint16_t u_dev = (buf[9] << 8) | buf[10];
int16_t s_dev = (int16_t) (u_dev);
if (!((s_dev == (int16_t) 0x8000 || (s_dev >= -720 && s_dev <= 720))))
return false;
uint8_t clock_status = buf[11];
return true;
}
constexpr uint16_t MAX_CLASS_ID = 0x00FF;
constexpr uint8_t MAX_ATTRIBUTE_ID = 0x20;
constexpr size_t MIN_UNTAGGED_ATTRIBUTE_DESCRIPTOR_SIZE = 9;
constexpr size_t MIN_TAGGED_ATTRIBUTE_DESCRIPTOR_SIZE = 14;
bool AxdrStreamParser::skip_data_(uint8_t type) {
int data_size = hlp_getDataTypeSize((DLMS_DATA_TYPE) type);
if (data_size == 0) // Zero-length data (NONE type) - nothing to skip
return true;
if (data_size > 0) { // Fixed size data
if (this->buffer_->position + data_size > this->buffer_->size) {
return false;
}
this->buffer_->position += data_size;
} else { // Variable size data
uint8_t length = read_byte_();
if (length == 0xFF) {
return false;
}
if (this->buffer_->position + length > this->buffer_->size) {
return false;
}
this->buffer_->position += length;
}
return true;
}
bool AxdrStreamParser::skip_sequence_(uint8_t type) {
uint8_t elements_count = read_byte_();
if (elements_count == 0xFF) {
ESP_LOGV(TAG, "Invalid sequence length when skipping at position %d", this->buffer_->position - 1);
return false;
}
ESP_LOGD(TAG, "Skipping %s with %d elements at position %d",
(type == DLMS_DATA_TYPE_STRUCTURE) ? "STRUCTURE" : "ARRAY", elements_count, this->buffer_->position - 1);
for (uint8_t i = 0; i < elements_count; i++) {
uint8_t elem_type = read_byte_();
if (!parse_element_(elem_type)) {
ESP_LOGV(TAG, "Failed to skip element %d of %s at position %d", i + 1,
(type == DLMS_DATA_TYPE_STRUCTURE) ? "STRUCTURE" : "ARRAY", this->buffer_->position - 1);
return false;
}
}
return true;
}
bool AxdrStreamParser::parse_data_(uint8_t type, uint8_t depth) { return skip_data_(type); }
bool AxdrStreamParser::parse_sequence_(uint8_t type, uint8_t depth) {
uint8_t elements_count = read_byte_();
if (elements_count == 0xFF) {
ESP_LOGVV(TAG, "Invalid sequence length at position %d", this->buffer_->position - 1);
return false;
}
uint8_t elements_consumed = 0;
while (elements_consumed < elements_count) {
uint32_t original_position = this->buffer_->position;
if (try_match_patterns_(elements_consumed)) {
uint8_t used = this->last_pattern_elements_consumed_ ? this->last_pattern_elements_consumed_ : 1;
elements_consumed += used;
this->last_pattern_elements_consumed_ = 0;
continue;
}
if (this->buffer_->position >= this->buffer_->size) {
ESP_LOGV(TAG, "Unexpected end while reading element %d of %s", elements_consumed + 1,
(type == DLMS_DATA_TYPE_STRUCTURE) ? "STRUCTURE" : "ARRAY");
return false;
}
uint8_t elem_type = read_byte_();
if (!parse_element_(elem_type, depth + 1)) {
return false;
}
elements_consumed++;
if (this->buffer_->position == original_position) {
ESP_LOGV(TAG, "No progress parsing element %d at position %d, aborting to avoid infinite loop", elements_consumed,
original_position);
return false;
}
}
return true;
}
bool AxdrStreamParser::parse_element_(uint8_t type, uint8_t depth) {
if (type == DLMS_DATA_TYPE_STRUCTURE || type == DLMS_DATA_TYPE_ARRAY) {
return parse_sequence_(type, depth);
} else {
return parse_data_(type, depth);
}
}
size_t AxdrStreamParser::parse() {
if (this->buffer_ == nullptr || this->buffer_->size == 0) {
ESP_LOGV(TAG, "Buffer is null or empty");
return 0;
}
// Skip to notification flag 0x0F
while (this->buffer_->position < this->buffer_->size) {
uint8_t flag = read_byte_();
if (flag == 0x0F) {
ESP_LOGD(TAG, "Found notification flag at position %d", this->buffer_->position - 1);
break;
}
}
// Skip 5 bytes (invoke id and priority)
for (int i = 0; i < 5; i++) {
uint8_t priority = read_byte_();
}
// Check for datetime object before the data
bool is_date_time = test_if_date_time_12b_();
if (is_date_time) {
ESP_LOGV(TAG, "Skipping datetime at position %d", this->buffer_->position);
this->buffer_->position += 12;
}
// First byte after flag should be the data type
uint8_t start_type = read_byte_();
if (start_type != (uint8_t) DLMS_DATA_TYPE_STRUCTURE && start_type != (uint8_t) DLMS_DATA_TYPE_ARRAY) {
ESP_LOGV(TAG, "Expected structure or array after notification flag, found type %02X at position %d", start_type,
this->buffer_->position);
return 0;
}
// Parse the data, looking for attribute descriptors
bool success = parse_element_(start_type, 0);
if (!success) {
ESP_LOGV(TAG, "Some errors occurred parsing AXDR data");
}
ESP_LOGD(TAG, "Fast parsing completed, processed %d bytes", this->buffer_->position);
return this->objects_found_;
}
bool AxdrStreamParser::capture_generic_value_(AxdrCaptures &c) {
uint8_t vt = read_byte_();
if (!hlp_isValueDataType((DLMS_DATA_TYPE) vt)) {
return false;
}
int ds = hlp_getDataTypeSize((DLMS_DATA_TYPE) vt);
const uint8_t *ptr = nullptr;
uint8_t len = 0;
if (ds > 0) {
if (this->buffer_->position + ds > this->buffer_->size)
return false;
ptr = &this->buffer_->data[this->buffer_->position];
len = (uint8_t) ds;
this->buffer_->position += ds;
} else if (ds == 0) {
ptr = nullptr;
len = 0;
} else {
uint8_t L = read_byte_();
if (L == 0xFF || this->buffer_->position + L > this->buffer_->size)
return false;
ptr = &this->buffer_->data[this->buffer_->position];
len = L;
this->buffer_->position += L;
}
c.value_type = (DLMS_DATA_TYPE) vt;
c.value_ptr = ptr;
c.value_len = len;
return true;
}
void AxdrStreamParser::emit_object_(const AxdrDescriptorPattern &pat, const AxdrCaptures &c) {
if (!c.obis)
return;
uint16_t cid = c.class_id ? c.class_id : pat.default_class_id;
if (this->show_log_) {
ESP_LOGD(TAG, "Pattern match '%s' at idx %d ===============", pat.name, c.elem_idx);
auto val_f = dlms_data_as_float((DLMS_DATA_TYPE) c.value_type, c.value_ptr, c.value_len);
auto val_s = dlms_data_as_string((DLMS_DATA_TYPE) c.value_type, c.value_ptr, c.value_len);
ESP_LOGI(TAG, "Found attribute descriptor: class_id=%d, obis=%d.%d.%d.%d.%d.%d", cid, c.obis[0], c.obis[1],
c.obis[2], c.obis[3], c.obis[4], c.obis[5], c.value_type);
if (c.has_scaler_unit) {
ESP_LOGI(TAG, "Value type: %s, len %d, scaler %d, unit %d (%s)",
dlms_data_type_to_string((DLMS_DATA_TYPE) c.value_type), c.value_len, c.scaler, c.unit_enum,
obj_getUnitAsString(c.unit_enum));
} else {
ESP_LOGI(TAG, "Value type: %s, len %d", dlms_data_type_to_string((DLMS_DATA_TYPE) c.value_type), c.value_len);
}
ESP_LOGI(TAG, " as hex dump : %s", esphome::format_hex_pretty(c.value_ptr, c.value_len).c_str());
ESP_LOGI(TAG, " as string :'%s'", val_s.c_str());
ESP_LOGI(TAG, " as number : %f", val_f);
if (c.has_scaler_unit) {
ESP_LOGI(TAG, " as number * scaler : %f", val_f * std::pow(10, c.scaler));
}
}
if (callback_) {
if (c.has_scaler_unit) {
callback_(cid, c.obis, c.value_type, c.value_ptr, c.value_len, &c.scaler, &c.unit_enum);
} else {
callback_(cid, c.obis, c.value_type, c.value_ptr, c.value_len, nullptr, nullptr);
}
}
this->objects_found_++;
}
bool AxdrStreamParser::match_pattern_(uint8_t elem_idx, const AxdrDescriptorPattern &pat,
uint8_t &elements_consumed_at_level0) {
AxdrCaptures cap{};
elements_consumed_at_level0 = 0;
uint8_t level = 0;
auto consume_one = [&]() {
if (level == 0)
elements_consumed_at_level0++;
};
auto initial_position = this->buffer_->position;
for (const auto &step : pat.steps) {
switch (step.type) {
case AxdrTokenType::EXPECT_TO_BE_FIRST: {
if (elem_idx != 0)
return false;
break;
}
case AxdrTokenType::EXPECT_TYPE_EXACT: {
uint8_t t = read_byte_();
if (t != step.param_u8_a)
return false;
consume_one();
break;
}
case AxdrTokenType::EXPECT_TYPE_U_I_8: {
uint8_t t = read_byte_();
if (!(t == DLMS_DATA_TYPE_INT8 || t == DLMS_DATA_TYPE_UINT8))
return false;
consume_one();
break;
}
case AxdrTokenType::EXPECT_CLASS_ID_UNTAGGED: {
uint16_t v = read_u16_();
if (
// v == 0 ||
v > MAX_CLASS_ID)
return false;
cap.class_id = v;
break;
}
case AxdrTokenType::EXPECT_OBIS6_TAGGED: {
uint8_t t = read_byte_();
if (t != DLMS_DATA_TYPE_OCTET_STRING)
return false;
uint8_t len = read_byte_();
if (len != 6)
return false;
if (this->buffer_->position + 6 > this->buffer_->size)
return false;
cap.obis = &this->buffer_->data[this->buffer_->position];
this->buffer_->position += 6;
consume_one();
break;
}
case AxdrTokenType::EXPECT_OBIS6_UNTAGGED: {
if (this->buffer_->position + 6 > this->buffer_->size)
return false;
cap.obis = &this->buffer_->data[this->buffer_->position];
this->buffer_->position += 6;
break;
}
case AxdrTokenType::EXPECT_ATTR8_UNTAGGED: {
uint8_t a = read_byte_();
if (a == 0)
return false;
// cap.attr_id = a;
break;
}
case AxdrTokenType::EXPECT_VALUE_GENERIC: {
if (!capture_generic_value_(cap))
return false;
consume_one();
break;
}
case AxdrTokenType::EXPECT_STRUCTURE_N: {
uint8_t t = read_byte_();
if (t != DLMS_DATA_TYPE_STRUCTURE)
return false;
uint8_t cnt = read_byte_();
if (cnt != step.param_u8_a)
return false;
consume_one();
break;
}
case AxdrTokenType::EXPECT_SCALER_TAGGED: {
uint8_t t = read_byte_();
if (t != DLMS_DATA_TYPE_INT8)
return false;
uint8_t b = read_byte_();
cap.scaler = (int8_t) b;
cap.has_scaler_unit = true;
consume_one();
break;
}
case AxdrTokenType::EXPECT_UNIT_ENUM_TAGGED: {
uint8_t t = read_byte_();
if (t != DLMS_DATA_TYPE_ENUM)
return false;
uint8_t b = read_byte_();
cap.unit_enum = b;
cap.has_scaler_unit = true;
consume_one();
break;
}
case AxdrTokenType::GOING_DOWN: {
level++;
break;
}
case AxdrTokenType::GOING_UP: {
level--;
break;
}
default:
return false;
}
}
if (elements_consumed_at_level0 == 0) {
elements_consumed_at_level0 = 1; // Fallback: one element to move forward
}
cap.elem_idx = initial_position;
emit_object_(pat, cap);
return true;
}
bool AxdrStreamParser::try_match_patterns_(uint8_t elem_idx) {
const auto &pats = registry_.patterns();
for (const auto &p : pats) {
uint8_t consumed = 0;
uint32_t saved_position = buffer_->position;
if (match_pattern_(elem_idx, p, consumed)) {
this->last_pattern_elements_consumed_ = consumed;
return true;
} else {
buffer_->position = saved_position;
}
}
return false;
}
void AxdrStreamParser::register_pattern_dsl(const char *name, const std::string &dsl, int priority) {
AxdrDescriptorPattern pat{name, priority, {}, 0};
// DSL tokens separated by commas, optional spaces. Supported atoms:
// F : must be first element in sequence
// C : raw class_id (uint16 payload, no type tag)
// TC : tagged class_id (type tag UINT16 + uint16 payload)
// O : raw OBIS (6 bytes payload, no type tag)
// TO : tagged OBIS (type tag OCTET_STRING + length=6 + 6 bytes)
// A : raw attribute id (uint8 payload, no type tag)
// TA : tagged attribute (type tag INT8/UINT8 + 1 byte)
// TV : tagged value (type tag + payload for any value type)
// TSU : tagged scaler+unit structure (STRUCTURE tag + count 2 + TS + TU)
// Additionally supported:
// TS : tagged scaler (type tag INT8 + int8 payload)
// TU : tagged unit (type tag ENUM + uint8 payload)
// S(...) : structure with N elements, expands inner tokens
// Examples: "TC,TO,TA,TV", "TO,TV,TSU", "F,C,O,A,TV"
// For simplicity we parse left-to-right and translate to steps.
auto trim = [](const std::string &s) {
size_t b = s.find_first_not_of(" \t\r\n");
size_t e = s.find_last_not_of(" \t\r\n");
if (b == std::string::npos)
return std::string();
return s.substr(b, e - b + 1);
};
std::list<std::string> tokens;
std::string current;
int paren = 0;
for (char c : dsl) {
if (c == '(') {
paren++;
current.push_back(c);
} else if (c == ')') {
paren--;
current.push_back(c);
} else if (c == ',' && paren == 0) {
tokens.push_back(trim(current));
current.clear();
} else
current.push_back(c);
}
if (!current.empty())
tokens.push_back(trim(current));
for (auto it = tokens.begin(); it != tokens.end(); ++it) {
auto &tok = *it;
if (tok.empty())
continue;
if (tok == "F") {
pat.steps.push_back({AxdrTokenType::EXPECT_TO_BE_FIRST});
} else if (tok == "C") {
pat.steps.push_back({AxdrTokenType::EXPECT_CLASS_ID_UNTAGGED});
} else if (tok == "TC") {
pat.steps.push_back({AxdrTokenType::EXPECT_TYPE_EXACT, (uint8_t) DLMS_DATA_TYPE_UINT16});
pat.steps.push_back({AxdrTokenType::EXPECT_CLASS_ID_UNTAGGED});
} else if (tok == "O") {
pat.steps.push_back({AxdrTokenType::EXPECT_OBIS6_UNTAGGED});
} else if (tok == "TO") {
pat.steps.push_back({AxdrTokenType::EXPECT_OBIS6_TAGGED});
} else if (tok == "A") {
pat.steps.push_back({AxdrTokenType::EXPECT_ATTR8_UNTAGGED});
} else if (tok == "TA") {
pat.steps.push_back({AxdrTokenType::EXPECT_TYPE_U_I_8});
pat.steps.push_back({AxdrTokenType::EXPECT_ATTR8_UNTAGGED});
} else if (tok == "TS") {
pat.steps.push_back({AxdrTokenType::EXPECT_SCALER_TAGGED});
} else if (tok == "TU") {
pat.steps.push_back({AxdrTokenType::EXPECT_UNIT_ENUM_TAGGED});
} else if (tok == "TSU") {
pat.steps.push_back({AxdrTokenType::EXPECT_STRUCTURE_N, 2});
pat.steps.push_back({AxdrTokenType::GOING_DOWN});
pat.steps.push_back({AxdrTokenType::EXPECT_SCALER_TAGGED});
pat.steps.push_back({AxdrTokenType::EXPECT_UNIT_ENUM_TAGGED});
pat.steps.push_back({AxdrTokenType::GOING_UP});
} else if (tok == "V" || tok == "TV") {
pat.steps.push_back({AxdrTokenType::EXPECT_VALUE_GENERIC});
} else if (tok.rfind("S", 0) == 0) {
size_t l = tok.find('(');
size_t r = tok.rfind(')');
std::list<std::string> inner_tokens;
if (l != std::string::npos && r != std::string::npos && r > l + 1) {
std::string inner = tok.substr(l + 1, r - l - 1);
std::vector<std::string> innerT;
std::string cur;
for (char c2 : inner) {
if (c2 == ',') {
inner_tokens.push_back(trim(cur));
cur.clear();
} else
cur.push_back(c2);
}
if (!cur.empty())
inner_tokens.push_back(trim(cur));
}
if (!inner_tokens.empty()) {
pat.steps.push_back({AxdrTokenType::EXPECT_STRUCTURE_N, static_cast<uint8_t>(inner_tokens.size())});
inner_tokens.push_front("DN");
inner_tokens.push_back("UP");
tokens.insert(std::next(it), inner_tokens.begin(), inner_tokens.end());
}
} else if (tok == "DN") {
pat.steps.push_back({AxdrTokenType::GOING_DOWN});
} else if (tok == "UP") {
pat.steps.push_back({AxdrTokenType::GOING_UP});
}
}
registry_.add_pattern(pat);
}
} // namespace xt211
} // namespace esphome

View File

@ -0,0 +1,118 @@
#pragma once
#include <cstdint>
#include <functional>
#include <list>
#include <string>
#include <vector>
#include "client.h"
#include "converters.h"
#include "cosem.h"
#include "dlmssettings.h"
namespace esphome {
namespace xt211 {
const char *dlms_data_type_to_string(DLMS_DATA_TYPE vt);
const char *dlms_error_to_string(int error);
float dlms_data_as_float(DLMS_DATA_TYPE value_type, const uint8_t *value_buffer_ptr, uint8_t value_length);
std::string dlms_data_as_string(DLMS_DATA_TYPE value_type, const uint8_t *value_buffer_ptr, uint8_t value_length);
bool hlp_isValueDataType(DLMS_DATA_TYPE type);
using CosemObjectFoundCallback =
std::function<void(uint16_t class_id, const uint8_t *obis, DLMS_DATA_TYPE value_type, const uint8_t *value_ptr,
uint8_t value_len, const int8_t *scaler, const uint8_t *unit)>;
enum class AxdrTokenType : uint8_t {
EXPECT_TO_BE_FIRST,
EXPECT_TYPE_EXACT, // param_u8_a = required DLMS type tag
EXPECT_TYPE_U_I_8, // param_u8_a = required DLMS type tag; accept UINT8 or INT8
EXPECT_CLASS_ID_UNTAGGED, // capture class_id (big endian)
EXPECT_OBIS6_TAGGED, // capture 6-byte tagged OBIS
EXPECT_OBIS6_UNTAGGED, // capture 6-byte OBIS
EXPECT_ATTR8_UNTAGGED, // capture attribute id (accept INT8/UINT8 depending on flags)
EXPECT_VALUE_GENERIC, // capture value: first byte is type tag; supports fixed/variable lengths
EXPECT_STRUCTURE_N, // expect a structure with element count = param_u8_a
EXPECT_SCALER_TAGGED, // capture scaler (INT8 or UINT8)
EXPECT_UNIT_ENUM_TAGGED, // capture unit enum (ENUM base + 1 byte value)
GOING_DOWN, // capture going down
GOING_UP, // capture going up
};
struct AxdrPatternStep {
AxdrTokenType type;
uint8_t param_u8_a{0};
};
struct AxdrDescriptorPattern {
const char *name;
int priority{0};
std::vector<AxdrPatternStep> steps;
uint16_t default_class_id{0};
uint8_t value_attr_id{2};
uint8_t scaler_unit_attr_id{3};
};
struct AxdrCaptures {
uint32_t elem_idx{0};
uint16_t class_id{0};
const uint8_t *obis{nullptr};
DLMS_DATA_TYPE value_type{DLMS_DATA_TYPE_NONE};
const uint8_t *value_ptr{nullptr};
uint8_t value_len{0};
bool has_scaler_unit{false};
int8_t scaler{0};
uint8_t unit_enum{DLMS_UNIT_NO_UNIT};
};
class AxdrPatternRegistry {
public:
void add_pattern(const AxdrDescriptorPattern &p);
const std::vector<AxdrDescriptorPattern> &patterns() const { return patterns_; }
void clear() { patterns_.clear(); }
private:
std::vector<AxdrDescriptorPattern> patterns_{};
};
class AxdrStreamParser {
gxByteBuffer *buffer_;
CosemObjectFoundCallback callback_;
size_t objects_found_ = 0;
bool show_log_ = false;
AxdrPatternRegistry registry_{};
uint8_t last_pattern_elements_consumed_{0};
uint8_t peek_byte_();
uint8_t read_byte_();
uint16_t read_u16_();
uint32_t read_u32_();
bool test_if_date_time_12b_();
bool parse_element_(uint8_t type, uint8_t depth = 0);
bool parse_sequence_(uint8_t type, uint8_t depth = 0);
bool parse_data_(uint8_t type, uint8_t depth = 0);
bool skip_data_(uint8_t type);
bool skip_sequence_(uint8_t type);
bool try_match_patterns_(uint8_t elem_idx);
bool match_pattern_(uint8_t elem_idx, const AxdrDescriptorPattern &pat, uint8_t &elements_consumed_at_level);
bool capture_generic_value_(AxdrCaptures &c);
void emit_object_(const AxdrDescriptorPattern &pat, const AxdrCaptures &c);
public:
AxdrStreamParser(gxByteBuffer *buf, CosemObjectFoundCallback callback, bool show_log)
: buffer_(buf), callback_(callback), show_log_(show_log) {}
size_t parse();
void register_pattern_dsl(const char *name, const std::string &dsl, int priority = 10);
void clear_patterns() { registry_.clear(); }
};
} // namespace xt211
} // namespace esphome

View File

@ -0,0 +1,110 @@
#pragma once
#include "esphome/components/sensor/sensor.h"
#ifdef USE_TEXT_SENSOR
#include "esphome/components/text_sensor/text_sensor.h"
#endif
#ifdef USE_BINARY_SENSOR
#include "esphome/components/binary_sensor/binary_sensor.h"
#endif
#include <cmath> // for std::pow
namespace esphome {
namespace xt211 {
enum SensorType { SENSOR, TEXT_SENSOR, BINARY_SENSOR };
// const char * UNIT_STR_UNKNOWN = "Unknown unit";
#define UNIT_STR_UNKNOWN_NOT_YET "Unknown unit / not yet known"
#define UNIT_STR_UNKNOWN "Unknown unit"
class XT211SensorBase {
public:
static const uint8_t MAX_REQUEST_SIZE = 15;
virtual SensorType get_type() const = 0;
virtual const StringRef &get_sensor_name() = 0;
virtual EntityBase *get_base() = 0;
virtual void publish() = 0;
void set_obis_code(const char *obis_code) { this->obis_code_ = obis_code; }
const std::string &get_obis_code() const { return this->obis_code_; }
void set_dont_publish(bool dont_publish) { this->we_shall_publish_ = !dont_publish; }
bool shall_we_publish() const { return this->we_shall_publish_; }
void set_obis_class(int obis_class) { this->obis_class_ = obis_class; }
int get_obis_class() { return this->obis_class_; }
virtual bool has_got_scale_and_unit() { return false; } // PULL mode logic removed
protected:
std::string obis_code_;
int obis_class_{3 /*DLMS_OBJECT_TYPE_REGISTER*/};
bool we_shall_publish_{true};
// Removed has_value_, tries_
};
class XT211Sensor : public XT211SensorBase, public sensor::Sensor {
public:
SensorType get_type() const override { return SENSOR; }
const StringRef &get_sensor_name() { return this->get_name(); }
EntityBase *get_base() { return this; }
void publish() override { publish_state(this->value_); }
bool has_got_scale_and_unit() override { return true; } // PULL mode logic removed
void set_multiplier(float multiplier) { this->multiplier_ = multiplier; }
void set_value(float value) {
// Scale is applied in XT211Component::set_sensor_value before calling this
this->value_ = value * multiplier_;
}
protected:
float value_{NAN};
float multiplier_{1.0f};
// Removed scaler_, scale_f_, unit_, unit_s_, scale_and_unit_detected_
};
#ifdef USE_TEXT_SENSOR
class XT211TextSensor : public XT211SensorBase, public text_sensor::TextSensor {
public:
SensorType get_type() const override { return TEXT_SENSOR; }
const StringRef &get_sensor_name() { return this->get_name(); }
EntityBase *get_base() { return this; }
void publish() override { publish_state(value_); }
bool has_got_scale_and_unit() override { return true; }
void set_value(const char *value) {
value_ = std::string(value);
}
protected:
std::string value_;
};
#endif
#ifdef USE_BINARY_SENSOR
class XT211BinarySensor : public XT211SensorBase, public binary_sensor::BinarySensor {
public:
SensorType get_type() const override { return BINARY_SENSOR; }
const StringRef &get_sensor_name() { return this->get_name(); }
EntityBase *get_base() { return this; }
void publish() override { publish_state(value_); }
bool has_got_scale_and_unit() override { return true; }
void set_value(bool value) {
value_ = value;
}
protected:
bool value_;
};
#endif
} // namespace xt211
} // namespace esphome

View File

@ -0,0 +1,139 @@
#pragma once
#include <cstdint>
#ifdef USE_ESP32
#include "esphome/components/uart/uart_component_esp_idf.h"
#include "esphome/core/log.h"
#endif
#ifdef USE_ESP8266
#include "esphome/components/uart/uart_component_esp8266.h"
#endif
namespace esphome {
namespace xt211 {
static const uint32_t TIMEOUT = 20; // default value in uart implementation is 100ms
#ifdef USE_ESP8266
class XSoftSerial : public uart::ESP8266SoftwareSerial {
public:
void set_bit_time(uint32_t bt) { bit_time_ = bt; }
};
class XT211Uart final : public uart::ESP8266UartComponent {
public:
XT211Uart(uart::ESP8266UartComponent const &uart)
: uart_(uart), hw_(uart.*(&XT211Uart::hw_serial_)), sw_(uart.*(&XT211Uart::sw_serial_)) {}
void update_baudrate(uint32_t baudrate) {
if (this->hw_ != nullptr) {
this->hw_->updateBaudRate(baudrate);
} else if (baudrate > 0) {
((XSoftSerial *) sw_)->set_bit_time(F_CPU / baudrate);
}
}
bool read_one_byte(uint8_t *data) {
if (this->hw_ != nullptr) {
if (!this->check_read_timeout_quick_(1))
return false;
this->hw_->readBytes(data, 1);
} else {
if (sw_->available() < 1)
return false;
assert(this->sw_ != nullptr);
optional<uint8_t> b = this->sw_->read_byte();
if (b) {
*data = *b;
} else {
return false;
}
}
return true;
}
protected:
bool check_read_timeout_quick_(size_t len) {
if (this->hw_->available() >= int(len))
return true;
uint32_t start_time = millis();
while (this->hw_->available() < int(len)) {
if (millis() - start_time > TIMEOUT) {
return false;
}
yield();
}
return true;
}
uart::ESP8266UartComponent const &uart_;
HardwareSerial *const hw_; // hardware Serial
uart::ESP8266SoftwareSerial *const sw_; // software serial
};
#endif
#ifdef USE_ESP32
// backward compatibility with old IDF versions
#ifndef portTICK_PERIOD_MS
#define portTICK_PERIOD_MS portTICK_RATE_MS
#endif
class XT211Uart final : public uart::IDFUARTComponent {
public:
XT211Uart(uart::IDFUARTComponent &uart)
: uart_(uart), iuart_num_(uart.*(&XT211Uart::uart_num_)), ilock_(uart.*(&XT211Uart::lock_)) {}
// Reconfigure baudrate
void update_baudrate(uint32_t baudrate) {
xSemaphoreTake(ilock_, portMAX_DELAY);
uart_set_baudrate(iuart_num_, baudrate);
xSemaphoreGive(ilock_);
}
bool read_one_byte(uint8_t *data) { return read_array_quick_(data, 1); }
protected:
bool check_read_timeout_quick_(size_t len) {
if (uart_.available() >= int(len))
return true;
uint32_t start_time = millis();
while (uart_.available() < int(len)) {
if (millis() - start_time > TIMEOUT) {
return false;
}
yield();
}
return true;
}
bool read_array_quick_(uint8_t *data, size_t len) {
size_t length_to_read = len;
if (!this->check_read_timeout_quick_(len))
return false;
xSemaphoreTake(this->ilock_, portMAX_DELAY);
if (this->has_peek_) {
length_to_read--;
*data = this->peek_byte_;
data++;
this->has_peek_ = false;
}
if (length_to_read > 0)
uart_read_bytes(this->iuart_num_, data, length_to_read, 20 / portTICK_PERIOD_MS);
xSemaphoreGive(this->ilock_);
return true;
}
uart::IDFUARTComponent &uart_;
uart_port_t iuart_num_;
SemaphoreHandle_t &ilock_;
};
#endif
} // namespace xt211
} // namespace esphome

182
esphome-smartmeter.yaml Normal file
View File

@ -0,0 +1,182 @@
esphome:
name: esphome-smartmeter
friendly_name: SmartMeter
esp32:
variant: esp32c3
framework:
type: esp-idf
# Enable logging
logger:
# Enable Home Assistant API
api:
# Allow Over-The-Air updates
ota:
- platform: esphome
wifi:
ssid: "wifi_ssid"
password: "wifi_password"
external_components:
- source:
type: local
path: components
uart:
id: bus_1
rx_pin: GPIO21
tx_pin: GPIO20
baud_rate: 9600
data_bits: 8
parity: NONE
stop_bits: 1
xt211:
push_show_log: true
text_sensor:
- platform: xt211
name: Serial number
obis_code: 0.0.96.1.1.255
entity_category: diagnostic
- platform: xt211
name: Disconnector state
obis_code: 0.0.96.3.10.255
entity_category: diagnostic
- platform: xt211
name: Limmiter
obis_code: 0.0.17.0.0.255
entity_category: diagnostic
- platform: xt211
name: Current tariff
obis_code: 0.0.96.14.0.255
entity_category: diagnostic
- platform: xt211
name: Relay 1
obis_code: 0.1.96.3.10.255
- platform: xt211
name: Relay 2
obis_code: 0.2.96.3.10.255
- platform: xt211
name: Relay 3
obis_code: 0.3.96.3.10.255
- platform: xt211
name: Relay 4
obis_code: 0.4.96.3.10.255
sensor:
- platform: xt211
id: active_energy_consumed
name: Energy
obis_code: 1.0.1.8.0.255
unit_of_measurement: kWh
accuracy_decimals: 0
device_class: energy
state_class: total_increasing
- platform: xt211
id: active_energy_consumed_t1
name: Energy T1
obis_code: 1.0.1.8.1.255
unit_of_measurement: kWh
accuracy_decimals: 0
device_class: energy
state_class: total_increasing
- platform: xt211
id: active_energy_consumed_t2
name: Energy T2
obis_code: 1.0.1.8.2.255
unit_of_measurement: kWh
accuracy_decimals: 0
device_class: energy
state_class: total_increasing
- platform: xt211
id: active_energy_consumed_t3
name: Energy T3
obis_code: 1.0.1.8.3.255
unit_of_measurement: kWh
accuracy_decimals: 0
device_class: energy
state_class: total_increasing
- platform: xt211
id: active_energy_consumed_t4
name: Energy T4
obis_code: 1.0.1.8.4.255
unit_of_measurement: kWh
accuracy_decimals: 0
device_class: energy
state_class: total_increasing
- platform: xt211
id: active_power
name: Active power consumption
obis_code: 1.0.1.7.0.255
unit_of_measurement: W
accuracy_decimals: 0
device_class: power
state_class: measurement
- platform: xt211
id: active_power_l1
name: Active power consumption L1
obis_code: 1.0.21.7.0.255
unit_of_measurement: W
accuracy_decimals: 0
device_class: power
state_class: measurement
- platform: xt211
id: active_power_l2
name: Active power consumption L2
obis_code: 1.0.41.7.0.255
unit_of_measurement: W
accuracy_decimals: 0
device_class: power
state_class: measurement
- platform: xt211
id: active_power_l3
name: Active power consumption L3
obis_code: 1.0.61.7.0.255
unit_of_measurement: W
accuracy_decimals: 0
device_class: power
state_class: measurement
- platform: xt211
id: active_power_delivery
name: Active power delivery
obis_code: 1.0.2.7.0.255
unit_of_measurement: W
accuracy_decimals: 0
device_class: power
state_class: measurement
- platform: xt211
id: active_power_l1_delivery
name: Active power L1 delivery
obis_code: 1.0.22.7.0.255
unit_of_measurement: W
accuracy_decimals: 0
device_class: power
state_class: measurement
- platform: xt211
id: active_power_l2_delivery
name: Active power L2 delivery
obis_code: 1.0.42.7.0.255
unit_of_measurement: W
accuracy_decimals: 0
device_class: power
state_class: measurement
- platform: xt211
id: active_power_l3_delivery
name: Active power L3 delivery
obis_code: 1.0.62.7.0.255
unit_of_measurement: W
accuracy_decimals: 0
device_class: power
state_class: measurement