Git Product home page Git Product logo

stepfunc / rodbus Goto Github PK

View Code? Open in Web Editor NEW
79.0 8.0 22.0 1.67 MB

Rust implementation of Modbus with idiomatic bindings for C, C++, .NET, and Java

Home Page: https://stepfunc.io/products/libraries/modbus/

License: Other

Rust 67.35% CMake 0.42% C 3.55% C# 4.81% Java 4.54% JavaScript 1.33% CSS 0.34% TypeScript 0.60% HTML 0.06% C++ 2.97% MDX 14.02%
modbus modbus-tcp modbus-library modbus-protocol rust tokio-rs scada c async tokio

rodbus's Introduction

Step Function I/O

Commercial Modbus library by Step Function I/O.

Please see the README for information on the core Rust library.

A user guide and documentation may be found here.

Refer to the CHANGELOG for a release history.

rodbus's People

Contributors

emgre avatar jadamcrain avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rodbus's Issues

Support discontiguous point maps on the server

Will require refactoring the Handler trait to retrieve one value at a time, returning Option<bool> or Option<u16>. The good news is that this would remove the lifetimes from all return values which made using "Service" traits difficult.

Remove code duplication in server

Ran into an issue using &[u8] as the ServerHandler response type. The compiler insisted that it needed a lifetime but it was unclear where to put it when using an associated type in a trait.

[Security] Workflow ci.yml is using vulnerable action actions/checkout

The workflow ci.yml is referencing action actions/checkout using references v1. However this reference is missing the commit a6747255bd19d7a757dbdda8c654a9f84db19839 which may contain fix to the some vulnerability.
The vulnerability fix that is missing by actions version could be related to:
(1) CVE fix
(2) upgrade of vulnerable dependency
(3) fix to secret leak and others.
Please consider to update the reference to the action.

Unable to load shared library 'rodbus_ffi' or one of its dependencies.

I'm trying to experiment with rodbus in C# but I'm getting this error about missing dylib: Unable to load shared library 'rodbus_ffi' or one of its dependencies.. Below is the full error:

 ---> System.DllNotFoundException: Unable to load shared library 'rodbus_ffi' or one of its dependencies. In order to help diagnose loading problems, consider setting the DYLD_PRINT_LIBRARIES environment variable:
dlopen(/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.9/rodbus_ffi.dylib, 0x0001): tried: '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.9/rodbus_ffi.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.9/rodbus_ffi.dylib' (no such file), '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.9/rodbus_ffi.dylib' (no such file)
dlopen(/Users/[User]/project/bin/Debug/net7.0/rodbus_ffi.dylib, 0x0001): tried: '/Users/[User]/project/bin/Debug/net7.0/rodbus_ffi.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Users/[User]/project/bin/Debug/net7.0/rodbus_ffi.dylib' (no such file), '/Users/[User]/project/bin/Debug/net7.0/rodbus_ffi.dylib' (no such file)
dlopen(rodbus_ffi.dylib, 0x0001): tried: 'rodbus_ffi.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OSrodbus_ffi.dylib' (no such file), '/usr/lib/rodbus_ffi.dylib' (no such file, not in dyld cache), 'rodbus_ffi.dylib' (no such file), '/usr/local/lib/rodbus_ffi.dylib' (no such file), '/usr/lib/rodbus_ffi.dylib' (no such file, not in dyld cache)
dlopen(/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.9/librodbus_ffi.dylib, 0x0001): tried: '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.9/librodbus_ffi.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.9/librodbus_ffi.dylib' (no such file), '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.9/librodbus_ffi.dylib' (no such file)
dlopen(/Users/[User]/project/bin/Debug/net7.0/librodbus_ffi.dylib, 0x0001): tried: '/Users/[User]/project/bin/Debug/net7.0/librodbus_ffi.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Users/[User]/project/bin/Debug/net7.0/librodbus_ffi.dylib' (no such file), '/Users/[User]/project/bin/Debug/net7.0/librodbus_ffi.dylib' (no such file)
dlopen(librodbus_ffi.dylib, 0x0001): tried: 'librodbus_ffi.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OSlibrodbus_ffi.dylib' (no such file), '/usr/lib/librodbus_ffi.dylib' (no such file, not in dyld cache), 'librodbus_ffi.dylib' (no such file), '/usr/local/lib/librodbus_ffi.dylib' (no such file), '/usr/lib/librodbus_ffi.dylib' (no such file, not in dyld cache)
dlopen(/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.9/rodbus_ffi, 0x0001): tried: '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.9/rodbus_ffi' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.9/rodbus_ffi' (no such file), '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.9/rodbus_ffi' (no such file)
dlopen(/Users/[User]/project/bin/Debug/net7.0/rodbus_ffi, 0x0001): tried: '/Users/[User]/project/bin/Debug/net7.0/rodbus_ffi' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Users/[User]/project/bin/Debug/net7.0/rodbus_ffi' (no such file), '/Users/[User]/project/bin/Debug/net7.0/rodbus_ffi' (no such file)
dlopen(rodbus_ffi, 0x0001): tried: 'rodbus_ffi' (no such file), '/System/Volumes/Preboot/Cryptexes/OSrodbus_ffi' (no such file), '/usr/lib/rodbus_ffi' (no such file, not in dyld cache), 'rodbus_ffi' (no such file), '/usr/local/lib/rodbus_ffi' (no such file), '/usr/lib/rodbus_ffi' (no such file, not in dyld cache)
dlopen(/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.9/librodbus_ffi, 0x0001): tried: '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.9/librodbus_ffi' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.9/librodbus_ffi' (no such file), '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.9/librodbus_ffi' (no such file)
dlopen(/Users/[User]/project/bin/Debug/net7.0/librodbus_ffi, 0x0001): tried: '/Users/[User]/project/bin/Debug/net7.0/librodbus_ffi' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Users/[User]/project/bin/Debug/net7.0/librodbus_ffi' (no such file), '/Users/[User]/project/bin/Debug/net7.0/librodbus_ffi' (no such file)
dlopen(librodbus_ffi, 0x0001): tried: 'librodbus_ffi' (no such file), '/System/Volumes/Preboot/Cryptexes/OSlibrodbus_ffi' (no such file), '/usr/lib/librodbus_ffi' (no such file, not in dyld cache), 'librodbus_ffi' (no such file), '/usr/local/lib/librodbus_ffi' (no such file), '/usr/lib/librodbus_ffi' (no such file, not in dyld cache)

