blob: e95f778e6733ab58f670a20878dae08ad98bfb61 [file]
/*
* 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
*
* https://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/driver_simulated.h>
#include <plc4c/plc4c.h>
#include <plc4c/transport_dummy.h>
#include <plc4c/utils/list.h>
#include <stdio.h>
#include <string.h>
#include "../../../spi/include/plc4c/spi/types_private.h"
enum plc4c_connection_state_t {
CONNECTING,
CONNECTED,
SUBSCRIPTION_REQUEST_SENT,
SUBSCRIPTION_RESPONSE_RECEIVED,
READING_EVENTS,
DISCONNECTING,
DISCONNECTED
};
typedef enum plc4c_connection_state_t plc4c_connection_state;
#pragma clang diagnostic push
#pragma ide diagnostic ignored "hicpp-multiway-paths-covered"
int main() {
bool loop = true;
plc4c_system *system = NULL;
plc4c_connection *connection = NULL;
plc4c_subscription_request *subscription_request = NULL;
plc4c_subscription_request_execution *subscription_request_execution = NULL;
int num_events = 0;
void *subscription_handle = NULL;
// Create a new uninitialized plc4c_system
printf("Creating new PLC4C System (Initializing inner data-structures) ... ");
plc4c_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");
// 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;
}
// Depending on the current state, implement some logic.
switch (state) {
case CONNECTING: {
// Check if the connection is established:
if (plc4c_connection_get_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 subscription-request.
printf("Preparing a subscription-request ... ");
result = plc4c_connection_create_subscription_request(
connection, &subscription_request);
if (result != OK) {
printf("FAILED\n");
return -1;
}
printf("SUCCESS\n");
printf("Adding cyclic item for 'RANDOM/foo:INTEGER' ... ");
result = plc4c_subscription_request_add_cyclic_item(
subscription_request, "RANDOM/foo:INTEGER", 500);
if (result != OK) {
printf("FAILED\n");
return -1;
}
printf("SUCCESS\n");
// Execute the subscription-request.
printf("Executing a subscription-request ... ");
result = plc4c_subscription_request_execute(
subscription_request, &subscription_request_execution);
if (result != OK) {
printf("FAILED\n");
return -1;
} else {
state = SUBSCRIPTION_REQUEST_SENT;
}
break;
}
// Wait until the read-request execution is finished.
case SUBSCRIPTION_REQUEST_SENT: {
if (plc4c_subscription_request_execution_check_finished_successfully(
subscription_request_execution)) {
printf("SUCCESS\n");
state = SUBSCRIPTION_RESPONSE_RECEIVED;
} else if (
plc4c_subscription_request_execution_check_finished_with_error(
subscription_request_execution)) {
printf("FAILED\n");
return -1;
}
break;
}
case SUBSCRIPTION_RESPONSE_RECEIVED: {
// Get the response for the given subscription-request.
plc4c_subscription_response *subscription_response =
plc4c_subscription_request_execution_get_response(
subscription_request_execution);
if (subscription_response == NULL) {
printf("FAILED (No Response)\n");
return -1;
}
// Save the subsciption handle.
plc4c_list_element *cur_element =
plc4c_utils_list_head(subscription_response->response_items);
plc4c_response_subscription_item *subscription_item_item =
cur_element->value;
printf("Value %s (%s):", subscription_item_item->item->name,
plc4c_response_code_to_message(
subscription_item_item->response_code));
// Check if the response was ok.
if (subscription_item_item->response_code == OK) {
// Save the subscription handles...
subscription_handle = subscription_item_item->subscription_handle;
} else {
printf("FAILED (No Response)\n");
return -1;
}
// Clean up the subscription..
plc4c_subscription_response_destroy(subscription_response);
plc4c_subscription_request_execution_destroy(
subscription_request_execution);
plc4c_subscription_request_destroy(subscription_request);
state = READING_EVENTS;
break;
}
// Wait for 10 incoming events.
case READING_EVENTS: {
// Check if an event is available ...
printf("Checking Events ... ");
if (plc4c_subscription_check_data_available(subscription_handle)) {
printf("New events available.\n");
printf("Getting Events ... ");
plc4c_list *events = NULL;
result = plc4c_subscription_get_subscription_events(
subscription_handle, &events);
if (result != OK) {
printf("FAILED\n");
return -1;
}
printf("SUCCESS\n");
plc4c_list_element *cur_element = plc4c_utils_list_head(events);
while (cur_element != NULL) {
plc4c_response_subscription_item *subscription_event_item =
cur_element->value;
// TODO: Do something with the event ...
printf("Got Event %s", subscription_event_item->item->name);
// Increment the number of processed events.
num_events++;
cur_element = cur_element->next;
}
// If at least 10 events have been processed, disconnect.
if (num_events > 10) {
// Disconnect.
printf("Disconnecting ... ");
result = plc4c_connection_disconnect(connection);
if (result != OK) {
printf("FAILED");
return -1;
}
state = DISCONNECTING;
}
} else {
printf("No events.\n");
}
break;
}
// Wait until the connection is disconnected
case DISCONNECTING: {
if (!plc4c_connection_get_connected(connection)) {
printf("SUCCESS\n");
// we could let the system shut this down,
// or do it ourselves
plc4c_system_remove_connection(system, connection);
plc4c_connection_destroy(connection);
state = DISCONNECTED;
// Terminate the main program loop.
loop = false;
}
break;
}
case DISCONNECTED: {
// End the loop.
loop = false;
break;
}
}
}
// Make sure everything is cleaned up correctly.
plc4c_system_shutdown(system);
// Finally destroy the plc4c_system, freeing up all memory allocated by plc4c.
plc4c_system_destroy(system);
return 0;
}
#pragma clang diagnostic pop