Device attributes
Attributes identify the device (vendor, model, firmware and configuration versions), report what it supports, and let you set names such as its location. The master can read and write them.
Reading attributes
Read attributes with a one-time read whose request names one or more attribute variations, each with its set (0 for the default set). The example reads all the attributes in the default set.
- Rust
- C
- C++
- Java
- C#
self.association
.read(ReadRequest::device_attribute(
AllAttributes,
AttrSet::Default,
))
.await?;
dnp3_request_t *request = dnp3_request_create();
dnp3_request_add_specific_attribute(request, DNP3_ATTRIBUTE_VARIATIONS_ALL_ATTRIBUTES_REQUEST, 0);
dnp3_read_task_callback_t cb = {
.on_complete = &on_read_complete,
.on_failure = &on_read_failure,
.on_destroy = NULL,
.ctx = "rda",
};
dnp3_param_error_t err = dnp3_master_channel_read(channel, association_id, request, cb);
dnp3_request_destroy(request);
dnp3::Request request;
request.add_specific_attribute(dnp3::attribute_variations::all_attributes_request, 0);
channel.read(assoc, request, create_read_callback("rda"));
Request request = new Request();
request.addSpecificAttribute(AttributeVariations.ALL_ATTRIBUTES_REQUEST, ubyte(0));
channel.read(association, request).toCompletableFuture().get();
var request = new Request();
request.AddSpecificAttribute(AttributeVariations.AllAttributesRequest, 0);
await channel.Read(association, request);
Receiving attributes
The ReadHandler receives the attributes the outstation returns, including the list of the attributes it supports. The Rust trait uses a single method and passes an enum representing the various types of values. The bindings use a distinct method for each type of value, i.e. one for strings, another for unsigned integers, etc.
All of the callbacks tell you whether the attribute is from the default set defined by DNP.org (set 0) or a privately defined set, and identify the attributes of the default set for you. You only have to match variation numbers yourself for attributes from a private set.
The default set includes a number of attributes that report whether the device supports a feature, such as analog input events or binary input events. The library delivers these as booleans instead of the raw integers.
Writing attributes
Attributes can be written one at a time or in batches by adding them to a request and sending it to the outstation with the
generic request and the WRITE function code. The Rust
API uses a single method to add any type of attribute to the request. The bindings can only write visible string and unsigned integer
attributes, using a separate method for each type.
The example below writes the user-assigned location, a visible string, to the outstation.
- Rust
- C
- C++
- Java
- C#
let headers = Headers::default()
.add_attribute(StringAttr::UserAssignedLocation.with_value("Mt. Olympus"));
self.association
.send_and_expect_empty_response(FunctionCode::Write, headers)
.await?;
dnp3_request_t *request = dnp3_request_create();
dnp3_request_add_string_attribute(request, DNP3_ATTRIBUTE_VARIATIONS_USER_ASSIGNED_LOCATION, 0, "Mt. Olympus");
dnp3_empty_response_callback_t cb = {
.on_complete = &on_empty_response_complete,
.on_failure = &on_empty_response_failure,
.on_destroy = NULL,
.ctx = "wda",
};
dnp3_param_error_t err = dnp3_master_channel_send_and_expect_empty_response(channel, association_id, DNP3_FUNCTION_CODE_WRITE, request, cb);
dnp3_request_destroy(request);
dnp3::Request request;
request.add_string_attribute(dnp3::attribute_variations::user_assigned_location, 0, "Mt. Olympus");
channel.send_and_expect_empty_response(assoc, dnp3::FunctionCode::write, request, create_empty_response_callback("wda"));
Request request = new Request();
request.addStringAttribute(AttributeVariations.USER_ASSIGNED_LOCATION, ubyte(0), "Mt. Olympus");
channel.sendAndExpectEmptyResponse(association, FunctionCode.WRITE, request).toCompletableFuture().get();
var request = new Request();
request.AddStringAttribute(AttributeVariations.UserAssignedLocation, 0, "Mt. Olympus");
await channel.SendAndExpectEmptyResponse(association, FunctionCode.Write, request);