Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Improvement of the Custom Function Code Feature (CFC) #6

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
1926d68
chore(send_cfc): Rename CFC README.me
dkoehler-dev Jan 29, 2024
cf2a350
fix(examples): Adjust TCP & TLS port for non-root Unix users
dkoehler-dev Jan 29, 2024
fcb4beb
refactor(custom_fc): Rename WriteCustomFC to SendCustomFC
dkoehler-dev Jan 29, 2024
7054730
refactor(custom_fc): Remove SendCustomBuffer functionality (PR 2 on I…
dkoehler-dev Jan 29, 2024
076f66c
feat(custom examples): add custom client and server examples for CFC6…
dkoehler-dev Feb 1, 2024
0e02219
feat(cli): add CLI tool to call CFC69 (CustomFunctionCode) via the CL…
dkoehler-dev Feb 1, 2024
1f9a046
refactor: move cli functionality
dkoehler-dev Feb 12, 2024
8d8441f
feat(custom client example): Extend the custom client example for the…
dkoehler-dev Feb 14, 2024
4dc5972
refactor(send_custom_fc): change CFC69 CustomFC implementation to sup…
dkoehler-dev Feb 14, 2024
97cbef1
refactor(send_custom_fc): implement parsing and serializing logic for…
dkoehler-dev Feb 14, 2024
5355f24
fix(custom_fc): fix serialize error for CFC request
dkoehler-dev Feb 15, 2024
7a150c2
test(parse): Extend CFC69 parse unit test cases
dkoehler-dev Feb 15, 2024
f696091
test(serialize): extend CFC69 serialize unit test cases
dkoehler-dev Feb 15, 2024
4c9510f
test(parse): extend CFC69 unit test cases
dkoehler-dev Feb 15, 2024
3b07294
test(serialize): extend CFC69 serialize unit test cases
dkoehler-dev Feb 15, 2024
be7a3f1
refactor(send_custom_fc): add expect empty cursor statement to parse …
dkoehler-dev Feb 15, 2024
64d60b2
docs(send_custom_fc): extend documentation for the CFC69 implementation
dkoehler-dev Feb 16, 2024
6bc6548
test(integration cfc): improve integration test readability
dkoehler-dev Feb 16, 2024
0cdc137
refactor(custom_FC): implement dynamic CFC handling
dkoehler-dev Feb 21, 2024
d85e629
refactor(custom_client): remove unused print_read_result() function
dkoehler-dev Feb 22, 2024
9e1fb98
feat(function): make CFC FC const more readable
dkoehler-dev Feb 22, 2024
988ef20
refactor(integration_test): add CFC69 integration test
dkoehler-dev Feb 22, 2024
4f994dd
refactor(send_custom_fc): improve vector handling
dkoehler-dev Feb 22, 2024
280607a
refactor(parse): improve CFC vector handling
dkoehler-dev Feb 22, 2024
7d4c3b9
fix(serialize): adjust CFC serialization to new CFC struct
dkoehler-dev Feb 22, 2024
5f5ca0b
feat(handler): add cfc handler traits
dkoehler-dev Feb 22, 2024
f778102
refactor(task): adjust CFC request logic to use the correct handler f…
dkoehler-dev Feb 22, 2024
5e67614
refactor(request): adjust CFC request logic to use the correct const …
dkoehler-dev Feb 22, 2024
dcfdfe6
refactor(custom_client): add cfc69 requesthandler to test the CFC69 r…
dkoehler-dev Feb 22, 2024
9c7abd0
refactor(task): adjust CFC cient request logic to use the correct con…
dkoehler-dev Feb 22, 2024
c0261cd
fix(custom_fc): fix CFC69 response always the same
dkoehler-dev Feb 23, 2024
5262d87
refactor(custom_fc): implement copy trait for CFC
dkoehler-dev Feb 23, 2024
0048131
fix(custom_fc): add lifetime specifier to CFC
dkoehler-dev Feb 23, 2024
7318370
fix(send_custom_fc): remove the introduced lifetime specifier from th…
dkoehler-dev Mar 4, 2024
9912be2
fix(send_custom_fc): fix the unmodified CFC return object
dkoehler-dev Mar 4, 2024
8700378
refactor(send_custom_fc): fix unmodified CFC object, introduce byte_c…
dkoehler-dev Mar 4, 2024
554b6c7
fix(send_custom_fc): fix incorect CFC buffer population
dkoehler-dev Mar 5, 2024
62e7bcc
test(send_custom_fc): adjust the CFC parse/serialize and integration …
dkoehler-dev Mar 5, 2024
6c11ee2
test(send_custom_fc): add CFC integration tests
dkoehler-dev Mar 5, 2024
5a52c1d
refactor(send_custom_fc): improved CFC output
dkoehler-dev Mar 6, 2024
9e81fdb
test(custom_server): Implement test CFC handlers to simulate differen…
dkoehler-dev Mar 6, 2024
2ba9ce0
feat(send_custom_fc): improve CFC documentation
dkoehler-dev Mar 6, 2024
52cd82a
test(send_custom_fc): remove failing incorrect CFC69 serial test
dkoehler-dev Mar 6, 2024
d89f403
refactor(send_custom_fc): remove panic statement from CFC function code
dkoehler-dev Mar 11, 2024
563fc22
refactor(send_custom_fc): replace individual CFC handlers with a gene…
dkoehler-dev Mar 11, 2024
8b026af
refactor(send_custom_fc): implement general purpose CFC handler in cu…
dkoehler-dev Mar 11, 2024
790eb3b
fix(send_custom_fc): fix request/parsing error when handling the CFC …
dkoehler-dev Mar 12, 2024
afbfbca
refactor(send_custom_fc): remove the blocking of standard function co…
dkoehler-dev Mar 12, 2024
2d1ccab
feat(custom_server): add standard FC handling in the server implement…
dkoehler-dev Mar 12, 2024
14e6134
feat(send_custom_fc): add standard FC routing for a CFC request in me…
dkoehler-dev Mar 12, 2024
d91ec3f
refactor(send_custom_fc): remove panic statement when no valid CFC is…
dkoehler-dev Mar 12, 2024
0ef05e4
Revert "refactor(send_custom_fc): remove panic statement when no vali…
dkoehler-dev Mar 13, 2024
cbf2d2e
Revert "feat(send_custom_fc): add standard FC routing for a CFC reque…
dkoehler-dev Mar 13, 2024
19d99d7
Revert "feat(custom_server): add standard FC handling in the server i…
dkoehler-dev Mar 13, 2024
6957bae
Revert "refactor(send_custom_fc): remove the blocking of standard fun…
dkoehler-dev Mar 13, 2024
aca481f
feat(send_custom_fc): updated CFC logic because of reversal conflicts
dkoehler-dev Mar 13, 2024
5b4694c
test(send_custom_fc): adjust integration test for CFCs
dkoehler-dev Mar 13, 2024
e6d374d
refactor(send_custom_fc): correct invalid CFC server handler fc match…
dkoehler-dev Mar 13, 2024
c2cb3f0
test(send_custom_fc): add integration test for the CFC range from 0 t…
dkoehler-dev Mar 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions rodbus/SCFC_README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Send Custom Function Code (65-72 & 100-110)

This document provides a detailed overview of the implemented rodbus custom function code feature. These user-defined function codes fall within the range of 65 to 72 and 100 to 110, as specified in the MODBUS Application Protocol Specification V1.1b3 (Page 10, Section 5: Function Code Categories), and allow custom server-side execution logic.


## Introduction
The custom function codes enable the implementation of user-defined logic on a remote server device. It facilitates the transmission, reception, and processing of a custom function code with a variable-size data buffer.


## Request Structure
| Parameter | Size | Range / Value |
|---------------------|---------------|-----------------------|
| Function code | 1 Byte | 0x41-0x48 / 0x64-0x6E |
| Byte Count (Input) | 1 Byte | 0x00 to 0xFF (N*) |
| Byte Count (Output) | 1 Byte | 0x00 to 0xFF |
| Data | N* x 2 Bytes | 0x0000 to 0xFFFF |


## Response Structure
| Parameter | Size | Value/Description |
|---------------------|--------------|-----------------------|
| Function code | 1 Byte | 0x41-0x48 / 0x64-0x6E |
| Byte Count (Input) | 1 Byte | 0x00 to 0xFF (N*) |
| Byte Count (Output) | 1 Byte | 0x00 to 0xFF |
| Data | N* x 2 Bytes | 0x0000 to 0xFFFF |


## Error Handling
| Parameter | Size | Description |
|----------------|---------|----------------------|
| Function code | 1 Byte | Function code + 0x80 |
| Exception code | 1 Byte | 01 or 02 or 03 or 04 |

### Error Codes:
- **01**: Illegal Function
- **02**: Illegal Data Address
- **03**: Illegal Data Value
- **04**: Server Device Failure


## Usage Example
### Request to send the custom FC 69 with a buffer of [0xC0DE, 0xCAFE, 0xC0DE, 0xCAFE] (Byte Count = 4 -> 8 bytes):
| Request Field | Hex | Response Field | Hex |
|---------------------------|-----|------------------------|-----|
| Function code | 45 | Function code | 45 |
| Byte Count (Input) | 04 | Byte Count (Input) | 04 |
| Byte Count (Output) | 04 | Byte Count (Output) | 04 |
| Arg1 Hi | C0 | Arg1 Hi | C0 |
| Arg1 Lo | DE | Arg1 Lo | DF |
| Arg2 Hi | CA | Arg2 Hi | CA |
| Arg2 Lo | FE | Arg2 Lo | FF |
| Arg3 Hi | C0 | Arg3 Hi | C0 |
| Arg3 Lo | DE | Arg3 Lo | DF |
| Arg4 Hi | CA | Arg4 Hi | CA |
| Arg4 Lo | FE | Arg4 Lo | FF |


## Usage
Make sure that you are in the `rodbus` project directory.


### Start the custom_server example
- `cargo run --example custom_server -- tcp`
- Once it's up, run `ed` to enable decoding

Leave the terminal open and open another terminal.


### Start the custom_client example
- `cargo run --example custom_client -- tcp`
- Once it's up, run `ed` to enable decoding


### Send the Custom Function Code 69
In the terminal with the running custom_client example, run:
- `scfc <u8 Function Code> <u8 Byte Count Input> <u8 Byte Count Output> <u16 Arguments>`
- E.g. `scfc 0x45 0x02 0x02 0xC0DE 0xCAFE`
- The response would be for example: `fc: 0x45, bytes in: 2, bytes out: 2, values: [49375, 51967], hex: [0xC0DF, 0xCAFF]`


## Troubleshooting Tips
- Ensure the server and client are using the same communication method and are connected to each other.
- Check for any error codes in the response and refer to the error handling section for resolution.


## Additional Resources
- For more information on the MODBUS protocol and function codes, refer to the [MODBUS Application Protocol Specification V1.1b3](https://modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf).
64 changes: 0 additions & 64 deletions rodbus/WCFC_README.md

This file was deleted.

34 changes: 11 additions & 23 deletions rodbus/examples/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ where
async fn run_tcp() -> Result<(), Box<dyn std::error::Error>> {
// ANCHOR: create_tcp_channel
let channel = spawn_tcp_client_task(
HostAddr::ip(IpAddr::V4(Ipv4Addr::LOCALHOST), 502),
HostAddr::ip(IpAddr::V4(Ipv4Addr::LOCALHOST), 10502),
1,
default_retry_strategy(),
DecodeLevel::default(),
Expand Down Expand Up @@ -96,7 +96,7 @@ async fn run_rtu() -> Result<(), Box<dyn std::error::Error>> {
async fn run_tls(tls_config: TlsClientConfig) -> Result<(), Box<dyn std::error::Error>> {
// ANCHOR: create_tls_channel
let channel = spawn_tls_client_task(
HostAddr::ip(IpAddr::V4(Ipv4Addr::LOCALHOST), 802),
HostAddr::ip(IpAddr::V4(Ipv4Addr::LOCALHOST), 10802),
1,
default_retry_strategy(),
tls_config,
Expand Down Expand Up @@ -267,33 +267,21 @@ async fn run_channel(mut channel: Channel) -> Result<(), Box<dyn std::error::Err
print_write_result(result);
// ANCHOR_END: write_multiple_registers
}
"scb" => {
// ANCHOR: send_custom_buffer
let result = channel
.send_custom_buffer(
params,
Indexed {
index: (0x1),
value: (0xAB),
},
)
.await;
print_write_result(result);
// ANCHOR_END: write_multiple_registers
}
"wcfc" => {
// ANCHOR: write_custom_function_code
let length = 0x04 as usize;
let values = [0xC0, 0xDE, 0xCA, 0xFE]; // i.e.: Voltage Hi = 0xC0 / Voltage Lo = 0xDE / Current Hi = 0xCA / Current Lo = 0xFE
"scfc" => {
// ANCHOR: send_custom_function_code
let fc = 0x45 as u8;
let byte_count_in = 0x04 as u8;
let byte_count_out = 0x04 as u8;
let values = vec![0xC0DE, 0xCAFE, 0xC0DE, 0xCAFE]; // i.e.: Voltage Hi = 0xC0 / Voltage Lo = 0xDE / Current Hi = 0xCA / Current Lo = 0xFE

let result = channel
.write_custom_function_code(
.send_custom_function_code(
params,
CustomFunctionCode::new(length, values)
CustomFunctionCode::new(fc, byte_count_in, byte_count_out, values)
)
.await;
print_write_result(result);
// ANCHOR_END: write_custom_function_code
// ANCHOR_END: send_custom_function_code
}
_ => println!("unknown command"),
}
Expand Down
Loading
Loading