Added support for Modbus Slave devices [experimental]

This commit is contained in:
thiagoralves 2018-08-10 19:18:20 -05:00
parent e6b31d62c3
commit b9d77a938a
8 changed files with 1854 additions and 5 deletions

View File

@ -28,6 +28,7 @@ if [ "$1" == "win" ]; then
python get-pip.py
pip install flask
pip install flask-login
pip install pyserial
echo ""
echo "[MATIEC COMPILER]"
@ -79,6 +80,19 @@ if [ "$1" == "win" ]; then
fi
cd ../..
echo ""
echo "[LIBMODBUS]"
cd utils/libmodbus_src
./autogen
./configure
make install
if [ $? -ne 0 ]; then
echo "Error installing Libmodbus"
echo "OpenPLC was NOT installed!"
exit 1
fi
cd ../..
echo ""
echo "[FINALIZING]"
cd webserver/scripts
@ -94,9 +108,11 @@ elif [ "$1" == "linux" ]; then
sudo apt-get install build-essential pkg-config bison flex autoconf automake libtool make git python2.7 python-pip sqlite3 cmake
pip install flask
pip install flask-login
#make sure that flask and flask-login are also installed for the super user
pip install pyserial
#make sure that packages are also installed for the super user
sudo pip install flask
sudo pip install flask-login
sudo pip install pyserial
echo ""
echo "[MATIEC COMPILER]"
@ -157,6 +173,20 @@ elif [ "$1" == "linux" ]; then
sudo rm -f ./swapfile
cd ../..
echo ""
echo "[LIBMODBUS]"
cd utils/libmodbus_src
./autogen
./configure
sudo make install
if [ $? -ne 0 ]; then
echo "Error installing Libmodbus"
echo "OpenPLC was NOT installed!"
exit 1
fi
sudo ldconfig
cd ../..
echo ""
echo "[FINALIZING]"
cd webserver/scripts
@ -172,9 +202,11 @@ elif [ "$1" == "rpi" ]; then
sudo apt-get install build-essential pkg-config bison flex autoconf automake libtool make git python2.7 python-pip sqlite3 cmake wiringpi
pip install flask
pip install flask-login
#make sure that flask and flask-login are also installed for the super user
pip install pyserial
#make sure that packages are also installed for the super user
sudo pip install flask
sudo pip install flask-login
sudo pip install pyserial
echo ""
echo "[MATIEC COMPILER]"
@ -235,6 +267,105 @@ elif [ "$1" == "rpi" ]; then
sudo rm -f ./swapfile
cd ../..
echo ""
echo "[LIBMODBUS]"
cd utils/libmodbus_src
./autogen
./configure
sudo make install
if [ $? -ne 0 ]; then
echo "Error installing Libmodbus"
echo "OpenPLC was NOT installed!"
exit 1
fi
sudo ldconfig
cd ../..
echo ""
echo "[FINALIZING]"
cd webserver/scripts
./change_hardware_layer.sh blank_linux
./compile_program.sh blank_program.st
cp ./start_openplc.sh ../../
elif [ "$1" == "custom" ]; then
echo "Installing OpenPLC on Custom Platform"
echo ""
echo "[MATIEC COMPILER]"
cd utils/matiec_src
autoreconf -i
./configure
make
cp ./iec2c ../../webserver/
if [ $? -ne 0 ]; then
echo "Error compiling MatIEC"
echo "OpenPLC was NOT installed!"
exit 1
fi
cd ../..
echo ""
echo "[ST OPTIMIZER]"
cd utils/st_optimizer_src
g++ st_optimizer.cpp -o st_optimizer
cp ./st_optimizer ../../webserver/
if [ $? -ne 0 ]; then
echo "Error compiling ST Optimizer"
echo "OpenPLC was NOT installed!"
exit 1
fi
cd ../..
echo ""
echo "[GLUE GENERATOR]"
cd utils/glue_generator_src
g++ glue_generator.cpp -o glue_generator
cp ./glue_generator ../../webserver/core
if [ $? -ne 0 ]; then
echo "Error compiling Glue Generator"
echo "OpenPLC was NOT installed!"
exit 1
fi
cd ../..
echo ""
echo "[OPEN DNP3]"
cd utils/dnp3_src
echo "creating swapfile..."
sudo dd if=/dev/zero of=swapfile bs=1M count=1000
sudo mkswap swapfile
sudo swapon swapfile
cmake ../dnp3_src
make
sudo make install
if [ $? -ne 0 ]; then
echo "Error installing OpenDNP3"
echo "OpenPLC was NOT installed!"
exit 1
fi
sudo ldconfig
echo "removing swapfile..."
sudo swapoff swapfile
sudo rm -f ./swapfile
cd ../..
echo ""
echo "[LIBMODBUS]"
cd utils/libmodbus_src
./autogen
./configure
sudo make install
if [ $? -ne 0 ]; then
echo "Error installing Libmodbus"
echo "OpenPLC was NOT installed!"
exit 1
fi
sudo ldconfig
cd ../..
echo ""
echo "[FINALIZING]"
cd webserver/scripts

View File

@ -127,6 +127,12 @@ extern time_t end_time;
int processModbusMessage(unsigned char *buffer, int bufferSize);
void mapUnusedIO();
//modbus_master.cpp
void initializeMB();
void querySlaveDevices();
void updateBuffersIn_MB();
void updateBuffersOut_MB();
//dnp3.cpp
void dnp3StartServer(int port);

View File

@ -164,6 +164,7 @@ int main(int argc,char **argv)
// HARDWARE INITIALIZATION
//======================================================
initializeHardware();
initializeMB();
initCustomLayer();
updateBuffersIn();
updateCustomIn();
@ -212,12 +213,16 @@ int main(int argc,char **argv)
//attached to the user variables
glueVars();
querySlaveDevices(); //query data from all slave devices
updateBuffersIn(); //read input image
pthread_mutex_lock(&bufferLock); //lock mutex
updateCustomIn();
updateBuffersIn_MB(); //update input image table with data from slave devices
config_run__(tick++); // execute plc program logic
updateCustomOut();
updateBuffersOut_MB(); //update slave devices with data from the output image table
pthread_mutex_unlock(&bufferLock); //unlock mutex
updateBuffersOut(); //write output image

512
webserver/core/modbus_master.cpp Executable file
View File

@ -0,0 +1,512 @@
//-----------------------------------------------------------------------------
// Copyright 2015 Thiago Alves
//
// Based on the LDmicro software by Jonathan Westhues
// 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 parse and discovery of slave devices by parsing
// the mbconfig.cfg file. This code also updates OpenPLC internal buffers with
// the data queried from the slave devices.
// Thiago Alves, Jul 2018
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <modbus.h>
#include <errno.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include <string>
#include "ladder.h"
#define MB_TCP 1
#define MB_RTU 2
#define MAX_MB_IO 400
using namespace std;
uint8_t bool_input_buf[MAX_MB_IO];
uint8_t bool_output_buf[MAX_MB_IO];
uint16_t int_input_buf[MAX_MB_IO];
uint16_t int_output_buf[MAX_MB_IO];
pthread_mutex_t ioLock;
struct MB_address
{
uint16_t start_address;
uint16_t num_regs;
};
struct MB_device
{
modbus_t *mb_ctx;
char dev_name[100];
uint8_t protocol;
char dev_address[100];
uint16_t ip_port;
int rtu_baud;
char rtu_parity;
int rtu_data_bit;
int rtu_stop_bit;
uint8_t dev_id;
bool isConnected;
struct MB_address discrete_inputs;
struct MB_address coils;
struct MB_address input_registers;
struct MB_address holding_registers;
};
struct MB_device *mb_devices;
uint8_t num_devices;
//-----------------------------------------------------------------------------
// Finds the data between the separators on the line provided
//-----------------------------------------------------------------------------
void getData(char *line, char *buf, char separator1, char separator2)
{
int i=0, j=0;
buf[j] = '\0';
while (line[i] != separator1 && line[i] != '\0')
{
i++;
}
i++;
while (line[i] != separator2 && line[i] != '\0')
{
buf[j] = line[i];
i++;
j++;
buf[j] = '\0';
}
}
//-----------------------------------------------------------------------------
// Get the number of the Modbus device
//-----------------------------------------------------------------------------
int getDeviceNumber(char *line)
{
char temp[5];
int i = 0, j = 6;
while (line[j] != '.')
{
temp[i] = line[j];
i++;
j++;
temp[i] = '\0';
}
return(atoi(temp));
}
//-----------------------------------------------------------------------------
// get the type of function or parameter for the Modbus device
//-----------------------------------------------------------------------------
void getFunction(char *line, char *parameter)
{
int i = 0, j = 0;
while (line[j] != '.')
{
j++;
}
j++;
while (line[j] != ' ' && line[j] != '=' && line[j] != '(')
{
parameter[i] = line[j];
i++;
j++;
parameter[i] = '\0';
}
}
void parseConfig()
{
string line;
char line_str[1024];
ifstream cfgfile("mbconfig.cfg");
if (cfgfile.is_open())
{
while (getline(cfgfile, line))
{
strncpy(line_str, line.c_str(), 1024);
if (line_str[0] != '#' && strlen(line_str) > 1)
{
if (!strncmp(line_str, "Num_Devices", 11))
{
char temp_buffer[5];
getData(line_str, temp_buffer, '"', '"');
num_devices = atoi(temp_buffer);
mb_devices = (struct MB_device *)malloc(num_devices*sizeof(struct MB_device));
}
else if (!strncmp(line_str, "device", 6))
{
int deviceNumber = getDeviceNumber(line_str);
char functionType[100];
getFunction(line_str, functionType);
if (!strncmp(functionType, "name", 4))
{
getData(line_str, mb_devices[deviceNumber].dev_name, '"', '"');
}
else if (!strncmp(functionType, "protocol", 8))
{
char temp_buffer[5];
getData(line_str, temp_buffer, '"', '"');
if (!strncmp(temp_buffer, "TCP", 3))
mb_devices[deviceNumber].protocol = MB_TCP;
else if (!strncmp(temp_buffer, "RTU", 3))
mb_devices[deviceNumber].protocol = MB_RTU;
}
else if (!strncmp(functionType, "slave_id", 8))
{
char temp_buffer[5];
getData(line_str, temp_buffer, '"', '"');
mb_devices[deviceNumber].dev_id = atoi(temp_buffer);
}
else if (!strncmp(functionType, "address", 7))
{
getData(line_str, mb_devices[deviceNumber].dev_address, '"', '"');
}
else if (!strncmp(functionType, "IP_Port", 7))
{
char temp_buffer[6];
getData(line_str, temp_buffer, '"', '"');
mb_devices[deviceNumber].ip_port = atoi(temp_buffer);
}
else if (!strncmp(functionType, "RTU_Baud_Rate", 13))
{
char temp_buffer[10];
getData(line_str, temp_buffer, '"', '"');
mb_devices[deviceNumber].rtu_baud = atoi(temp_buffer);
}
else if (!strncmp(functionType, "RTU_Parity", 10))
{
char temp_buffer[3];
getData(line_str, temp_buffer, '"', '"');
mb_devices[deviceNumber].rtu_parity = temp_buffer[0];
}
else if (!strncmp(functionType, "RTU_Data_Bits", 13))
{
char temp_buffer[6];
getData(line_str, temp_buffer, '"', '"');
mb_devices[deviceNumber].rtu_data_bit = atoi(temp_buffer);
}
else if (!strncmp(functionType, "RTU_Stop_Bits", 13))
{
char temp_buffer[6];
getData(line_str, temp_buffer, '"', '"');
mb_devices[deviceNumber].rtu_stop_bit = atoi(temp_buffer);
}
else if (!strncmp(functionType, "Discrete_Inputs_Start", 21))
{
char temp_buffer[10];
getData(line_str, temp_buffer, '"', '"');
mb_devices[deviceNumber].discrete_inputs.start_address = atoi(temp_buffer);
}
else if (!strncmp(functionType, "Discrete_Inputs_Size", 20))
{
char temp_buffer[10];
getData(line_str, temp_buffer, '"', '"');
mb_devices[deviceNumber].discrete_inputs.num_regs = atoi(temp_buffer);
}
else if (!strncmp(functionType, "Coils_Start", 11))
{
char temp_buffer[10];
getData(line_str, temp_buffer, '"', '"');
mb_devices[deviceNumber].coils.start_address = atoi(temp_buffer);
}
else if (!strncmp(functionType, "Coils_Size", 10))
{
char temp_buffer[10];
getData(line_str, temp_buffer, '"', '"');
mb_devices[deviceNumber].coils.num_regs = atoi(temp_buffer);
}
else if (!strncmp(functionType, "Input_Registers_Start", 21))
{
char temp_buffer[10];
getData(line_str, temp_buffer, '"', '"');
mb_devices[deviceNumber].input_registers.start_address = atoi(temp_buffer);
}
else if (!strncmp(functionType, "Input_Registers_Size", 20))
{
char temp_buffer[10];
getData(line_str, temp_buffer, '"', '"');
mb_devices[deviceNumber].input_registers.num_regs = atoi(temp_buffer);
}
else if (!strncmp(functionType, "Holding_Registers_Start", 23))
{
char temp_buffer[10];
getData(line_str, temp_buffer, '"', '"');
mb_devices[deviceNumber].holding_registers.start_address = atoi(temp_buffer);
}
else if (!strncmp(functionType, "Holding_Registers_Size", 22))
{
char temp_buffer[10];
getData(line_str, temp_buffer, '"', '"');
mb_devices[deviceNumber].holding_registers.num_regs = atoi(temp_buffer);
}
}
}
}
}
else
{
unsigned char log_msg[1000];
sprintf(log_msg, "Error opening mbconfig.cfg file\n");
log(log_msg);
}
//Parser Debug
///*
for (int i = 0; i < num_devices; i++)
{
printf("Device %d\n", i);
printf("Name: %s\n", mb_devices[i].dev_name);
printf("Protocol: %d\n", mb_devices[i].protocol);
printf("Address: %s\n", mb_devices[i].dev_address);
printf("IP Port: %d\n", mb_devices[i].ip_port);
printf("Baud rate: %d\n", mb_devices[i].rtu_baud);
printf("Parity: %c\n", mb_devices[i].rtu_parity);
printf("Data Bits: %d\n", mb_devices[i].rtu_data_bit);
printf("Stop Bits: %d\n", mb_devices[i].rtu_stop_bit);
printf("DI Start: %d\n", mb_devices[i].discrete_inputs.start_address);
printf("DI Size: %d\n", mb_devices[i].discrete_inputs.num_regs);
printf("Coils Start: %d\n", mb_devices[i].coils.start_address);
printf("Coils Size: %d\n", mb_devices[i].coils.num_regs);
printf("IR Start: %d\n", mb_devices[i].input_registers.start_address);
printf("IR Size: %d\n", mb_devices[i].input_registers.num_regs);
printf("HR Start: %d\n", mb_devices[i].holding_registers.start_address);
printf("HR Size: %d\n", mb_devices[i].holding_registers.num_regs);
printf("\n\n");
}
//*/
}
void querySlaveDevices()
{
unsigned char log_msg[1000];
uint16_t bool_input_index = 0;
uint16_t bool_output_index = 0;
uint16_t int_input_index = 0;
uint16_t int_output_index = 0;
for (int i = 0; i < num_devices; i++)
{
//Verify if device is connected
if (!mb_devices[i].isConnected)
{
sprintf(log_msg, "Device %s is disconnected. Attempting to reconnect...\n", mb_devices[i].dev_name);
log(log_msg);
if (modbus_connect(mb_devices[i].mb_ctx) == -1)
{
sprintf(log_msg, "Connection failed on MB device %s: %s\n", mb_devices[i].dev_name, modbus_strerror(errno));
log(log_msg);
}
else
{
sprintf(log_msg, "Connected to MB device %s\n", mb_devices[i].dev_name);
log(log_msg);
mb_devices[i].isConnected = true;
}
}
if (mb_devices[i].isConnected)
{
//Read discrete inputs
if (mb_devices[i].discrete_inputs.num_regs != 0)
{
uint8_t *tempBuff;
tempBuff = (uint8_t *)malloc(mb_devices[i].discrete_inputs.num_regs);
int return_val = modbus_read_input_bits(mb_devices[i].mb_ctx, mb_devices[i].discrete_inputs.start_address,
mb_devices[i].discrete_inputs.num_regs, tempBuff);
if (return_val == -1)
{
sprintf(log_msg, "Modbus Read Discrete Input Registers failed on MB device %s: %s\n", mb_devices[i].dev_name, modbus_strerror(errno));
log(log_msg);
modbus_close(mb_devices[i].mb_ctx);
bool_input_index += (mb_devices[i].discrete_inputs.num_regs);
mb_devices[i].isConnected = false;
}
else
{
pthread_mutex_lock(&ioLock);
for (int j = 0; j < return_val; j++)
{
bool_input_buf[bool_input_index] = tempBuff[j];
bool_input_index++;
}
pthread_mutex_unlock(&ioLock);
}
free(tempBuff);
}
//Write coils
if (mb_devices[i].coils.num_regs != 0)
{
uint8_t *tempBuff;
tempBuff = (uint8_t *)malloc(mb_devices[i].coils.num_regs);
pthread_mutex_lock(&ioLock);
for (int j = 0; j < mb_devices[i].coils.num_regs; j++)
{
tempBuff[j] = bool_output_buf[bool_output_index];
bool_output_index++;
}
pthread_mutex_unlock(&ioLock);
int return_val = modbus_write_bits(mb_devices[i].mb_ctx, mb_devices[i].coils.start_address, mb_devices[i].coils.num_regs, tempBuff);
if (return_val == -1)
{
modbus_close(mb_devices[i].mb_ctx);
mb_devices[i].isConnected = false;
}
free(tempBuff);
}
//Read input registers
if (mb_devices[i].input_registers.num_regs != 0)
{
uint16_t *tempBuff;
tempBuff = (uint16_t *)malloc(2*mb_devices[i].input_registers.num_regs);
int return_val = modbus_read_input_registers( mb_devices[i].mb_ctx, mb_devices[i].input_registers.start_address,
mb_devices[i].input_registers.num_regs, tempBuff);
if (return_val == -1)
{
sprintf(log_msg, "Modbus Read Discrete Input Registers failed on MB device %s: %s\n", mb_devices[i].dev_name, modbus_strerror(errno));
log(log_msg);
modbus_close(mb_devices[i].mb_ctx);
bool_input_index += (mb_devices[i].discrete_inputs.num_regs);
mb_devices[i].isConnected = false;
}
else
{
pthread_mutex_lock(&ioLock);
for (int j = 0; j < return_val; j++)
{
int_input_buf[int_input_index] = tempBuff[j];
int_input_index++;
}
pthread_mutex_unlock(&ioLock);
}
free(tempBuff);
}
//Write holding registers
if (mb_devices[i].holding_registers.num_regs != 0)
{
uint16_t *tempBuff;
tempBuff = (uint16_t *)malloc(2*mb_devices[i].holding_registers.num_regs);
pthread_mutex_lock(&ioLock);
for (int j = 0; j < mb_devices[i].holding_registers.num_regs; j++)
{
tempBuff[j] = int_output_buf[int_output_index];
int_output_index++;
}
pthread_mutex_unlock(&ioLock);
int return_val = modbus_write_registers(mb_devices[i].mb_ctx, mb_devices[i].holding_registers.start_address,
mb_devices[i].holding_registers.num_regs, tempBuff);
if (return_val == -1)
{
modbus_close(mb_devices[i].mb_ctx);
mb_devices[i].isConnected = false;
}
free(tempBuff);
}
}
}
}
//-----------------------------------------------------------------------------
// This function is called by the main OpenPLC routine when it is initializing.
// Modbus master initialization procedures are here.
//-----------------------------------------------------------------------------
void initializeMB()
{
parseConfig();
for (int i = 0; i < num_devices; i++)
{
if (mb_devices[i].protocol == MB_TCP)
{
mb_devices[i].mb_ctx = modbus_new_tcp(mb_devices[i].dev_address, mb_devices[i].ip_port);
}
else if (mb_devices[i].protocol == MB_RTU)
{
mb_devices[i].mb_ctx = modbus_new_rtu( mb_devices[i].dev_address, mb_devices[i].rtu_baud,
mb_devices[i].rtu_parity, mb_devices[i].rtu_data_bit,
mb_devices[i].rtu_stop_bit);
}
modbus_set_slave(mb_devices[i].mb_ctx, mb_devices[i].dev_id);
}
}
//-----------------------------------------------------------------------------
// This function is called by the OpenPLC in a loop. Here the internal buffers
// must be updated to reflect the actual Input state.
//-----------------------------------------------------------------------------
void updateBuffersIn_MB()
{
pthread_mutex_lock(&ioLock);
for (int i = 0; i < MAX_MB_IO; i++)
{
if (bool_input[100+(i/8)][i%8] != NULL) *bool_input[100+(i/8)][i%8] = bool_input_buf[i];
if (int_input[100+i] != NULL) *int_input[100+i] = int_input_buf[i];
}
pthread_mutex_unlock(&ioLock);
}
//-----------------------------------------------------------------------------
// This function is called by the OpenPLC in a loop. Here the internal buffers
// must be updated to reflect the actual Output state.
//-----------------------------------------------------------------------------
void updateBuffersOut_MB()
{
pthread_mutex_lock(&ioLock);
for (int i = 0; i < MAX_MB_IO; i++)
{
if (bool_output[i/8][i%8] != NULL) bool_output_buf[i] = *bool_output[i/8][i%8];
if (int_output[i] != NULL) int_output_buf[i] = *int_output[i];
}
pthread_mutex_unlock(&ioLock);
}

