Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for SML_TimestampLocal #96

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions sml/include/sml/sml_time.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,28 @@ extern "C" {

#define SML_TIME_SEC_INDEX 0x01
#define SML_TIME_TIMESTAMP 0x02
#define SML_TIME_LOCAL_TIMESTAMP 0x03

typedef struct {
u32 *timestamp;
i16 *local_offset;
i16 *season_time_offset;
} sml_timestamp_local;

typedef struct {
u8 *tag;
union {
u32 *sec_index;
u32 *timestamp;
sml_timestamp_local *local_timestamp;
} data;
} sml_time;

sml_timestamp_local *sml_timestamp_local_init();
sml_timestamp_local *sml_timestamp_local_parse(sml_buffer *buf);
void sml_timestamp_local_write(sml_timestamp_local *time, sml_buffer *buf);
void sml_timestamp_local_free(sml_timestamp_local *time);

sml_time *sml_time_init();
sml_time *sml_time_parse(sml_buffer *buf);
void sml_time_write(sml_time *time, sml_buffer *buf);
Expand Down
113 changes: 74 additions & 39 deletions sml/src/sml_time.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,63 @@
#include <sml/sml_time.h>
#include <stdio.h>

sml_timestamp_local *sml_timestamp_local_init() {
sml_timestamp_local *t = (sml_timestamp_local *)malloc(sizeof(sml_timestamp_local));
*t = (sml_timestamp_local){.timestamp = NULL, .local_offset = NULL, .season_time_offset = NULL};
return t;
}

sml_timestamp_local *sml_timestamp_local_parse(sml_buffer *buf) {
if (sml_buf_optional_is_skipped(buf)) {
return NULL;
}

if (sml_buf_get_next_length(buf) != 3) {
buf->error = 1;
goto error;
}

sml_timestamp_local *time = sml_timestamp_local_init();

time->timestamp = sml_u32_parse(buf);
if (sml_buf_has_errors(buf))
goto error;

time->local_offset = sml_i16_parse(buf);
if (sml_buf_has_errors(buf))
goto error;

time->season_time_offset = sml_i16_parse(buf);
if (sml_buf_has_errors(buf))
goto error;

return time;

error:
sml_timestamp_local_free(time);
return NULL;
}

void sml_timestamp_local_write(sml_timestamp_local *time, sml_buffer *buf) {
if (time == 0) {
sml_buf_optional_write(buf);
return;
}

sml_u32_write(time->timestamp, buf);
sml_i16_write(time->local_offset, buf);
sml_i16_write(time->season_time_offset, buf);
}

void sml_timestamp_local_free(sml_timestamp_local *time) {
if (time) {
sml_number_free(time->timestamp);
sml_number_free(time->local_offset);
sml_number_free(time->season_time_offset);
free(time);
}
}

sml_time *sml_time_init() {
sml_time *t = (sml_time *)malloc(sizeof(sml_time));
*t = (sml_time){.tag = NULL, .data.sec_index = NULL};
Expand Down Expand Up @@ -67,44 +124,9 @@ sml_time *sml_time_parse(sml_buffer *buf) {
goto error;
break;
case SML_TYPE_LIST:
// Some meters (e.g. FROETEC Multiflex ZG22) giving not one uint32
// as timestamp, but a list of 3 values.
// Ignoring these values, so that parsing does not fail.
sml_buf_get_next_length(buf); // should we check the length here?
u32 *t1 = sml_u32_parse(buf);
if (sml_buf_has_errors(buf)) {
if (t1)
sml_number_free(t1);
goto error;
}
i16 *t2 = sml_i16_parse(buf);
if (sml_buf_has_errors(buf)) {
if (t1)
sml_number_free(t1);
if (t2)
sml_number_free(t2);
goto error;
}
i16 *t3 = sml_i16_parse(buf);
if (sml_buf_has_errors(buf)) {
if (t1)
sml_number_free(t1);
if (t2)
sml_number_free(t2);
if (t3)
sml_number_free(t3);
tme->data.local_timestamp = sml_timestamp_local_parse(buf);
if (sml_buf_has_errors(buf))
goto error;
}
fprintf(
stderr,
"libsml: error: sml_time as list[3]: ignoring value[0]=%u value[1]=%d value[2]=%d\n",
t1 ? *t1 : 0, t2 ? *t2 : 0, t3 ? *t3 : 0);
if (t1)
sml_number_free(t1);
if (t2)
sml_number_free(t2);
if (t3)
sml_number_free(t3);
break;
default:
goto error;
Expand All @@ -125,13 +147,26 @@ void sml_time_write(sml_time *t, sml_buffer *buf) {

sml_buf_set_type_and_length(buf, SML_TYPE_LIST, 2);
sml_u8_write(t->tag, buf);
sml_u32_write(t->data.timestamp, buf);
if (*t->tag == SML_TIME_LOCAL_TIMESTAMP) {
sml_buf_set_type_and_length(buf, SML_TYPE_LIST, 3);
sml_timestamp_local_write(t->data.local_timestamp, buf);
} else {
sml_u32_write(t->data.timestamp, buf);
}
}

void sml_time_free(sml_time *tme) {
if (tme) {
if (tme->tag) {
switch (*tme->tag) {
case SML_TIME_LOCAL_TIMESTAMP:
sml_timestamp_local_free(tme->data.local_timestamp);
break;
default:
sml_number_free(tme->data.timestamp);
}
}
sml_number_free(tme->tag);
sml_number_free(tme->data.timestamp);
free(tme);
}
}
47 changes: 35 additions & 12 deletions test/src/sml_time_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,14 @@ TEST_GROUP(sml_time);

static sml_buffer *buf;

TEST_SETUP(sml_time) {
buf = sml_buffer_init(512);
}
TEST_SETUP(sml_time) { buf = sml_buffer_init(512); }

TEST_TEAR_DOWN(sml_time) {
sml_buffer_free(buf);
}
TEST_TEAR_DOWN(sml_time) { sml_buffer_free(buf); }

TEST(sml_time, init) {
sml_time *t = sml_time_init();
TEST_ASSERT_NOT_NULL(t);
sml_time_free( t );
sml_time_free(t);
}

TEST(sml_time, parse_sec_index) {
Expand All @@ -46,7 +42,7 @@ TEST(sml_time, parse_sec_index) {
TEST_ASSERT_EQUAL(SML_TIME_SEC_INDEX, *(t->tag));
TEST_ASSERT_EQUAL(8, buf->cursor);

sml_time_free( t );
sml_time_free(t);
}

TEST(sml_time, parse_timestamp) {
Expand All @@ -57,7 +53,18 @@ TEST(sml_time, parse_timestamp) {
TEST_ASSERT_EQUAL(SML_TIME_TIMESTAMP, *(t->tag));
TEST_ASSERT_EQUAL(8, buf->cursor);

sml_time_free( t );
sml_time_free(t);
}

TEST(sml_time, parse_timestamp_local) {
hex2binary("7262037365000000FF53003C530001", sml_buf_get_current_buf(buf));
sml_time *t = sml_time_parse(buf);

TEST_ASSERT_NOT_NULL(t);
TEST_ASSERT_EQUAL(SML_TIME_LOCAL_TIMESTAMP, *(t->tag));
TEST_ASSERT_EQUAL(15, buf->cursor);

sml_time_free(t);
}

TEST(sml_time, parse_optional) {
Expand All @@ -67,7 +74,7 @@ TEST(sml_time, parse_optional) {
TEST_ASSERT_NULL(t);
TEST_ASSERT_EQUAL(1, buf->cursor);

sml_time_free( t );
sml_time_free(t);
}

TEST(sml_time, write_sec_index) {
Expand All @@ -78,7 +85,22 @@ TEST(sml_time, write_sec_index) {
sml_time_write(t, buf);
expected_buf(buf, "72620165000000FF", 8);

sml_time_free( t );
sml_time_free(t);
}

TEST(sml_time, write_timestamp_local) {
sml_time *t = sml_time_init();
sml_timestamp_local *local_t = sml_timestamp_local_init();
local_t->timestamp = sml_u32_init(255);
local_t->local_offset = sml_i16_init(20);
local_t->season_time_offset = sml_i16_init(10);
t->data.local_timestamp = local_t;
t->tag = sml_u8_init(SML_TIME_LOCAL_TIMESTAMP);

sml_time_write(t, buf);
expected_buf(buf, "7262037365000000FF53001453000A", 15);

sml_time_free(t);
}

TEST(sml_time, write_optional) {
Expand All @@ -90,8 +112,9 @@ TEST_GROUP_RUNNER(sml_time) {
RUN_TEST_CASE(sml_time, init);
RUN_TEST_CASE(sml_time, parse_sec_index);
RUN_TEST_CASE(sml_time, parse_timestamp);
RUN_TEST_CASE(sml_time, parse_timestamp_local);
RUN_TEST_CASE(sml_time, parse_optional);
RUN_TEST_CASE(sml_time, write_sec_index);
RUN_TEST_CASE(sml_time, write_timestamp_local);
RUN_TEST_CASE(sml_time, write_optional);
}