Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
opcua-asyncio
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Nikola Balog
opcua-asyncio
Commits
b23fcfcb
Commit
b23fcfcb
authored
Aug 28, 2016
by
olivier R-D
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
improve parsing of values in xml
parent
52dd77dd
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
72 additions
and
45 deletions
+72
-45
opcua/common/xmlparser.py
opcua/common/xmlparser.py
+37
-14
schemas/generate_address_space.py
schemas/generate_address_space.py
+35
-31
No files found.
opcua/common/xmlparser.py
View file @
b23fcfcb
...
...
@@ -36,8 +36,8 @@ class NodeData(object):
# referencetype
self
.
inversename
=
""
self
.
abstract
=
"false"
self
.
symmetric
=
"false"
self
.
abstract
=
False
self
.
symmetric
=
False
# datatype
self
.
definition
=
[]
...
...
@@ -51,6 +51,15 @@ class RefStruct(object):
self
.
target
=
None
class
ExtObj
(
object
):
def
__init__
(
self
):
self
.
typeid
=
None
self
.
objname
=
None
self
.
bodytype
=
None
self
.
body
=
{}
class
XMLParser
(
object
):
def
__init__
(
self
,
xmlpath
,
server
):
...
...
@@ -194,6 +203,7 @@ class XMLParser(object):
obj
.
nodetype
=
name
for
key
,
val
in
child
.
attrib
.
items
():
self
.
_set_attr
(
key
,
val
,
obj
)
self
.
logger
.
info
(
"
\
n
Parsing node: %s %s"
,
obj
.
nodeid
,
obj
.
browsename
)
obj
.
displayname
=
obj
.
browsename
# give a default value to display name
for
el
in
child
:
self
.
_parse_tag
(
el
,
obj
)
...
...
@@ -211,7 +221,9 @@ class XMLParser(object):
elif
key
==
"DataType"
:
obj
.
datatype
=
val
elif
key
==
"IsAbstract"
:
obj
.
abstract
=
val
obj
.
abstract
=
self
.
_to_bool
(
val
)
elif
key
==
"Executable"
:
obj
.
executable
=
self
.
_to_bool
(
val
)
elif
key
==
"EventNotifier"
:
obj
.
eventnotifier
=
1
if
val
==
"1"
else
0
elif
key
==
"ValueRank"
:
...
...
@@ -225,10 +237,15 @@ class XMLParser(object):
elif
key
==
"UserAccessLevel"
:
obj
.
useraccesslevel
=
int
(
val
)
elif
key
==
"Symmetric"
:
obj
.
symmetric
=
True
if
val
==
"true"
else
False
obj
.
symmetric
=
self
.
_to_bool
(
val
)
else
:
self
.
logger
.
info
(
"Attribute not implemented: %s:%s"
,
key
,
val
)
def
_to_bool
(
self
,
val
):
if
val
in
(
"False, false"
):
return
False
else
:
return
True
def
_parse_tag
(
self
,
el
,
obj
):
tag
=
self
.
_retag
.
match
(
el
.
tag
).
groups
()[
1
]
...
...
@@ -249,7 +266,9 @@ class XMLParser(object):
self
.
logger
.
info
(
"Not implemented tag: %s"
,
el
)
def
_parse_value
(
self
,
el
,
obj
):
self
.
logger
.
info
(
"Parsing value"
)
for
val
in
el
:
self
.
logger
.
info
(
"tag %s"
,
val
.
tag
)
ntag
=
self
.
_retag
.
match
(
val
.
tag
).
groups
()[
1
]
obj
.
valuetype
=
ntag
if
ntag
in
(
"Int8"
,
"UInt8"
,
"Int16"
,
"UInt16"
,
"Int32"
,
"UInt32"
,
"Int64"
,
"UInt64"
):
...
...
@@ -271,11 +290,13 @@ class XMLParser(object):
elif
ntag
in
(
"Guid"
):
self
.
_parse_value
(
val
,
obj
)
elif
ntag
==
"ListOfExtensionObject"
:
obj
.
value
,
obj
.
valuetype
=
self
.
_parse_list_of_extension_object
(
el
)
obj
.
valuetype
=
"ExtensionObject"
obj
.
value
=
self
.
_parse_list_of_extension_object
(
el
)
elif
ntag
==
"ListOfLocalizedText"
:
obj
.
valuetype
=
"LocalizedText"
obj
.
value
=
self
.
_parse_list_of_localized_text
(
el
)
else
:
self
.
logger
.
info
(
"Value type not implemented: %s"
,
ntag
)
self
.
logger
.
info
(
"Value type not implemented:
'%s',
%s"
,
ntag
)
def
_get_text
(
self
,
el
):
txt
=
""
...
...
@@ -302,26 +323,28 @@ class XMLParser(object):
also the valuetype is returned. The valuetype is uax:ExtensionObject/*/tag()
'''
value
=
[]
valuetype
=
None
for
extension_object_list
in
el
:
for
extension_object
in
extension_object_list
:
extension_object
.
find
(
'Body'
)
for
extension_object_part
in
extension_object
:
ext
=
ExtObj
()
ntag
=
self
.
_retag
.
match
(
extension_object_part
.
tag
).
groups
()[
1
]
if
ntag
==
'Body'
:
data
=
{}
if
ntag
==
'TypeId'
:
ntag
=
self
.
_retag
.
match
(
extension_object_part
.
find
(
'*'
).
tag
).
groups
()[
1
]
ext
.
typeid
=
self
.
_get_text
(
extension_object_part
)
elif
ntag
==
'Body'
:
ntag
=
self
.
_retag
.
match
(
extension_object_part
.
find
(
'*'
).
tag
).
groups
()[
1
]
valuetyp
e
=
ntag
ext
.
objnam
e
=
ntag
for
body_item
in
extension_object_part
.
findall
(
'*/*'
):
ntag
=
self
.
_retag
.
match
(
body_item
.
tag
).
groups
()[
1
]
child
=
body_item
.
find
(
'*'
)
if
child
is
not
None
:
data
[
ntag
]
=
self
.
_get_text
(
child
)
ext
.
body
[
ntag
]
=
self
.
_get_text
(
child
)
else
:
data
[
ntag
]
=
self
.
_get_text
(
body_item
)
value
.
append
(
data
)
return
value
,
valuetype
ext
.
body
[
ntag
]
=
self
.
_get_text
(
body_item
)
value
.
append
(
ext
)
return
value
def
_parse_refs
(
self
,
el
,
obj
):
for
ref
in
el
:
...
...
schemas/generate_address_space.py
View file @
b23fcfcb
...
...
@@ -3,6 +3,7 @@ Generate address space c++ code from xml file specification
xmlparser.py is a requirement. it is in opcua folder but to avoid importing all code, developer can link xmlparser.py in current directory
"""
import
sys
import
logging
# sys.path.insert(0, "..") # load local freeopcua implementation
#from opcua import xmlparser
import
xmlparser
...
...
@@ -21,7 +22,7 @@ class CodeGenerator(object):
sys
.
stderr
.
write
(
"Generating Python code {} for XML file {}"
.
format
(
self
.
output_path
,
self
.
input_path
)
+
"
\
n
"
)
self
.
output_file
=
open
(
self
.
output_path
,
"w"
)
self
.
make_header
()
self
.
parser
=
xmlparser
.
XMLParser
(
self
.
input_path
)
self
.
parser
=
xmlparser
.
XMLParser
(
self
.
input_path
,
None
)
for
node
in
self
.
parser
:
if
node
.
nodetype
==
'UAObject'
:
self
.
make_object_code
(
node
)
...
...
@@ -53,8 +54,6 @@ It is automatically generated from opcfoundation.org schemas.
from opcua import ua
false = False #FIXME
true = True #FIXME
def create_standard_address_space_%s(server):
'''
%
(
self
.
part
))
...
...
@@ -110,27 +109,48 @@ def create_standard_address_space_%s(server):
self
.
writecode
(
indent
,
'server.add_nodes([node])'
)
self
.
make_refs_code
(
obj
,
indent
)
def
make_variable_code
(
self
,
obj
):
indent
=
" "
self
.
writecode
(
indent
)
self
.
make_node_code
(
obj
,
indent
)
self
.
writecode
(
indent
,
'attrs = ua.VariableAttributes()'
)
def
make_common_variable_code
(
self
,
indent
,
obj
):
if
obj
.
desc
:
self
.
writecode
(
indent
,
'attrs.Description = ua.LocalizedText("{}")'
.
format
(
obj
.
desc
))
self
.
writecode
(
indent
,
'attrs.DisplayName = ua.LocalizedText("{}")'
.
format
(
obj
.
displayname
))
self
.
writecode
(
indent
,
'attrs.DataType = {}'
.
format
(
self
.
to_data_type
(
obj
.
datatype
)))
if
obj
.
value
:
self
.
writecode
(
indent
,
'attrs.Value = ua.Variant({}, ua.VariantType.{})'
.
format
(
self
.
to_value
(
obj
.
value
),
obj
.
valuetype
))
if
obj
.
value
is
not
None
:
if
obj
.
valuetype
==
"ExtensionObject"
:
if
isinstance
(
obj
.
value
,
(
list
,
tuple
)):
self
.
writecode
(
indent
,
'value = []'
)
for
ext
in
obj
.
value
:
self
.
make_ext_obj_code
(
indent
,
ext
)
self
.
writecode
(
indent
,
'value.append(extobj)'
)
else
:
self
.
make_ext_obj_code
(
indent
,
obj
.
value
)
self
.
writecode
(
indent
,
'value = extobj'
)
self
.
writecode
(
indent
,
'attrs.Value = ua.Variant(value, ua.VariantType.ExtensionObject)'
)
else
:
self
.
writecode
(
indent
,
'attrs.Value = ua.Variant({}, ua.VariantType.{})'
.
format
(
self
.
to_value
(
obj
.
value
),
obj
.
valuetype
))
if
obj
.
rank
:
self
.
writecode
(
indent
,
'attrs.ValueRank = {}'
.
format
(
obj
.
rank
))
if
obj
.
accesslevel
:
self
.
writecode
(
indent
,
'attrs.AccessLevel = {}'
.
format
(
obj
.
accesslevel
))
if
obj
.
useraccesslevel
:
self
.
writecode
(
indent
,
'attrs.UserAccessLevel = {}'
.
format
(
obj
.
useraccesslevel
))
if
obj
.
dimensions
:
self
.
writecode
(
indent
,
'attrs.ArrayDimensions = {}'
.
format
(
obj
.
dimensions
))
def
make_ext_obj_code
(
self
,
indent
,
extobj
):
self
.
writecode
(
indent
,
'extobj = ua.{}()'
.
format
(
extobj
.
objname
))
for
name
,
val
in
extobj
.
body
.
items
():
val
=
val
.
strip
()
if
val
not
in
(
None
,
""
):
self
.
writecode
(
indent
,
'extobj.{} = "{}"'
.
format
(
name
,
val
))
def
make_variable_code
(
self
,
obj
):
indent
=
" "
self
.
writecode
(
indent
)
self
.
make_node_code
(
obj
,
indent
)
self
.
writecode
(
indent
,
'attrs = ua.VariableAttributes()'
)
if
obj
.
minsample
:
self
.
writecode
(
indent
,
'attrs.MinimumSamplingInterval = {}'
.
format
(
obj
.
minsample
))
if
obj
.
dimensions
:
self
.
writecode
(
indent
,
'attrs.ArrayDimensions = '
.
format
(
obj
.
dimensions
))
self
.
make_common_variable_code
(
indent
,
obj
)
self
.
writecode
(
indent
,
'node.NodeAttributes = attrs'
)
self
.
writecode
(
indent
,
'server.add_nodes([node])'
)
self
.
make_refs_code
(
obj
,
indent
)
...
...
@@ -143,18 +163,9 @@ def create_standard_address_space_%s(server):
if
obj
.
desc
:
self
.
writecode
(
indent
,
'attrs.Description = ua.LocalizedText("{}")'
.
format
(
obj
.
desc
))
self
.
writecode
(
indent
,
'attrs.DisplayName = ua.LocalizedText("{}")'
.
format
(
obj
.
displayname
))
self
.
writecode
(
indent
,
'attrs.DataType = {}'
.
format
(
self
.
to_data_type
(
obj
.
datatype
)))
if
obj
.
value
:
self
.
writecode
(
indent
,
'attrs.Value = {}'
.
format
(
self
.
to_value
(
obj
.
value
)))
if
obj
.
value
:
self
.
writecode
(
indent
,
'attrs.Value = {}'
.
format
(
self
.
to_value
(
obj
.
value
)))
if
obj
.
rank
:
self
.
writecode
(
indent
,
'attrs.ValueRank = {}'
.
format
(
obj
.
rank
))
if
obj
.
abstract
:
self
.
writecode
(
indent
,
'attrs.IsAbstract = {}'
.
format
(
obj
.
abstract
))
print
(
obj
.
dimensions
)
if
obj
.
dimensions
:
self
.
writecode
(
indent
,
'attrs.ArrayDimensions = {}'
.
format
(
obj
.
dimensions
))
self
.
make_common_variable_code
(
indent
,
obj
)
self
.
writecode
(
indent
,
'node.NodeAttributes = attrs'
)
self
.
writecode
(
indent
,
'server.add_nodes([node])'
)
self
.
make_refs_code
(
obj
,
indent
)
...
...
@@ -174,14 +185,6 @@ def create_standard_address_space_%s(server):
if
obj
.
desc
:
self
.
writecode
(
indent
,
'attrs.Description = ua.LocalizedText("{}")'
.
format
(
obj
.
desc
))
self
.
writecode
(
indent
,
'attrs.DisplayName = ua.LocalizedText("{}")'
.
format
(
obj
.
displayname
))
if
obj
.
accesslevel
:
self
.
writecode
(
indent
,
'attrs.AccessLevel = {}'
.
format
(
obj
.
accesslevel
))
if
obj
.
useraccesslevel
:
self
.
writecode
(
indent
,
'attrs.UserAccessLevel = {}'
.
format
(
obj
.
useraccesslevel
))
if
obj
.
minsample
:
self
.
writecode
(
indent
,
'attrs.MinimumSamplingInterval = {}'
.
format
(
obj
.
minsample
))
if
obj
.
dimensions
:
self
.
writecode
(
indent
,
'attrs.ArrayDimensions = {}'
.
format
(
obj
.
dimensions
))
self
.
writecode
(
indent
,
'node.NodeAttributes = attrs'
)
self
.
writecode
(
indent
,
'server.add_nodes([node])'
)
self
.
make_refs_code
(
obj
,
indent
)
...
...
@@ -224,7 +227,7 @@ def create_standard_address_space_%s(server):
self
.
writecode
(
indent
,
"refs = []"
)
for
ref
in
obj
.
refs
:
self
.
writecode
(
indent
,
'ref = ua.AddReferencesItem()'
)
self
.
writecode
(
indent
,
'ref.IsForward =
t
rue'
)
self
.
writecode
(
indent
,
'ref.IsForward =
T
rue'
)
self
.
writecode
(
indent
,
'ref.ReferenceTypeId = {}'
.
format
(
self
.
to_ref_type
(
ref
.
reftype
)))
self
.
writecode
(
indent
,
'ref.SourceNodeId = ua.NodeId.from_string("{}")'
.
format
(
obj
.
nodeid
))
self
.
writecode
(
indent
,
'ref.TargetNodeClass = ua.NodeClass.DataType'
)
...
...
@@ -245,6 +248,7 @@ def save_aspace_to_disk():
aspace
.
dump
(
path
)
if
__name__
==
"__main__"
:
logging
.
basicConfig
(
level
=
logging
.
WARN
)
for
i
in
(
3
,
4
,
5
,
8
,
9
,
10
,
11
,
13
):
xmlpath
=
"Opc.Ua.NodeSet2.Part{}.xml"
.
format
(
str
(
i
))
cpppath
=
"../opcua/server/standard_address_space/standard_address_space_part{}.py"
.
format
(
str
(
i
))
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment