blob: f809b26788f0689dca8b7a3e046f9136b9ed76ca [file] [log] [blame]
/*
* 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/driver_simulated.h>
#include <plc4c/driver_s7.h>
#include <plc4c/driver_modbus.h>
#include <plc4c/plc4c.h>
#include <plc4c/transport_dummy.h>
#include <plc4c/transport_tcp.h>
#include <plc4c/transport_serial.h>
#include <plc4c/utils/list.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "../../../spi/include/plc4c/spi/types_private.h"
int numOpenConnections = 0;
/**
* Here we could implement something that keeps track of all open connections.
* For example on embedded devices using the W5100 SPI Network device, this can
* only handle 4 simultaneous connections.
*
* @param connection the connection that was just established
*/
void onGlobalConnect(plc4c_connection *cur_connection) {
printf("Connected to %s",
plc4c_connection_get_connection_string(cur_connection));
numOpenConnections++;
}
void onGlobalDisconnect(plc4c_connection *cur_connection) {
printf("Disconnected from %s",
plc4c_connection_get_connection_string(cur_connection));
numOpenConnections--;
}
void delete_read_response_item(plc4c_list_element *response_read_item_element) {
}
void delete_write_response_item(
plc4c_list_element *response_write_item_element) {}
enum plc4c_connection_state_t {
CONNECTING,
CONNECTED,
READ_REQUEST_SENT,
READ_RESPONSE_RECEIVED,
WRITE_REQUEST_SENT,
WRITE_RESPONSE_RECEIVED,
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_read_request *read_request = NULL;
plc4c_write_request *write_request = NULL;
plc4c_read_request_execution *read_request_execution = NULL;
plc4c_write_request_execution *write_request_execution = 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 adding simulated driver\n");
return -1;
}
printf("Registering driver for the 's7' protocol ... ");
plc4c_driver *s7_driver = plc4c_driver_s7_create();
result = plc4c_system_add_driver(system, s7_driver);
if (result != OK) {
printf("FAILED adding s7 driver\n");
return -1;
}
printf("Registering driver for the 'modbus' protocol ... ");
plc4c_driver *modbus_driver = plc4c_driver_modbus_create();
result = plc4c_system_add_driver(system, modbus_driver);
if (result != OK) {
printf("FAILED adding modbus driver\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 adding dummy transport\n");
return -1;
}
plc4c_transport *tcp_transport = plc4c_transport_tcp_create();
result = plc4c_system_add_transport(system, tcp_transport);
if (result != OK) {
printf("FAILED adding tcp transport\n");
return -1;
}
plc4c_transport *serial_transport = plc4c_transport_serial_create();
result = plc4c_system_add_transport(system, serial_transport);
if (result != OK) {
printf("FAILED adding serial transport\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);
plc4c_system_set_on_disconnect_success_callback(system, &onGlobalDisconnect);
// Establish connections to remote devices
// you may or may not care about the connection handle
printf("Connecting to 's7:tcp://192.168.23.30' ... ");
result = plc4c_system_connect(system, "s7:tcp://192.168.23.30", &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 read-request.
printf("Preparing a read-request ... ");
result =
plc4c_connection_create_read_request(connection, &read_request);
if (result != OK) {
printf("FAILED\n");
return -1;
}
printf("SUCCESS\n");
printf("Adding an item for '%I0.0:BOOL' ... ");
result =
plc4c_read_request_add_item(read_request, "hurz", "%I0.0:BOOL");
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;
}
break;
}
// Wait until the read-request execution is finished.
case READ_REQUEST_SENT: {
if (plc4c_read_request_execution_check_finished_successfully(
read_request_execution)) {
printf("SUCCESS\n");
state = READ_RESPONSE_RECEIVED;
} else if (plc4c_read_request_execution_check_finished_with_error(
read_request_execution)) {
printf("FAILED\n");
return -1;
}
break;
}
case READ_RESPONSE_RECEIVED: {
// Get the response for the given read-request.
plc4c_read_response *read_response =
plc4c_read_request_execution_get_response(read_request_execution);
if (read_response == NULL) {
printf("FAILED (No Response)\n");
return -1;
}
// Iterate over all returned items.
plc4c_list_element *cur_element =
plc4c_utils_list_tail(read_response->items);
while (cur_element != NULL) {
plc4c_response_value_item *value_item = cur_element->value;
printf("Value %s (%s):", value_item->item->name,
plc4c_response_code_to_message(value_item->response_code));
plc4c_data_printf(value_item->value);
printf("\n");
cur_element = cur_element->next;
}
// Clean up.
plc4c_read_destroy_read_response(read_response);
plc4c_read_request_execution_destroy(read_request_execution);
plc4c_read_request_destroy(read_request);
// TODO: Comment out after implementing the write functionality.
// Disconnect.
printf("Disconnecting ... ");
result = plc4c_connection_disconnect(connection);
if (result != OK) {
printf("FAILED");
return -1;
}
state = DISCONNECTING;
// Create a new write-request.
/* printf("Preparing a write-request ... ");
char value[] = "bar";
result =
plc4c_connection_create_write_request(connection, &write_request);
if (result != OK) {
printf("FAILED\n");
return -1;
}
printf("SUCCESS\n");
printf("Adding an item for 'STDOUT/foo:INTEGER' ... ");
result = plc4c_write_request_add_item(
write_request, "STDOUT/foo:STRING",
plc4c_data_create_constant_string_data(strlen(value), value));
if (result != OK) {
printf("FAILED\n");
return -1;
}
printf("SUCCESS\n");
// Execute the write-request.
printf("Executing a write-request ... \n");
result = plc4c_write_request_execute(write_request,
&write_request_execution);
if (result != OK) {
printf("FAILED\n");
return -1;
} else {
state = WRITE_REQUEST_SENT;
}*/
break;
}
// Wait until the write-request execution is finished.
case WRITE_REQUEST_SENT: {
if (plc4c_write_request_check_finished_successfully(
write_request_execution)) {
printf("SUCCESS\n");
state = WRITE_RESPONSE_RECEIVED;
} else if (plc4c_write_request_execution_check_completed_with_error(
write_request_execution)) {
printf("FAILED\n");
return -1;
}
break;
}
case WRITE_RESPONSE_RECEIVED: {
plc4c_write_response *write_response =
plc4c_write_request_execution_get_response(write_request_execution);
// Iterate over the responses ...
plc4c_list_element *cur_element =
plc4c_utils_list_head(write_response->response_items);
while (cur_element != NULL) {
plc4c_response_item *response_item = cur_element->value;
printf(" - Write Value %s (%s)\n", response_item->item->name,
plc4c_response_code_to_message(response_item->response_code));
cur_element = cur_element->next;
}
// Clean up.
plc4c_write_destroy_write_response(write_response);
plc4c_write_request_execution_destroy(write_request_execution);
// Disconnect.
printf("Disconnecting ... ");
result = plc4c_connection_disconnect(connection);
if (result != OK) {
printf("FAILED");
return -1;
}
state = DISCONNECTING;
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