Skip to content

Commit

Permalink
Add CSV input example model.
Browse files Browse the repository at this point in the history
Signed-off-by: Timothy Rule (VM/EMT3) <[email protected]>
  • Loading branch information
timrulebosch committed Dec 13, 2024
1 parent 0634f82 commit b0461e1
Show file tree
Hide file tree
Showing 9 changed files with 271 additions and 1 deletion.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export TESTSCRIPT_E2E_DIR ?= tests/testscript/e2e
TESTSCRIPT_E2E_FILES = \
$(TESTSCRIPT_E2E_DIR)/minimal.txtar \
$(TESTSCRIPT_E2E_DIR)/extended.txtar \
$(TESTSCRIPT_E2E_DIR)/csv.txtar \
$(TESTSCRIPT_E2E_DIR)/transform.txtar \
$(TESTSCRIPT_E2E_DIR)/binary.txtar \
$(TESTSCRIPT_E2E_DIR)/ncodec.txtar \
Expand Down
1 change: 1 addition & 0 deletions dse/modelc/examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

# Example Models.
add_subdirectory(binary)
add_subdirectory(csv)
add_subdirectory(extended)
add_subdirectory(gateway)
add_subdirectory(gdb)
Expand Down
48 changes: 48 additions & 0 deletions dse/modelc/examples/csv/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Copyright 2024 Robert Bosch GmbH
#
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.21)

project(Csv)
set(MODEL_PATH "examples/csv")

include(FetchContent)
FetchContent_Declare(dse_clib
URL $ENV{DSE_CLIB_URL}
HTTP_USERNAME $ENV{GHE_USER}
HTTP_PASSWORD $ENV{GHE_TOKEN}
)
FetchContent_MakeAvailable(dse_clib)
set(DSE_CLIB_INCLUDE_DIR ${dse_clib_SOURCE_DIR})

add_library(csv SHARED
model.c
)
target_include_directories(csv
PRIVATE
${DSE_CLIB_INCLUDE_DIR}
../../../..
)
target_link_libraries(csv
PRIVATE
$<$<BOOL:${WIN32}>:${modelc_link_lib}>
)
install(TARGETS csv
LIBRARY DESTINATION
${MODEL_PATH}/lib
RUNTIME DESTINATION
${MODEL_PATH}/lib
COMPONENT
csv
)
install(
FILES
model.yaml
simulation.yaml
valueset.csv
DESTINATION
${MODEL_PATH}/data
COMPONENT
csv
)
116 changes: 116 additions & 0 deletions dse/modelc/examples/csv/model.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// Copyright 2024 Robert Bosch GmbH
//
// SPDX-License-Identifier: Apache-2.0

#include <stddef.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <dse/modelc/model.h>
#include <dse/logger.h>


#define CSV_LINE_MAXLEN 1024
#define CSV_DELIMITER ",;"
#define CSV_FILE_ENVAR "CSV_FILE"


typedef struct {
ModelDesc model;

/* CSV specific members. */
const char* file_name;
FILE* file;
char line[CSV_LINE_MAXLEN];
double timestamp;
SignalVector* sv;
} CsvModelDesc;


static bool read_csv_line(CsvModelDesc* c)
{
c->timestamp = -1; // Set a safe time (i.e. no valid value set).
while (c->timestamp < 0) {
// Read a line.
char* line = fgets(c->line, CSV_LINE_MAXLEN, c->file);
if (line == NULL) return false;
if (strlen(line) == 0) continue;

// Get the timestamp.
log_trace("csv::%s", c->line);
errno = 0;
double ts = strtod(c->line, NULL);
if (errno) {
log_error("Bad line, timestamp conversion failed");
log_error(c->line);
continue;
}
if (ts >= 0) c->timestamp = ts;
}

return true;
}


ModelDesc* model_create(ModelDesc* model)
{
/* Extend the ModelDesc object (using a shallow copy). */
CsvModelDesc* c = calloc(1, sizeof(CsvModelDesc));
memcpy(c, model, sizeof(ModelDesc));
if (model->sv && model->sv->name) {
c->sv = model->sv;
} else {
log_fatal("No signal vector configured");
}

/* Open and prepare the CSV file (i.e. consume the first line). */
c->file_name = getenv(CSV_FILE_ENVAR);
c->file = fopen(c->file_name, "r");
if (c->file == NULL) {
log_fatal("Unable to open CSV file (%s)", c->file_name);
}
fgets(c->line, CSV_LINE_MAXLEN, c->file);
log_trace("csv::%s", c->line);

/* Read the first CSV value set. */
read_csv_line(c);

/* Return the extended object. */
return (ModelDesc*)c;
}