I'm attempting this on an M1 Mac (not sure if this has anything to do with what's wrong)

Add TLS support conforming to Modbus security spec

Would prefer to use tokio-rustls, but it appears that ATM rustls forces server hostname validation.

I opened up a pair of tickets to track this:

rustls/rustls#331
quininer/tokio-rustls#59

It looks like the native-tls create on which tokio-tls depends may also force server hostname validation?

https://docs.rs/native-tls/0.2.3/native_tls/struct.TlsConnector.html#method.connect

The openssl bindings too:

https://docs.rs/openssl/0.10.26/openssl/ssl/struct.SslConnector.html#method.connect

Cannot connect to rodbus server

Hi,

I have the server in Rodbus, and client in other library(sorry have to use that). When client and server are in same process (say same SpringBoot application), client can connect to server successfully:
RodbusLog - Feb 17 01:34:43.756 INFO Modbus-Server-TCP{listen=0.0.0.0:502}: accepted connection from: 172.17.0.2:50384 - assigned session id: 0

However, if client and master are in different process (same machine), I'll get connection refused error. Please suggest what could be go wrong?

Thanks!

Invalid JSON Log Formatting

I have enabled the JSON formatting in the rodbus log configuration to extract specific log data and log it with the spdlog library.

I have trouble extracting the IP and Port from this specific log, because the JSON is invalid.

Also, do you have documentation on the general JSON format used in the rodbus lib?
Which data field are always used/ which ones only on server / client log etc..

Thank you very much!

{
    "fields": {
        "message": "channel enabled"
    },
    "span": {
        "endpoint": "HostAddr { addr: IpAddr(192.168.1.2), port: 502 }",
        "name": "Modbus-Client-TCP"
    },
    "spans": [
        {
            "endpoint": "HostAddr { addr: IpAddr(192.168.1.2), port: 502 }",
            "name": "Modbus-Client-TCP"
        }
    ]
}

Decide how to host the C documentation

I recently pushed complete docs for C API. It builds nicely w/ doxygen. We can decide if we want to style it, but a biggest question is how/where to host. We could do this on automatak.com or readthedocs.

pros/cons of Automatak:

  • gets the company exposure and ups our google foo?
  • need to do non-standard build automatak against this server whereas readthedocs has a simple API

replace log with tracing

Tracing can provide additional context, e.g. each connection can be identified in some way, whereas the log crate has no such info and will make it impossible to correlate logs with sessions without injecting identifiers down into the log calls themselves.

Java 17 Rodbus Setup Question: Unable to load any of the included native libraries

I have a project that I am trying to setup. Its a spring boot app using Java 17
When I attempt to create the Runtime object similarly to the example files I run into an issue regarding some native libraries.

I have hopefully formatted the structure below into somewhat orderly manner so that it can be easy to follow my setup and identify any glaring issues.

Thanks!

Exception Stack Trace

  2023-12-14 13:47:14.877 [http-nio-591-exec-1] ERROR o.a.c.c.C.[.[localhost].[/].[dispatcherServlet] - Servlet.service() for                    servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed; nested exception is java.lang.ExceptionInInitializerError] with root cause
  java.lang.Exception: Unable to load any of the included native libraries
	  at io.stepfunc.rodbus.NativeFunctions.<clinit>(NativeFunctions.java:53)
	  at io.stepfunc.rodbus.NativeFunctions$Wrapped.runtime_create(NativeFunctions.java:193)
	  at io.stepfunc.rodbus.Runtime.<init>(Runtime.java:37)

Method Throwing Error (specifically the second line here is the culprit)

        RuntimeConfig runtimeConfig = new RuntimeConfig().withNumCoreThreads(ushort(4));
        Runtime runtime = new Runtime(runtimeConfig);