BIN
webserver/openplc.db Executable file → Normal file

Binary file not shown.

View File

@ -1110,3 +1110,695 @@ hardware_tail = """</textarea>
</script>
</html>"""
add_slave_devices_tail = """
</select>
<label for='dev_baud'><b>Baud Rate</b></label>
<input type='text' id='dev_baud' name='device_baud' placeholder='19200'>
<label for='dev_parity'><b>Parity</b></label>
<select id='dev_parity' name='device_parity'>
<option value='None'>None</option>
<option value='Even'>Even</option>
<option value='Odd'>Odd</option>
</select>
<label for='dev_data'><b>Data Bits</b></label>
<input type='text' id='dev_data' name='device_data' placeholder='8'>
<label for='dev_stop'><b>Stop Bits</b></label>
<input type='text' id='dev_stop' name='device_stop' placeholder='1'>
</div>
</div>
<div style="float:right; width:45%; height:730px">
<p style='font-size:20px; margin-top:0px'><b>Discrete Inputs (%IX100.0)</b></p>
<label for='di_start'><b>Start Address:</b></label>
<input type='text' style='width: 20%' id='di_start' name='di_start' placeholder='0'>
<label for='di_size' style='padding-left:20px'><b>Size:</b></label>
<input type='text' style='width: 20%' id='di_size' name='di_size' placeholder='8'>
<p style='font-size:20px'><b>Coils (%QX100.0)</b></p>
<label for='do_start'><b>Start Address:</b></label>
<input type='text' style='width: 20%' id='do_start' name='do_start' placeholder='0'>
<label for='do_size' style='padding-left:20px'><b>Size:</b></label>
<input type='text' style='width: 20%' id='do_size' name='do_size' placeholder='8'>
<p style='font-size:20px'><b>Input Registers (%IW100)</b></p>
<label for='ai_start'><b>Start Address:</b></label>
<input type='text' style='width: 20%' id='ai_start' name='ai_start' placeholder='0'>
<label for='ai_size' style='padding-left:20px'><b>Size:</b></label>
<input type='text' style='width: 20%' id='ai_size' name='ai_size' placeholder='8'>
<p style='font-size:20px'><b>Holding Registers - Read (%IW100)</b></p>
<label for='aor_start'><b>Start Address:</b></label>
<input type='text' style='width: 20%' id='aor_start' name='aor_start' placeholder='0'>
<label for='aor_size' style='padding-left:20px'><b>Size:</b></label>
<input type='text' style='width: 20%' id='aor_size' name='aor_size' placeholder='8'>
<p style='font-size:20px'><b>Holding Registers - Write (%QW100)</b></p>
<label for='aow_start'><b>Start Address:</b></label>
<input type='text' style='width: 20%' id='aow_start' name='aow_start' placeholder='0'>
<label for='aow_size' style='padding-left:20px'><b>Size:</b></label>
<input type='text' style='width: 20%' id='aow_size' name='aow_size' placeholder='8'>
</div>
<br>
<center><input type="submit" class="button" style="font-weight:bold; width: 310px; height: 53px; margin: 0px 20px 0px 20px;" value='Save device'></center>
</form>
</div>
</div>
</div>
</body>"""
add_devices_script = """
<script type="text/javascript">
window.onload = function()
{
setupPageContent()
LoadValuesFromDB()
}
function turnElementOn(element)
{
element.readOnly = false
element.value = ""
element.style.backgroundColor = "white"
element.style.color = "black"
}
function turnElementOff(element)
{
element.readOnly = true
element.style.backgroundColor = "#F8F8F8"
element.style.color = "#9C9C9C"
}
function setupPageContent()
{
var dropmenu = document.getElementById('dev_protocol');
var tcpdiv = document.getElementById("tcp-stuff");
var rtudiv = document.getElementById("rtu-stuff");
var devport = document.getElementById("dev_port");
var devid = document.getElementById("dev_id");
var devbaud = document.getElementById("dev_baud");
var devparity = document.getElementById("dev_parity");
var devdata = document.getElementById("dev_data");
var devstop = document.getElementById("dev_stop");
var distart = document.getElementById("di_start");
var disize = document.getElementById("di_size");
var dostart = document.getElementById("do_start");
var dosize = document.getElementById("do_size");
var aistart = document.getElementById("ai_start");
var aisize = document.getElementById("ai_size");
var aorstart = document.getElementById("aor_start");
var aorsize = document.getElementById("aor_size");
var aowstart = document.getElementById("aow_start");
var aowsize = document.getElementById("aow_size");
if (dropmenu.options[dropmenu.selectedIndex].value=="TCP")
{
tcpdiv.style.display = "block"
rtudiv.style.display = "none"
turnElementOn(devport)
turnElementOn(devid)
turnElementOn(distart)
turnElementOn(disize)
turnElementOn(dostart)
turnElementOn(dosize)
turnElementOn(aistart)
turnElementOn(aisize)
turnElementOn(aorstart)
turnElementOn(aorsize)
turnElementOn(aowstart)
turnElementOn(aowsize)
}
else if (dropmenu.options[dropmenu.selectedIndex].value=="ESP32")
{
tcpdiv.style.display = "block"
rtudiv.style.display = "none"
turnElementOff(devport)
devport.value = "502"
turnElementOff(devid)
devid.value = "0"
turnElementOff(distart)
distart.value = "0"
turnElementOff(disize)
disize.value = "8"
turnElementOff(dostart)
dostart.value = "0"
turnElementOff(dosize)
dosize.value = "8"
turnElementOff(aistart)
aistart.value = "0"
turnElementOff(aisize)
aisize.value = "1"
turnElementOff(aorstart)
aorstart.value = "0"
turnElementOff(aorsize)
aorsize.value = "0"
turnElementOff(aowstart)
aowstart.value = "0"
turnElementOff(aowsize)
aowsize.value = "1"
}
else if (dropmenu.options[dropmenu.selectedIndex].value=="ESP8266")
{
tcpdiv.style.display = "block"
rtudiv.style.display = "none"
turnElementOff(devport)
devport.value = "502"
turnElementOff(devid)
devid.value = "0"
turnElementOff(distart)
distart.value = "0"
turnElementOff(disize)
disize.value = "8"
turnElementOff(dostart)
dostart.value = "0"
turnElementOff(dosize)
dosize.value = "8"
turnElementOff(aistart)
aistart.value = "0"
turnElementOff(aisize)
aisize.value = "1"
turnElementOff(aorstart)
aorstart.value = "0"
turnElementOff(aorsize)
aorsize.value = "0"
turnElementOff(aowstart)
aowstart.value = "0"
turnElementOff(aowsize)
aowsize.value = "1"
}
else if (dropmenu.options[dropmenu.selectedIndex].value=="RTU")
{
tcpdiv.style.display = "none"
rtudiv.style.display = "block"
turnElementOn(devid)
turnElementOn(devbaud)
turnElementOn(devparity)
devparity.value = "None"
turnElementOn(devdata)
turnElementOn(devstop)
turnElementOn(distart)
turnElementOn(disize)
turnElementOn(dostart)
turnElementOn(dosize)
turnElementOn(aistart)
turnElementOn(aisize)
turnElementOn(aorstart)
turnElementOn(aorsize)
turnElementOn(aowstart)
turnElementOn(aowsize)
}
else if (dropmenu.options[dropmenu.selectedIndex].value=="Uno")
{
tcpdiv.style.display = "none"
rtudiv.style.display = "block"
turnElementOff(devid)
devid.value = "0"
turnElementOff(devbaud)
devbaud.value = "115200"
turnElementOff(devparity)
devparity.value = "None"
turnElementOff(devdata)
devdata.value = "8"
turnElementOff(devstop)
devstop.value = "1"
turnElementOff(distart)
distart.value = "0"
turnElementOff(disize)
disize.value = "5"
turnElementOff(dostart)
dostart.value = "0"
turnElementOff(dosize)
dosize.value = "4"
turnElementOff(aistart)
aistart.value = "0"
turnElementOff(aisize)
aisize.value = "6"
turnElementOff(aorstart)
aorstart.value = "0"
turnElementOff(aorsize)
aorsize.value = "0"
turnElementOff(aowstart)
aowstart.value = "0"
turnElementOff(aowsize)
aowsize.value = "3"
}
else if (dropmenu.options[dropmenu.selectedIndex].value=="Mega")
{
tcpdiv.style.display = "none"
rtudiv.style.display = "block"
turnElementOff(devid)
devid.value = "0"
turnElementOff(devbaud)
devbaud.value = "115200"
turnElementOff(devparity)
devparity.value = "None"
turnElementOff(devdata)
devdata.value = "8"
turnElementOff(devstop)
devstop.value = "1"
turnElementOff(distart)
distart.value = "0"
turnElementOff(disize)
disize.value = "24"
turnElementOff(dostart)
dostart.value = "0"
turnElementOff(dosize)
dosize.value = "16"
turnElementOff(aistart)
aistart.value = "0"
turnElementOff(aisize)
aisize.value = "16"
turnElementOff(aorstart)
aorstart.value = "0"
turnElementOff(aorsize)
aorsize.value = "0"
turnElementOff(aowstart)
aowstart.value = "0"
turnElementOff(aowsize)
aowsize.value = "12"
}
}
document.getElementById('dev_protocol').onchange = function()
{
first_time_edit = false;
setupPageContent()
}
function validateForm()
{
var devname = document.forms["uploadForm"]["dev_name"].value;
var devid = document.forms["uploadForm"]["dev_id"].value;
var devip = document.forms["uploadForm"]["dev_ip"].value;
var devport = document.forms["uploadForm"]["dev_port"].value;
var devbaud = document.forms["uploadForm"]["dev_baud"].value;
var devdata = document.forms["uploadForm"]["dev_data"].value;
var devstop = document.forms["uploadForm"]["dev_stop"].value;
var distart = document.forms["uploadForm"]["di_start"].value;
var disize = document.forms["uploadForm"]["di_size"].value;
var dostart = document.forms["uploadForm"]["do_start"].value;
var dosize = document.forms["uploadForm"]["do_size"].value;
var aistart = document.forms["uploadForm"]["ai_start"].value;
var aisize = document.forms["uploadForm"]["ai_size"].value;
var aorstart = document.forms["uploadForm"]["aor_start"].value;
var aorsize = document.forms["uploadForm"]["aor_size"].value;
var aowstart = document.forms["uploadForm"]["aow_start"].value;
var aowsize = document.forms["uploadForm"]["aow_size"].value;
if (devname == "" || devid == "" || distart == "" || disize == "" || dostart == "" || dosize == "" || aistart == "" || aisize == "" || aorstart == "" || aorsize == "" || aowstart == "" || aowsize == "")
{
alert("Please fill out all the fields before saving!");
return false;
}
var dropmenu = document.getElementById('dev_protocol');
var device_type = dropmenu.options[dropmenu.selectedIndex].value
if (device_type=="TCP" || device_type=="ESP32" || device_type=="ESP8266")
{
if (devip == "" || devport == "")
{
alert("Please fill out all the fields before saving!");
return false;
}
}
else
{
if (devbaud == "" || devdata == "" || devstop == "")
{
alert("Please fill out all the fields before saving!");
return false;
}
}
return true;
}
</script>
</html>"""
edit_slave_devices_tail = """
</select>
<label for='dev_baud'><b>Baud Rate</b></label>
<input type='text' id='dev_baud' name='device_baud' placeholder='19200'>
<label for='dev_parity'><b>Parity</b></label>
<select id='dev_parity' name='device_parity'>
<option value='None'>None</option>
<option value='Even'>Even</option>
<option value='Odd'>Odd</option>
</select>
<label for='dev_data'><b>Data Bits</b></label>
<input type='text' id='dev_data' name='device_data' placeholder='8'>
<label for='dev_stop'><b>Stop Bits</b></label>
<input type='text' id='dev_stop' name='device_stop' placeholder='1'>
</div>
</div>
<div style="float:right; width:45%; height:730px">
<p style='font-size:20px; margin-top:0px'><b>Discrete Inputs (%IX100.0)</b></p>
<label for='di_start'><b>Start Address:</b></label>
<input type='text' style='width: 20%' id='di_start' name='di_start' placeholder='0'>
<label for='di_size' style='padding-left:20px'><b>Size:</b></label>
<input type='text' style='width: 20%' id='di_size' name='di_size' placeholder='8'>
<p style='font-size:20px'><b>Coils (%QX100.0)</b></p>
<label for='do_start'><b>Start Address:</b></label>
<input type='text' style='width: 20%' id='do_start' name='do_start' placeholder='0'>
<label for='do_size' style='padding-left:20px'><b>Size:</b></label>
<input type='text' style='width: 20%' id='do_size' name='do_size' placeholder='8'>
<p style='font-size:20px'><b>Input Registers (%IW100)</b></p>
<label for='ai_start'><b>Start Address:</b></label>
<input type='text' style='width: 20%' id='ai_start' name='ai_start' placeholder='0'>
<label for='ai_size' style='padding-left:20px'><b>Size:</b></label>
<input type='text' style='width: 20%' id='ai_size' name='ai_size' placeholder='8'>
<p style='font-size:20px'><b>Holding Registers - Read (%IW100)</b></p>
<label for='aor_start'><b>Start Address:</b></label>
<input type='text' style='width: 20%' id='aor_start' name='aor_start' placeholder='0'>
<label for='aor_size' style='padding-left:20px'><b>Size:</b></label>
<input type='text' style='width: 20%' id='aor_size' name='aor_size' placeholder='8'>
<p style='font-size:20px'><b>Holding Registers - Write (%QW100)</b></p>
<label for='aow_start'><b>Start Address:</b></label>
<input type='text' style='width: 20%' id='aow_start' name='aow_start' placeholder='0'>
<label for='aow_size' style='padding-left:20px'><b>Size:</b></label>
<input type='text' style='width: 20%' id='aow_size' name='aow_size' placeholder='8'>
</div>
<br>
<center><input type="submit" class="button" style="font-weight:bold; width: 310px; height: 53px; margin: 0px 20px 0px 20px;" value='Save device'><a href='delete-device?dev_id="""
edit_devices_script = """
<script type="text/javascript">
window.onload = function()
{
setupPageContent()
LoadValuesFromDB()
}
function turnElementOn(element)
{
element.readOnly = false
element.value = ""
element.style.backgroundColor = "white"
element.style.color = "black"
}
function turnElementOff(element)
{
element.readOnly = true
element.style.backgroundColor = "#F8F8F8"
element.style.color = "#9C9C9C"
}
function setupPageContent()
{
var dropmenu = document.getElementById('dev_protocol');
var tcpdiv = document.getElementById("tcp-stuff");
var rtudiv = document.getElementById("rtu-stuff");
var devport = document.getElementById("dev_port");
var devid = document.getElementById("dev_id");
var devbaud = document.getElementById("dev_baud");
var devparity = document.getElementById("dev_parity");
var devdata = document.getElementById("dev_data");
var devstop = document.getElementById("dev_stop");
var distart = document.getElementById("di_start");
var disize = document.getElementById("di_size");
var dostart = document.getElementById("do_start");
var dosize = document.getElementById("do_size");
var aistart = document.getElementById("ai_start");
var aisize = document.getElementById("ai_size");
var aorstart = document.getElementById("aor_start");
var aorsize = document.getElementById("aor_size");
var aowstart = document.getElementById("aow_start");
var aowsize = document.getElementById("aow_size");
if (dropmenu.options[dropmenu.selectedIndex].value=="TCP")
{
tcpdiv.style.display = "block"
rtudiv.style.display = "none"
turnElementOn(devport)
turnElementOn(devid)
turnElementOn(distart)
turnElementOn(disize)
turnElementOn(dostart)
turnElementOn(dosize)
turnElementOn(aistart)
turnElementOn(aisize)
turnElementOn(aorstart)
turnElementOn(aorsize)
turnElementOn(aowstart)
turnElementOn(aowsize)
}
else if (dropmenu.options[dropmenu.selectedIndex].value=="ESP32")
{
tcpdiv.style.display = "block"
rtudiv.style.display = "none"
turnElementOff(devport)
devport.value = "502"
turnElementOff(devid)
devid.value = "0"
turnElementOff(distart)
distart.value = "0"
turnElementOff(disize)
disize.value = "8"
turnElementOff(dostart)
dostart.value = "0"
turnElementOff(dosize)
dosize.value = "8"
turnElementOff(aistart)
aistart.value = "0"
turnElementOff(aisize)
aisize.value = "1"
turnElementOff(aorstart)
aorstart.value = "0"
turnElementOff(aorsize)
aorsize.value = "0"
turnElementOff(aowstart)
aowstart.value = "0"
turnElementOff(aowsize)
aowsize.value = "1"
}
else if (dropmenu.options[dropmenu.selectedIndex].value=="ESP8266")
{
tcpdiv.style.display = "block"
rtudiv.style.display = "none"
turnElementOff(devport)
devport.value = "502"
turnElementOff(devid)
devid.value = "0"
turnElementOff(distart)
distart.value = "0"
turnElementOff(disize)
disize.value = "8"
turnElementOff(dostart)
dostart.value = "0"
turnElementOff(dosize)
dosize.value = "8"
turnElementOff(aistart)
aistart.value = "0"
turnElementOff(aisize)
aisize.value = "1"
turnElementOff(aorstart)
aorstart.value = "0"
turnElementOff(aorsize)
aorsize.value = "0"
turnElementOff(aowstart)
aowstart.value = "0"
turnElementOff(aowsize)
aowsize.value = "1"
}
else if (dropmenu.options[dropmenu.selectedIndex].value=="RTU")
{
tcpdiv.style.display = "none"
rtudiv.style.display = "block"
turnElementOn(devid)
turnElementOn(devbaud)
turnElementOn(devparity)
devparity.value = "None"
turnElementOn(devdata)
turnElementOn(devstop)
turnElementOn(distart)
turnElementOn(disize)
turnElementOn(dostart)
turnElementOn(dosize)
turnElementOn(aistart)
turnElementOn(aisize)
turnElementOn(aorstart)
turnElementOn(aorsize)
turnElementOn(aowstart)
turnElementOn(aowsize)
}
else if (dropmenu.options[dropmenu.selectedIndex].value=="Uno")
{
tcpdiv.style.display = "none"
rtudiv.style.display = "block"
turnElementOff(devid)
devid.value = "0"
turnElementOff(devbaud)
devbaud.value = "115200"
turnElementOff(devparity)
devparity.value = "None"
turnElementOff(devdata)
devdata.value = "8"
turnElementOff(devstop)
devstop.value = "1"
turnElementOff(distart)
distart.value = "0"
turnElementOff(disize)
disize.value = "5"
turnElementOff(dostart)
dostart.value = "0"
turnElementOff(dosize)
dosize.value = "4"
turnElementOff(aistart)
aistart.value = "0"
turnElementOff(aisize)
aisize.value = "6"
turnElementOff(aorstart)
aorstart.value = "0"
turnElementOff(aorsize)
aorsize.value = "0"
turnElementOff(aowstart)
aowstart.value = "0"
turnElementOff(aowsize)
aowsize.value = "3"
}
else if (dropmenu.options[dropmenu.selectedIndex].value=="Mega")
{
tcpdiv.style.display = "none"
rtudiv.style.display = "block"
turnElementOff(devid)
devid.value = "0"
turnElementOff(devbaud)
devbaud.value = "115200"
turnElementOff(devparity)
devparity.value = "None"
turnElementOff(devdata)
devdata.value = "8"
turnElementOff(devstop)
devstop.value = "1"
turnElementOff(distart)
distart.value = "0"
turnElementOff(disize)
disize.value = "24"
turnElementOff(dostart)
dostart.value = "0"
turnElementOff(dosize)
dosize.value = "16"
turnElementOff(aistart)
aistart.value = "0"
turnElementOff(aisize)
aisize.value = "16"
turnElementOff(aorstart)
aorstart.value = "0"
turnElementOff(aorsize)
aorsize.value = "0"
turnElementOff(aowstart)
aowstart.value = "0"
turnElementOff(aowsize)
aowsize.value = "12"
}
}
document.getElementById('dev_protocol').onchange = function()
{
setupPageContent()
}
function validateForm()
{
var devname = document.forms["uploadForm"]["dev_name"].value;
var devid = document.forms["uploadForm"]["dev_id"].value;
var devip = document.forms["uploadForm"]["dev_ip"].value;
var devport = document.forms["uploadForm"]["dev_port"].value;
var devcport = document.forms["uploadForm"]["dev_cport"].value;
var devbaud = document.forms["uploadForm"]["dev_baud"].value;
var devdata = document.forms["uploadForm"]["dev_data"].value;
var devstop = document.forms["uploadForm"]["dev_stop"].value;
var distart = document.forms["uploadForm"]["di_start"].value;
var disize = document.forms["uploadForm"]["di_size"].value;
var dostart = document.forms["uploadForm"]["do_start"].value;
var dosize = document.forms["uploadForm"]["do_size"].value;
var aistart = document.forms["uploadForm"]["ai_start"].value;
var aisize = document.forms["uploadForm"]["ai_size"].value;
var aorstart = document.forms["uploadForm"]["aor_start"].value;
var aorsize = document.forms["uploadForm"]["aor_size"].value;
var aowstart = document.forms["uploadForm"]["aow_start"].value;
var aowsize = document.forms["uploadForm"]["aow_size"].value;
if (devname == "" || devid == "" || distart == "" || disize == "" || dostart == "" || dosize == "" || aistart == "" || aisize == "" || aorstart == "" || aorsize == "" || aowstart == "" || aowsize == "")
{
alert("Please fill out all the fields before saving!");
return false;
}
var dropmenu = document.getElementById('dev_protocol');
var device_type = dropmenu.options[dropmenu.selectedIndex].value
if (device_type=="TCP" || device_type=="ESP32" || device_type=="ESP8266")
{
if (devip == "" || devport == "")
{
alert("Please fill out all the fields before saving!");
return false;
}
}
else
{
if (devcport == "" || devbaud == "" || devdata == "" || devstop == "")
{
alert("Please fill out all the fields before saving!");
return false;
}
}
return true;
}
function LoadValuesFromDB()
{
var devid = document.getElementById("dev_id");
var devip = document.getElementById("dev_ip");
var devport = document.getElementById("dev_port");
var devcport = document.getElementById("dev_cport");
var devbaud = document.getElementById("dev_baud");
var devparity = document.getElementById("dev_parity");
var devdata = document.getElementById("dev_data");
var devstop = document.getElementById("dev_stop");
var distart = document.getElementById("di_start");
var disize = document.getElementById("di_size");
var dostart = document.getElementById("do_start");
var dosize = document.getElementById("do_size");
var aistart = document.getElementById("ai_start");
var aisize = document.getElementById("ai_size");
var aorstart = document.getElementById("aor_start");
var aorsize = document.getElementById("aor_size");
var aowstart = document.getElementById("aow_start");
var aowsize = document.getElementById("aow_size");"""

