Skip to content

Commit

Permalink
Merge pull request thiagoralves#1 from r2k-in-the-vortex/ethercat_dev
Browse files Browse the repository at this point in the history
Ethercat dev
  • Loading branch information
r2k-in-the-vortex authored Nov 13, 2022
2 parents 96e36a3 + 757d934 commit df84946
Show file tree
Hide file tree
Showing 8 changed files with 248 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ CMakeSettings.json
webserver/bin
webserver/build
obj/
utils/dnp3_src/CMakeFiles/
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "utils/ethercat_src"]
path = utils/ethercat_src
url = https://github.com/r2k-in-the-vortex/ethercat_src.git
10 changes: 10 additions & 0 deletions background_installer.sh
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,16 @@ function install_all_libs {
fi
cd ../..

echo ""
echo "[EtherCAT]"
cd utils/ethercat_src
mkdir -p build
sudo cmake -S . -B build/
sudo cmake --build build/
sudo cmake --install build/
sudo /sbin/ldconfig -v | grep ethercat
cd ../..

echo ""
echo "[OPEN DNP3]"
cd utils/dnp3_src
Expand Down
1 change: 1 addition & 0 deletions utils/ethercat_src
Submodule ethercat_src added at 9e7007
156 changes: 156 additions & 0 deletions webserver/check_openplc_db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
##############################################################################
#
# Checks and initializes default database if needed
#
##############################################################################


import sqlite3
from sqlite3 import Error
import os

builddir = r"build/"
dbfile = r"build/openplc.db"

createTablePrograms = r"""CREATE TABLE `Programs` (
`Prog_ID` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
`Name` TEXT NOT NULL,
`Description` TEXT,
`File` TEXT NOT NULL,
`Date_upload` INTEGER NOT NULL
)"""

insertblankProgram = r"INSERT INTO Programs VALUES (1, 'Blank Program', 'Dummy empty program', 'blank_program.st', 1527184953)"

createTableSettings = r"""CREATE TABLE `Settings` (
`Key` TEXT NOT NULL UNIQUE,
`Value` TEXT NOT NULL,
PRIMARY KEY(`Key`)
)"""


createTableSlave_dev = r"""CREATE TABLE "Slave_dev" (
"dev_id" INTEGER NOT NULL UNIQUE,
"dev_name" TEXT NOT NULL UNIQUE,
"dev_type" TEXT NOT NULL,
"slave_id" INTEGER NOT NULL,
"com_port" TEXT,
"baud_rate" INTEGER,
"parity" TEXT,
"data_bits" INTEGER,
"stop_bits" INTEGER,
"ip_address" TEXT,
"ip_port" INTEGER,
"di_start" INTEGER NOT NULL,
"di_size" INTEGER NOT NULL,
"coil_start" INTEGER NOT NULL,
"coil_size" INTEGER NOT NULL,
"ir_start" INTEGER NOT NULL,
"ir_size" INTEGER NOT NULL,
"hr_read_start" INTEGER NOT NULL,
"hr_read_size" INTEGER NOT NULL,
"hr_write_start" INTEGER NOT NULL,
"hr_write_size" INTEGER NOT NULL,
"pause" INTEGER,
PRIMARY KEY("dev_id" AUTOINCREMENT)
)"""

createTableUsers = r"""CREATE TABLE "Users" (
`user_id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
`name` TEXT NOT NULL,
`username` TEXT NOT NULL UNIQUE,
`email` TEXT,
`password` TEXT NOT NULL,
`pict_file` TEXT
)"""

insertDefaultUser = r"INSERT INTO Users VALUES (10, 'OpenPLC User', 'openplc', '[email protected]','openplc', NULL)"



gettablesQuery = r"""SELECT name FROM sqlite_master
WHERE type='table';"""
getsettingsQuery = r"""SELECT Key FROM Settings"""

# return true if created fresh table
def checkTableExists(conn, tablename, tablecreatecommand):
cur = conn.cursor()
cur.execute(gettablesQuery)
rows = cur.fetchall()
for row in rows:
if row[0] == tablename:
cur.close()
return False
print(tablename, " didn't exist, creating")
cur.execute(tablecreatecommand)
cur.close()
return True

def checkTablePrograms(conn):
if checkTableExists(conn, "Programs", createTablePrograms):
cur = conn.cursor()
cur.execute(insertblankProgram)
cur.close()
return

def checkTableUsers(conn):
if checkTableExists(conn, "Users", createTableUsers):
cur = conn.cursor()
cur.execute(insertDefaultUser)
cur.close()
return

# if code has new features, old database might not have required settings
def checkSettingExists(conn, setting, defaultvalue):
cur = conn.cursor()
cur.execute(getsettingsQuery)
rows = cur.fetchall()
for row in rows:
if row[0] == setting:
cur.close()
return False
print(setting, " didn't exist, creating")
cur.execute("INSERT INTO Settings VALUES (?, ?)", (setting, defaultvalue))
cur.close()
return

def checkTableSettings(conn):
checkTableExists(conn, "Settings", createTableSettings)
checkSettingExists(conn, 'Modbus_port', '502')
checkSettingExists(conn, 'Dnp3_port', '20000')
checkSettingExists(conn, 'Start_run_mode', 'false')
checkSettingExists(conn, 'Slave_polling', '100')
checkSettingExists(conn, 'Slave_timeout', '1000')
checkSettingExists(conn, 'Enip_port', '44818')
checkSettingExists(conn, 'Pstorage_polling', 'disabled')
return

def checkTableSlave_dev(conn):
checkTableExists(conn, "Slave_dev", createTableSlave_dev)
return

def create_connection():
""" create a database connection to a SQLite database """
if not os.path.exists(builddir):
os.mkdir(builddir)

conn = None
try:
conn = sqlite3.connect(dbfile)
checkTablePrograms(conn)
checkTableUsers(conn)
checkTableSettings(conn)
checkTableSlave_dev(conn)
except Error as e:
print(sqlite3.version)
print(e)
finally:
if conn:
# NB, if you close without commiting, last actions might not be saved
conn.commit()
return conn


if __name__ == '__main__':
conn = create_connection()
conn.close()
44 changes: 44 additions & 0 deletions webserver/core/interactive_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,11 @@
#include <time.h>

#include "ladder.h"
#define BUFFER_SIZE 1024

//Global Variables
bool ethercat_configured = 0;
char ethercat_conf_file[BUFFER_SIZE];
bool run_modbus = 0;
uint16_t modbus_port = 502;
bool run_dnp3 = 0;
Expand All @@ -58,6 +61,12 @@ pthread_t dnp3_thread;
pthread_t enip_thread;
pthread_t pstorage_thread;

//-----------------------------------------------------------------------------
// Configure Ethercat
//-----------------------------------------------------------------------------
int configureEthercat(){
return 1;
}
//-----------------------------------------------------------------------------
// Start the Modbus Thread
//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -111,6 +120,28 @@ int readCommandArgument(unsigned char *command)

return atoi(argument);
}
//-----------------------------------------------------------------------------
// Read string argument from a command function
//-----------------------------------------------------------------------------
unsigned char *readCommandArgumentStr(unsigned char *command)
{
int i = 0;
int j = 0;
unsigned char *argument;
argument = (unsigned char *)malloc(1024 * sizeof(unsigned char));

while (command[i] != '(' && command[i] != '\0') i++;
if (command[i] == '(') i++;
while (command[i] != ')' && command[i] != '\0')
{
argument[j] = command[i];
i++;
j++;
argument[j] = '\0';
}

return argument;
}

