Merge pull request #90 from smartergridsolutions/feature/PR-709

PR-709 Address several dnp3 issues
This commit is contained in:
Thiago Alves 2019-10-25 08:35:02 -04:00 committed by GitHub
commit 9257e0bb3b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 64 additions and 25 deletions

4
.gitignore vendored
View File

@ -3,6 +3,10 @@ public/
.sass-cache/
.idea/
.settings/
.classpath
.project
target/
*.pyc

View File

@ -237,10 +237,13 @@ if(OPLC_MAIN_PROGRAM)
set_target_properties(openplc PROPERTIES PREFIX "")
add_dependencies(openplc files_generator)
if(OPLC_MODBUS)
add_dependencies(openplc libmodbus_proj)
endif()
target_link_libraries(openplc ${OPLC_PTHREAD} modbus)
if (OPLC_DNP3_OUTSTATION)
add_definitions(-DOPLC_DNP3_OUTSTATION)
target_compile_definitions(openplc PRIVATE OPLC_DNP3_OUTSTATION)
target_link_libraries(openplc asiodnp3 asiopal opendnp3 openpal)
endif()

View File

@ -5,20 +5,41 @@
OpenPLC is an open-source [Programmable Logic Controller](https://en.wikipedia.org/wiki/Programmable_logic_controller) that is based on easy to use software. Our focus is to provide a low cost industrial solution for automation and research. OpenPLC has been used in [many research papers](https://scholar.google.com/scholar?as_ylo=2014&q=openplc&hl=en&as_sdt=0,1) as a framework for industrial cyber security research, given that it is the only controller to provide the entire source code.
The OpenPLC Project consists of three sub-projects:
1. [Runtime](https://github.com/thiagoralves/OpenPLC_v3)
2. [Programming editor](http://www.openplcproject.com/plcopen-editor)
3. [HMI builder](http://www.openplcproject.com/reference-installing-scadabr)
## Installation:
## Installation
Follow the steps below to install OpenPLC runtime by ensuring your system
satisfies the prerequisites then following the setup steps.
### Prerequisites
If you system is Debian-based Linux, then the OpenPLC install script will automatically
satisfy dependencies. Otherwise, see below for requirements.
| System | Prerequisites |
|--------------------------------------------|------------------------------------------|
| Linux (Debian based, including Ubuntu) | None required |
| Raspberry PI | None required |
| Linux (other) | See `background_installer.sh` |
| Docker | Just the docker client |
| Windows | Git, Python 2.7, Cygwin with gcc, autoconf, automake, bison, cmake, flex, gcc-c++ |
### Install
To setup OpenPLC, clone the repository, then run the `install.sh` script. If you are
running Docker, then see Docker-specific steps below.
```bash
git clone https://github.com/thiagoralves/OpenPLC_v3.git
cd OpenPLC_v3
./install.sh [platform]
```
Where `[platform]` can be:
`win` - Install OpenPLC on Windows over Cygwin
where `[platform]` is one of:
`linux` - Install OpenPLC on a Debian-based Linux distribution
@ -26,21 +47,25 @@ Where `[platform]` can be:
`rpi` - Install OpenPLC on a Raspberry Pi
`custom` - Skip all specific package installation and tries to install OpenPLC assuming your system already has all dependencies met. This option can be useful if you're trying to install OpenPLC on an unsuported Linux platform or had manually installed all the dependency packages before.
`win` - Install OpenPLC on Windows over Cygwin
`custom` - Skip all specific package installation and tries to install OpenPLC assuming your system already has all dependencies met. This option can be useful if you're trying to install OpenPLC on an unsupported Linux platform or had manually installed all the dependency packages before.
### Building, Installing and Running inside Docker
Make sure [`docker` is installed](https://docs.docker.com/install/linux/docker-ce/ubuntu/)
#### Build
```
```bash
# instead of running install.sh as stated above, run:
docker build -t openplc:v3 .
```
#### RUN
#### Run
_Devices can be passed to the `docker` daemon using the `-v` flag (e.g. `-v /dev/ttyACM0:/dev/ttyACM0`)_
```bash
docker run -it --rm --privileged -p 8080:8080 openplc:v3
```

View File

@ -64,8 +64,14 @@ function cmake_build_and_test {
echo "Executing platform tests"
cd ../bin
./gg_unit_test
./oplc_unit_test
if [ "$1" == "win" ]; then
./gg_unit_test.exe
./oplc_unit_test.exe
else
./gg_unit_test
./oplc_unit_test
fi
}
if [ "$1" == "win" ]; then

View File

@ -115,7 +115,7 @@ std::pair<asiodnp3::OutstationStackConfig, Dnp3Range> create_config(std::istream
}
auto config = asiodnp3::OutstationStackConfig(DatabaseSizes::AllTypes(default_size));
Dnp3Range range = { 0, OPLCGLUE_INPUT_SIZE, 0, 0, OPLCGLUE_OUTPUT_SIZE, 0, 0, 0, 0, 0, 0, 0};
Dnp3Range range = { 0, OPLCGLUE_INPUT_SIZE, 0, 0, OPLCGLUE_OUTPUT_SIZE, 0, 0, BUFFER_SIZE, 0, 0, BUFFER_SIZE, 0};
// Finally, handle the remaining items
for (auto it = cfg_values.begin(); it != cfg_values.end(); ++it) {
@ -235,7 +235,8 @@ void dnp3StartServer(int port, std::unique_ptr<std::istream, std::function<void(
// Run this until we get a signal to stop.
while (*run) {
publisher->WriteToPoints();
int num_writes = publisher->WriteToPoints();
spdlog::trace("{} data points written to outstation", num_writes);
sleep_until(&timer_start, OPLC_CYCLE);
}
@ -255,7 +256,7 @@ void dnp3StartServer(int port, std::unique_ptr<std::istream, std::function<void(
/// @param port The port to run against.
////////////////////////////////////////////////////////////////////////////////
void dnp3StartServer(int port) {
std::unique_ptr<std::istream, std::function<void(std::istream*)>> cfg_stream(new std::ifstream("dnp3.cfg"), [](std::istream* s)
std::unique_ptr<std::istream, std::function<void(std::istream*)>> cfg_stream(new std::ifstream("./../webserver/dnp3.cfg"), [](std::istream* s)
{
reinterpret_cast<std::ifstream*>(s)->close();
delete s;

View File

@ -71,7 +71,6 @@ CommandStatus Dnp3Receiver::Select(const ControlRelayOutputBlock& command, uint1
}
CommandStatus Dnp3Receiver::Operate(const ControlRelayOutputBlock& command, uint16_t index, OperateType opType) {
spdlog::trace("DNP3 operate CROB");
auto code = command.functionCode;
auto glue_index = mapDnp3IndexToGlueIndex(range.bool_outputs_start, range.bool_outputs_end, range.bool_outputs_offset, index);
@ -88,7 +87,7 @@ CommandStatus Dnp3Receiver::Operate(const ControlRelayOutputBlock& command, uint
std::lock_guard<std::mutex> lock(*glue_variables->buffer_lock);
*glue = crob_val;
}
spdlog::trace("DNP3 CROB: {} written at index: {}", code == ControlCode::LATCH_ON ? "True": "False", index);
return CommandStatus::SUCCESS;
}
@ -100,7 +99,7 @@ CommandStatus Dnp3Receiver::Select(const AnalogOutputInt16& command, uint16_t in
}
CommandStatus Dnp3Receiver::Operate(const AnalogOutputInt16& command, uint16_t index, OperateType opType) {
spdlog::trace("DNP3 select AO int16 point status");
spdlog::trace("DNP3 select AO int16 point status: {} written at index: {}", command.value, index);
return this->UpdateGlueVariable<int16_t>(command.value, index);
}
@ -112,7 +111,7 @@ CommandStatus Dnp3Receiver::Select(const AnalogOutputInt32& command, uint16_t in
}
CommandStatus Dnp3Receiver::Operate(const AnalogOutputInt32& command, uint16_t index, OperateType opType) {
spdlog::trace("DNP3 select AO int32 point status");
spdlog::trace("DNP3 select AO int32 point status: {} written at index: {}", command.value, index);
return this->UpdateGlueVariable<int32_t>(command.value, index);
}
@ -124,7 +123,7 @@ CommandStatus Dnp3Receiver::Select(const AnalogOutputFloat32& command, uint16_t
}
CommandStatus Dnp3Receiver::Operate(const AnalogOutputFloat32& command, uint16_t index, OperateType opType) {
spdlog::trace("DNP3 select AO float32 point status");
spdlog::trace("DNP3 select AO float32 point status: {} written at index: {}", command.value, index);
return this->UpdateGlueVariable<float>(command.value, index);
}
@ -136,7 +135,7 @@ CommandStatus Dnp3Receiver::Select(const AnalogOutputDouble64& command, uint16_t
}
CommandStatus Dnp3Receiver::Operate(const AnalogOutputDouble64& command, uint16_t index, OperateType opType) {
spdlog::trace("DNP3 select AO double64 point status");
spdlog::trace("DNP3 select AO double64 point status: {} written at index: {}", command.value, index);
return this->UpdateGlueVariable<double>(command.value, index);
}
@ -244,13 +243,14 @@ CommandStatus Dnp3Receiver::UpdateGlueVariable(T value, uint16_t dnp3_index) con
}
void Dnp3Receiver::Start() {
spdlog::info("DNP3 Receiver Started");
spdlog::info("DNP3 receiver started");
}
void Dnp3Receiver::End() {
spdlog::info("DNP3 Receiver Stopped");
spdlog::info("DNP3 receiver stopped");
}
#endif // OPLC_DNP3_OUTSTATION
/** @}*/

View File

@ -13,7 +13,7 @@ echo ""
if [ "$OPENPLC_PLATFORM" = "linux" ]; then
cd ../build
cmake .. -DOPLC_ALL=OFF -DOPLC_BUILD_USER_APPLICATION=ON -Dprogram_name=$1
cmake .. -Dprogram_name=$1
make
if [ $? -ne 0 ]; then
echo "Compilation finished with errors!"
@ -24,7 +24,7 @@ if [ "$OPENPLC_PLATFORM" = "linux" ]; then
elif [ "$OPENPLC_PLATFORM" = "win" ]; then
cd ../build
cmake .. -DOPLC_ALL=OFF -OPLC_BUILD_USER_APPLICATION=ON -Dprogram_name=$1
cmake .. -Dprogram_name=$1
make
if [ $? -ne 0 ]; then
echo "Compilation finished with errors!"
@ -36,7 +36,7 @@ elif [ "$OPENPLC_PLATFORM" = "win" ]; then
elif [ "$OPENPLC_PLATFORM" = "rpi" ]; then
cd ../build
cmake .. -DOPLC_ALL=OFF -OPLC_BUILD_USER_APPLICATION=ON -Dprogram_name=$1 -DOPLC_PLATFORM_RPI=ON
cmake .. -Dprogram_name=$1 -DOPLC_PLATFORM_RPI=ON
make
if [ $? -ne 0 ]; then