Java Version

  java 17.0.6 2023-01-17 LTS
  Java(TM) SE Runtime Environment (build 17.0.6+9-LTS-190)
  Java HotSpot(TM) 64-Bit Server VM (build 17.0.6+9-LTS-190, mixed mode, sharing)

pom.xml snippet

        <dependency>
            <groupId>io.stepfunc</groupId>
            <artifactId>rodbus</artifactId>
            <version>1.3.1</version>
        </dependency>

        <dependency>
            <groupId>org.jooq</groupId>
            <artifactId>joou</artifactId>
            <version>0.9.4</version>
        </dependency>

class imports

  import static org.joou.Unsigned.ubyte;
  import static org.joou.Unsigned.ushort;
  import io.stepfunc.rodbus.*;
  import io.stepfunc.rodbus.Runtime;

Let me know if I am overlooking something in my setup here or if there is any additional information that you need to help me with this issue!
Thanks

Feature Request: Rodbus-client: Show TX/RX bytes and output hex

There are two features that are very useful in mbtget. The first is the ability to output the values in hex (rather than decimal) and the second is to display the TX and RX bytes. The following is an example that shows both.

`
CutSec 2020-09-17 07:38:03

./mbtget -d -hex -a 0 -n 5
Tx
[84 C6 00 00 00 06 01] 03 00 00 00 05

Rx
[84 C6 00 00 00 0D 01] 03 0A 00 00 00 1E 00 00 00 00 00 3C

values:
1 (ad 00000): 0x0000
2 (ad 00001): 0x001e
3 (ad 00002): 0x0000
4 (ad 00003): 0x0000
5 (ad 00004): 0x003c
`

I'm reviewing the code to see if I can implement it, but I'm new to Rust (just installed) and it might take a while for me to do it. Plus, I doubt I would do it in the most effective manner.

Thank you,
cutaway

Java runtime reference

Assuming I'm using the java library correctly, I believe there's either a missing Runtime reference hold or the documentation may need to be updated to reflect how Runtime should be treated.

In my multi-threaded use of the library:

        final RuntimeConfig runtimeConfig =
                new RuntimeConfig()
                        .withNumCoreThreads(ushort(4));
        final Runtime runtime = new Runtime(runtimeConfig);
        this.channel =
                ClientChannel.createTcp(
                        runtime,
                        ip,
                        ushort(port),
                        ushort(1),
                        new RetryStrategy(),
                        DecodeLevel.nothing(),
                        state -> LOG.warn("State change: {}", state));
        this.channel.enable();

A separate scheduled executor periodically initiates reads from the channel.

With nothing holding the runtime reference, the gc seems to prune it, calling finalize(), which shuts down the Runtime and "SHUTDOWN" exceptions start to get thrown.

To fix this, holding the reference to Runtime on the class keeps the gc from deleting it, which keeps things going.

Couldn't find reference to this anywhere, so wanted to share. Unsure if intended or not.

Panic when creating RTU server

create_outstation_serial panics when called:

Jul 08 13:51:01.176  INFO creating runtime with 4 threads
creating outstation task
thread '<unnamed>' panicked at 'there is no reactor running, must be called from the context of a Tokio 1.x runtime'

This occurs b/c SerialStream::open must be called from within the runtime so that it can register itself with the I/O driver.

Runtime error when updating register values

Hi @jadamcrain ,

I'm actively using your library and facing another issue. When I update the register values from server side by this code:

RuntimeConfig runtimeConfig = new RuntimeConfig().withNumCoreThreads(ushort(4));
Runtime runtime = new Runtime(runtimeConfig);

DeviceMap map = new DeviceMap();
map.addEndpoint(ubyte(1), new ExampleWriteHandler(), db -> {
    for(int i = 0; i < 1000; i++) {
        db.addHoldingRegister(ushort(i), ushort(1));
        db.addInputRegister(ushort(i), ushort(2));
    }
});
AddressFilter addressFilter = new AddressFilter("*.*.*.*");
Server server = Server.createTcp(runtime, "0.0.0.0", ushort(8888), addressFilter, ushort(100), map, DecodeLevel.nothing());
server.updateDatabase(ubyte(1), db -> {
    db.updateHoldingRegister(ushort(100), ushort(-1));
});

And the error is:

thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: JavaException', /target/aarch64-unknown-linux-gnu/release/build/rodbus-ffi-java-1095f2a2549debe7/out/jni.rs:3439:187
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
fatal runtime error: failed to initiate panic, error 2216477728

I'm running on ubuntu VM, and cpu info:

  CPU op-mode(s):       64-bit
  Byte Order:           Little Endian

Please advise what can be done to get rid of this issue?

Thanks!

Re-order TX logs

The TX logs are currently written in this order: ADU -> PDU -> Phys, but we expect it to be PDU -> ADU -> Phys.

ServerTask should enforce a maximum number of connections

Currently the server accepts an infinite number of connections. When spawning the server task a maximum number of sessions should be specified. The task accepting connections can maintain a FIFO queue of active connections (how to notify it when a connection closes on its own, e.g. remote termination)?. When a connection is accepted and the maximum number of connections are already running, the oldest connection should be dropped.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.