//-----------------------------------------------------------------------------
// Create the socket and bind it. Returns the file descriptor for the socket
Expand Down Expand Up @@ -235,6 +266,19 @@ void processCommand(unsigned char *buffer, int client_fd)
run_openplc = 0;
processing_command = false;
}
else if (strncmp(buffer, "start_ethercat(", 15) == 0)
{
processing_command = true;
char *argument;
argument = (char)readCommandArgumentStr(buffer);
strcpy(ethercat_conf_file, argument);
free(argument);
sprintf(log_msg, "Issued start_ethercat() command to start with config: %s\n", ethercat_conf_file);
log(log_msg);
//Configure ethercat
ethercat_configured = configureEthercat();
processing_command = false;
}
else if (strncmp(buffer, "start_modbus(", 13) == 0)
{
processing_command = true;
Expand Down
32 changes: 32 additions & 0 deletions webserver/core/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

#include "iec_types.h"
#include "ladder.h"
#include "ethercat_src.h"

#define OPLC_CYCLE 50000000

Expand Down Expand Up @@ -181,6 +182,15 @@ void handleSpecialFunctions()
//insert other special functions below
}

// pointers to IO *array[const][const] from cpp to c and back again don't work as expected, so instead callbacks
u_int8_t *bool_input_call_back(int a, int b){ return bool_input[a][b]; }
u_int8_t *bool_output_call_back(int a, int b){ return bool_output[a][b]; }
u_int8_t *byte_input_call_back(int a){ return byte_input[a]; }
u_int8_t *byte_output_call_back(int a){ return byte_output[a]; }
u_int16_t *int_input_call_back(int a){ return int_input[a]; }
u_int16_t *int_output_call_back(int a){ return int_output[a]; }


