use super::modbus::ModbusTransaction;
use crate::jsonbuilder::{JsonBuilder, JsonError};
use sawp_modbus::{Data, Message, Read, Write};
#[no_mangle]
pub extern "C" fn SCModbusToJson(tx: &ModbusTransaction, js: &mut JsonBuilder) -> bool {
log(tx, js).is_ok()
}
fn log(tx: &ModbusTransaction, js: &mut JsonBuilder) -> Result<(), JsonError> {
js.open_object("modbus")?;
js.set_uint("id", tx.id)?;
if let Some(req) = &tx.request {
js.open_object("request")?;
log_message(req, js)?;
js.close()?;
}
if let Some(resp) = &tx.response {
js.open_object("response")?;
log_message(resp, js)?;
js.close()?;
}
js.close()?;
Ok(())
}
fn log_message(msg: &Message, js: &mut JsonBuilder) -> Result<(), JsonError> {
js.set_uint("transaction_id", msg.transaction_id)?;
js.set_uint("protocol_id", msg.protocol_id)?;
js.set_uint("unit_id", msg.unit_id)?;
js.set_uint("function_raw", msg.function.raw)?;
js.set_string("function_code", &msg.function.code.to_string())?;
js.set_string("access_type", &msg.access_type.to_string())?;
js.set_string("category", &msg.category.to_string())?;
js.set_string("error_flags", &msg.error_flags.to_string())?;
match &msg.data {
Data::Exception(exc) => {
js.open_object("exception")?;
js.set_uint("raw", exc.raw)?;
js.set_string("code", &exc.code.to_string())?;
js.close()?;
}
Data::Diagnostic { func, data } => {
js.open_object("diagnostic")?;
js.set_uint("raw", func.raw)?;
js.set_string("code", &func.code.to_string())?;
js.set_string_from_bytes("data", data)?;
js.close()?;
}
Data::MEI { mei_type, data } => {
js.open_object("mei")?;
js.set_uint("raw", mei_type.raw)?;
js.set_string("code", &mei_type.code.to_string())?;
js.set_string_from_bytes("data", data)?;
js.close()?;
}
Data::Read(read) => {
js.open_object("read")?;
log_read(read, js)?;
js.close()?;
}
Data::Write(write) => {
js.open_object("write")?;
log_write(write, js)?;
js.close()?;
}
Data::ReadWrite { read, write } => {
js.open_object("read")?;
log_read(read, js)?;
js.close()?;
js.open_object("write")?;
log_write(write, js)?;
js.close()?;
}
Data::ByteVec(data) => {
js.set_string_from_bytes("data", data)?;
}
Data::Empty => {}
}
Ok(())
}
fn log_read(read: &Read, js: &mut JsonBuilder) -> Result<(), JsonError> {
match read {
Read::Request { address, quantity } => {
js.set_uint("address", *address)?;
js.set_uint("quantity", *quantity)?;
}
Read::Response(data) => {
js.set_string_from_bytes("data", data)?;
}
}
Ok(())
}
fn log_write(write: &Write, js: &mut JsonBuilder) -> Result<(), JsonError> {
match write {
Write::MultReq {
address,
quantity,
data,
} => {
js.set_uint("address", *address)?;
js.set_uint("quantity", *quantity)?;
js.set_string_from_bytes("data", data)?;
}
Write::Mask {
address,
and_mask,
or_mask,
} => {
js.set_uint("address", *address)?;
js.set_uint("and_mask", *and_mask)?;
js.set_uint("or_mask", *or_mask)?;
}
Write::Other { address, data } => {
js.set_uint("address", *address)?;
js.set_uint("data", *data)?;
}
}
Ok(())
}