Skip to content

Latest commit

 

History

History
305 lines (212 loc) · 8.92 KB

File metadata and controls

305 lines (212 loc) · 8.92 KB

OPC UA Client Improvements - Suggestions from opcua-smart Analysis

Comparison Analysis: opcua-client vs opcua-smart

Architecture & Code Organization

opcua-smart advantages:

  • Modular C Extension Structure: Splits code into separate directories (client/, server/, helpers/)
  • Shared Helper Functions: Reusable functions in finders.c and values.c
  • Separate Header Files: Clean separation of interface (.h) and implementation (.c)

opcua-client current state:

  • Single monolithic C file (opcua_client.c) with all functionality

SUGGESTIONS FOR IMPROVEMENT

1. Value Conversion & Type Handling [HIGH PRIORITY]

Current Issue: Repetitive type conversion code scattered throughout read/write functions

Suggestion: Extract value conversion to helper functions (like opcua-smart's values.c)

  • Create extract_value() function that returns [value, type_symbol]
  • Create value_to_variant() function that converts Ruby values to UA_Variant
  • Support automatic type detection from Ruby values
  • Return type metadata along with values (useful for debugging)

Benefits:

  • Reduce code duplication significantly
  • Support automatic type detection from Ruby values
  • Return type metadata along with values
  • Enable easier addition of new types

Example from opcua-smart: VALUE extract_value(UA_Variant value) { VALUE ret = rb_ary_new2(2); rb_ary_store(ret,0,Qnil); // actual value rb_ary_store(ret,1,Qnil); // type symbol // ... conversion logic return ret; }


2. Generic Read/Write Methods [HIGH PRIORITY]

Current Issue: Separate methods for each type (read_int32, read_float, etc.)

Suggestion: Add generic get() method (like opcua-smart) that:

  • Accepts namespace and node identifier (numeric or string)
  • Returns a node object with .value accessor
  • Automatically detects and converts types
  • Supports both get(ns, id) and get(id) with default namespace

Benefits:

  • Simpler API for users who don't know the exact type
  • Fewer method calls to remember
  • More flexible - works with any type
  • Keep existing type-specific methods for performance-critical code

3. Node Objects [MEDIUM PRIORITY]

Current Issue: Returns raw values; no node abstraction

Suggestion: Introduce Node classes (like opcua-smart's cVarNode, cMethodNode)

  • Client#get() returns a Node object
  • Node has .value and .value= methods
  • Node has .id() and .to_s() methods for inspection
  • Different node classes for variables, methods, objects

Benefits:

  • Object-oriented API - more Ruby-like
  • Lazy evaluation - read value only when accessed
  • Metadata access - inspect node properties
  • Method invocation - call OPC UA methods naturally

4. URL Parsing with Authentication [MEDIUM PRIORITY]

Current Issue: Requires separate connect and authentication calls

Suggestion: Parse URL in initialize() to extract credentials (like opcua-smart)

Example:

Support URLs like: opc.tcp://user:pass@localhost:4840

def initialize(url, user=nil, pass=nil) if url =~ /(^[^:]+)://([^:]+):([^@]+)@(.*)$/ initialize_base("#{$1}://#{$4}", $2, $3) else initialize_base(url, user, pass) end end

Benefits:

  • Single-line connection with authentication
  • Standard URL format familiar to developers
  • Backward compatible - still accepts separate user/pass

5. Node ID String Parsing [HIGH PRIORITY]

Current Issue: Requires separate namespace and identifier parameters

Suggestion: Add support for OPC UA standard node ID strings (like opcua-smart)

Example:

Support both:

client.get(5, "temperature") # Current style client.get("ns=5;s=temperature") # OPC UA standard format client.get("ns=5;i=1234") # Numeric identifier

Benefits:

  • Standard OPC UA format - copy-paste from other tools
  • Simpler for string identifiers - one parameter instead of two
  • Backward compatible - keep existing API

6. Default Namespace Support [HIGH PRIORITY]

Current Issue: Must always specify namespace index

Suggestion: Add default_ns property (like opcua-smart)

Example: client.default_ns = 5 client.get("temperature") # Uses namespace 5

Benefits:

  • Less repetition when working with single namespace
  • Cleaner code for common use cases
  • Still allows override when needed

7. Subscription Management [MEDIUM PRIORITY]

Current Issue: Basic subscription support

Suggestion: Improve subscription API (inspired by opcua-smart)

  • Add subscription_interval property
  • Add check_subscription() method for manual iteration
  • Support on_change blocks with timestamp and type metadata
  • Return [value, timestamp, type] to callbacks

10. Memory Management [COMPLETE]

Current Status: ALREADY FIXED!

Note: opcua-client now uses TypedData_Get_Struct correctly opcua-smart still uses older Data_Get_Struct - opcua-client is ahead here!


11. Helper Functions for Node Browsing [LOW PRIORITY]

Current Issue: No helper functions for browsing node references

Suggestion: Add helper functions (like opcua-smart's finders.c)

  • client_node_get_reference_by_name() - find child by name
  • client_node_get_reference_by_type() - find reference by type
  • client_node_list_references() - list all references

Benefits:

  • Node discovery - explore server structure
  • Relationship traversal - follow references
  • Reusable code - DRY principle

12. Array Dimension Support [LOW PRIORITY]

Current Issue: Arrays supported but no multi-dimensional array support

Suggestion: Add array dimension handling (like opcua-smart)

  • Read/write arrayDimensions attribute
  • Support multi-dimensional arrays
  • Set valueRank when writing arrays

Benefits:

  • Full OPC UA compliance - support all array types
  • Matrix data - 2D/3D arrays for scientific applications

13. Alias Methods [LOW PRIORITY]

Current Issue: Only one method name per operation

Suggestion: Add Ruby-style aliases

Example: rb_define_method(cClient, "read_bool", rb_readBooleanValue, 2); rb_define_method(cClient, "read_boolean", rb_readBooleanValue, 2); // alias

Benefits:

  • Flexibility - users choose preferred style
  • Compatibility - match other OPC UA libraries

14. Code Structure Improvements [LOW PRIORITY]

Suggestion: Refactor into multiple files

  • opcua_client.c - main client code
  • opcua_values.c - value conversion helpers
  • opcua_finders.c - node browsing helpers
  • opcua_types.c - type definitions and constants

Benefits:

  • Maintainability - easier to find and modify code
  • Testability - test helpers independently
  • Reusability - share code between client/server if needed

15. DateTime Support [LOW PRIORITY]

Current Issue: No DateTime type support

Suggestion: Add DateTime type (like opcua-smart)

Example: UA_DateTime tmp = UA_DateTime_fromUnixTime(rb_time_timeval(value).tv_sec);

Benefits:

  • Timestamp values - essential for industrial data
  • Time-series data - historical data access

PRIORITY RANKING

High Priority (Most Impact):

  1. Value conversion helpers (#1) - Reduces code duplication significantly
  2. Generic get() method (#2) - Simplifies API dramatically
  3. Node ID string parsing (#5) - Standard OPC UA format
  4. Default namespace (#6) - Cleaner code for common cases

Medium Priority (Nice to Have):

  1. Node objects (#3) - More Ruby-like API
  2. URL parsing (#4) - Convenience feature
  3. Type constants (#8) - Better documentation
  4. Error messages (#9) - Better debugging
  5. Subscription management (#7) - Advanced features

Low Priority (Advanced Features):

  1. Helper functions (#11) - For advanced browsing
  2. Array dimensions (#12) - For scientific applications
  3. DateTime support (#15) - For time-series data
  4. Alias methods (#13) - Convenience
  5. Code restructuring (#14) - Long-term maintainability

SUMMARY

The opcua-smart repository demonstrates several excellent patterns:

  • Cleaner abstraction with node objects
  • Better code organization with helper functions
  • More flexible API with generic methods and string parsing
  • Ruby-friendly conventions with default values and aliases

However, opcua-client has some advantages:

  • More complete type support (Int64, UInt64, SByte, etc.)
  • Better array support (comprehensive read/write for all types)
  • Modern Ruby C API (TypedData_Get_Struct)

RECOMMENDED APPROACH

Combine the strengths of both:

  • Keep opcua-client's comprehensive type and array support
  • Add opcua-smart's cleaner API and helper functions
  • Maintain backward compatibility while adding new features

IMPLEMENTATION NOTES

When implementing these suggestions:

  1. Start with high-priority items that provide most value
  2. Maintain backward compatibility - don't break existing code
  3. Add new features alongside existing methods
  4. Write tests for each new feature
  5. Update documentation as features are added
  6. Consider creating a migration guide for users

REFERENCES


End of suggestions.