int model_step(ModelDesc* model, double* model_time, double stop_time)
{
CsvModelDesc* c = (CsvModelDesc*)model;

/* Apply value sets from CSV. */
while ((c->timestamp >= 0) && (c->timestamp <= *model_time)) {
size_t idx = 0;
char* _saveptr = NULL;
char* _valueptr;
strtok_r(c->line, CSV_DELIMITER, &_saveptr); // Consume the timestamp.
while ((_valueptr = strtok_r(NULL, CSV_DELIMITER, &_saveptr))) {
errno = 0;
double v = strtod(_valueptr, NULL);
if (errno == 0) {
c->sv->scalar[idx] = v;
}
if (++idx >= c->sv->count) break; /* Too many values. */
}
/* Load the next line. */
if (read_csv_line(c) == false) break;
}

/* Advance the model time. */
*model_time = stop_time;
return 0;
}


void model_destroy(ModelDesc* model)
{
CsvModelDesc* c = (CsvModelDesc*)model;
if (c->file) fclose(c->file);
}
27 changes: 27 additions & 0 deletions dse/modelc/examples/csv/model.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Copyright 2024 Robert Bosch GmbH
#
# SPDX-License-Identifier: Apache-2.0

---
kind: Model
metadata:
name: Csv
spec:
runtime:
dynlib:
- os: linux
arch: amd64
path: lib/libcsv.so
- os: linux
arch: x86
path: lib/libcsv.so
- os: windows
arch: x64
path: lib/libcsv.dll
- os: windows
arch: x86
path: lib/libcsv.dll
channels:
- alias: scalar
selectors:
channel: scalar_channel
46 changes: 46 additions & 0 deletions dse/modelc/examples/csv/simulation.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Copyright 2024 Robert Bosch GmbH
#
# SPDX-License-Identifier: Apache-2.0

---
kind: Stack
metadata:
name: csv_stack
spec:
connection:
transport:
redispubsub:
uri: redis://localhost:6379
timeout: 60
models:
- name: simbus
model:
name: simbus
channels:
- name: scalar_channel
expectedModelCount: 1
- name: csv_inst
uid: 42
model:
name: Csv
runtime:
env:
CSV_FILE: data/valueset.csv
channels:
- name: scalar_channel
alias: scalar
---
kind: Model
metadata:
name: simbus
---
kind: SignalGroup
metadata:
name: scalar_channel
labels:
channel: scalar_channel
spec:
signals:
- signal: A
- signal: B
- signal: C
5 changes: 5 additions & 0 deletions dse/modelc/examples/csv/valueset.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Timestamp;A;B;C
0.0000;1.0;2.0;3.0
0.0005;-1.1;2.1;3.1
0.0010;1.2;-2.2;3.2
0.0015;1.3;2.3;-3.3
26 changes: 26 additions & 0 deletions tests/testscript/e2e/csv.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
env NAME=csv_inst
env SIM=dse/modelc/build/_out/examples/csv


# TEST: csv example model
exec sh -e $WORK/test.sh

stderr 'Using Valgrind'
stdout 'Load YAML File: data/simulation.yaml'
stdout 'Loading symbol: model_create ... ok'
stdout 'Loading symbol: model_step ... ok'
stdout 'Loading symbol: model_destroy ... ok'
stdout 'Run the Simulation ...'
stdout 'Controller exit ...'
stdout 'SignalValue: 3289118412 = 1.300000 \[name=A\]'
stdout 'SignalValue: 3339451269 = 2.300000 \[name=B\]'
stdout 'SignalValue: 3322673650 = -3.300000 \[name=C\]'

-- test.sh --
SIMER="${SIMER:-ghcr.io/boschglobal/dse-simer:latest}"
docker run --name simer -i --rm \
-v $ENTRYHOSTDIR/$SIM:/sim \
$SIMER \
-valgrind $NAME \
-env $NAME:SIMBUS_LOGLEVEL=2 \
-logger 2
2 changes: 1 addition & 1 deletion tests/testscript/e2e/gateway.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,5 @@ docker run --name simer -i --rm \
--network=host \
$SIMER \
-env simbus:SIMBUS_LOGLEVEL=4 \
-stack local
-stack local \
-timeout 5

0 comments on commit b0461e1

Please sign in to comment.