36 lstcolwidths = [ 100, 50, 100, 100, 100, 50] |
36 lstcolwidths = [ 100, 50, 100, 100, 100, 50] |
37 lstcoltypess = [ str, int, str, str, str, int] |
37 lstcoltypess = [ str, int, str, str, str, int] |
38 |
38 |
39 directions = ["input", "output"] |
39 directions = ["input", "output"] |
40 |
40 |
|
41 authParams = { |
|
42 "x509":[ |
|
43 ("Certificate", "certificate.der"), |
|
44 ("PrivateKey", "private_key.pem"), |
|
45 ("Policy", "Basic256Sha256"), |
|
46 ("Mode", "SignAndEncrypt")], |
|
47 "UserPassword":[ |
|
48 ("User", None), |
|
49 ("Password", None)]} |
|
50 |
41 class OPCUASubListModel(dv.DataViewIndexListModel): |
51 class OPCUASubListModel(dv.DataViewIndexListModel): |
42 def __init__(self, data, log): |
52 def __init__(self, data, log): |
43 dv.DataViewIndexListModel.__init__(self, len(data)) |
53 dv.DataViewIndexListModel.__init__(self, len(data)) |
44 self.data = data |
54 self.data = data |
45 self.log = log |
55 self.log = log |
228 fileidx = il.Add(wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, isz)) |
238 fileidx = il.Add(wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, isz)) |
229 smileidx = il.Add(wx.ArtProvider.GetBitmap(wx.ART_ADD_BOOKMARK, wx.ART_OTHER, isz)) |
239 smileidx = il.Add(wx.ArtProvider.GetBitmap(wx.ART_ADD_BOOKMARK, wx.ART_OTHER, isz)) |
230 |
240 |
231 |
241 |
232 class OPCUAClientPanel(wx.SplitterWindow): |
242 class OPCUAClientPanel(wx.SplitterWindow): |
233 def __init__(self, parent, modeldata, log, uri_getter): |
243 def __init__(self, parent, modeldata, log, config_getter): |
234 self.log = log |
244 self.log = log |
235 wx.SplitterWindow.__init__(self, parent, -1) |
245 wx.SplitterWindow.__init__(self, parent, -1) |
236 |
246 |
237 self.ordered_nodes = [] |
247 self.ordered_nodes = [] |
238 |
248 |
240 self.inout_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) |
250 self.inout_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) |
241 self.inout_sizer.AddGrowableCol(0) |
251 self.inout_sizer.AddGrowableCol(0) |
242 self.inout_sizer.AddGrowableRow(1) |
252 self.inout_sizer.AddGrowableRow(1) |
243 |
253 |
244 self.client = None |
254 self.client = None |
245 self.uri_getter = uri_getter |
255 self.config_getter = config_getter |
246 |
256 |
247 self.connect_button = wx.ToggleButton(self.inout_panel, -1, "Browse Server") |
257 self.connect_button = wx.ToggleButton(self.inout_panel, -1, "Browse Server") |
248 |
258 |
249 self.selected_splitter = wx.SplitterWindow(self.inout_panel, style=wx.SUNKEN_BORDER | wx.SP_3D) |
259 self.selected_splitter = wx.SplitterWindow(self.inout_panel, style=wx.SUNKEN_BORDER | wx.SP_3D) |
250 |
260 |
296 self.tree.AddColumn(colname) |
306 self.tree.AddColumn(colname) |
297 self.tree.SetColumnWidth(idx, width) |
307 self.tree.SetColumnWidth(idx, width) |
298 |
308 |
299 self.tree.SetMainColumn(0) |
309 self.tree.SetMainColumn(0) |
300 |
310 |
301 self.client = Client(self.uri_getter()) |
311 config = self.config_getter() |
|
312 self.client = Client(config["URI"]) |
|
313 |
|
314 # TODO: crypto stuff |
|
315 # client.set_security_string("Basic256Sha256,SignAndEncrypt,certificate-example.der,private-key-example.pem") |
|
316 |
302 self.client.connect() |
317 self.client.connect() |
303 self.client.load_type_definitions() # load definition of server specific structures/extension objects |
318 self.client.load_type_definitions() # load definition of server specific structures/extension objects |
304 rootnode = self.client.get_root_node() |
319 rootnode = self.client.get_root_node() |
305 |
320 |
306 rootitem = self.AddNodeItem(self.tree.AddRoot, rootnode) |
321 rootitem = self.AddNodeItem(self.tree.AddRoot, rootnode) |
476 writer = csv.writer(csvfile, delimiter=',', |
491 writer = csv.writer(csvfile, delimiter=',', |
477 quotechar='"', quoting=csv.QUOTE_MINIMAL) |
492 quotechar='"', quoting=csv.QUOTE_MINIMAL) |
478 for row in data: |
493 for row in data: |
479 writer.writerow([direction] + row) |
494 writer.writerow([direction] + row) |
480 |
495 |
481 def GenerateC(self, path, locstr, server_uri): |
496 def GenerateC(self, path, locstr, config): |
482 template = """/* code generated by beremiz OPC-UA extension */ |
497 template = """/* code generated by beremiz OPC-UA extension */ |
483 |
498 |
484 #include <open62541/client_config_default.h> |
499 #include <open62541/client_config_default.h> |
485 #include <open62541/client_highlevel.h> |
500 #include <open62541/client_highlevel.h> |
486 #include <open62541/plugin/log_stdout.h> |
501 #include <open62541/plugin/log_stdout.h> |
490 #define DECL_VAR(ua_type, C_type, c_loc_name) \\ |
505 #define DECL_VAR(ua_type, C_type, c_loc_name) \\ |
491 static UA_Variant c_loc_name##_variant; \\ |
506 static UA_Variant c_loc_name##_variant; \\ |
492 static C_type c_loc_name##_buf = 0; \\ |
507 static C_type c_loc_name##_buf = 0; \\ |
493 C_type *c_loc_name = &c_loc_name##_buf; |
508 C_type *c_loc_name = &c_loc_name##_buf; |
494 |
509 |
495 %(decl)s |
510 {decl} |
496 |
511 |
497 void __cleanup_%(locstr)s(void) |
512 void __cleanup_{locstr}(void) |
498 { |
513 {{ |
499 UA_Client_disconnect(client); |
514 UA_Client_disconnect(client); |
500 UA_Client_delete(client); |
515 UA_Client_delete(client); |
501 } |
516 }} |
502 |
517 |
503 |
518 |
504 #define INIT_READ_VARIANT(ua_type, c_loc_name) \\ |
519 #define INIT_READ_VARIANT(ua_type, c_loc_name) \\ |
505 UA_Variant_init(&c_loc_name##_variant); |
520 UA_Variant_init(&c_loc_name##_variant); |
506 |
521 |
507 #define INIT_WRITE_VARIANT(ua_type, ua_type_enum, c_loc_name) \\ |
522 #define INIT_WRITE_VARIANT(ua_type, ua_type_enum, c_loc_name) \\ |
508 UA_Variant_setScalar(&c_loc_name##_variant, (ua_type*)c_loc_name, &UA_TYPES[ua_type_enum]); |
523 UA_Variant_setScalar(&c_loc_name##_variant, (ua_type*)c_loc_name, &UA_TYPES[ua_type_enum]); |
509 |
524 |
510 int __init_%(locstr)s(int argc,char **argv) |
525 int __init_{locstr}(int argc,char **argv) |
511 { |
526 {{ |
512 UA_StatusCode retval; |
527 UA_StatusCode retval; |
513 client = UA_Client_new(); |
528 client = UA_Client_new(); |
514 UA_ClientConfig_setDefault(UA_Client_getConfig(client)); |
529 UA_ClientConfig_setDefault(UA_Client_getConfig(client)); |
515 %(init)s |
530 {init} |
516 |
531 |
517 /* Connect to server */ |
532 /* Connect to server */ |
518 retval = UA_Client_connect(client, "%(uri)s"); |
533 retval = UA_Client_connect(client, "{uri}"); |
519 if(retval != UA_STATUSCODE_GOOD) { |
534 if(retval != UA_STATUSCODE_GOOD) {{ |
520 UA_Client_delete(client); |
535 UA_Client_delete(client); |
521 return EXIT_FAILURE; |
536 return EXIT_FAILURE; |
522 } |
537 }} |
523 } |
538 }} |
524 |
539 |
525 #define READ_VALUE(ua_type, ua_type_enum, c_loc_name, ua_nodeid_type, ua_nsidx, ua_node_id) \\ |
540 #define READ_VALUE(ua_type, ua_type_enum, c_loc_name, ua_nodeid_type, ua_nsidx, ua_node_id) \\ |
526 retval = UA_Client_readValueAttribute( \\ |
541 retval = UA_Client_readValueAttribute( \\ |
527 client, ua_nodeid_type(ua_nsidx, ua_node_id), &c_loc_name##_variant); \\ |
542 client, ua_nodeid_type(ua_nsidx, ua_node_id), &c_loc_name##_variant); \\ |
528 if(retval == UA_STATUSCODE_GOOD && UA_Variant_isScalar(&c_loc_name##_variant) && \\ |
543 if(retval == UA_STATUSCODE_GOOD && UA_Variant_isScalar(&c_loc_name##_variant) && \\ |
529 c_loc_name##_variant.type == &UA_TYPES[ua_type_enum]) { \\ |
544 c_loc_name##_variant.type == &UA_TYPES[ua_type_enum]) {{ \\ |
530 c_loc_name##_buf = *(ua_type*)c_loc_name##_variant.data; \\ |
545 c_loc_name##_buf = *(ua_type*)c_loc_name##_variant.data; \\ |
531 UA_Variant_clear(&c_loc_name##_variant); /* Unalloc requiered on each read ! */ \\ |
546 UA_Variant_clear(&c_loc_name##_variant); /* Unalloc requiered on each read ! */ \\ |
532 } |
547 }} |
533 |
548 |
534 void __retrieve_%(locstr)s(void) |
549 void __retrieve_{locstr}(void) |
535 { |
550 {{ |
536 UA_StatusCode retval; |
551 UA_StatusCode retval; |
537 %(retrieve)s |
552 {retrieve} |
538 } |
553 }} |
539 |
554 |
540 #define WRITE_VALUE(ua_type, c_loc_name, ua_nodeid_type, ua_nsidx, ua_node_id) \\ |
555 #define WRITE_VALUE(ua_type, c_loc_name, ua_nodeid_type, ua_nsidx, ua_node_id) \\ |
541 UA_Client_writeValueAttribute( \\ |
556 UA_Client_writeValueAttribute( \\ |
542 client, ua_nodeid_type(ua_nsidx, ua_node_id), &c_loc_name##_variant); |
557 client, ua_nodeid_type(ua_nsidx, ua_node_id), &c_loc_name##_variant); |
543 |
558 |
544 void __publish_%(locstr)s(void) |
559 void __publish_{locstr}(void) |
545 { |
560 {{ |
546 %(publish)s |
561 {publish} |
547 } |
562 }} |
548 |
563 |
549 """ |
564 """ |
550 |
565 |
551 formatdict = dict( |
566 formatdict = dict( |
552 locstr = locstr, |
567 locstr = locstr, |
553 uri = server_uri, |
568 uri = config["URI"], |
|
569 # TODO: pass authentication code. |
554 decl = "", |
570 decl = "", |
555 cleanup = "", |
571 cleanup = "", |
556 init = "", |
572 init = "", |
557 retrieve = "", |
573 retrieve = "", |
558 publish = "" |
574 publish = "" |
579 formatdict["init"] +=""" |
595 formatdict["init"] +=""" |
580 INIT_WRITE_VARIANT({ua_type}, {ua_type_enum}, {c_loc_name})""".format(**locals()) |
596 INIT_WRITE_VARIANT({ua_type}, {ua_type_enum}, {c_loc_name})""".format(**locals()) |
581 formatdict["publish"] += """ |
597 formatdict["publish"] += """ |
582 WRITE_VALUE({ua_type}, {c_loc_name}, {ua_nodeid_type}, {ua_nsidx}, {ua_node_id})""".format(**locals()) |
598 WRITE_VALUE({ua_type}, {c_loc_name}, {ua_nodeid_type}, {ua_nsidx}, {ua_node_id})""".format(**locals()) |
583 |
599 |
584 Ccode = template%formatdict |
600 Ccode = template.format(**formatdict) |
585 |
601 |
586 return Ccode |
602 return Ccode |
587 |
603 |
588 if __name__ == "__main__": |
604 if __name__ == "__main__": |
589 |
605 |
592 |
608 |
593 app = wit.InspectableApp() |
609 app = wit.InspectableApp() |
594 |
610 |
595 frame = wx.Frame(None, -1, "OPCUA Client Test App", size=(800,600)) |
611 frame = wx.Frame(None, -1, "OPCUA Client Test App", size=(800,600)) |
596 |
612 |
597 uri = sys.argv[1] if len(sys.argv)>1 else "opc.tcp://localhost:4840" |
613 argc = len(sys.argv) |
|
614 |
|
615 config={} |
|
616 config["URI"] = sys.argv[1] if argc>1 else "opc.tcp://localhost:4840" |
|
617 |
|
618 if argc > 2: |
|
619 AuthType = sys.argv[2] |
|
620 config["AuthType"] = AuthType |
|
621 for (name, default), value in izip_longest(authParams[AuthType], sys.argv[3:]): |
|
622 if value is None: |
|
623 if default is None: |
|
624 raise Exception(name+" param expected") |
|
625 value = default |
|
626 config[name] = value |
598 |
627 |
599 test_panel = wx.Panel(frame) |
628 test_panel = wx.Panel(frame) |
600 test_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) |
629 test_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) |
601 test_sizer.AddGrowableCol(0) |
630 test_sizer.AddGrowableCol(0) |
602 test_sizer.AddGrowableRow(0) |
631 test_sizer.AddGrowableRow(0) |
603 |
632 |
604 modeldata = OPCUAClientModel(print) |
633 modeldata = OPCUAClientModel(print) |
605 |
634 |
606 opcuatestpanel = OPCUAClientPanel(test_panel, modeldata, print, lambda:uri) |
635 opcuatestpanel = OPCUAClientPanel(test_panel, modeldata, print, lambda:config) |
607 |
636 |
608 def OnGenerate(evt): |
637 def OnGenerate(evt): |
609 dlg = wx.FileDialog( |
638 dlg = wx.FileDialog( |
610 frame, message="Generate file as ...", defaultDir=os.getcwd(), |
639 frame, message="Generate file as ...", defaultDir=os.getcwd(), |
611 defaultFile="", |
640 defaultFile="", |