You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2020/05/04 16:43:28 UTC
[plc4x] branch feature/c-api updated: - Continued working on the
read support ... - Implemented connect and disconnect via system-task
This is an automated email from the ASF dual-hosted git repository.
cdutz pushed a commit to branch feature/c-api
in repository https://gitbox.apache.org/repos/asf/plc4x.git
The following commit(s) were added to refs/heads/feature/c-api by this push:
new 7cd7ddf - Continued working on the read support ... - Implemented connect and disconnect via system-task
7cd7ddf is described below
commit 7cd7ddf8c90fa56532e7c8aad4b81623892f872e
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Mon May 4 18:43:21 2020 +0200
- Continued working on the read support ...
- Implemented connect and disconnect via system-task
---
.../plc4c/drivers/simulated/src/driver_simulated.c | 149 ++++++++++++++++++---
.../plc4c/examples/hello-world/src/hello_world.c | 33 +++++
.../plc4c/spi/include/plc4c/spi/types_private.h | 11 +-
sandbox/plc4c/spi/src/connection.c | 8 +-
sandbox/plc4c/spi/src/read.c | 17 ++-
5 files changed, 193 insertions(+), 25 deletions(-)
diff --git a/sandbox/plc4c/drivers/simulated/src/driver_simulated.c b/sandbox/plc4c/drivers/simulated/src/driver_simulated.c
index 4c54be4..7a3d63f 100644
--- a/sandbox/plc4c/drivers/simulated/src/driver_simulated.c
+++ b/sandbox/plc4c/drivers/simulated/src/driver_simulated.c
@@ -18,12 +18,21 @@
*/
#include <stdlib.h>
+#include <string.h>
#include <plc4c/spi/types_private.h>
#include <plc4c/driver_simulated.h>
+enum plc4c_driver_simulated_field_type_t {
+ RANDOM,
+ STATE,
+ STDOUT
+};
+typedef enum plc4c_driver_simulated_field_type_t plc4c_driver_simulated_field_type;
+
// State definitions
enum read_states {
- READ_INIT
+ READ_INIT,
+ READ_FINISHED
};
enum write_states {
@@ -31,25 +40,64 @@ enum write_states {
};
struct plc4c_driver_simulated_item_t {
- // Sort of senseless, but for keeping track of the fact that it's an plc4c_item.
- plc4c_item super;
-
- // Actual properties goes here ...
+ plc4c_driver_simulated_field_type type;
+ char *name;
+ char *data_type;
+ int num_elements;
};
typedef struct plc4c_driver_simulated_item_t plc4c_driver_simulated_item;
+return_code plc4c_driver_simulated_connect_machine_function(plc4c_system_task *task) {
+ plc4c_connection *connection = task->context;
+ if(connection == NULL) {
+ return INTERNAL_ERROR;
+ }
+ if(connection->connected) {
+ return INTERNAL_ERROR;
+ }
+ connection->connected = true;
+ task->completed = true;
+ return OK;
+}
+
+return_code plc4c_driver_simulated_disconnect_machine_function(plc4c_system_task *task) {
+ plc4c_connection *connection = task->context;
+ if(connection == NULL) {
+ return INTERNAL_ERROR;
+ }
+ if(!connection->connected) {
+ return INTERNAL_ERROR;
+ }
+ connection->connected = false;
+ task->completed = true;
+ return OK;
+}
+
return_code plc4c_driver_simulated_read_machine_function(plc4c_system_task *task) {
- if(task->context == NULL) {
+ if (task->context == NULL) {
return INTERNAL_ERROR;
}
plc4c_read_request_execution *read_request_execution = task->context;
- plc4c_system_task *system_task = read_request_execution->system_task;
- switch (system_task->state_id) {
+ plc4c_read_request *read_request = read_request_execution->read_request;
+ switch (task->state_id) {
case READ_INIT: {
+ // Process every field in the request.
+ plc4c_list_element *cur_element = plc4c_utils_list_head(read_request->items);
+ while (cur_element != NULL) {
+ plc4c_driver_simulated_item *cur_item = cur_element->value;
+ cur_element = cur_element->next;
+ }
+
+ // Create a response.
plc4c_read_response *read_response = malloc(sizeof(plc4c_read_response));
read_request_execution->read_response = read_response;
- system_task->completed = true;
+ task->state_id = READ_FINISHED;
+ task->completed = true;
+ break;
+ }
+ case READ_FINISHED: {
+ // Do nothing
break;
}
default: {
@@ -59,9 +107,65 @@ return_code plc4c_driver_simulated_read_machine_function(plc4c_system_task *task
return OK;
}
-plc4c_item *plc4c_driver_simulated_parse_address(const char *address_string) {
+plc4c_item *plc4c_driver_simulated_parse_address(char *address_string) {
+ plc4c_driver_simulated_field_type type = RANDOM;
+ char *name = NULL;
+ char *data_type = NULL;
+ int num_elements = 0;
+ int start_segment_index = 0;
+ char *start_segment = address_string;
+ for (int i = 0; i <= strlen(address_string); i++) {
+ // This marks the end of the type part.
+ if (*(address_string + i) == '/') {
+ char *type_str = malloc(sizeof(char) * (i + 1));
+ strlcpy(type_str, start_segment, i + 1);
+ if(strcmp(type_str, "RANDOM") == 0) {
+ type = RANDOM;
+ } else if(strcmp(type_str, "STATE") == 0) {
+ type = STATE;
+ } else if(strcmp(type_str, "STDOUT") == 0) {
+ type = STDOUT;
+ } else {
+ return NULL;
+ }
+ start_segment = address_string + i + 1;
+ start_segment_index = i + 1;
+ }
+ // This marks the end of the name part.
+ if (*(address_string + i) == ':') {
+ name = malloc(sizeof(char) * ((i - start_segment_index) + 1));
+ strlcpy(name, start_segment, (i - start_segment_index) + 1);
+ start_segment = address_string + i + 1;
+ start_segment_index = i + 1;
+ }
+ // This marks the end of the data-type part if there is a size coming in addition.
+ if ((i == strlen(address_string)) || (*(address_string + i) == '[')) {
+ data_type = malloc(sizeof(char) * ((i - start_segment_index) + 1));
+ strlcpy(data_type, start_segment, (i - start_segment_index) + 1);
+ start_segment = address_string + i + 1;
+ start_segment_index = i + 1;
+ if(i == strlen(address_string)) {
+ num_elements = 1;
+ break;
+ }
+ }
+ // This marks the end of the size part.
+ if (*(address_string + i) == ']') {
+ char *num_elements_str = malloc(sizeof(char) * ((i - start_segment_index) + 1));
+ strlcpy(num_elements_str, start_segment, (i - start_segment_index) + 1);
+ char *success = NULL;
+ num_elements = (int) strtol(num_elements_str, &success, 10);
+ break;
+ }
+ }
+
+ // Create a new driver specific item.
plc4c_driver_simulated_item *item = (plc4c_driver_simulated_item *) malloc(sizeof(plc4c_driver_simulated_item));
- // TODO: Actually to the parsing of the address ...
+ item->type = type;
+ item->name = name;
+ item->data_type = data_type;
+ item->num_elements = num_elements;
+
return (plc4c_item *) item;
}
@@ -71,28 +175,36 @@ return_code plc4c_driver_simulated_connect_function(plc4c_connection *connection
new_task->context = connection;
// There's nothing to do here, so no need for a state-machine.
new_task->state_id = -1;
- new_task->state_machine_function = NULL;
- // We're setting this to true as there's nothing to do.
- new_task->completed = true;
+ new_task->state_machine_function = &plc4c_driver_simulated_connect_machine_function;
*task = new_task;
return OK;
}
-return_code plc4c_driver_simulated_read_function(plc4c_read_request *read_request, plc4c_system_task **task) {
+return_code plc4c_driver_simulated_disconnect_function(plc4c_connection *connection,
+ plc4c_system_task **task) {
+ plc4c_system_task *new_task = malloc(sizeof(plc4c_system_task));
+ new_task->context = connection;
+ // There's nothing to do here, so no need for a state-machine.
+ new_task->state_id = -1;
+ new_task->state_machine_function = &plc4c_driver_simulated_disconnect_machine_function;
+ *task = new_task;
+ return OK;
+}
+
+return_code plc4c_driver_simulated_read_function(plc4c_system_task **task) {
plc4c_system_task *new_task = malloc(sizeof(plc4c_system_task));
new_task->state_id = READ_INIT;
new_task->state_machine_function = &plc4c_driver_simulated_read_machine_function;
- new_task->context = read_request;
new_task->completed = false;
*task = new_task;
return OK;
}
-return_code plc4c_driver_simulated_write_function(plc4c_write_request *write_request, plc4c_system_task **task) {
+return_code plc4c_driver_simulated_write_function(plc4c_system_task **task) {
plc4c_system_task *new_task = malloc(sizeof(plc4c_system_task));
new_task->state_id = WRITE_INIT;
new_task->state_machine_function = NULL;
- new_task->context = write_request;
+ new_task->completed = false;
*task = new_task;
return OK;
}
@@ -104,6 +216,7 @@ plc4c_driver *plc4c_driver_simulated_create() {
driver->default_transport_code = "dummy";
driver->parse_address_function = &plc4c_driver_simulated_parse_address;
driver->connect_function = &plc4c_driver_simulated_connect_function;
+ driver->disconnect_function = &plc4c_driver_simulated_disconnect_function;
driver->read_function = &plc4c_driver_simulated_read_function;
driver->write_function = &plc4c_driver_simulated_write_function;
return driver;
diff --git a/sandbox/plc4c/examples/hello-world/src/hello_world.c b/sandbox/plc4c/examples/hello-world/src/hello_world.c
index 3ab0ef2..ed536c6 100644
--- a/sandbox/plc4c/examples/hello-world/src/hello_world.c
+++ b/sandbox/plc4c/examples/hello-world/src/hello_world.c
@@ -61,29 +61,41 @@ int main() {
plc4c_read_request_execution *read_request_execution = NULL;
// Create a new uninitialized plc4c_system
+ printf("Creating new PLC4C System (Initializing inner data-structures) ... ");
return_code result = plc4c_system_create(&system);
if (result != OK) {
+ printf("FAILED\n");
return -1;
}
+ printf("SUCCESS\n");
// Manually register the "simulated" driver with the system.
+ printf("Registering driver for the 'simulated' protocol ... ");
plc4c_driver *simulated_driver = plc4c_driver_simulated_create();
result = plc4c_system_add_driver(system, simulated_driver);
if (result != OK) {
+ printf("FAILED\n");
return -1;
}
+ printf("SUCCESS\n");
+ printf("Registering transport for the 'dummy' transport ... ");
plc4c_transport *dummy_transport = plc4c_transport_dummy_create();
result = plc4c_system_add_transport(system, dummy_transport);
if (result != OK) {
+ printf("FAILED\n");
return -1;
}
+ printf("SUCCESS\n");
// Initialize the plc4c_system (loading of drivers, setting up other stuff, ...)
+ printf("Initializing the PLC4C system (Loading of drivers and transports) ... ");
result = plc4c_system_init(system);
if (result != OK) {
+ printf("FAILED\n");
return -1;
}
+ printf("SUCCESS\n");
// Register the global callbacks.
plc4c_system_set_on_connect_success_callback(system, &onGlobalConnect);
@@ -91,17 +103,23 @@ int main() {
// Establish connections to remote devices
// you may or may not care about the connection handle
+ printf("Connecting to 'simulated://foo' ... ");
result = plc4c_system_connect(system, "simulated://foo", &connection);
if (result != OK) {
+ printf("FAILED\n");
return -1;
}
// Central program loop ...
plc4c_connection_state state = CONNECTING;
while (loop) {
+
+ printf("* ");
+
// Give plc4c a chance to do something.
// This is where all I/O is being done.
if (plc4c_system_loop(system) != OK) {
+ printf("ERROR in the system loop\n");
break;
}
@@ -110,23 +128,30 @@ int main() {
case CONNECTING: {
// Check if the connection is established:
if (plc4c_connection_is_connected(connection)) {
+ printf("SUCCESS\n");
state = CONNECTED;
} else if (plc4c_connection_has_error(connection)) {
+ printf("FAILED\n");
return -1;
}
break;
}
case CONNECTED: {
// Create a new read-request.
+ printf("Preparing a read-request for 'RANDOM/foo:INTEGER' ... ");
char *addresses[] = {"RANDOM/foo:INTEGER"};
result = plc4c_connection_create_read_request(connection, 1, addresses, &read_request);
if(result != OK) {
+ printf("FAILED\n");
return -1;
}
+ printf("SUCCESS\n");
// Execute the read-request.
+ printf("Executing a read-request ... ");
result = plc4c_read_request_execute(read_request, &read_request_execution);
if(result != OK) {
+ printf("FAILED\n");
return -1;
} else {
state = READ_REQUEST_SENT;
@@ -136,8 +161,10 @@ int main() {
// Wait until the read-request execution is finished.
case READ_REQUEST_SENT: {
if(plc4c_read_request_finished_successfully(read_request_execution)) {
+ printf("SUCCESS\n");
state = READ_RESPONSE_RECEIVED;
} else if(plc4c_read_request_has_error(read_request_execution)) {
+ printf("FAILED\n");
return -1;
}
break;
@@ -153,8 +180,10 @@ int main() {
plc4c_read_request_destroy(read_request);
// Disconnect.
+ printf("Disconnecting ... ");
result = plc4c_connection_disconnect(connection);
if(result != OK) {
+ printf("FAILED");
return -1;
}
state = DISCONNECTING;
@@ -163,8 +192,12 @@ int main() {
// Wait until the connection is disconnected
case DISCONNECTING: {
if(!plc4c_connection_is_connected(connection)) {
+ printf("SUCCESS\n");
plc4c_connection_destroy(connection);
state = DISCONNECTED;
+
+ // Terminate the main program loop.
+ loop = false;
}
break;
}
diff --git a/sandbox/plc4c/spi/include/plc4c/spi/types_private.h b/sandbox/plc4c/spi/include/plc4c/spi/types_private.h
index a02d499..14e53cb 100644
--- a/sandbox/plc4c/spi/include/plc4c/spi/types_private.h
+++ b/sandbox/plc4c/spi/include/plc4c/spi/types_private.h
@@ -30,7 +30,7 @@ typedef struct plc4c_transport_list_item_t plc4c_transport_list_item;
typedef struct plc4c_connection_list_item_t plc4c_connection_list_item;
typedef struct plc4c_write_item_t plc4c_write_item;
-typedef plc4c_item *(*plc4c_connection_parse_address_item)(const char *address_string);
+typedef plc4c_item *(*plc4c_connection_parse_address_item)(char *address_string);
typedef struct plc4c_system_task_t plc4c_system_task;
@@ -38,9 +38,11 @@ typedef return_code (*plc4c_system_task_state_machine_function)(plc4c_system_tas
typedef return_code (*plc4c_connection_connect_function)(plc4c_connection *connection, plc4c_system_task **task);
-typedef return_code (*plc4c_connection_read_function)(plc4c_read_request *read_request, plc4c_system_task **task);
+typedef return_code (*plc4c_connection_disconnect_function)(plc4c_connection *connection, plc4c_system_task **task);
-typedef return_code (*plc4c_connection_write_function)(plc4c_write_request *write_request, plc4c_system_task **task);
+typedef return_code (*plc4c_connection_read_function)(plc4c_system_task **task);
+
+typedef return_code (*plc4c_connection_write_function)(plc4c_system_task **task);
struct plc4c_system_t {
/* drivers */
@@ -74,6 +76,7 @@ struct plc4c_driver_t {
char *default_transport_code;
plc4c_connection_parse_address_item parse_address_function;
plc4c_connection_connect_function connect_function;
+ plc4c_connection_disconnect_function disconnect_function;
plc4c_connection_read_function read_function;
plc4c_connection_write_function write_function;
};
@@ -103,6 +106,8 @@ struct plc4c_connection_t {
char *transport_connect_information;
char *parameters;
+ bool connected;
+
plc4c_system *system;
plc4c_driver *driver;
plc4c_transport *transport;
diff --git a/sandbox/plc4c/spi/src/connection.c b/sandbox/plc4c/spi/src/connection.c
index 21280ac..edcb7fa 100644
--- a/sandbox/plc4c/spi/src/connection.c
+++ b/sandbox/plc4c/spi/src/connection.c
@@ -22,7 +22,7 @@
#include <plc4c/spi/types_private.h>
bool plc4c_connection_is_connected(plc4c_connection *connection) {
- return true;
+ return connection->connected;
}
bool plc4c_connection_has_error(plc4c_connection *connection) {
@@ -30,6 +30,12 @@ bool plc4c_connection_has_error(plc4c_connection *connection) {
}
return_code plc4c_connection_disconnect(plc4c_connection *connection) {
+ plc4c_system_task *new_disconnection_task = NULL;
+ return_code result = connection->driver->disconnect_function(connection, &new_disconnection_task);
+ if(result != OK) {
+ return -1;
+ }
+ plc4c_utils_list_insert_tail_value(connection->system->task_list, new_disconnection_task);
return OK;
}
diff --git a/sandbox/plc4c/spi/src/read.c b/sandbox/plc4c/spi/src/read.c
index 0830a73..5c4648a 100644
--- a/sandbox/plc4c/spi/src/read.c
+++ b/sandbox/plc4c/spi/src/read.c
@@ -25,21 +25,29 @@
return_code plc4c_read_request_execute(plc4c_read_request *read_request,
plc4c_read_request_execution **read_request_execution) {
plc4c_system_task *system_task;
- read_request->connection->driver->read_function(read_request, &system_task);
+ read_request->connection->driver->read_function(&system_task);
// Add the new task to the task-list.
plc4c_utils_list_insert_tail_value(read_request->connection->system->task_list, system_task);
+ // Inject the default read context into the system task.
plc4c_read_request_execution *new_read_request_execution = malloc(sizeof(plc4c_read_request_execution));
new_read_request_execution->read_request = read_request;
new_read_request_execution->read_response = NULL;
new_read_request_execution->system_task = system_task;
+ new_read_request_execution->system_task->context = new_read_request_execution;
*read_request_execution = new_read_request_execution;
return OK;
}
bool plc4c_read_request_finished_successfully(plc4c_read_request_execution *read_request_execution) {
- return true;
+ if(read_request_execution == NULL) {
+ return true;
+ }
+ if(read_request_execution->system_task == NULL) {
+ return true;
+ }
+ return read_request_execution->system_task->completed;
}
bool plc4c_read_request_has_error(plc4c_read_request_execution *read_request_execution) {
@@ -47,7 +55,10 @@ bool plc4c_read_request_has_error(plc4c_read_request_execution *read_request_exe
}
plc4c_read_response *plc4c_read_request_get_response(plc4c_read_request_execution *read_request_execution) {
- return NULL;
+ if(read_request_execution == NULL) {
+ return NULL;
+ }
+ return read_request_execution->read_response;
}
void plc4c_read_request_destroy(plc4c_read_request *read_request) {