Skip to content

Commit

Permalink
Add stricter checks to adding a node to address space - the namespace…
Browse files Browse the repository at this point in the history
… index must exist or it will panic. Fix samples to do things the proper way.
  • Loading branch information
locka99 committed Mar 14, 2020
1 parent cab2a9a commit afc063a
Show file tree
Hide file tree
Showing 10 changed files with 87 additions and 53 deletions.
23 changes: 14 additions & 9 deletions samples/chess-server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,33 +40,38 @@ fn main() {

let address_space = server.address_space();

{
let ns = {
let mut address_space = address_space.write().unwrap();

let ns = address_space.register_namespace("urn:chess-server").unwrap();

let board_node_id = address_space
.add_folder("Board", "Board", &NodeId::objects_folder_id())
.unwrap();

BOARD_SQUARES.iter().for_each(|square| {
// Variable represents each square's state
let browse_name = *square;
let node_id = NodeId::new(2, *square);
let node_id = NodeId::new(ns, *square);
VariableBuilder::new(&node_id, browse_name, browse_name)
.organized_by(&board_node_id)
.value(0u8)
.insert(&mut address_space);

// Another variable is a highlighting flag for the square
let browse_name = format!("{}.highlight", square);
let node_id = NodeId::new(2, browse_name.clone());
let node_id = NodeId::new(ns, browse_name.clone());
VariableBuilder::new(&node_id, browse_name, "")
.organized_by(&board_node_id)
.value(false)
.insert(&mut address_space);
});

let game = game.lock().unwrap();
update_board_state(&game, &mut address_space);
}
update_board_state(&game, &mut address_space, ns);

ns
};

// Spawn a thread for the game which will update server state

Expand Down Expand Up @@ -96,7 +101,7 @@ fn main() {

{
let mut address_space = address_space.write().unwrap();
update_board_state(&game, &mut address_space);
update_board_state(&game, &mut address_space, ns);
}
}

Expand All @@ -108,17 +113,17 @@ fn main() {
server.run();
}

fn update_board_state(game: &game::Game, address_space: &mut AddressSpace) {
fn update_board_state(game: &game::Game, address_space: &mut AddressSpace, ns: u16) {
let now = DateTime::now();
BOARD_SQUARES.iter().for_each(|square| {
// Piece on the square
let square_value = game.square_from_str(square);
let node_id = NodeId::new(2, *square);
let node_id = NodeId::new(ns, *square);

let _ = address_space.set_variable_value(node_id, square_value as u8, &now, &now);

// Highlight the square
let node_id = NodeId::new(2, format!("{}.highlight", square));
let node_id = NodeId::new(ns, format!("{}.highlight", square));
let highlight_square = if let Some(ref last_move) = game.last_move {
last_move.contains(square)
} else {
Expand Down
4 changes: 2 additions & 2 deletions samples/demo-server/src/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use opcua_server::{
prelude::*,
};

pub fn add_control_switches(server: &mut Server) {
pub fn add_control_switches(server: &mut Server, ns: u16) {
// The address space is guarded so obtain a lock to change it
let abort_node_id = NodeId::new(2u16, "abort");
let abort_node_id = NodeId::new(ns, "abort");

let address_space = server.address_space();
let server_state = server.server_state();
Expand Down
14 changes: 10 additions & 4 deletions samples/demo-server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,26 @@ fn main() {
// Create an OPC UA server with sample configuration and default node set
let mut server = Server::new(ServerConfig::load(&PathBuf::from("../server.conf")).unwrap());

let ns = {
let address_space = server.address_space();
let mut address_space = address_space.write().unwrap();
address_space.register_namespace("urn:demo-server").unwrap()
};

// Add some objects representing machinery
machine::add_machinery(&mut server);

// Add some scalar variables
scalar::add_scalar_variables(&mut server);
scalar::add_scalar_variables(&mut server, ns);

// Add some rapidly changing values
scalar::add_stress_variables(&mut server);
scalar::add_stress_variables(&mut server, ns);

// Add some control switches, e.g. abort flag
control::add_control_switches(&mut server);
control::add_control_switches(&mut server, ns);

// Add some methods
methods::add_methods(&mut server);
methods::add_methods(&mut server, ns);

// Add historical data providers
historical::add_providers(&mut server);
Expand Down
6 changes: 3 additions & 3 deletions samples/demo-server/src/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ use opcua_server::{
session::Session,
};

pub fn add_methods(server: &mut Server) {
pub fn add_methods(server: &mut Server, ns: u16) {
let address_space = server.address_space();
let mut address_space = address_space.write().unwrap();

let object_id = NodeId::new(2, "Functions");
let object_id = NodeId::new(ns, "Functions");
ObjectBuilder::new(&object_id, "Functions", "Functions")
.event_notifier(EventNotifier::SUBSCRIBE_TO_EVENTS)
.organized_by(ObjectId::ObjectsFolder)
.insert(&mut address_space);

let fn_node_id = NodeId::new(2, "HelloWorld");
let fn_node_id = NodeId::new(ns, "HelloWorld");
MethodBuilder::new(&fn_node_id, "HelloWorld", "HelloWorld")
.component_of(object_id.clone())
.output_args(&mut address_space, &[
Expand Down
42 changes: 21 additions & 21 deletions samples/demo-server/src/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use opcua_server::{
prelude::*,
};

pub fn add_scalar_variables(server: &mut Server) {
pub fn add_scalar_variables(server: &mut Server, ns: u16) {
let (static_folder_id, dynamic_folder_id) = {
let address_space = server.address_space();
let mut address_space = address_space.write().unwrap();
Expand All @@ -20,13 +20,13 @@ pub fn add_scalar_variables(server: &mut Server) {
};

// Add static scalar values
add_static_scalar_variables(server, &static_folder_id);
add_static_array_variables(server, &static_folder_id);
add_static_scalar_variables(server, ns, &static_folder_id);
add_static_array_variables(server, ns, &static_folder_id);

// Add dynamically changing scalar values
add_dynamic_scalar_variables(server, &dynamic_folder_id);
add_dynamic_array_variables(server, &dynamic_folder_id);
set_dynamic_timers(server);
add_dynamic_scalar_variables(server, ns, &dynamic_folder_id);
add_dynamic_array_variables(server, ns, &dynamic_folder_id);
set_dynamic_timers(server, ns);
}

const SCALAR_TYPES: [DataTypeId; 14] = [
Expand All @@ -35,15 +35,15 @@ const SCALAR_TYPES: [DataTypeId; 14] = [
DataTypeId::Double, DataTypeId::String, DataTypeId::DateTime, DataTypeId::Guid
];

pub fn scalar_node_id(id: DataTypeId, is_dynamic: bool, is_array: bool) -> NodeId {
pub fn scalar_node_id(ns: u16, id: DataTypeId, is_dynamic: bool, is_array: bool) -> NodeId {
let mut name = scalar_name(id).to_string();
if is_dynamic {
name.push_str("Dynamic");
}
if is_array {
name.push_str("Array");
}
NodeId::new(2, name)
NodeId::new(ns, name)
}

pub fn scalar_name(id: DataTypeId) -> &'static str {
Expand Down Expand Up @@ -113,7 +113,7 @@ pub fn scalar_random_value(id: DataTypeId) -> Variant {
}

/// Creates some sample variables, and some push / pull examples that update them
fn add_static_scalar_variables(server: &mut Server, static_folder_id: &NodeId) {
fn add_static_scalar_variables(server: &mut Server, ns: u16, static_folder_id: &NodeId) {
// The address space is guarded so obtain a lock to change it
let address_space = server.address_space();
let mut address_space = address_space.write().unwrap();
Expand All @@ -125,7 +125,7 @@ fn add_static_scalar_variables(server: &mut Server, static_folder_id: &NodeId) {

for sn in SCALAR_TYPES.iter() {
let name = scalar_name(*sn);
let node_id = scalar_node_id(*sn, false, false);
let node_id = scalar_node_id(ns, *sn, false, false);
VariableBuilder::new(&node_id, name, name)
.data_type(sn)
.value(scalar_default_value(*sn))
Expand All @@ -134,7 +134,7 @@ fn add_static_scalar_variables(server: &mut Server, static_folder_id: &NodeId) {
}
}

fn add_static_array_variables(server: &mut Server, static_folder_id: &NodeId) {
fn add_static_array_variables(server: &mut Server, ns: u16, static_folder_id: &NodeId) {
// The address space is guarded so obtain a lock to change it
let address_space = server.address_space();
let mut address_space = address_space.write().unwrap();
Expand All @@ -145,7 +145,7 @@ fn add_static_array_variables(server: &mut Server, static_folder_id: &NodeId) {
.unwrap();

SCALAR_TYPES.iter().for_each(|sn| {
let node_id = scalar_node_id(*sn, false, true);
let node_id = scalar_node_id(ns, *sn, false, true);
let name = scalar_name(*sn);
let values = (0..100).map(|_| scalar_default_value(*sn)).collect::<Vec<Variant>>();
VariableBuilder::new(&node_id, name, name)
Expand All @@ -157,7 +157,7 @@ fn add_static_array_variables(server: &mut Server, static_folder_id: &NodeId) {
});
}

fn add_dynamic_scalar_variables(server: &mut Server, dynamic_folder_id: &NodeId) {
fn add_dynamic_scalar_variables(server: &mut Server, ns: u16, dynamic_folder_id: &NodeId) {
// The address space is guarded so obtain a lock to change it
let address_space = server.address_space();
let mut address_space = address_space.write().unwrap();
Expand All @@ -168,7 +168,7 @@ fn add_dynamic_scalar_variables(server: &mut Server, dynamic_folder_id: &NodeId)
.unwrap();

SCALAR_TYPES.iter().for_each(|sn| {
let node_id = scalar_node_id(*sn, true, false);
let node_id = scalar_node_id(ns, *sn, true, false);
let name = scalar_name(*sn);
VariableBuilder::new(&node_id, name, name)
.data_type(*sn)
Expand All @@ -178,7 +178,7 @@ fn add_dynamic_scalar_variables(server: &mut Server, dynamic_folder_id: &NodeId)
});
}

fn add_dynamic_array_variables(server: &mut Server, dynamic_folder_id: &NodeId) {
fn add_dynamic_array_variables(server: &mut Server, ns: u16, dynamic_folder_id: &NodeId) {
// The address space is guarded so obtain a lock to change it
let address_space = server.address_space();
let mut address_space = address_space.write().unwrap();
Expand All @@ -189,7 +189,7 @@ fn add_dynamic_array_variables(server: &mut Server, dynamic_folder_id: &NodeId)
.unwrap();

SCALAR_TYPES.iter().for_each(|sn| {
let node_id = scalar_node_id(*sn, true, true);
let node_id = scalar_node_id(ns, *sn, true, true);
let name = scalar_name(*sn);
let values = (0..10).map(|_| scalar_default_value(*sn)).collect::<Vec<Variant>>();
VariableBuilder::new(&node_id, name, name)
Expand All @@ -201,7 +201,7 @@ fn add_dynamic_array_variables(server: &mut Server, dynamic_folder_id: &NodeId)
});
}

fn set_dynamic_timers(server: &mut Server) {
fn set_dynamic_timers(server: &mut Server, ns: u16) {
let address_space = server.address_space();

// Standard change timers
Expand All @@ -210,18 +210,18 @@ fn set_dynamic_timers(server: &mut Server) {
// Scalar
let now = DateTime::now();
SCALAR_TYPES.iter().for_each(|sn| {
let node_id = scalar_node_id(*sn, true, false);
let node_id = scalar_node_id(ns, *sn, true, false);
let _ = address_space.set_variable_value_by_ref(&node_id, scalar_random_value(*sn), &now, &now);

let node_id = scalar_node_id(*sn, true, true);
let node_id = scalar_node_id(ns, *sn, true, true);
let values = (0..10).map(|_| scalar_random_value(*sn)).collect::<Vec<Variant>>();
let _ = address_space.set_variable_value_by_ref(&node_id, values, &now, &now);
});
});
}

pub fn add_stress_variables(server: &mut Server) {
let node_ids = (0..1000).map(|i| NodeId::new(2, format!("v{:04}", i))).collect::<Vec<NodeId>>();
pub fn add_stress_variables(server: &mut Server, ns: u16) {
let node_ids = (0..1000).map(|i| NodeId::new(ns, format!("v{:04}", i))).collect::<Vec<NodeId>>();

let address_space = server.address_space();
let mut address_space = address_space.write().unwrap();
Expand Down
7 changes: 4 additions & 3 deletions samples/mqtt-client/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,16 +93,17 @@ fn main() -> Result<(), ()> {
// endpoints one of which is marked as the default.
let mut client = Client::new(ClientConfig::load(&PathBuf::from(config_file)).unwrap());
let endpoint_id: Option<&str> = if !endpoint_id.is_empty() { Some(&endpoint_id) } else { None };
let ns = 2;
if let Ok(session) = client.connect_to_endpoint_id(endpoint_id) {
let _ = subscription_loop(session, tx).map_err(|err| {
let _ = subscription_loop(session, tx, ns).map_err(|err| {
println!("ERROR: Got an error while performing action - {}", err);
});
}
}
Ok(())
}

fn subscription_loop(session: Arc<RwLock<Session>>, tx: mpsc::Sender<(NodeId, DataValue)>) -> Result<(), StatusCode> {
fn subscription_loop(session: Arc<RwLock<Session>>, tx: mpsc::Sender<(NodeId, DataValue)>, ns: u16) -> Result<(), StatusCode> {
// Create a subscription
println!("Creating subscription");

Expand All @@ -127,7 +128,7 @@ fn subscription_loop(session: Arc<RwLock<Session>>, tx: mpsc::Sender<(NodeId, Da

// Create some monitored items
let items_to_create: Vec<MonitoredItemCreateRequest> = ["v1", "v2", "v3", "v4"].iter()
.map(|v| NodeId::new(2, *v).into()).collect();
.map(|v| NodeId::new(ns, *v).into()).collect();
let _ = session.create_monitored_items(subscription_id, TimestampsToReturn::Both, &items_to_create)?;
}

Expand Down
6 changes: 3 additions & 3 deletions samples/simple-client/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ fn main() -> Result<(), ()> {
.client().unwrap();

if let Ok(session) = client.connect_to_endpoint((args.url.as_ref(), SecurityPolicy::None.to_str(), MessageSecurityMode::None, UserTokenPolicy::anonymous()), IdentityToken::Anonymous) {
if let Err(result) = subscribe_to_variables(session.clone()) {
if let Err(result) = subscribe_to_variables(session.clone(), 2) {
println!("ERROR: Got an error while subscribing to variables - {}", result);
} else {
// Loops forever. The publish thread will call the callback with changes on the variables
Expand All @@ -62,7 +62,7 @@ fn main() -> Result<(), ()> {
Ok(())
}

fn subscribe_to_variables(session: Arc<RwLock<Session>>) -> Result<(), StatusCode> {
fn subscribe_to_variables(session: Arc<RwLock<Session>>, ns: u16) -> Result<(), StatusCode> {
let mut session = session.write().unwrap();
// Creates a subscription with a data change callback
let subscription_id = session.create_subscription(2000.0, 10, 30, 0, 0, true, DataChangeCallback::new(|changed_monitored_items| {
Expand All @@ -73,7 +73,7 @@ fn subscribe_to_variables(session: Arc<RwLock<Session>>) -> Result<(), StatusCod

// Create some monitored items
let items_to_create: Vec<MonitoredItemCreateRequest> = ["v1", "v2", "v3", "v4"].iter()
.map(|v| NodeId::new(2, *v).into()).collect();
.map(|v| NodeId::new(ns, *v).into()).collect();
let _ = session.create_monitored_items(subscription_id, TimestampsToReturn::Both, &items_to_create)?;

Ok(())
Expand Down
18 changes: 12 additions & 6 deletions samples/simple-server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,26 @@ fn main() {
// Create an OPC UA server with sample configuration and default node set
let mut server = Server::new(ServerConfig::load(&PathBuf::from("../server.conf")).unwrap());

let ns = {
let address_space = server.address_space();
let mut address_space = address_space.write().unwrap();
address_space.register_namespace("urn:simple-server").unwrap()
};

// Add some variables of our own
add_example_variables(&mut server);
add_example_variables(&mut server, ns);

// Run the server. This does not ordinarily exit so you must Ctrl+C to terminate
server.run();
}

/// Creates some sample variables, and some push / pull examples that update them
fn add_example_variables(server: &mut Server) {
fn add_example_variables(server: &mut Server, ns: u16) {
// These will be the node ids of the new variables
let v1_node = NodeId::new(2, "v1");
let v2_node = NodeId::new(2, "v2");
let v3_node = NodeId::new(2, "v3");
let v4_node = NodeId::new(2, "v4");
let v1_node = NodeId::new(ns, "v1");
let v2_node = NodeId::new(ns, "v2");
let v3_node = NodeId::new(ns, "v3");
let v4_node = NodeId::new(ns, "v4");

let address_space = server.address_space();

Expand Down
Loading

0 comments on commit afc063a

Please sign in to comment.