int main(int argc,char **argv)
{
unsigned char log_msg[1000];
Expand Down Expand Up @@ -209,6 +219,7 @@ int main(int argc,char **argv)
//======================================================
// HARDWARE INITIALIZATION
//======================================================
ethercat_configure("../utils/ethercat_src/conf/ethercatcfg.txt");
initializeHardware();
initializeMB();
initCustomLayer();
Expand All @@ -225,6 +236,8 @@ int main(int argc,char **argv)
readPersistentStorage();
//pthread_t persistentThread;
//pthread_create(&persistentThread, NULL, persistentStorage, NULL);



#ifdef __linux__
//======================================================
Expand Down Expand Up @@ -261,9 +274,28 @@ int main(int argc,char **argv)
//attached to the user variables
glueVars();

boolvar_call_back bool_input_callback = bool_input_call_back;
boolvar_call_back bool_output_callback = bool_output_call_back;
int8var_call_back byte_input_callback = byte_input_call_back;
int8var_call_back byte_output_callback = byte_output_call_back;
int16var_call_back int_input_callback = int_input_call_back;
int16var_call_back int_output_callback = int_output_call_back;

updateBuffersIn(); //read input image

pthread_mutex_lock(&bufferLock); //lock mutex


if(ethercat_callcyclic(BUFFER_SIZE,
bool_input_callback,
bool_output_callback,
byte_input_callback,
byte_output_callback,
int_input_callback,
int_output_callback)){
printf("EtherCAT cyclic failed\n");
break;
}
updateCustomIn();
updateBuffersIn_MB(); //update input image table with data from slave devices
handleSpecialFunctions();
Expand Down
2 changes: 1 addition & 1 deletion webserver/scripts/compile_program.sh
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ elif [ "$OPENPLC_PLATFORM" = "linux" ]; then
echo "Generating glueVars..."
./glue_generator
echo "Compiling main program..."
g++ -std=gnu++11 *.cpp *.o -o openplc -I ./lib -pthread -fpermissive `pkg-config --cflags --libs libmodbus` -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w
g++ -std=gnu++11 *.cpp *.o -o openplc -I ./lib -pthread -fpermissive `pkg-config --cflags --libs libmodbus` -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w -L../../utils/ethercat_src/build/lib -lethercat_src -I../../utils/ethercat_src/src
if [ $? -ne 0 ]; then
echo "Error compiling C files"
echo "Compilation finished with errors!"
Expand Down

0 comments on commit df84946

Please sign in to comment.