View File

@ -51,7 +51,7 @@ if [ "$OPENPLC_PLATFORM" = "win" ]; then
echo "Generating glueVars..."
./glue_generator
echo "Compiling main program..."
g++ *.cpp *.o -o openplc -I ./lib -pthread -fpermissive -w
g++ *.cpp *.o -o openplc -I ./lib -pthread -fpermissive -I /usr/local/include/modbus -L /usr/local/lib -lmodbus -w
if [ $? -ne 0 ]; then
echo "Error compiling C files"
echo "Compilation finished with errors!"
@ -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 -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
if [ $? -ne 0 ]; then
echo "Error compiling C files"
echo "Compilation finished with errors!"
@ -105,7 +105,7 @@ elif [ "$OPENPLC_PLATFORM" = "rpi" ]; then
echo "Generating glueVars..."
./glue_generator
echo "Compiling main program..."
g++ -std=gnu++11 *.cpp *.o -o openplc -I ./lib -lrt -lwiringPi -lpthread -fpermissive -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w
g++ -std=gnu++11 *.cpp *.o -o openplc -I ./lib -lrt -lwiringPi -lpthread -fpermissive `pkg-config --cflags --libs libmodbus` -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w
if [ $? -ne 0 ]; then
echo "Error compiling C files"
echo "Compilation finished with errors!"

