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:12 UTC

[plc4x] branch feature/c-api-subscriptions created (now 470d751)

This is an automated email from the ASF dual-hosted git repository.

cdutz pushed a change to branch feature/c-api-subscriptions
in repository https://gitbox.apache.org/repos/asf/plc4x.git.


      at 470d751  - First draft of a subscription API

This branch includes the following new commits:

     new 470d751  - First draft of a subscription API

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[plc4x] 01/01: - First draft of a subscription API

Posted by cd...@apache.org.
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);
+}
+