97 # notify the view(s) using this model that it has been removed |
97 # notify the view(s) using this model that it has been removed |
98 self.RowDeleted(row) |
98 self.RowDeleted(row) |
99 |
99 |
100 |
100 |
101 def AddRow(self, value): |
101 def AddRow(self, value): |
102 v = dict(zip(lstcolnames, value)) |
102 if self.data.append(value): |
103 |
103 # notify views |
104 if type(v["IEC"]) != int: |
104 self.RowAppended() |
105 if len(self.data) == 0: |
|
106 v["IEC"] = 0 |
|
107 else: |
|
108 iecnums = set(zip(*self.data)[lstcolnames.index("IEC")]) |
|
109 greatest = max(iecnums) |
|
110 holes = set(range(greatest)) - iecnums |
|
111 v["IEC"] = min(holes) if holes else greatest+1 |
|
112 |
|
113 if v["IdType"] not in UA_NODE_ID_types: |
|
114 self.log("Unknown IdType\n".format(value)) |
|
115 return |
|
116 |
|
117 try: |
|
118 for t,n in zip(lstcoltypess, lstcolnames): |
|
119 v[n] = t(v[n]) |
|
120 except ValueError: |
|
121 self.log("Variable {} (Id={}) has invalid type\n".format(v["Name"],v["Id"])) |
|
122 return |
|
123 |
|
124 if len(self.data)>0 and v["Id"] in zip(*self.data)[lstcolnames.index("Id")]: |
|
125 self.log("Variable {} (Id={}) already in list\n".format(v["Name"],v["Id"])) |
|
126 return |
|
127 |
|
128 self.data.append([v[n] for n in lstcolnames]) |
|
129 |
|
130 # notify views |
|
131 self.RowAppended() |
|
132 |
105 |
133 def ResetData(self): |
106 def ResetData(self): |
134 self.Reset(len(self.data)) |
107 self.Reset(len(self.data)) |
135 |
108 |
136 OPCUAClientDndMagicWord = "text/beremiz-opcuaclient" |
109 OPCUAClientDndMagicWord = "text/beremiz-opcuaclient" |
199 # splitter. panel. splitter |
172 # splitter. panel. splitter |
200 ClientPanel = self.GetParent().GetParent().GetParent() |
173 ClientPanel = self.GetParent().GetParent().GetParent() |
201 nodes = ClientPanel.GetSelectedNodes() |
174 nodes = ClientPanel.GetSelectedNodes() |
202 for node in nodes: |
175 for node in nodes: |
203 cname = node.get_node_class().name |
176 cname = node.get_node_class().name |
204 dname = node.get_display_name().to_string() |
177 dname = node.get_display_name().Text |
205 if cname != "Variable": |
178 if cname != "Variable": |
206 self.log("Node {} ignored (not a variable)".format(dname)) |
179 self.log("Node {} ignored (not a variable)".format(dname)) |
207 continue |
180 continue |
208 |
181 |
209 tname = node.get_data_type_as_variant_type().name |
182 tname = node.get_data_type_as_variant_type().name |
443 def Reset(self): |
416 def Reset(self): |
444 for direction in directions: |
417 for direction in directions: |
445 self.selected_models[direction].ResetData() |
418 self.selected_models[direction].ResetData() |
446 |
419 |
447 |
420 |
|
421 class OPCUAClientList(list): |
|
422 def __init__(self, log = lambda m:None): |
|
423 super(OPCUAClientList, self).__init__(self) |
|
424 self.log = log |
|
425 |
|
426 def append(self, value): |
|
427 v = dict(zip(lstcolnames, value)) |
|
428 |
|
429 if type(v["IEC"]) != int: |
|
430 if len(self) == 0: |
|
431 v["IEC"] = 0 |
|
432 else: |
|
433 iecnums = set(zip(*self)[lstcolnames.index("IEC")]) |
|
434 greatest = max(iecnums) |
|
435 holes = set(range(greatest)) - iecnums |
|
436 v["IEC"] = min(holes) if holes else greatest+1 |
|
437 |
|
438 if v["IdType"] not in UA_NODE_ID_types: |
|
439 self.log("Unknown IdType\n".format(value)) |
|
440 return False |
|
441 |
|
442 try: |
|
443 for t,n in zip(lstcoltypess, lstcolnames): |
|
444 v[n] = t(v[n]) |
|
445 except ValueError: |
|
446 self.log("Variable {} (Id={}) has invalid type\n".format(v["Name"],v["Id"])) |
|
447 return False |
|
448 |
|
449 if len(self)>0 and v["Id"] in zip(*self)[lstcolnames.index("Id")]: |
|
450 self.log("Variable {} (Id={}) already in list\n".format(v["Name"],v["Id"])) |
|
451 return False |
|
452 |
|
453 list.append(self, [v[n] for n in lstcolnames]) |
|
454 |
|
455 return True |
|
456 |
448 class OPCUAClientModel(dict): |
457 class OPCUAClientModel(dict): |
449 def __init__(self): |
458 def __init__(self, log = lambda m:None): |
|
459 super(OPCUAClientModel, self).__init__() |
450 for direction in directions: |
460 for direction in directions: |
451 self[direction] = list() |
461 self[direction] = OPCUAClientList(log) |
452 |
462 |
453 def LoadCSV(self,path): |
463 def LoadCSV(self,path): |
454 with open(path, 'rb') as csvfile: |
464 with open(path, 'rb') as csvfile: |
455 reader = csv.reader(csvfile, delimiter=',', quotechar='"') |
465 reader = csv.reader(csvfile, delimiter=',', quotechar='"') |
456 buf = {direction:[] for direction, _model in self.iteritems()} |
466 buf = {direction:[] for direction, _model in self.iteritems()} |
|
467 for direction, model in self.iteritems(): |
|
468 self[direction][:] = [] |
457 for row in reader: |
469 for row in reader: |
458 direction = row[0] |
470 direction = row[0] |
459 buf[direction].append(row[1:]) |
471 self[direction].append(row[1:]) |
460 for direction, model in self.iteritems(): |
|
461 self[direction][:] = buf[direction] |
|
462 |
472 |
463 def SaveCSV(self,path): |
473 def SaveCSV(self,path): |
464 with open(path, 'wb') as csvfile: |
474 with open(path, 'wb') as csvfile: |
465 for direction, data in self.iteritems(): |
475 for direction, data in self.iteritems(): |
466 writer = csv.writer(csvfile, delimiter=',', |
476 writer = csv.writer(csvfile, delimiter=',', |
585 test_panel = wx.Panel(frame) |
595 test_panel = wx.Panel(frame) |
586 test_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) |
596 test_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) |
587 test_sizer.AddGrowableCol(0) |
597 test_sizer.AddGrowableCol(0) |
588 test_sizer.AddGrowableRow(0) |
598 test_sizer.AddGrowableRow(0) |
589 |
599 |
590 modeldata = OPCUAClientModel() |
600 modeldata = OPCUAClientModel(print) |
591 |
601 |
592 opcuatestpanel = OPCUAClientPanel(test_panel, modeldata, print, lambda:uri) |
602 opcuatestpanel = OPCUAClientPanel(test_panel, modeldata, print, lambda:uri) |
593 |
603 |
594 def OnGenerate(evt): |
604 def OnGenerate(evt): |
595 dlg = wx.FileDialog( |
605 dlg = wx.FileDialog( |