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/11 15:01:13 UTC
[plc4x] 01/01: - First draft of a subscription API
This is an automated email from the ASF dual-hosted git repository.
cdutz pushed a commit to branch feature/c-api-subscriptions
in repository https://gitbox.apache.org/repos/asf/plc4x.git
commit 470d751a548e599d85ce5d1434899a4bf9720f1d
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Mon May 11 16:58:14 2020 +0200
- First draft of a subscription API
---
sandbox/plc4c/api/include/plc4c/connection.h | 50 ++--
sandbox/plc4c/api/include/plc4c/read.h | 6 +
sandbox/plc4c/api/include/plc4c/subscribe.h | 189 ++++++++++++++
sandbox/plc4c/api/include/plc4c/types.h | 38 +++
sandbox/plc4c/api/include/plc4c/write.h | 6 +
.../plc4c/examples/hello-world/src/hello_world.c | 4 +-
.../plc4c/spi/include/plc4c/spi/types_private.h | 65 ++++-
sandbox/plc4c/spi/src/connection.c | 12 -
sandbox/plc4c/spi/src/read.c | 8 +
sandbox/plc4c/spi/src/subscribe.c | 274 +++++++++++++++++++++
sandbox/plc4c/spi/src/write.c | 7 +
11 files changed, 627 insertions(+), 32 deletions(-)
diff --git a/sandbox/plc4c/api/include/plc4c/connection.h b/sandbox/plc4c/api/include/plc4c/connection.h
index ace6d00..531d2ca 100644
--- a/sandbox/plc4c/api/include/plc4c/connection.h
+++ b/sandbox/plc4c/api/include/plc4c/connection.h
@@ -97,7 +97,7 @@ plc4c_transport *plc4c_connection_get_transport(plc4c_connection *connection);
* @param transport plc4c_transport
*/
void plc4c_connection_set_transport(plc4c_connection *connection,
- plc4c_transport *transport);
+ plc4c_transport *transport);
/**
* Returns the transport connection information for a given connection
@@ -188,7 +188,7 @@ plc4c_driver *plc4c_connection_get_driver(plc4c_connection *connection);
* @param connection plc4c_connection
* @param plc4c_driver
*/
- void plc4c_connection_set_driver(plc4c_connection *connection,
+void plc4c_connection_set_driver(plc4c_connection *connection,
plc4c_driver *driver);
/**
@@ -229,12 +229,6 @@ plc4c_return_code plc4c_connection_create_read_request(
plc4c_read_request **read_request);
/**
- * Destroys a given read_response
- * @param read_response the read_response
- */
-void plc4c_connection_destroy_read_response(plc4c_read_response *read_response);
-
-/**
* Check if the current connection supports write operations.
*
* @param connection reference to the connection
@@ -246,24 +240,16 @@ bool plc4c_connection_get_supports_writing(plc4c_connection *connection);
* Initializes an empty write-request.
*
* @param connection connection that this write-request will be executed on.
- * @param num_items number of items we want to write.
* @param addresses list of address strings.
* @param values list of pointers to values.
* @param write_request pointer to the write-request
- * @param plc4c_return_code
+ * @return plc4c_return_code
*/
plc4c_return_code plc4c_connection_create_write_request(
plc4c_connection *connection, plc4c_list *addresses, plc4c_list *values,
plc4c_write_request **write_request);
/**
- * Destroys a given write_response
- * @param write_response the write_response
- */
-void plc4c_connection_destroy_write_response(
- plc4c_write_response *write_response);
-
-/**
* Check if the current connection supports subscriptions.
*
* @param connection reference to the connection
@@ -272,6 +258,36 @@ void plc4c_connection_destroy_write_response(
bool plc4c_connection_get_supports_subscriptions(plc4c_connection *connection);
/**
+ * Initializes an empty subscription-request.
+ *
+ * @param connection connection that this subscription-request will be executed
+ * on.
+ * TODO: Somehow we need to provide the subscription type and depending on the
+ * type some additional parameters (Cycle-time).
+ * @param addresses list of address strings.
+ * @param subscription_request pointer to the subscription-request
+ * @return plc4c_return_code
+ */
+plc4c_return_code plc4c_connection_create_subscription_request(
+ plc4c_connection *connection, plc4c_list *addresses,
+ plc4c_subscription_request **subscription_request);
+
+/**
+ * Initializes an empty unsubscription-request.
+ *
+ * @param connection connection that this unsubscription-request will be
+ * executed on.
+ * TODO: Somehow we need to provide the unsubscription type and depending on the
+ * type some additional parameters (Cycle-time).
+ * @param addresses list of address strings.
+ * @param unsubscription_request pointer to the unsubscription-request
+ * @return plc4c_return_code
+ */
+plc4c_return_code plc4c_connection_create_unsubscription_request(
+ plc4c_connection *connection, plc4c_list *addresses,
+ plc4c_unsubscription_request **unsubscription_request);
+
+/**
* Returns the current number of running tasks for this connection
* @param connection plc4c_connection
* @return the count of running tasks
diff --git a/sandbox/plc4c/api/include/plc4c/read.h b/sandbox/plc4c/api/include/plc4c/read.h
index e22882a..38d03b3 100644
--- a/sandbox/plc4c/api/include/plc4c/read.h
+++ b/sandbox/plc4c/api/include/plc4c/read.h
@@ -94,6 +94,12 @@ bool plc4c_read_request_execution_check_finished_with_error(
plc4c_read_response *plc4c_read_request_execution_get_response(
plc4c_read_request_execution *read_request_execution);
+/**
+ * Destroys a given read_response
+ * @param read_response the read_response
+ */
+void plc4c_read_destroy_read_response(plc4c_read_response *read_response);
+
#ifdef __cplusplus
}
#endif
diff --git a/sandbox/plc4c/api/include/plc4c/subscribe.h b/sandbox/plc4c/api/include/plc4c/subscribe.h
new file mode 100644
index 0000000..b34ba60
--- /dev/null
+++ b/sandbox/plc4c/api/include/plc4c/subscribe.h
@@ -0,0 +1,189 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#ifndef PLC4C_SUBSCRIBE_H_
+#define PLC4C_SUBSCRIBE_H_
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "plc4c/types.h"
+
+/*
+ *
+ * Subscriptions
+ *
+ */
+
+/**
+ * Destroys a given subscription-request.
+ *
+ * @param subscription_request the subscription-request.
+ */
+void plc4c_subscription_request_destroy(
+ plc4c_subscription_request *subscription_request);
+
+/**
+ * Returns the plc4c_connection for a give subscription request
+ * @param subscription_request plc4c_subscription_request
+ * @return plc4c_connection
+ */
+plc4c_connection *plc4c_subscription_request_get_connection(
+ plc4c_subscription_request *subscription_request);
+
+/**
+ * Sets the plc4c_connection for a given subscription request
+ * @param subscription_request plc4c_subscription_request
+ * @param connection plc4c_connection
+ */
+void plc4c_subscription_request_set_connection(
+ plc4c_subscription_request *subscription_request,
+ plc4c_connection *connection);
+
+/**
+ * Actually executes the subscription-request.
+ * @param connection connection this subscription-request will be executed on.
+ * @param subscription_request the subscription-request object.
+ * @param subscription_request_execution pointer to a data-structure handling
+ * one execution of the subscription-request.
+ * @return plc4c_return_code
+ */
+plc4c_return_code plc4c_subscription_request_execute(
+ plc4c_subscription_request *subscription_request,
+ plc4c_subscription_request_execution **subscription_request_execution);
+
+/**
+ * Destroys a given subscription-request execution.
+ *
+ * @param subscription_request_execution the subscription-request execution.
+ */
+void plc4c_subscription_request_execution_destroy(
+ plc4c_subscription_request_execution *subscription_request_execution);
+
+/**
+ * Check if the subscription-request is completed successfully.
+ *
+ * @param subscription_request_execution the subscription-request execution.
+ * @return true if the subscription-request is completed successfully.
+ */
+bool plc4c_subscription_request_execution_check_finished_successfully(
+ plc4c_subscription_request_execution *subscription_request_execution);
+
+/**
+ * Check if the subscription-request is completed unsuccessfully.
+ *
+ * @param subscription_request_execution the subscription-request execution.
+ * @return true if the subscription-request is completed with an error.
+ */
+bool plc4c_subscription_request_execution_check_finished_with_error(
+ plc4c_subscription_request_execution *subscription_request_execution);
+
+/**
+ * Retrieve the subscription-response from a given subscription-request
+ * execution.
+ *
+ * @param subscription_request_execution the subscription-request execution.
+ * @return the subscription-response.
+ */
+plc4c_subscription_response *plc4c_subscription_request_execution_get_response(
+ plc4c_subscription_request_execution *subscription_request_execution);
+
+/*
+ *
+ * Unsubscriptions
+ *
+ */
+
+/**
+ * Destroys a given unsubscription-request.
+ *
+ * @param unsubscription_request the unsubscription-request.
+ */
+void plc4c_unsubscription_request_destroy(
+ plc4c_unsubscription_request *unsubscription_request);
+
+/**
+ * Returns the plc4c_connection for a give unsubscription request
+ * @param unsubscription_request plc4c_unsubscription_request
+ * @return plc4c_connection
+ */
+plc4c_connection *plc4c_unsubscription_request_get_connection(
+ plc4c_unsubscription_request *unsubscription_request);
+
+/**
+ * Sets the plc4c_connection for a given unsubscription request
+ * @param unsubscription_request plc4c_unsubscription_request
+ * @param connection plc4c_connection
+ */
+void plc4c_unsubscription_request_set_connection(
+ plc4c_unsubscription_request *unsubscription_request,
+ plc4c_connection *connection);
+
+/**
+ * Actually executes the unsubscription-request.
+ * @param connection connection this unsubscription-request will be executed on.
+ * @param unsubscription_request the unsubscription-request object.
+ * @param unsubscription_request_execution pointer to a data-structure handling
+ * one execution of the unsubscription-request.
+ * @return plc4c_return_code
+ */
+plc4c_return_code plc4c_unsubscription_request_execute(
+ plc4c_unsubscription_request *unsubscription_request,
+ plc4c_unsubscription_request_execution **unsubscription_request_execution);
+
+/**
+ * Destroys a given unsubscription-request execution.
+ *
+ * @param unsubscription_request_execution the unsubscription-request execution.
+ */
+void plc4c_unsubscription_request_execution_destroy(
+ plc4c_unsubscription_request_execution *unsubscription_request_execution);
+
+/**
+ * Check if the unsubscription-request is completed successfully.
+ *
+ * @param unsubscription_request_execution the unsubscription-request execution.
+ * @return true if the unsubscription-request is completed successfully.
+ */
+bool plc4c_unsubscription_request_execution_check_finished_successfully(
+ plc4c_unsubscription_request_execution *unsubscription_request_execution);
+
+/**
+ * Check if the unsubscription-request is completed unsuccessfully.
+ *
+ * @param unsubscription_request_execution the unsubscription-request execution.
+ * @return true if the unsubscription-request is completed with an error.
+ */
+bool plc4c_unsubscription_request_execution_check_finished_with_error(
+ plc4c_unsubscription_request_execution *unsubscription_request_execution);
+
+/**
+ * Retrieve the unsubscription-response from a given unsubscription-request
+ * execution.
+ *
+ * @param unsubscription_request_execution the unsubscription-request execution.
+ * @return the unsubscription-response.
+ */
+plc4c_unsubscription_response *
+plc4c_unsubscription_request_execution_get_response(
+ plc4c_unsubscription_request_execution *unsubscription_request_execution);
+
+#ifdef __cplusplus
+}
+#endif
+#endif // PLC4C_SUBSCRIBE_H_
\ No newline at end of file
diff --git a/sandbox/plc4c/api/include/plc4c/types.h b/sandbox/plc4c/api/include/plc4c/types.h
index 5040616..e20b52d 100644
--- a/sandbox/plc4c/api/include/plc4c/types.h
+++ b/sandbox/plc4c/api/include/plc4c/types.h
@@ -76,6 +76,12 @@ typedef enum plc4c_data_type {
PLC4C_VOID_POINTER
} plc4c_data_type;
+typedef enum plc4c_subscription_type {
+ PLC4C_SUBSCRIPTION_CYCLIC,
+ PLC4C_SUBSCRIPTION_CHANGE_OF_STATE,
+ PLC4C_SUBSCRIPTION_EVENT
+} plc4c_subscription_type;
+
/**
* Helper that translates from a return_code enum value to something a human can
* work with.
@@ -152,6 +158,38 @@ typedef struct plc4c_write_request_execution_t plc4c_write_request_execution;
*/
typedef struct plc4c_write_response_t plc4c_write_response;
+/**
+ * A plc4c subscription-request.
+ */
+typedef struct plc4c_subscription_request_t plc4c_subscription_request;
+
+/**
+ * A plc4c subscription-request-execution.
+ */
+typedef struct plc4c_subscription_request_execution_t
+ plc4c_subscription_request_execution;
+
+/**
+ * A plc4c subscription-response.
+ */
+typedef struct plc4c_unsubscription_response_t plc4c_subscription_response;
+
+/**
+ * A plc4c unsubscription-request.
+ */
+typedef struct plc4c_unsubscription_request_t plc4c_unsubscription_request;
+
+/**
+ * A plc4c unsubscription-request-execution.
+ */
+typedef struct plc4c_unsubscription_request_execution_t
+ plc4c_unsubscription_request_execution;
+
+/**
+ * A plc4c unsubscription-response.
+ */
+typedef struct plc4c_unsubscription_response_t plc4c_unsubscription_response;
+
typedef struct plc4c_data_t plc4c_data;
#ifdef __cplusplus
diff --git a/sandbox/plc4c/api/include/plc4c/write.h b/sandbox/plc4c/api/include/plc4c/write.h
index 05c388d..c7b62fe 100644
--- a/sandbox/plc4c/api/include/plc4c/write.h
+++ b/sandbox/plc4c/api/include/plc4c/write.h
@@ -94,6 +94,12 @@ bool plc4c_write_request_execution_check_completed_with_error(
plc4c_write_response *plc4c_write_request_execution_get_response(
plc4c_write_request_execution *write_request_execution);
+/**
+ * Destroys a given write_response
+ * @param write_response the write_response
+ */
+void plc4c_write_destroy_write_response(plc4c_write_response *write_response);
+
#ifdef __cplusplus
}
#endif
diff --git a/sandbox/plc4c/examples/hello-world/src/hello_world.c b/sandbox/plc4c/examples/hello-world/src/hello_world.c
index 10ac7db..1a7fe0a 100644
--- a/sandbox/plc4c/examples/hello-world/src/hello_world.c
+++ b/sandbox/plc4c/examples/hello-world/src/hello_world.c
@@ -230,7 +230,7 @@ int main() {
}
// Clean up.
- plc4c_connection_destroy_read_response(read_response);
+ plc4c_read_destroy_read_response(read_response);
plc4c_read_request_execution_destroy(read_request_execution);
plc4c_read_request_destroy(read_request);
@@ -302,7 +302,7 @@ int main() {
}
// Clean up.
- plc4c_connection_destroy_write_response(write_response);
+ plc4c_write_destroy_write_response(write_response);
plc4c_write_request_execution_destroy(write_request_execution);
// Disconnect.
diff --git a/sandbox/plc4c/spi/include/plc4c/spi/types_private.h b/sandbox/plc4c/spi/include/plc4c/spi/types_private.h
index daa755b..bf0ce56 100644
--- a/sandbox/plc4c/spi/include/plc4c/spi/types_private.h
+++ b/sandbox/plc4c/spi/include/plc4c/spi/types_private.h
@@ -58,12 +58,26 @@ typedef plc4c_return_code (*plc4c_connection_write_function)(
plc4c_write_request_execution *write_request_execution,
plc4c_system_task **task);
+typedef plc4c_return_code (*plc4c_connection_subscribe_function)(
+ plc4c_subscription_request_execution *subscription_request_execution,
+ plc4c_system_task **task);
+
+typedef plc4c_return_code (*plc4c_connection_unsubscribe_function)(
+ plc4c_unsubscription_request_execution *unsubscription_request_execution,
+ plc4c_system_task **task);
+
typedef void (*plc4c_connect_free_read_response_function)(
plc4c_read_response *response);
typedef void (*plc4c_connect_free_write_response_function)(
plc4c_write_response *response);
+typedef void (*plc4c_connect_free_subscription_response_function)(
+ plc4c_subscription_response *response);
+
+typedef void (*plc4c_connect_free_unsubscription_response_function)(
+ plc4c_unsubscription_response *response);
+
struct plc4c_system_t {
/* drivers */
plc4c_list *driver_list;
@@ -100,8 +114,12 @@ struct plc4c_driver_t {
plc4c_connection_disconnect_function disconnect_function;
plc4c_connection_read_function read_function;
plc4c_connection_write_function write_function;
+ plc4c_connection_subscribe_function subscribe_function;
+ plc4c_connection_unsubscribe_function unsubscribe_function;
plc4c_connect_free_read_response_function free_read_response_function;
plc4c_connect_free_write_response_function free_write_response_function;
+ plc4c_connect_free_subscription_response_function free_subscription_response_function;
+ plc4c_connect_free_unsubscription_response_function free_unsubscription_response_function;
};
struct plc4c_driver_list_item_t {
@@ -178,7 +196,20 @@ struct plc4c_request_value_item_t {
struct plc4c_response_value_item_t {
plc4c_item *item;
plc4c_response_code response_code;
- void *value;
+ plc4c_data *value;
+};
+
+struct plc4c_response_subscription_item_t {
+ plc4c_item *item;
+ plc4c_response_code response_code;
+ // This is highly coupled to the protocol used.
+ void *subscription_handle;
+};
+
+struct plc4c_request_unsubscription_item_t {
+ plc4c_item *item;
+ // This is highly coupled to the protocol used.
+ void *subscription_handle;
};
struct plc4c_response_item_t {
@@ -196,6 +227,16 @@ struct plc4c_write_request_t {
plc4c_list *items;
};
+struct plc4c_subscription_request_t {
+ plc4c_connection *connection;
+ plc4c_list *items;
+};
+
+struct plc4c_unsubscription_request_t {
+ plc4c_connection *connection;
+ plc4c_list *items;
+};
+
struct plc4c_read_request_execution_t {
plc4c_read_request *read_request;
plc4c_read_response *read_response;
@@ -208,6 +249,18 @@ struct plc4c_write_request_execution_t {
plc4c_system_task *system_task;
};
+struct plc4c_subscription_request_execution_t {
+ plc4c_subscription_request *subscription_request;
+ plc4c_subscription_response *subscription_response;
+ plc4c_system_task *system_task;
+};
+
+struct plc4c_unsubscription_request_execution_t {
+ plc4c_unsubscription_request *unsubscription_request;
+ plc4c_unsubscription_response *unsubscription_response;
+ plc4c_system_task *system_task;
+};
+
struct plc4c_read_response_t {
plc4c_read_request *read_request;
plc4c_list *items;
@@ -218,6 +271,16 @@ struct plc4c_write_response_t {
plc4c_list *response_items;
};
+struct plc4c_subscription_response_t {
+ plc4c_subscription_request *subscription_request;
+ plc4c_list *response_items;
+};
+
+struct plc4c_unsubscription_response_t {
+ plc4c_unsubscription_request *unsubscription_request;
+ plc4c_list *response_items;
+};
+
struct plc4c_system_task_t {
int state_id;
plc4c_system_task_state_machine_function state_machine_function;
diff --git a/sandbox/plc4c/spi/src/connection.c b/sandbox/plc4c/spi/src/connection.c
index 61ca280..04450ee 100644
--- a/sandbox/plc4c/spi/src/connection.c
+++ b/sandbox/plc4c/spi/src/connection.c
@@ -228,12 +228,6 @@ plc4c_return_code plc4c_connection_create_read_request(
return OK;
}
-void plc4c_connection_destroy_read_response(
- plc4c_read_response *read_response) {
- read_response->read_request->connection->driver->free_read_response_function(
- read_response);
-}
-
bool plc4c_connection_get_supports_writing(plc4c_connection *connection) {
return connection->supports_writing;
}
@@ -285,12 +279,6 @@ plc4c_return_code plc4c_connection_create_write_request(
return OK;
}
-void plc4c_connection_destroy_write_response(
- plc4c_write_response *write_response) {
- write_response->write_request->connection->driver
- ->free_write_response_function(write_response);
-}
-
int plc4c_connection_get_running_tasks_count(plc4c_connection *connection) {
return connection->num_running_system_tasks;
}
diff --git a/sandbox/plc4c/spi/src/read.c b/sandbox/plc4c/spi/src/read.c
index 7d90e63..3066d02 100644
--- a/sandbox/plc4c/spi/src/read.c
+++ b/sandbox/plc4c/spi/src/read.c
@@ -71,6 +71,7 @@ bool plc4c_read_request_execution_check_finished_successfully(
bool plc4c_read_request_execution_check_finished_with_error(
plc4c_read_request_execution *read_request_execution) {
+ // TODO: Implement this sensibly ...
return false;
}
@@ -90,3 +91,10 @@ void plc4c_read_request_execution_destroy(
plc4c_read_request_execution *read_request_execution) {
free(read_request_execution);
}
+
+void plc4c_read_destroy_read_response(
+ plc4c_read_response *read_response) {
+ read_response->read_request->connection->driver->free_read_response_function(
+ read_response);
+}
+
diff --git a/sandbox/plc4c/spi/src/subscribe.c b/sandbox/plc4c/spi/src/subscribe.c
new file mode 100644
index 0000000..22b30f4
--- /dev/null
+++ b/sandbox/plc4c/spi/src/subscribe.c
@@ -0,0 +1,274 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <plc4c/plc4c.h>
+#include <plc4c/subscribe.h>
+#include <plc4c/spi/types_private.h>
+#include <stdlib.h>
+
+/*
+ *
+ * Subscriptions
+ *
+ */
+
+/**
+ * Destroys a given subscription-request.
+ *
+ * @param subscription_request the subscription-request.
+ */
+void plc4c_subscription_request_destroy(
+ plc4c_subscription_request *subscription_request) {
+ free(subscription_request);
+}
+
+/**
+ * Returns the plc4c_connection for a give subscription request
+ * @param subscription_request plc4c_subscription_request
+ * @return plc4c_connection
+ */
+plc4c_connection *plc4c_subscription_request_get_connection(
+ plc4c_subscription_request *subscription_request) {
+ return subscription_request->connection;
+}
+
+/**
+ * Sets the plc4c_connection for a given subscription request
+ * @param subscription_request plc4c_subscription_request
+ * @param connection plc4c_connection
+ */
+void plc4c_subscription_request_set_connection(
+ plc4c_subscription_request *subscription_request,
+ plc4c_connection *connection) {
+ subscription_request->connection = connection;
+}
+
+/**
+ * Actually executes the subscription-request.
+ * @param connection connection this subscription-request will be executed on.
+ * @param subscription_request the subscription-request object.
+ * @param subscription_request_execution pointer to a data-structure handling
+ * one execution of the subscription-request.
+ * @return plc4c_return_code
+ */
+plc4c_return_code plc4c_subscription_request_execute(
+ plc4c_subscription_request *subscription_request,
+ plc4c_subscription_request_execution **subscription_request_execution) {
+ // Inject the default subscription context into the system task.
+ plc4c_subscription_request_execution *new_subscription_request_execution =
+ malloc(sizeof(plc4c_subscription_request_execution));
+ new_subscription_request_execution->subscription_request = subscription_request;
+ new_subscription_request_execution->subscription_response = NULL;
+ new_subscription_request_execution->system_task = NULL;
+
+ plc4c_system_task *system_task;
+ plc4c_connection_get_driver(plc4c_subscription_request_get_connection(subscription_request))
+ ->subscribe_function(new_subscription_request_execution, &system_task);
+
+ // Increment the number of running tasks for this connection.
+ plc4c_connection_task_added(subscription_request->connection);
+ // Add the new task to the task-list.
+ plc4c_utils_list_insert_tail_value(
+ plc4c_system_get_task_list(plc4c_connection_get_system(
+ plc4c_subscription_request_get_connection(subscription_request))),
+ system_task);
+
+ *subscription_request_execution = new_subscription_request_execution;
+ return OK;
+}
+
+/**
+ * Destroys a given subscription-request execution.
+ *
+ * @param subscription_request_execution the subscription-request execution.
+ */
+void plc4c_subscription_request_execution_destroy(
+ plc4c_subscription_request_execution *subscription_request_execution) {
+ free(subscription_request_execution);
+}
+
+/**
+ * Check if the subscription-request is completed successfully.
+ *
+ * @param subscription_request_execution the subscription-request execution.
+ * @return true if the subscription-request is completed successfully.
+ */
+bool plc4c_subscription_request_execution_check_finished_successfully(
+ plc4c_subscription_request_execution *subscription_request_execution) {
+ if (subscription_request_execution == NULL) {
+ return true;
+ }
+ if (subscription_request_execution->system_task == NULL) {
+ return true;
+ }
+ return subscription_request_execution->system_task->completed;
+}
+
+/**
+ * Check if the subscription-request is completed unsuccessfully.
+ *
+ * @param subscription_request_execution the subscription-request execution.
+ * @return true if the subscription-request is completed with an error.
+ */
+bool plc4c_subscription_request_execution_check_finished_with_error(
+ plc4c_subscription_request_execution *subscription_request_execution) {
+ // TODO: Implement this sensibly ...
+ return false;
+}
+
+/**
+ * Retrieve the subscription-response from a given subscription-request
+ * execution.
+ *
+ * @param subscription_request_execution the subscription-request execution.
+ * @return the subscription-response.
+ */
+plc4c_subscription_response *plc4c_subscription_request_execution_get_response(
+ plc4c_subscription_request_execution *subscription_request_execution) {
+ if (subscription_request_execution == NULL) {
+ return NULL;
+ }
+ return subscription_request_execution->subscription_response;
+}
+
+/*
+ *
+ * Unsubscriptions
+ *
+ */
+
+/**
+ * Destroys a given unsubscription-request.
+ *
+ * @param unsubscription_request the unsubscription-request.
+ */
+void plc4c_unsubscription_request_destroy(
+ plc4c_unsubscription_request *unsubscription_request) {
+ free(unsubscription_request);
+}
+
+/**
+ * Returns the plc4c_connection for a give unsubscription request
+ * @param unsubscription_request plc4c_unsubscription_request
+ * @return plc4c_connection
+ */
+plc4c_connection *plc4c_unsubscription_request_get_connection(
+ plc4c_unsubscription_request *unsubscription_request) {
+ return unsubscription_request->connection;
+}
+
+/**
+ * Sets the plc4c_connection for a given unsubscription request
+ * @param unsubscription_request plc4c_unsubscription_request
+ * @param connection plc4c_connection
+ */
+void plc4c_unsubscription_request_set_connection(
+ plc4c_unsubscription_request *unsubscription_request,
+ plc4c_connection *connection) {
+ unsubscription_request->connection = connection;
+}
+
+/**
+ * Actually executes the unsubscription-request.
+ * @param connection connection this unsubscription-request will be executed on.
+ * @param unsubscription_request the unsubscription-request object.
+ * @param unsubscription_request_execution pointer to a data-structure handling
+ * one execution of the unsubscription-request.
+ * @return plc4c_return_code
+ */
+plc4c_return_code plc4c_unsubscription_request_execute(
+ plc4c_unsubscription_request *unsubscription_request,
+ plc4c_unsubscription_request_execution **unsubscription_request_execution) {
+ // Inject the default unsubscription context into the system task.
+ plc4c_unsubscription_request_execution *new_unsubscription_request_execution =
+ malloc(sizeof(plc4c_unsubscription_request_execution));
+ new_unsubscription_request_execution->unsubscription_request = unsubscription_request;
+ new_unsubscription_request_execution->unsubscription_response = NULL;
+ new_unsubscription_request_execution->system_task = NULL;
+
+ plc4c_system_task *system_task;
+ plc4c_connection_get_driver(plc4c_unsubscription_request_get_connection(unsubscription_request))
+ ->unsubscribe_function(new_unsubscription_request_execution, &system_task);
+
+ // Increment the number of running tasks for this connection.
+ plc4c_connection_task_added(unsubscription_request->connection);
+ // Add the new task to the task-list.
+ plc4c_utils_list_insert_tail_value(
+ plc4c_system_get_task_list(plc4c_connection_get_system(
+ plc4c_unsubscription_request_get_connection(unsubscription_request))),
+ system_task);
+
+ *unsubscription_request_execution = new_unsubscription_request_execution;
+ return OK;
+}
+
+/**
+ * Destroys a given unsubscription-request execution.
+ *
+ * @param unsubscription_request_execution the unsubscription-request execution.
+ */
+void plc4c_unsubscription_request_execution_destroy(
+ plc4c_unsubscription_request_execution *unsubscription_request_execution) {
+ free(unsubscription_request_execution);
+}
+
+/**
+ * Check if the unsubscription-request is completed successfully.
+ *
+ * @param unsubscription_request_execution the unsubscription-request execution.
+ * @return true if the unsubscription-request is completed successfully.
+ */
+bool plc4c_unsubscription_request_execution_check_finished_successfully(
+ plc4c_unsubscription_request_execution *unsubscription_request_execution) {
+ if (unsubscription_request_execution == NULL) {
+ return true;
+ }
+ if (unsubscription_request_execution->system_task == NULL) {
+ return true;
+ }
+ return unsubscription_request_execution->system_task->completed;
+}
+
+/**
+ * Check if the unsubscription-request is completed unsuccessfully.
+ *
+ * @param unsubscription_request_execution the unsubscription-request execution.
+ * @return true if the unsubscription-request is completed with an error.
+ */
+bool plc4c_unsubscription_request_execution_check_finished_with_error(
+ plc4c_unsubscription_request_execution *unsubscription_request_execution) {
+ // TODO: Implement this sensibly ...
+ return false;
+}
+
+/**
+ * Retrieve the unsubscription-response from a given unsubscription-request
+ * execution.
+ *
+ * @param unsubscription_request_execution the unsubscription-request execution.
+ * @return the unsubscription-response.
+ */
+plc4c_unsubscription_response *
+plc4c_unsubscription_request_execution_get_response(
+ plc4c_unsubscription_request_execution *unsubscription_request_execution) {
+ if (unsubscription_request_execution == NULL) {
+ return NULL;
+ }
+ return unsubscription_request_execution->unsubscription_response;
+}
diff --git a/sandbox/plc4c/spi/src/write.c b/sandbox/plc4c/spi/src/write.c
index d2ade49..ae65674 100644
--- a/sandbox/plc4c/spi/src/write.c
+++ b/sandbox/plc4c/spi/src/write.c
@@ -89,3 +89,10 @@ void plc4c_write_request_execution_destroy(
plc4c_write_request_execution *write_request_execution) {
free(write_request_execution);
}
+
+void plc4c_write_destroy_write_response(
+ plc4c_write_response *write_response) {
+ write_response->write_request->connection->driver
+ ->free_write_response_function(write_response);
+}
+