Initial Persistent Storage support + minor bug fixes
This commit is contained in:
parent
3ad96c294c
commit
eaf5112286
|
@ -39,11 +39,13 @@
|
||||||
|
|
||||||
//Global Variables
|
//Global Variables
|
||||||
bool run_modbus = 0;
|
bool run_modbus = 0;
|
||||||
int modbus_port = 502;
|
uint16_t modbus_port = 502;
|
||||||
bool run_dnp3 = 0;
|
bool run_dnp3 = 0;
|
||||||
int dnp3_port = 20000;
|
uint16_t dnp3_port = 20000;
|
||||||
bool run_enip = 0;
|
bool run_enip = 0;
|
||||||
int enip_port = 44818;
|
uint16_t enip_port = 44818;
|
||||||
|
bool run_pstorage = 0;
|
||||||
|
uint16_t pstorage_polling = 10;
|
||||||
unsigned char server_command[1024];
|
unsigned char server_command[1024];
|
||||||
int command_index = 0;
|
int command_index = 0;
|
||||||
bool processing_command = 0;
|
bool processing_command = 0;
|
||||||
|
@ -54,6 +56,7 @@ time_t end_time;
|
||||||
pthread_t modbus_thread;
|
pthread_t modbus_thread;
|
||||||
pthread_t dnp3_thread;
|
pthread_t dnp3_thread;
|
||||||
pthread_t enip_thread;
|
pthread_t enip_thread;
|
||||||
|
pthread_t pstorage_thread;
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Start the Modbus Thread
|
// Start the Modbus Thread
|
||||||
|
@ -79,6 +82,14 @@ void *enipThread(void *arg)
|
||||||
startServer(enip_port, ENIP_PROTOCOL);
|
startServer(enip_port, ENIP_PROTOCOL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Start the Persistent Storage Thread
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void *pstorageThread(void *arg)
|
||||||
|
{
|
||||||
|
startPstorage();
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Read the argument from a command function
|
// Read the argument from a command function
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -329,6 +340,35 @@ void processCommand(unsigned char *buffer, int client_fd)
|
||||||
}
|
}
|
||||||
processing_command = false;
|
processing_command = false;
|
||||||
}
|
}
|
||||||
|
else if (strncmp(buffer, "start_pstorage(", 15) == 0)
|
||||||
|
{
|
||||||
|
processing_command = true;
|
||||||
|
pstorage_polling = readCommandArgument(buffer);
|
||||||
|
sprintf(log_msg, "Issued start_pstorage() command with polling rate of %d seconds\n", pstorage_polling);
|
||||||
|
log(log_msg);
|
||||||
|
if (run_pstorage)
|
||||||
|
{
|
||||||
|
sprintf(log_msg, "Persistent Storage server already active. Changing polling rate to: %d\n", pstorage_polling);
|
||||||
|
log(log_msg);
|
||||||
|
}
|
||||||
|
//Start Enip server
|
||||||
|
run_pstorage = 1;
|
||||||
|
pthread_create(&pstorage_thread, NULL, pstorageThread, NULL);
|
||||||
|
processing_command = false;
|
||||||
|
}
|
||||||
|
else if (strncmp(buffer, "stop_pstorage()", 15) == 0)
|
||||||
|
{
|
||||||
|
processing_command = true;
|
||||||
|
sprintf(log_msg, "Issued stop_pstorage() command\n");
|
||||||
|
log(log_msg);
|
||||||
|
if (run_pstorage)
|
||||||
|
{
|
||||||
|
run_pstorage = 0;
|
||||||
|
sprintf(log_msg, "Persistent Storage thread was stopped\n");
|
||||||
|
log(log_msg);
|
||||||
|
}
|
||||||
|
processing_command = false;
|
||||||
|
}
|
||||||
else if (strncmp(buffer, "runtime_logs()", 14) == 0)
|
else if (strncmp(buffer, "runtime_logs()", 14) == 0)
|
||||||
{
|
{
|
||||||
processing_command = true;
|
processing_command = true;
|
||||||
|
@ -452,9 +492,18 @@ void startInteractiveServer(int port)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("Closing socket...");
|
|
||||||
|
printf("Shutting down internal threads\n");
|
||||||
|
run_modbus = 0;
|
||||||
|
run_dnp3 = 0;
|
||||||
|
run_enip = 0;
|
||||||
|
run_pstorage = 0;
|
||||||
|
pthread_join(modbus_thread, NULL);
|
||||||
|
pthread_join(dnp3_thread, NULL);
|
||||||
|
pthread_join(enip_thread, NULL);
|
||||||
|
|
||||||
|
printf("Closing socket...\n");
|
||||||
closeSocket(socket_fd);
|
closeSocket(socket_fd);
|
||||||
closeSocket(client_fd);
|
closeSocket(client_fd);
|
||||||
sprintf(log_msg, "Terminating interactive server thread\r\n");
|
printf("Terminating interactive server thread\n");
|
||||||
log(log_msg);
|
|
||||||
}
|
}
|
|
@ -121,7 +121,7 @@ extern int log_index;
|
||||||
void handleSpecialFunctions();
|
void handleSpecialFunctions();
|
||||||
|
|
||||||
//server.cpp
|
//server.cpp
|
||||||
void startServer(int port, int protocol_type);
|
void startServer(uint16_t port, int protocol_type);
|
||||||
int getSO_ERROR(int fd);
|
int getSO_ERROR(int fd);
|
||||||
void closeSocket(int fd);
|
void closeSocket(int fd);
|
||||||
bool SetSocketBlockingEnabled(int fd, bool blocking);
|
bool SetSocketBlockingEnabled(int fd, bool blocking);
|
||||||
|
@ -131,6 +131,8 @@ void startInteractiveServer(int port);
|
||||||
extern bool run_modbus;
|
extern bool run_modbus;
|
||||||
extern bool run_dnp3;
|
extern bool run_dnp3;
|
||||||
extern bool run_enip;
|
extern bool run_enip;
|
||||||
|
extern bool run_pstorage;
|
||||||
|
extern uint16_t pstorage_polling;
|
||||||
extern time_t start_time;
|
extern time_t start_time;
|
||||||
extern time_t end_time;
|
extern time_t end_time;
|
||||||
|
|
||||||
|
@ -151,5 +153,5 @@ void updateBuffersOut_MB();
|
||||||
void dnp3StartServer(int port);
|
void dnp3StartServer(int port);
|
||||||
|
|
||||||
//persistent_storage.cpp
|
//persistent_storage.cpp
|
||||||
void *persistentStorage(void *args);
|
void startPstorage();
|
||||||
int readPersistentStorage();
|
int readPersistentStorage();
|
||||||
|
|
|
@ -216,7 +216,9 @@ int main(int argc,char **argv)
|
||||||
//======================================================
|
//======================================================
|
||||||
// PERSISTENT STORAGE INITIALIZATION
|
// PERSISTENT STORAGE INITIALIZATION
|
||||||
//======================================================
|
//======================================================
|
||||||
//readPersistentStorage();
|
glueVars();
|
||||||
|
mapUnusedIO();
|
||||||
|
readPersistentStorage();
|
||||||
//pthread_t persistentThread;
|
//pthread_t persistentThread;
|
||||||
//pthread_create(&persistentThread, NULL, persistentStorage, NULL);
|
//pthread_create(&persistentThread, NULL, persistentStorage, NULL);
|
||||||
|
|
||||||
|
|
|
@ -115,10 +115,20 @@ void mapUnusedIO()
|
||||||
for (int i = 0; i <= MAX_16B_RANGE; i++)
|
for (int i = 0; i <= MAX_16B_RANGE; i++)
|
||||||
{
|
{
|
||||||
if (i < MIN_16B_RANGE)
|
if (i < MIN_16B_RANGE)
|
||||||
if (int_output[i] == NULL) int_output[i] = &mb_holding_regs[i];
|
{
|
||||||
|
if (int_output[i] == NULL)
|
||||||
|
{
|
||||||
|
int_output[i] = &mb_holding_regs[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (i >= MIN_16B_RANGE && i <= MAX_16B_RANGE)
|
else if (i >= MIN_16B_RANGE && i <= MAX_16B_RANGE)
|
||||||
if (int_memory[i - MIN_16B_RANGE] == NULL) int_memory[i] = &mb_holding_regs[i];
|
{
|
||||||
|
if (int_memory[i - MIN_16B_RANGE] == NULL)
|
||||||
|
{
|
||||||
|
int_memory[i - MIN_16B_RANGE] = &mb_holding_regs[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_unlock(&bufferLock);
|
pthread_mutex_unlock(&bufferLock);
|
||||||
|
|
|
@ -0,0 +1,151 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright 2019 Thiago Alves
|
||||||
|
// This file is part of the OpenPLC Software Stack.
|
||||||
|
//
|
||||||
|
// OpenPLC is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// OpenPLC is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with OpenPLC. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//------
|
||||||
|
//
|
||||||
|
// This file is responsible for the persistent storage on the OpenPLC
|
||||||
|
// Thiago Alves, Jun 2019
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include "ladder.h"
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Main function for the thread. Should create a buffer for the persistent
|
||||||
|
// data, compare it with the actual data and write back to the persistent
|
||||||
|
// file if the data has changed
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void startPstorage()
|
||||||
|
{
|
||||||
|
unsigned char log_msg[1000];
|
||||||
|
IEC_UINT persistentBuffer[BUFFER_SIZE];
|
||||||
|
|
||||||
|
//Read initial buffers into persistent struct
|
||||||
|
pthread_mutex_lock(&bufferLock); //lock mutex
|
||||||
|
for (int i = 0; i < BUFFER_SIZE; i++)
|
||||||
|
{
|
||||||
|
if (int_memory[i] != NULL) persistentBuffer[i] = *int_memory[i];
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&bufferLock); //unlock mutex
|
||||||
|
|
||||||
|
//Perform the first write
|
||||||
|
if (access("persistent.file", F_OK) == -1)
|
||||||
|
{
|
||||||
|
sprintf(log_msg, "Creating Persistent Storage file\n");
|
||||||
|
log(log_msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *ps = fopen("persistent.file", "w"); //if file already exists, it will be overwritten
|
||||||
|
if (ps == NULL)
|
||||||
|
{
|
||||||
|
sprintf(log_msg, "Persistent Storage: Error creating persistent memory file!\n");
|
||||||
|
log(log_msg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fwrite(persistentBuffer, sizeof(IEC_INT), BUFFER_SIZE, ps) < BUFFER_SIZE)
|
||||||
|
{
|
||||||
|
sprintf(log_msg, "Persistent Storage: Error writing to persistent memory file!\n");
|
||||||
|
log(log_msg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
fclose(ps);
|
||||||
|
|
||||||
|
//Run the main thread
|
||||||
|
while (run_pstorage)
|
||||||
|
{
|
||||||
|
|
||||||
|
//Verify if persistent buffer is outdated
|
||||||
|
bool bufferOutdated = false;
|
||||||
|
pthread_mutex_lock(&bufferLock); //lock mutex
|
||||||
|
for (int i = 0; i < BUFFER_SIZE; i++)
|
||||||
|
{
|
||||||
|
if (int_memory[i] != NULL)
|
||||||
|
{
|
||||||
|
if (persistentBuffer[i] != *int_memory[i])
|
||||||
|
{
|
||||||
|
persistentBuffer[i] = *int_memory[i];
|
||||||
|
bufferOutdated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&bufferLock); //unlock mutex
|
||||||
|
|
||||||
|
//If buffer is outdated, write the changes back to the file
|
||||||
|
if (bufferOutdated)
|
||||||
|
{
|
||||||
|
FILE *fd = fopen("persistent.file", "w"); //if file already exists, it will be overwritten
|
||||||
|
if (fd == NULL)
|
||||||
|
{
|
||||||
|
sprintf(log_msg, "Persistent Storage: Error creating persistent memory file!\n");
|
||||||
|
log(log_msg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fwrite(persistentBuffer, sizeof(IEC_INT), BUFFER_SIZE, fd) < BUFFER_SIZE)
|
||||||
|
{
|
||||||
|
sprintf(log_msg, "Persistent Storage: Error writing to persistent memory file!\n");
|
||||||
|
log(log_msg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
fclose(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
sleepms(pstorage_polling*1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// This function reads the contents from persistent.file into OpenPLC internal
|
||||||
|
// buffers. Must be called when OpenPLC is initializing. If persistent storage
|
||||||
|
// is disabled, the persistent.file will not be found and the function will
|
||||||
|
// exit gracefully.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
int readPersistentStorage()
|
||||||
|
{
|
||||||
|
unsigned char log_msg[1000];
|
||||||
|
FILE *fd = fopen("persistent.file", "r");
|
||||||
|
if (fd == NULL)
|
||||||
|
{
|
||||||
|
sprintf(log_msg, "Warning: Persistent Storage file not found\n");
|
||||||
|
log(log_msg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
IEC_INT persistentBuffer[BUFFER_SIZE];
|
||||||
|
|
||||||
|
if (fread(persistentBuffer, sizeof(IEC_INT), BUFFER_SIZE, fd) < BUFFER_SIZE)
|
||||||
|
{
|
||||||
|
sprintf(log_msg, "Persistent Storage: Error while trying to read persistent.file!\n");
|
||||||
|
log(log_msg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
fclose(fd);
|
||||||
|
|
||||||
|
sprintf(log_msg, "Persistent Storage: Reading persistent.file into local buffers\n");
|
||||||
|
log(log_msg);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&bufferLock); //lock mutex
|
||||||
|
for (int i = 0; i < BUFFER_SIZE; i++)
|
||||||
|
{
|
||||||
|
if (int_memory[i] != NULL) *int_memory[i] = persistentBuffer[i];
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&bufferLock); //unlock mutex
|
||||||
|
}
|
|
@ -84,7 +84,7 @@ bool SetSocketBlockingEnabled(int fd, bool blocking)
|
||||||
// Create the socket and bind it. Returns the file descriptor for the socket
|
// Create the socket and bind it. Returns the file descriptor for the socket
|
||||||
// created.
|
// created.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
int createSocket(int port)
|
int createSocket(uint16_t port)
|
||||||
{
|
{
|
||||||
unsigned char log_msg[1000];
|
unsigned char log_msg[1000];
|
||||||
int socket_fd;
|
int socket_fd;
|
||||||
|
@ -249,7 +249,7 @@ void *handleConnections(void *arguments)
|
||||||
// creates an infinite loop to listen and parse the messages sent by the
|
// creates an infinite loop to listen and parse the messages sent by the
|
||||||
// clients
|
// clients
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void startServer(int port, int protocol_type)
|
void startServer(uint16_t port, int protocol_type)
|
||||||
{
|
{
|
||||||
unsigned char log_msg[1000];
|
unsigned char log_msg[1000];
|
||||||
int socket_fd, client_fd;
|
int socket_fd, client_fd;
|
||||||
|
@ -259,7 +259,7 @@ void startServer(int port, int protocol_type)
|
||||||
|
|
||||||
if (protocol_type == MODBUS_PROTOCOL)
|
if (protocol_type == MODBUS_PROTOCOL)
|
||||||
{
|
{
|
||||||
mapUnusedIO();
|
//mapUnusedIO();
|
||||||
run_server = &run_modbus;
|
run_server = &run_modbus;
|
||||||
}
|
}
|
||||||
else if (protocol_type == ENIP_PROTOCOL)
|
else if (protocol_type == ENIP_PROTOCOL)
|
||||||
|
|
Binary file not shown.
|
@ -201,6 +201,28 @@ class runtime:
|
||||||
except:
|
except:
|
||||||
print("Error connecting to OpenPLC runtime")
|
print("Error connecting to OpenPLC runtime")
|
||||||
|
|
||||||
|
def start_pstorage(self, poll_rate):
|
||||||
|
if (self.status() == "Running"):
|
||||||
|
try:
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
s.connect(('localhost', 43628))
|
||||||
|
s.send('start_pstorage(' + str(poll_rate) + ')\n')
|
||||||
|
data = s.recv(1000)
|
||||||
|
s.close()
|
||||||
|
except:
|
||||||
|
print("Error connecting to OpenPLC runtime")
|
||||||
|
|
||||||
|
def stop_pstorage(self):
|
||||||
|
if (self.status() == "Running"):
|
||||||
|
try:
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
s.connect(('localhost', 43628))
|
||||||
|
s.send('stop_pstorage()\n')
|
||||||
|
data = s.recv(1000)
|
||||||
|
s.close()
|
||||||
|
except:
|
||||||
|
print("Error connecting to OpenPLC runtime")
|
||||||
|
|
||||||
def logs(self):
|
def logs(self):
|
||||||
if (self.status() == "Running"):
|
if (self.status() == "Running"):
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -1034,6 +1034,8 @@ settings_tail = """
|
||||||
var dnp3_text = document.getElementById('dnp3_server_port');
|
var dnp3_text = document.getElementById('dnp3_server_port');
|
||||||
var enip_checkbox = document.getElementById('enip_server');
|
var enip_checkbox = document.getElementById('enip_server');
|
||||||
var enip_text = document.getElementById('enip_server_port');
|
var enip_text = document.getElementById('enip_server_port');
|
||||||
|
var pstorage_checkbox = document.getElementById('pstorage_thread');
|
||||||
|
var pstorage_text = document.getElementById('pstorage_thread_poll');
|
||||||
var auto_run_checkbox = document.getElementById('auto_run');
|
var auto_run_checkbox = document.getElementById('auto_run');
|
||||||
var auto_run_text = document.getElementById('auto_run_text');
|
var auto_run_text = document.getElementById('auto_run_text');
|
||||||
|
|
||||||
|
@ -1064,6 +1066,15 @@ settings_tail = """
|
||||||
enip_text.disabled = true;
|
enip_text.disabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pstorage_checkbox.checked == true)
|
||||||
|
{
|
||||||
|
pstorage_text.disabled = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pstorage_text.disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (auto_run_checkbox.checked == true)
|
if (auto_run_checkbox.checked == true)
|
||||||
{
|
{
|
||||||
auto_run_text.value = 'true';
|
auto_run_text.value = 'true';
|
||||||
|
@ -1089,6 +1100,11 @@ settings_tail = """
|
||||||
setupCheckboxes();
|
setupCheckboxes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
document.getElementById('pstorage_thread').onchange = function()
|
||||||
|
{
|
||||||
|
setupCheckboxes();
|
||||||
|
}
|
||||||
|
|
||||||
document.getElementById('auto_run').onchange = function()
|
document.getElementById('auto_run').onchange = function()
|
||||||
{
|
{
|
||||||
setupCheckboxes();
|
setupCheckboxes();
|
||||||
|
@ -1102,6 +1118,8 @@ settings_tail = """
|
||||||
var dnp3_port = document.forms["uploadForm"]["dnp3_server_port"].value;
|
var dnp3_port = document.forms["uploadForm"]["dnp3_server_port"].value;
|
||||||
var enip_checkbox = document.forms["uploadForm"]["enip_server"].checked;
|
var enip_checkbox = document.forms["uploadForm"]["enip_server"].checked;
|
||||||
var enip_port = document.forms["uploadForm"]["enip_server_port"].value;
|
var enip_port = document.forms["uploadForm"]["enip_server_port"].value;
|
||||||
|
var pstorage_checkbox = document.forms["uploadForm"]["pstorage_thread"].checked;
|
||||||
|
var pstorage_poll = document.forms["uploadForm"]["pstorage_thread_poll"].value;
|
||||||
|
|
||||||
if (modbus_checkbox && (Number(modbus_port) < 0 || Number(modbus_port) > 65535))
|
if (modbus_checkbox && (Number(modbus_port) < 0 || Number(modbus_port) > 65535))
|
||||||
{
|
{
|
||||||
|
@ -1118,6 +1136,11 @@ settings_tail = """
|
||||||
alert("Please select a port number between 0 and 65535");
|
alert("Please select a port number between 0 and 65535");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (pstorage_checkbox && Number(pstorage_poll) < 0)
|
||||||
|
{
|
||||||
|
alert("Persistent Storage polling rate must be bigger than zero");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -61,12 +61,26 @@ def configure_runtime():
|
||||||
else:
|
else:
|
||||||
print("Disabling EtherNet/IP")
|
print("Disabling EtherNet/IP")
|
||||||
openplc_runtime.stop_enip()
|
openplc_runtime.stop_enip()
|
||||||
|
elif (row[0] == "Pstorage_polling"):
|
||||||
|
if (row[1] != "disabled"):
|
||||||
|
print("Enabling Persistent Storage with polling rate of " + str(int(row[1])) + " seconds")
|
||||||
|
openplc_runtime.start_pstorage(int(row[1]))
|
||||||
|
else:
|
||||||
|
print("Disabling Persistent Storage")
|
||||||
|
openplc_runtime.stop_pstorage()
|
||||||
|
delete_persistent_file()
|
||||||
except Error as e:
|
except Error as e:
|
||||||
print("error connecting to the database" + str(e))
|
print("error connecting to the database" + str(e))
|
||||||
else:
|
else:
|
||||||
print("Error opening DB")
|
print("Error opening DB")
|
||||||
|
|
||||||
|
|
||||||
|
def delete_persistent_file():
|
||||||
|
if (os.path.isfile("persistent.file")):
|
||||||
|
os.remove("persistent.file")
|
||||||
|
print("persistent.file removed!")
|
||||||
|
|
||||||
|
|
||||||
def generate_mbconfig():
|
def generate_mbconfig():
|
||||||
database = "openplc.db"
|
database = "openplc.db"
|
||||||
conn = create_connection(database)
|
conn = create_connection(database)
|
||||||
|
@ -836,6 +850,7 @@ def compile_program():
|
||||||
else:
|
else:
|
||||||
print("error connecting to the database")
|
print("error connecting to the database")
|
||||||
|
|
||||||
|
delete_persistent_file()
|
||||||
openplc_runtime.compile_program(st_file)
|
openplc_runtime.compile_program(st_file)
|
||||||
|
|
||||||
return draw_compiling_page()
|
return draw_compiling_page()
|
||||||
|
@ -1763,7 +1778,6 @@ def settings():
|
||||||
<div style="w3-container">
|
<div style="w3-container">
|
||||||
<br>
|
<br>
|
||||||
<h2>Settings</h2>
|
<h2>Settings</h2>
|
||||||
<br>
|
|
||||||
<form id = "uploadForm"
|
<form id = "uploadForm"
|
||||||
enctype = "multipart/form-data"
|
enctype = "multipart/form-data"
|
||||||
action = "settings"
|
action = "settings"
|
||||||
|
@ -1790,6 +1804,8 @@ def settings():
|
||||||
dnp3_port = str(row[1])
|
dnp3_port = str(row[1])
|
||||||
elif (row[0] == "Enip_port"):
|
elif (row[0] == "Enip_port"):
|
||||||
enip_port = str(row[1])
|
enip_port = str(row[1])
|
||||||
|
elif (row[0] == "Pstorage_polling"):
|
||||||
|
pstorage_poll = str(row[1])
|
||||||
elif (row[0] == "Start_run_mode"):
|
elif (row[0] == "Start_run_mode"):
|
||||||
start_run = str(row[1])
|
start_run = str(row[1])
|
||||||
elif (row[0] == "Slave_polling"):
|
elif (row[0] == "Slave_polling"):
|
||||||
|
@ -1856,6 +1872,28 @@ def settings():
|
||||||
<label for='enip_server_port'><b>EtherNet/IP Server Port</b></label>
|
<label for='enip_server_port'><b>EtherNet/IP Server Port</b></label>
|
||||||
<input type='text' id='enip_server_port' name='enip_server_port' value='""" + enip_port + "'>"
|
<input type='text' id='enip_server_port' name='enip_server_port' value='""" + enip_port + "'>"
|
||||||
|
|
||||||
|
return_str += """
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<label class="container">
|
||||||
|
<b>Enable Persistent Storage Thread</b>"""
|
||||||
|
|
||||||
|
if (pstorage_poll == 'disabled'):
|
||||||
|
return_str += """
|
||||||
|
<input id="pstorage_thread" type="checkbox">
|
||||||
|
<span class="checkmark"></span>
|
||||||
|
</label>
|
||||||
|
<label for='pstorage_thread_poll'><b>Persistent Storage polling rate</b></label>
|
||||||
|
<input type='text' id='pstorage_thread_poll' name='pstorage_thread_poll' value='10'>"""
|
||||||
|
else:
|
||||||
|
return_str += """
|
||||||
|
<input id="pstorage_thread" type="checkbox" checked>
|
||||||
|
<span class="checkmark"></span>
|
||||||
|
</label>
|
||||||
|
<label for='pstorage_thread_poll'><b>Persistent Storage polling rate</b></label>
|
||||||
|
<input type='text' id='pstorage_thread_poll' name='pstorage_thread_poll' value='""" + pstorage_poll + "'>"
|
||||||
|
|
||||||
return_str += """
|
return_str += """
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
|
@ -1877,11 +1915,8 @@ def settings():
|
||||||
<input type='hidden' value='true' id='auto_run_text' name='auto_run_text'/>"""
|
<input type='hidden' value='true' id='auto_run_text' name='auto_run_text'/>"""
|
||||||
|
|
||||||
return_str += """
|
return_str += """
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
<br>
|
<br>
|
||||||
<h2>Slave Devices</h2>
|
<h2>Slave Devices</h2>
|
||||||
<br>
|
|
||||||
<label for='slave_polling_period'><b>Polling Period (ms)</b></label>
|
<label for='slave_polling_period'><b>Polling Period (ms)</b></label>
|
||||||
<input type='text' id='slave_polling_period' name='slave_polling_period' value='""" + slave_polling + "'>"
|
<input type='text' id='slave_polling_period' name='slave_polling_period' value='""" + slave_polling + "'>"
|
||||||
|
|
||||||
|
@ -1905,6 +1940,7 @@ def settings():
|
||||||
modbus_port = flask.request.form.get('modbus_server_port')
|
modbus_port = flask.request.form.get('modbus_server_port')
|
||||||
dnp3_port = flask.request.form.get('dnp3_server_port')
|
dnp3_port = flask.request.form.get('dnp3_server_port')
|
||||||
enip_port = flask.request.form.get('enip_server_port')
|
enip_port = flask.request.form.get('enip_server_port')
|
||||||
|
pstorage_poll = flask.request.form.get('pstorage_thread_poll')
|
||||||
start_run = flask.request.form.get('auto_run_text')
|
start_run = flask.request.form.get('auto_run_text')
|
||||||
slave_polling = flask.request.form.get('slave_polling_period')
|
slave_polling = flask.request.form.get('slave_polling_period')
|
||||||
slave_timeout = flask.request.form.get('slave_timeout')
|
slave_timeout = flask.request.form.get('slave_timeout')
|
||||||
|
@ -1935,6 +1971,13 @@ def settings():
|
||||||
cur.execute("UPDATE Settings SET Value = ? WHERE Key = 'Enip_port'", (str(enip_port),))
|
cur.execute("UPDATE Settings SET Value = ? WHERE Key = 'Enip_port'", (str(enip_port),))
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
|
if (pstorage_poll == None):
|
||||||
|
cur.execute("UPDATE Settings SET Value = 'disabled' WHERE Key = 'Pstorage_polling'")
|
||||||
|
conn.commit()
|
||||||
|
else:
|
||||||
|
cur.execute("UPDATE Settings SET Value = ? WHERE Key = 'Pstorage_polling'", (str(pstorage_poll),))
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
if (start_run == 'true'):
|
if (start_run == 'true'):
|
||||||
cur.execute("UPDATE Settings SET Value = 'true' WHERE Key = 'Start_run_mode'")
|
cur.execute("UPDATE Settings SET Value = 'true' WHERE Key = 'Start_run_mode'")
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
Loading…
Reference in New Issue