OpenPLC
2024-02-02 19:03:35 0 举报
AI智能生成
OpenPLC项目解析
作者其他创作
大纲/内容
install.sh
background_installer.sh
linux_install_deps
install_py_deps
install_all_libs
使用make编译开源编译器matiec生成iec2c
把编译后的iec2c拷贝到webserver文件夹
编译utils/st_optimizer_src
把编译后的st_optimizer拷贝到webserver文件夹
编译utils/glue_generator_src
把编译后的glue_generator拷贝到webserver文件夹
使用make编译dnp3源码
使用make编译libmodbus源码
创建openplc.service,把项目设置为开机自启动服务
change_hardware_layer.sh
compile_program.sh
使用st_optimizer优化st文件
使用iec2c把st文件编译成c文件并移动到core文件夹
编译st生产的c文件和其它core文件生产object文件
glue_generator
链接生成可执行文件openplc
start_openplc.sh
main.cpp
初始化PLC
pthread_create(&interactive_thread, NULL, interactiveServerThread, NULL)
startInteractiveServer(43628)
socket_fd = createSocket_interactive(port)
client_fd = waitForClient_interactive(socket_fd)
ret = pthread_create(&thread, NULL, handleConnections_interactive, arguments)
messageSize = listenToClient_interactive(client_fd, buffer)
int n = read(client_fd, buffer, 1024);
processMessage_interactive(buffer, messageSize, client_fd)
processCommand(server_command, client_fd)
quit
run_modbus = 0
run_dnp3 = 0
run_openplc = 0
start_ethercat
argument = (char)readCommandArgumentStr(buffer)
log(log_msg)
ethercat_configured = configureEthercat()
start_modbus
modbus_port = readCommandArgument(buffer);
已开启则重启modbus服务
run_modbus = 1;
pthread_create(&modbus_thread, NULL, modbusThread, NULL)
startServer(modbus_port, MODBUS_PROTOCOL);
socket_fd = createSocket(port);
client_fd = waitForClient(socket_fd, protocol_type);
ret = pthread_create(&thread, NULL, handleConnections, (void*)arguments);
messageSize = listenToClient(client_fd, buffer)
int n = read(client_fd, buffer, NET_BUFFER_SIZE)
processMessage(buffer, messageSize, client_fd, protocol_type);
protocol_type == MODBUS_PROTOCOL
int messageSize = processModbusMessage(buffer, bufferSize);
bufferSize < 8
ModbusError(buffer, ERR_ILLEGAL_FUNCTION);
buffer[7] == MB_FC_READ_COILS
ReadCoils(buffer, bufferSize);
buffer[7] == MB_FC_READ_INPUTS
ReadDiscreteInputs(buffer, bufferSize);
buffer[7] == MB_FC_READ_HOLDING_REGISTERS
ReadHoldingRegisters(buffer, bufferSize);
buffer[7] == MB_FC_READ_INPUT_REGISTERS
ReadInputRegisters(buffer, bufferSize);
buffer[7] == MB_FC_WRITE_COIL
WriteCoil(buffer, bufferSize);
buffer[7] == MB_FC_WRITE_REGISTER
WriteRegister(buffer, bufferSize);
buffer[7] == MB_FC_WRITE_MULTIPLE_COILS
WriteMultipleCoils(buffer, bufferSize);
buffer[7] == MB_FC_WRITE_MULTIPLE_REGISTERS
WriteMultipleRegisters(buffer, bufferSize);
其他
ModbusError(buffer, ERR_ILLEGAL_FUNCTION);
write(client_fd, buffer, messageSize);
stop_modbus
run_modbus=0
start_dnp3
dnp3_port = readCommandArgument(buffer);
run_dnp3 = 1
pthread_create(&dnp3_thread, NULL, dnp3Thread, NULL)
dnp3StartServer(dnp3_port)
auto channel = manager.AddTCPServer("DNP3_Server", FILTERS, ChannelRetry::Default(), "0.0.0.0", port, PrintingChannelListener::Create());
stop_dnp3
run_dnp3 = 0
start_enip
enip_port = readCommandArgument(buffer)
已开启则重启enip服务
run_enip = 0
run_enip = 1
run_enip = 1
pthread_create(&enip_thread, NULL, enipThread, NULL)
startServer(enip_port, ENIP_PROTOCOL)
socket_fd = createSocket(port);
client_fd = waitForClient(socket_fd, protocol_type);
ret = pthread_create(&thread, NULL, handleConnections, (void*)arguments);
messageSize = listenToClient(client_fd, buffer)
int n = read(client_fd, buffer, NET_BUFFER_SIZE)
processMessage(buffer, messageSize, client_fd, protocol_type);
protocol_type == ENIP_PROTOCOL
int messageSize = processEnipMessage(buffer, bufferSize);
write(client_fd, buffer, messageSize);
stop_enip
run_enip = 0
start_pstorage
pstorage_polling = readCommandArgument(buffer)
run_pstorage = 1
pthread_create(&pstorage_thread, NULL, pstorageThread, NULL)
startPstorage()
把int_memory数组中的数据保存到persistent.file文件中
persistentBuffer[i] = *int_memory[i]
FILE *ps = fopen("persistent.file", "w")
fwrite(persistentBuffer, sizeof(IEC_INT), BUFFER_SIZE, ps)
int_memory中数据变化时重新持久化
if (persistentBuffer[i] != *int_memory[i])
{
persistentBuffer[i] = *int_memory[i];
}
{
persistentBuffer[i] = *int_memory[i];
}
FILE *fd = fopen("persistent.file", "w")
fwrite(persistentBuffer, sizeof(IEC_INT), BUFFER_SIZE, fd)
stop_pstorage
run_pstorage = 0
runtime_logs
write(client_fd, log_buffer, log_index)
exec_time
count_char = sprintf(buffer, "%llu\n", (unsigned long long)difftime(end_time, start_time))
write(client_fd, buffer, count_char)
未知指令直接报错
count_char = sprintf(buffer, "Error: unrecognized command\n")
write(client_fd, buffer, count_char)
config_init__
glueVars
void glueVars()
{
}
{
}
MUTEX INITIALIZATION
pthread_mutex_init(&bufferLock, NULL)
初始化HARDWARE
#ifdef _ethercat_src
ethercat_configure("../utils/ethercat_src/build/ethercat.cfg", logger)
initializeHardware
initializeMB
parseConfig
modbus_new_tcp
modbus_set_slave
modbus_set_response_timeout
pthread_create(&thread, NULL, querySlaveDevices, NULL)
initCustomLayer
updateBuffersIn
updateCustomIn
updateBuffersOut
updateCustomOut
初始化持久化存储
glueVars()
mapUnusedIO()
readPersistentStorage()
FILE *fd = fopen("persistent.file", "r")
fread(persistentBuffer, sizeof(IEC_INT), BUFFER_SIZE, fd)
*int_memory[i] = persistentBuffer[i]
pstorage_read = true;
设置线程优先级
struct sched_param sp
pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp)
mlockall(MCL_FUTURE|MCL_CURRENT)
MAIN LOOP
webserver.py
main
读取active_program中保存的当前runtime所对应的st_file文件名
在去Programs表中查询其project_name,project_description,project_file并绑定到runtime实例上
查询settings表,根据表中Start_run_mode字段值决定是否启动core代码编译出的plc软件
默认为False,为True时
openplc_runtime.start_runtime()
self.theprocess = subprocess.Popen(['./core/openplc'])
configure_runtime()
查询settings表中的Modbus_port字段值
502
openplc_runtime.start_modbus(502)
self._rpc('start_modbus(502)')
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 43628))
s.send(f'{msg}\n'.encode('utf-8'))
s.connect(('localhost', 43628))
s.send(f'{msg}\n'.encode('utf-8'))
disabled
openplc_runtime.stop_modbus()
self._rpc('stop_modbus()')
查询settings表中的Dnp3_port字段值
20000
openplc_runtime.start_dnp3(20000)
self._rpc('start_dnp3(20000)')
disabled
openplc_runtime.stop_dnp3()
self._rpc('stop_dnp3()')
查询settings表中的Enip_port字段值
44818
openplc_runtime.start_enip(44818)
self._rpc('start_enip(44818)')
disabled
openplc_runtime.stop_enip()
self._rpc('stop_enip()')
查询settings表中的Pstorage_polling字段值
poll_rate
openplc_runtime.start_pstorage(poll_rate)
self._rpc(f'start_pstorage({poll_rate})')
disabled
openplc_runtime.stop_pstorage()
self._rpc('stop_pstorage()')
monitor.parse_st(openplc_runtime.project_file)
启动python的web服务
login界面
get请求返回登录页面
post请求校验用户名和密码
成功则跳转到Dashboard页面
失败则跳转回到登录页面
点击首页左侧导航栏的start_plc按钮
monitor.stop_monitor()
monitor_active = False;
mb_client.close();
mb_client.close();
openplc_runtime.start_runtime()
self.theprocess = subprocess.Popen(['./core/openplc'])
configure_runtime()
查询settings表中的Modbus_port字段值
502
openplc_runtime.start_modbus(502)
self._rpc('start_modbus(502)')
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 43628))
s.send(f'{msg}\n'.encode('utf-8'))
s.connect(('localhost', 43628))
s.send(f'{msg}\n'.encode('utf-8'))
disabled
openplc_runtime.stop_modbus()
self._rpc('stop_modbus()')
查询settings表中的Dnp3_port字段值
20000
openplc_runtime.start_dnp3(20000)
self._rpc('start_dnp3(20000)')
disabled
openplc_runtime.stop_dnp3()
self._rpc('stop_dnp3()')
查询settings表中的Enip_port字段值
44818
openplc_runtime.start_enip(44818)
self._rpc('start_enip(44818)')
disabled
openplc_runtime.stop_enip()
self._rpc('stop_enip()')
查询settings表中的Pstorage_polling字段值
poll_rate
openplc_runtime.start_pstorage(poll_rate)
self._rpc(f'start_pstorage({poll_rate})')
disabled
openplc_runtime.stop_pstorage()
self._rpc('stop_pstorage()')
monitor.cleanup()
del debug_vars[:]
monitor.parse_st(openplc_runtime.project_file)
点击首页左侧导航栏的stop_plc按钮
openplc_runtime.stop_runtime()
self._rpc('quit()')
monitor.stop_monitor()
monitor_active = False;
mb_client.close();
mb_client.close();
Dashboard界面
monitor.stop_monitor()
绘制dashboard网页
从runtime实例属性上获取Status,Program,Description,File值绘制网页
openplc_runtime.status()
openplc_runtime.project_name
openplc_runtime.project_description
openplc_runtime.project_file
openplc_runtime.exec_time()
self._rpc(f'exec_time()',10000)
使用ajax请求/runtime_logs接口获取runtime运行日志绘制在网页上
openplc_runtime.logs()
self._rpc(f'runtime_logs()',1000000)
Programs界面
monitor.stop_monitor()
查询数据库中存储的所有/部分program展示在网页的表格中
点击表格中的program会访问/reload-program页面
在数据库中查询点击的program信息
在网页表单中展示当前program的详细信息
点击Launch program按钮访问/compile-program页面
compile_program
查询数据库获取当前program信息保存到runtime实例属性上,用于绘制网页
delete_persistent_file()
os.remove("persistent.file")
openplc_runtime.compile_program(st_file)
a = subprocess.Popen(['./scripts/compile_program.sh', str(st_file)], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
compilation_object = NonBlockingStreamReader(a.stdout)
点击Update_program按钮访问/Update-program网页
在/Update-program网页中选择新的st文件,点击Upload Program按钮
访问/update_program_action接口
progfile.save(os.path.join('stfiles', filename))
重定向到/compile-program页面编译st文件
compile_program
查询数据库获取当前program信息保存到runtime实例属性上,用于绘制网页
delete_persistent_file()
os.remove("persistent.file")
openplc_runtime.compile_program(st_file)
a = subprocess.Popen(['./scripts/compile_program.sh', str(st_file)], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
compilation_object = NonBlockingStreamReader(a.stdout)
draw_compiling_page()
使用ajax请求/compilation-logs接口获取编译日志
openplc_runtime.compilation_status()
line = compilation_object.readline()
点击Remove_program按钮访问/remove-program接口
从数据库中删除当前program
在Upload Program部分,选择完st文件点击Upload Program按钮会访问/upload-program页面
prog_file.save(os.path.join('st_files', filename))
返回/upload-program页面
填写完页面中的表单,点击Upload program按钮
访问/upload-program-action接口
INSERT INTO Programs (Name, Description, File, Date_upload) VALUES (prog_name, prog_descr, prog_file, epoch_time)
重定向到/compile-program页面编译st文件
compile_program
查询数据库获取当前program信息保存到runtime实例属性上,用于绘制网页
delete_persistent_file()
os.remove("persistent.file")
openplc_runtime.compile_program(st_file)
a = subprocess.Popen(['./scripts/compile_program.sh', str(st_file)], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
compilation_object = NonBlockingStreamReader(a.stdout)
draw_compiling_page()
使用ajax请求/compilation-logs接口获取编译日志
openplc_runtime.compilation_status()
line = compilation_object.readline()
Slave Devices界面
monitor.stop_monitor()
从Slave_dev表中查出slave设备信息以表格的形式显示在网页上
点击Add New Device按钮会跳转到/add-modbus-device页面
GET请求
返回添加slave信息的表单页面
填写完slave设备信息后点击Save Device按钮后向当前页面以POST方式提交表单
POST请求
把slave设备信息保存到数据库
generate_mbconfig()
根据数据库中保存的设备信息生成mbconfig.cfg文件
重定向回Slave Device界面,即/modbus页面
点击表格中的slave信息会跳转到/modbus-edit-device页面
GET请求
返回修改slave信息的表单页面
填写完slave设备信息后点击Save Device按钮后向当前页面以POST方式提交表单
点击Delete device按钮访问/delete-device接口
从数据库中删除当前设备信息
generate_mbconfig()
根据数据库中保存的设备信息重新生成mbconfig.cfg文件
重定向回Slave Device界面,即/modbus页面
POST请求
更新数据库中的slave设备信息
generate_mbconfig()
根据数据库中保存的设备信息重新生成mbconfig.cfg文件
重定向回Slave Device界面,即/modbus页面
monitoring界面
从Settings表中查询modbus_port_cfg
monitor.start_monitor(modbus_port_cfg)
mb_client = ModbusTcpClient('127.0.0.1', port=modbus_port_cfg)
modbus_monitor()
把debug_vars中数据渲染到html
point_info
根据表单中table_id去debug_var查询数据生成html
point_update
monitor_update
从表单中获取modbus_port_cfg
monitor.start_monitor(modbus_port_cfg)
mb_client = ModbusTcpClient('127.0.0.1', port=modbus_port_cfg)
modbus_monitor()
根据debug_vars生成html
hardware界面
GET:读取./core/psm/main.py文件内容生成html
POST:
把从表单中读取的custom_layer_code保存到main文件中
把从表单中读取的hardware_layer作为change_hardware_layer.sh脚本的参数执行
restore_custom_hardware
用main.original文件内容覆盖到mian
settings界面
查询settings表显示到网页上
修改设置后点击Save Changes按钮后把表单中配置项写入到settings表
configure_runtime()
查询settings表中的Modbus_port字段值
502
openplc_runtime.start_modbus(502)
self._rpc('start_modbus(502)')
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 43628))
s.send(f'{msg}\n'.encode('utf-8'))
s.connect(('localhost', 43628))
s.send(f'{msg}\n'.encode('utf-8'))
disabled
openplc_runtime.stop_modbus()
self._rpc('stop_modbus()')
查询settings表中的Dnp3_port字段值
20000
openplc_runtime.start_dnp3(20000)
self._rpc('start_dnp3(20000)')
disabled
openplc_runtime.stop_dnp3()
self._rpc('stop_dnp3()')
查询settings表中的Enip_port字段值
44818
openplc_runtime.start_enip(44818)
self._rpc('start_enip(44818)')
disabled
openplc_runtime.stop_enip()
self._rpc('stop_enip()')
查询settings表中的Pstorage_polling字段值
poll_rate
openplc_runtime.start_pstorage(poll_rate)
self._rpc(f'start_pstorage({poll_rate})')
disabled
openplc_runtime.stop_pstorage()
self._rpc('stop_pstorage()')
generate_mbconfig()
根据数据库中保存的设备信息重新生成mbconfig.cfg文件
users界面
user CRUD
add_user
edit_user
delete_user
logout
0 条评论
下一页
为你推荐
查看更多
抱歉,暂无相关内容