View File

@ -2,6 +2,8 @@ import sqlite3
from sqlite3 import Error
import os
import subprocess
import platform
import serial.tools.list_ports
import random
import datetime
import time
@ -55,6 +57,72 @@ def configure_runtime():
else:
print("Error opening DB")
def generate_mbconfig():
database = "openplc.db"
conn = create_connection(database)
if (conn != None):
try:
cur = conn.cursor()
cur.execute("SELECT COUNT(*) FROM Slave_dev")
row = cur.fetchone()
num_devices = int(row[0])
mbconfig = 'Num_Devices = "' + str(num_devices) + '"'
cur = conn.cursor()
cur.execute("SELECT * FROM Slave_dev")
rows = cur.fetchall()
cur.close()
conn.close()
device_counter = 0
for row in rows:
mbconfig += """
# ------------
# DEVICE """
mbconfig += str(device_counter)
mbconfig += """
# ------------
"""
mbconfig += 'device' + str(device_counter) + '.name = "' + str(row[1]) + '"\n'
mbconfig += 'device' + str(device_counter) + '.slave_id = "' + str(row[3]) + '"\n'
if (str(row[2]) == 'ESP32' or str(row[2]) == 'ESP8266' or str(row[2]) == 'TCP'):
mbconfig += 'device' + str(device_counter) + '.protocol = "TCP"\n'
mbconfig += 'device' + str(device_counter) + '.address = "' + str(row[9]) + '"\n'
else:
mbconfig += 'device' + str(device_counter) + '.protocol = "RTU"\n'
if (str(row[4]).startswith("COM")):
port_name = "/dev/ttyS" + str(int(str(row[4]).split("COM")[1]) - 1)
else:
port_name = str(row[4])
mbconfig += 'device' + str(device_counter) + '.address = "' + port_name + '"\n'
mbconfig += 'device' + str(device_counter) + '.IP_Port = "' + str(row[10]) + '"\n'
mbconfig += 'device' + str(device_counter) + '.RTU_Baud_Rate = "' + str(row[5]) + '"\n'
mbconfig += 'device' + str(device_counter) + '.RTU_Parity = "' + str(row[6]) + '"\n'
mbconfig += 'device' + str(device_counter) + '.RTU_Data_Bits = "' + str(row[7]) + '"\n'
mbconfig += 'device' + str(device_counter) + '.RTU_Stop_Bits = "' + str(row[8]) + '"\n\n'
mbconfig += 'device' + str(device_counter) + '.Discrete_Inputs_Start = "' + str(row[11]) + '"\n'
mbconfig += 'device' + str(device_counter) + '.Discrete_Inputs_Size = "' + str(row[12]) + '"\n'
mbconfig += 'device' + str(device_counter) + '.Coils_Start = "' + str(row[13]) + '"\n'
mbconfig += 'device' + str(device_counter) + '.Coils_Size = "' + str(row[14]) + '"\n'
mbconfig += 'device' + str(device_counter) + '.Input_Registers_Start = "' + str(row[15]) + '"\n'
mbconfig += 'device' + str(device_counter) + '.Input_Registers_Size = "' + str(row[16]) + '"\n'
mbconfig += 'device' + str(device_counter) + '.Holding_Registers_Read_Start = "' + str(row[17]) + '"\n'
mbconfig += 'device' + str(device_counter) + '.Holding_Registers_Read_Size = "' + str(row[18]) + '"\n'
mbconfig += 'device' + str(device_counter) + '.Holding_Registers_Start = "' + str(row[19]) + '"\n'
mbconfig += 'device' + str(device_counter) + '.Holding_Registers_Size = "' + str(row[20]) + '"\n'
device_counter += 1
with open('./mbconfig.cfg', 'w+') as f: f.write(mbconfig)
except Error as e:
print("error connecting to the database" + str(e))
else:
print("Error opening DB")
def draw_top_div():
global openplc_runtime
top_div = ("<div class='top'>"
@ -751,6 +819,441 @@ def compilation_logs():
return openplc_runtime.compilation_status()
@app.route('/modbus', methods=['GET', 'POST'])
def modbus():
if (flask_login.current_user.is_authenticated == False):
return flask.redirect(flask.url_for('login'))
else:
if (openplc_runtime.status() == "Compiling"): return draw_compiling_page()
return_str = pages.w3_style + pages.style + draw_top_div()
return_str += """
<div class='main'>
<div class='w3-sidebar w3-bar-block' style='width:250px; background-color:#3D3D3D'>
<br>
<br>
<a href="dashboard" class="w3-bar-item w3-button"><img src="/static/home-icon-64x64.png" alt="Dashboard" style="width:47px;height:32px;padding:0px 15px 0px 0px;float:left"><p style='font-family:"Roboto", sans-serif; font-size:20px; color:white;margin: 2px 0px 0px 0px'>Dashboard</p></a>
<a href="programs" class="w3-bar-item w3-button"><img src="/static/programs-icon-64x64.png" alt="Programs" style="width:47px;height:32px;padding:0px 15px 0px 0px;float:left"><p style='font-family:"Roboto", sans-serif; font-size:20px; color:white;margin: 2px 0px 0px 0px'>Programs</p></a>
<a href="modbus" class="w3-bar-item w3-button" style="background-color:#E02222; padding-right:0px;padding-top:0px;padding-bottom:0px"><img src="/static/modbus-icon-512x512.png" alt="Modbus" style="width:47px;height:39px;padding:7px 15px 0px 0px;float:left"><img src="/static/arrow.png" style="width:17px;height:49px;padding:0px 0px 0px 0px;margin: 0px 0px 0px 0px; float:right"><p style='font-family:"Roboto", sans-serif; font-size:20px; color:white;margin: 10px 0px 0px 0px'>Slave Devices</p></a>
<a href='monitoring' class='w3-bar-item w3-button'><img src='/static/monitoring-icon-64x64.png' alt='Monitoring' style='width:47px;height:32px;padding:0px 15px 0px 0px;float:left'><p style='font-family:\"Roboto\", sans-serif; font-size:20px; color:white;margin: 2px 0px 0px 0px'>Monitoring</p></a>
<a href='hardware' class='w3-bar-item w3-button'><img src='/static/hardware-icon-980x974.png' alt='Hardware' style='width:47px;height:32px;padding:0px 15px 0px 0px;float:left'><p style='font-family:\"Roboto\", sans-serif; font-size:20px; color:white;margin: 2px 0px 0px 0px'>Hardware</p></a>
<a href='users' class='w3-bar-item w3-button'><img src='/static/users-icon-64x64.png' alt='Users' style='width:47px;height:32px;padding:0px 15px 0px 0px;float:left'><p style='font-family:\"Roboto\", sans-serif; font-size:20px; color:white;margin: 2px 0px 0px 0px'>Users</p></a>
<a href='settings' class='w3-bar-item w3-button'><img src='/static/settings-icon-64x64.png' alt='Settings' style='width:47px;height:32px;padding:0px 15px 0px 0px;float:left'><p style='font-family:\"Roboto\", sans-serif; font-size:20px; color:white;margin: 2px 0px 0px 0px'>Settings</p></a>
<a href='logout' class='w3-bar-item w3-button'><img src='/static/logout-icon-64x64.png' alt='Logout' style='width:47px;height:32px;padding:0px 15px 0px 0px;float:left'><p style='font-family:\"Roboto\", sans-serif; font-size:20px; color:white;margin: 2px 0px 0px 0px'>Logout</p></a>
<br>
<br>"""
return_str += draw_status()
return_str += """
</div>
<div style="margin-left:320px; margin-right:70px">
<div style="w3-container">
<br>
<h2>Slave Devices</h2>
<p>List of Slave devices attached to OpenPLC.</p>
<p><b>Attention:</b> Slave devices are attached to address 100 onward (i.e. %IX100.0, %IW100, %QX100.0, and %QW100)
<table>
<tr style='background-color: white'>
<th>Device Name</th><th>Device Type</th><th>DI</th><th>DO</th><th>AI</th><th>AO</th>
</tr>"""
database = "openplc.db"
conn = create_connection(database)
if (conn != None):
try:
cur = conn.cursor()
cur.execute("SELECT dev_id, dev_name, dev_type, di_size, coil_size, ir_size, hr_read_size, hr_write_size FROM Slave_dev")
rows = cur.fetchall()
cur.close()
conn.close()
counter_di = 0
counter_do = 0
counter_ai = 0
counter_ao = 0
for row in rows:
return_str += "<tr onclick=\"document.location='modbus-edit-device?table_id=" + str(row[0]) + "'\">"
#calculate di
if (row[3] == 0):
di = "-"
else:
di = "%IX" + str(100 + (counter_di/8)) + "." + str(counter_di%8) + " to "
counter_di += row[3];
di += "%IX" + str(100 + ((counter_di-1)/8)) + "." + str((counter_di-1)%8)
#calculate do
if (row[4] == 0):
do = "-"
else:
do = "%QX" + str(100 + (counter_do/8)) + "." + str(counter_do%8) + " to "
counter_do += row[4];
do += "%QX" + str(100 + ((counter_do-1)/8)) + "." + str((counter_do-1)%8)
#calculate ai
if (row[5] + row[6] == 0):
ai = "-"
else:
ai = "%IW" + str(100 + counter_ai) + " to "
counter_ai += row[5]+row[6];
ai += "%IW" + str(100 + (counter_ai-1))
#calculate ao
if (row[7] == 0):
ao = "-"
else:
ao = "%QW" + str(100 + counter_ao) + " to "
counter_ao += row[7];
ao += "%QW" + str(100 + (counter_ao-1))
return_str += "<td>" + str(row[1]) + "</td><td>" + str(row[2]) + "</td><td>" + di + "</td><td>" + do + "</td><td>" + ai + "</td><td>" + ao + "</td></tr>"
return_str += """
</table>
<br>
<center><a href="add-modbus-device" class="button" style="width: 310px; height: 53px; margin: 0px 20px 0px 20px;"><b>Add new device</b></a></center>
</div>
</div>
</div>
</body>
</html>"""
except Error as e:
print("error connecting to the database" + str(e))
return_str += 'Error connecting to the database. Make sure that your openplc.db file is not corrupt.<br><br>Error: ' + str(e)
else:
return_str += 'Error connecting to the database. Make sure that your openplc.db file is not corrupt.'
return return_str
@app.route('/add-modbus-device', methods=['GET', 'POST'])
def add_modbus_device():
if (flask_login.current_user.is_authenticated == False):
return flask.redirect(flask.url_for('login'))
else:
if (openplc_runtime.status() == "Compiling"): return draw_compiling_page()
if (flask.request.method == 'GET'):
return_str = pages.w3_style + pages.style + draw_top_div()
return_str += """
<div class='main'>
<div class='w3-sidebar w3-bar-block' style='width:250px; background-color:#3D3D3D'>
<br>
<br>
<a href="dashboard" class="w3-bar-item w3-button"><img src="/static/home-icon-64x64.png" alt="Dashboard" style="width:47px;height:32px;padding:0px 15px 0px 0px;float:left"><p style='font-family:"Roboto", sans-serif; font-size:20px; color:white;margin: 2px 0px 0px 0px'>Dashboard</p></a>
<a href="programs" class="w3-bar-item w3-button"><img src="/static/programs-icon-64x64.png" alt="Programs" style="width:47px;height:32px;padding:0px 15px 0px 0px;float:left"><p style='font-family:"Roboto", sans-serif; font-size:20px; color:white;margin: 2px 0px 0px 0px'>Programs</p></a>
<a href="modbus" class="w3-bar-item w3-button" style="background-color:#E02222; padding-right:0px;padding-top:0px;padding-bottom:0px"><img src="/static/modbus-icon-512x512.png" alt="Modbus" style="width:47px;height:39px;padding:7px 15px 0px 0px;float:left"><img src="/static/arrow.png" style="width:17px;height:49px;padding:0px 0px 0px 0px;margin: 0px 0px 0px 0px; float:right"><p style='font-family:"Roboto", sans-serif; font-size:20px; color:white;margin: 10px 0px 0px 0px'>Slave Devices</p></a>
<a href='monitoring' class='w3-bar-item w3-button'><img src='/static/monitoring-icon-64x64.png' alt='Monitoring' style='width:47px;height:32px;padding:0px 15px 0px 0px;float:left'><p style='font-family:\"Roboto\", sans-serif; font-size:20px; color:white;margin: 2px 0px 0px 0px'>Monitoring</p></a>
<a href='hardware' class='w3-bar-item w3-button'><img src='/static/hardware-icon-980x974.png' alt='Hardware' style='width:47px;height:32px;padding:0px 15px 0px 0px;float:left'><p style='font-family:\"Roboto\", sans-serif; font-size:20px; color:white;margin: 2px 0px 0px 0px'>Hardware</p></a>
<a href='users' class='w3-bar-item w3-button'><img src='/static/users-icon-64x64.png' alt='Users' style='width:47px;height:32px;padding:0px 15px 0px 0px;float:left'><p style='font-family:\"Roboto\", sans-serif; font-size:20px; color:white;margin: 2px 0px 0px 0px'>Users</p></a>
<a href='settings' class='w3-bar-item w3-button'><img src='/static/settings-icon-64x64.png' alt='Settings' style='width:47px;height:32px;padding:0px 15px 0px 0px;float:left'><p style='font-family:\"Roboto\", sans-serif; font-size:20px; color:white;margin: 2px 0px 0px 0px'>Settings</p></a>
<a href='logout' class='w3-bar-item w3-button'><img src='/static/logout-icon-64x64.png' alt='Logout' style='width:47px;height:32px;padding:0px 15px 0px 0px;float:left'><p style='font-family:\"Roboto\", sans-serif; font-size:20px; color:white;margin: 2px 0px 0px 0px'>Logout</p></a>
<br>
<br>"""
return_str += draw_status()
return_str += """
</div>
<div style="margin-left:320px; margin-right:70px">
<div style="w3-container">
<br>
<h2>Add new device</h2>
<br>
<div style="float:left; width:45%; height:730px">
<form id = "uploadForm"
enctype = "multipart/form-data"
action = "add-modbus-device"
method = "post"
onsubmit = "return validateForm()">
<label for='dev_name'><b>Device Name</b></label>
<input type='text' id='dev_name' name='device_name' placeholder='My Device'>
<label for='dev_protocol'><b>Device Type</b></label>
<select id='dev_protocol' name='device_protocol'>
<option selected='selected' value='Uno'>Arduino Uno</option>
<option value='Mega'>Arduino Mega</option>
<option value='ESP32'>ESP32</option>
<option value='ESP8266'>ESP8266</option>
<option value='TCP'>Generic Modbus TCP Device</option>
<option value='RTU'>Generic Modbus RTU Device</option>
</select>
<label for='dev_id'><b>Slave ID</b></label>
<input type='text' id='dev_id' name='device_id' placeholder='0'>
<div id="tcp-stuff" style="display: none">
<label for='dev_ip'><b>IP Address</b></label>
<input type='text' id='dev_ip' name='device_ip' placeholder='192.168.0.1'>
<label for='dev_port'><b>IP Port</b></label>
<input type='text' id='dev_port' name='device_port' placeholder='502'>
</div>
<div id="rtu-stuff">
<label for='dev_cport'><b>COM Port</b></label>
<select id='dev_cport' name='device_cport'>"""
ports = [comport.device for comport in serial.tools.list_ports.comports()]
for port in ports:
if (platform.system().startswith("CYGWIN")):
port_name = "COM" + str(int(port.split("/dev/ttyS")[1]) + 1)
else:
port_name = port
return_str += "<option value='" + port_name + "'>" + port_name + "</option>"
return_str += pages.add_slave_devices_tail + pages.add_devices_script
return return_str
elif (flask.request.method == 'POST'):
devname = flask.request.form['device_name']
devtype = flask.request.form['device_protocol']
devid = flask.request.form['device_id']
devip = flask.request.form['device_ip']
devport = flask.request.form['device_port']
devcport = flask.request.form['device_cport']
devbaud = flask.request.form['device_baud']
devparity = flask.request.form['device_parity']
devdata = flask.request.form['device_data']
devstop = flask.request.form['device_stop']
di_start = flask.request.form['di_start']
di_size = flask.request.form['di_size']
do_start = flask.request.form['do_start']
do_size = flask.request.form['do_size']
ai_start = flask.request.form['ai_start']
ai_size = flask.request.form['ai_size']
aor_start = flask.request.form['aor_start']
aor_size = flask.request.form['aor_size']
aow_start = flask.request.form['aow_start']
aow_size = flask.request.form['aow_size']
database = "openplc.db"
conn = create_connection(database)
if (conn != None):
try:
cur = conn.cursor()
cur.execute("INSERT INTO Slave_dev (dev_name, dev_type, slave_id, com_port, baud_rate, parity, data_bits, stop_bits, ip_address, ip_port, di_start, di_size, coil_start, coil_size, ir_start, ir_size, hr_read_start, hr_read_size, hr_write_start, hr_write_size) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", (devname, devtype, devid, devcport, devbaud, devparity, devdata, devstop, devip, devport, di_start, di_size, do_start, do_size, ai_start, ai_size, aor_start, aor_size, aow_start, aow_size))
conn.commit()
cur.close()
conn.close()
generate_mbconfig()
return flask.redirect(flask.url_for('modbus'))
except Error as e:
print("error connecting to the database" + str(e))
return 'Error connecting to the database. Make sure that your openplc.db file is not corrupt.<br><br>Error: ' + str(e)
else:
return 'Error connecting to the database. Make sure that your openplc.db file is not corrupt.'
@app.route('/modbus-edit-device', methods=['GET', 'POST'])
def modbus_edit_device():
if (flask_login.current_user.is_authenticated == False):
return flask.redirect(flask.url_for('login'))
else:
if (openplc_runtime.status() == "Compiling"): return draw_compiling_page()
if (flask.request.method == 'GET'):
dev_id = flask.request.args.get('table_id')
return_str = pages.w3_style + pages.style + draw_top_div()
return_str += """
<div class='main'>
<div class='w3-sidebar w3-bar-block' style='width:250px; background-color:#3D3D3D'>
<br>
<br>
<a href="dashboard" class="w3-bar-item w3-button"><img src="/static/home-icon-64x64.png" alt="Dashboard" style="width:47px;height:32px;padding:0px 15px 0px 0px;float:left"><p style='font-family:"Roboto", sans-serif; font-size:20px; color:white;margin: 2px 0px 0px 0px'>Dashboard</p></a>
<a href="programs" class="w3-bar-item w3-button"><img src="/static/programs-icon-64x64.png" alt="Programs" style="width:47px;height:32px;padding:0px 15px 0px 0px;float:left"><p style='font-family:"Roboto", sans-serif; font-size:20px; color:white;margin: 2px 0px 0px 0px'>Programs</p></a>
<a href="modbus" class="w3-bar-item w3-button" style="background-color:#E02222; padding-right:0px;padding-top:0px;padding-bottom:0px"><img src="/static/modbus-icon-512x512.png" alt="Modbus" style="width:47px;height:39px;padding:7px 15px 0px 0px;float:left"><img src="/static/arrow.png" style="width:17px;height:49px;padding:0px 0px 0px 0px;margin: 0px 0px 0px 0px; float:right"><p style='font-family:"Roboto", sans-serif; font-size:20px; color:white;margin: 10px 0px 0px 0px'>Slave Devices</p></a>
<a href='monitoring' class='w3-bar-item w3-button'><img src='/static/monitoring-icon-64x64.png' alt='Monitoring' style='width:47px;height:32px;padding:0px 15px 0px 0px;float:left'><p style='font-family:\"Roboto\", sans-serif; font-size:20px; color:white;margin: 2px 0px 0px 0px'>Monitoring</p></a>
<a href='hardware' class='w3-bar-item w3-button'><img src='/static/hardware-icon-980x974.png' alt='Hardware' style='width:47px;height:32px;padding:0px 15px 0px 0px;float:left'><p style='font-family:\"Roboto\", sans-serif; font-size:20px; color:white;margin: 2px 0px 0px 0px'>Hardware</p></a>
<a href='users' class='w3-bar-item w3-button'><img src='/static/users-icon-64x64.png' alt='Users' style='width:47px;height:32px;padding:0px 15px 0px 0px;float:left'><p style='font-family:\"Roboto\", sans-serif; font-size:20px; color:white;margin: 2px 0px 0px 0px'>Users</p></a>
<a href='settings' class='w3-bar-item w3-button'><img src='/static/settings-icon-64x64.png' alt='Settings' style='width:47px;height:32px;padding:0px 15px 0px 0px;float:left'><p style='font-family:\"Roboto\", sans-serif; font-size:20px; color:white;margin: 2px 0px 0px 0px'>Settings</p></a>
<a href='logout' class='w3-bar-item w3-button'><img src='/static/logout-icon-64x64.png' alt='Logout' style='width:47px;height:32px;padding:0px 15px 0px 0px;float:left'><p style='font-family:\"Roboto\", sans-serif; font-size:20px; color:white;margin: 2px 0px 0px 0px'>Logout</p></a>
<br>
<br>"""
return_str += draw_status()
return_str += """
</div>
<div style="margin-left:320px; margin-right:70px">
<div style="w3-container">
<br>
<h2>Edit slave device</h2>
<br>
<div style="float:left; width:45%; height:730px">
<form id = "uploadForm"
enctype = "multipart/form-data"
action = "modbus-edit-device"
method = "post"
onsubmit = "return validateForm()">"""
database = "openplc.db"
conn = create_connection(database)
if (conn != None):
try:
cur = conn.cursor()
cur.execute("SELECT * FROM Slave_dev WHERE dev_id = ?", (int(dev_id),))
row = cur.fetchone()
cur.close()
conn.close()
return_str += "<input type='hidden' value='" + dev_id + "' id='db_dev_id' name='db_dev_id'/>"
return_str += "<label for='dev_name'><b>Device Name</b></label><input type='text' id='dev_name' name='device_name' placeholder='My Device' value='" + str(row[1]) + "'>"
return_str += "<label for='dev_protocol'><b>Device Type</b></label><select id='dev_protocol' name='device_protocol'>"
if (str(row[2]) == "Uno"):
return_str += "<option selected='selected' value='Uno'>Arduino Uno</option>"
else:
return_str += "<option value='Uno'>Arduino Uno</option>"
if (str(row[2]) == "Mega"):
return_str += "<option selected='selected' value='Mega'>Arduino Mega</option>"
else:
return_str += "<option value='Mega'>Arduino Mega</option>"
if (str(row[2]) == "ESP32"):
return_str += "<option selected='selected' value='ESP32'>ESP32</option>"
else:
return_str += "<option value='ESP32'>ESP32</option>"
if (str(row[2]) == "ESP8266"):
return_str += "<option selected='selected' value='ESP8266'>ESP8266</option>"
else:
return_str += "<option value='ESP8266'>ESP8266</option>"
if (str(row[2]) == "TCP"):
return_str += "<option selected='selected' value='TCP'>Generic Modbus TCP Device</option>"
else:
return_str += "<option value='TCP'>Generic Modbus TCP Device</option>"
if (str(row[2]) == "RTU"):
return_str += "<option selected='selected' value='RTU'>Generic Modbus RTU Device</option></select>"
else:
return_str += "<option value='RTU'>Generic Modbus RTU Device</option></select>"
return_str += "<label for='dev_id'><b>Slave ID</b></label><input type='text' id='dev_id' name='device_id' placeholder='0' value='" + str(row[3]) + "'>"
return_str += "<div id=\"tcp-stuff\" style=\"display: none\"><label for='dev_ip'><b>IP Address</b></label><input type='text' id='dev_ip' name='device_ip' placeholder='192.168.0.1' value='" + str(row[9]) + "'>"
return_str += "<label for='dev_port'><b>IP Port</b></label><input type='text' id='dev_port' name='device_port' placeholder='502' value='" + str(row[10]) + "'></div>"
return_str += "<div id=\"rtu-stuff\"><label for='dev_cport'><b>COM Port</b></label><select id='dev_cport' name='device_cport'>"
ports = [comport.device for comport in serial.tools.list_ports.comports()]
for port in ports:
if (platform.system().startswith("CYGWIN")):
port_name = "COM" + str(int(port.split("/dev/ttyS")[1]) + 1)
else:
port_name = port
if (str(row[4]) == port_name):
return_str += "<option selected='selected' value'" + port_name + "'>" + port_name + "</option>"
else:
return_str += "<option value='" + port_name + "'>" + port_name + "</option>"
return_str += pages.edit_slave_devices_tail
return_str += dev_id
return_str += """' class="button" style="width: 310px; height: 53px; margin: 0px 20px 0px 20px;"><b>Delete device</b></a></center>
</form>
</div>
</div>
</div>
</body>"""
return_str += pages.edit_devices_script
return_str += 'devid.value = "' + str(row[3]) + '";'
return_str += 'devcport.value = "' + str(row[4]) + '";'
return_str += 'devbaud.value = "' + str(row[5]) + '";'
return_str += 'devparity.value = "' + str(row[6]) + '";'
return_str += 'devdata.value = "' + str(row[7]) + '";'
return_str += 'devstop.value = "' + str(row[8]) + '";'
return_str += 'devip.value = "' + str(row[9]) + '";'
return_str += 'devport.value = "' + str(row[10]) + '";'
return_str += 'distart.value = "' + str(row[11]) + '";'
return_str += 'disize.value = "' + str(row[12]) + '";'
return_str += 'dostart.value = "' + str(row[13]) + '";'
return_str += 'dosize.value = "' + str(row[14]) + '";'
return_str += 'aistart.value = "' + str(row[15]) + '";'
return_str += 'aisize.value = "' + str(row[16]) + '";'
return_str += 'aorstart.value = "' + str(row[17]) + '";'
return_str += 'aorsize.value = "' + str(row[18]) + '";'
return_str += 'aowstart.value = "' + str(row[19]) + '";'
return_str += 'aowsize.value = "' + str(row[20]) + '";}</script></html>'
except Error as e:
print("error connecting to the database" + str(e))
return_str += 'Error connecting to the database. Make sure that your openplc.db file is not corrupt.<br><br>Error: ' + str(e)
else:
return_str += 'Error connecting to the database. Make sure that your openplc.db file is not corrupt.'
return return_str
elif (flask.request.method == 'POST'):
devid_db = flask.request.form['db_dev_id']
devname = flask.request.form['device_name']
devtype = flask.request.form['device_protocol']
devid = flask.request.form['device_id']
devip = flask.request.form['device_ip']
devport = flask.request.form['device_port']
devcport = flask.request.form['device_cport']
devbaud = flask.request.form['device_baud']
devparity = flask.request.form['device_parity']
devdata = flask.request.form['device_data']
devstop = flask.request.form['device_stop']
di_start = flask.request.form['di_start']
di_size = flask.request.form['di_size']
do_start = flask.request.form['do_start']
do_size = flask.request.form['do_size']
ai_start = flask.request.form['ai_start']
ai_size = flask.request.form['ai_size']
aor_start = flask.request.form['aor_start']
aor_size = flask.request.form['aor_size']
aow_start = flask.request.form['aow_start']
aow_size = flask.request.form['aow_size']
database = "openplc.db"
conn = create_connection(database)
if (conn != None):
try:
cur = conn.cursor()
cur.execute("UPDATE Slave_dev SET dev_name = ?, dev_type = ?, slave_id = ?, com_port = ?, baud_rate = ?, parity = ?, data_bits = ?, stop_bits = ?, ip_address = ?, ip_port = ?, di_start = ?, di_size = ?, coil_start = ?, coil_size = ?, ir_start = ?, ir_size = ?, hr_read_start = ?, hr_read_size = ?, hr_write_start = ?, hr_write_size = ? WHERE dev_id = ?", (devname, devtype, devid, devcport, devbaud, devparity, devdata, devstop, devip, devport, di_start, di_size, do_start, do_size, ai_start, ai_size, aor_start, aor_size, aow_start, aow_size, int(devid_db)))
conn.commit()
cur.close()
conn.close()
generate_mbconfig()
return flask.redirect(flask.url_for('modbus'))
except Error as e:
print("error connecting to the database" + str(e))
return 'Error connecting to the database. Make sure that your openplc.db file is not corrupt.<br><br>Error: ' + str(e)
else:
return 'Error connecting to the database. Make sure that your openplc.db file is not corrupt.'
@app.route('/delete-device', methods=['GET', 'POST'])
def delete_device():
if (flask_login.current_user.is_authenticated == False):
return flask.redirect(flask.url_for('login'))
else:
if (openplc_runtime.status() == "Compiling"): return draw_compiling_page()
devid_db = flask.request.args.get('dev_id')
database = "openplc.db"
conn = create_connection(database)
if (conn != None):
try:
cur = conn.cursor()
cur.execute("DELETE FROM Slave_dev WHERE dev_id = ?", (int(devid_db),))
conn.commit()
cur.close()
conn.close()
generate_mbconfig()
return flask.redirect(flask.url_for('modbus'))
except Error as e:
print("error connecting to the database" + str(e))
return 'Error connecting to the database. Make sure that your openplc.db file is not corrupt.<br><br>Error: ' + str(e)
else:
return 'Error connecting to the database. Make sure that your openplc.db file is not corrupt.'
@app.route('/monitoring', methods=['GET', 'POST'])
def monitoring():
if (flask_login.current_user.is_authenticated == False):
return flask.redirect(flask.url_for('login'))
else:
if (openplc_runtime.status() == "Compiling"): return draw_compiling_page()
return_str = draw_blank_page()
return_str += """
<h2>Monitoring</h2>
<p>This feature is not available yet! Check back later...<p>
</div>
</div>
</div>
</body>
</html>"""
return return_str
@app.route('/hardware', methods=['GET', 'POST'])
def hardware():
if (flask_login.current_user.is_authenticated == False):