def update_recurse(con, submodel, path): err = -1 if len(path) < 1: logger.error("recusion into model went wrong") err = -1 elif len(path) == 1: if submodel[path[0]] and 'reftype' in submodel[ path[0]] and submodel[path[0]]['reftype'] == 'DA': fcName = submodel[path[0]]['FC'] #read DA fc = lib61850.FunctionalConstraint_fromString(fcName) error = lib61850.IedClientError() value = lib61850.IedConnection_readObject( con, ctypes.byref(error), ref, fc) if error.value == 0: submodel[path[0]]['value'], submodel[ path[0]]['type'] = iec61850client.printValue(value) lib61850.MmsValue_delete(value) err = 0 else: logger.error("could not read DA: %s from device" % ref) err = -1 else: submodel[path[0]] = iec61850client.printDataDirectory( con, ref) if submodel[path[0]]: # check if value or empty returned err = 0 else: err = -1 else: submodel[path[0]], err = update_recurse( con, submodel[path[0]], path[1:]) return submodel, err
def getIED(self, host, port): if port == "" or port == None: port = 102 if host == None: logger.error("missing hostname") return -1 tupl = host + ":" + str(port) if tupl in self.connections and self.connections[tupl]["con"] != None: if not self.connections[tupl]["model"]: con = self.connections[tupl]["con"] model = iec61850client.discovery(con) if model: #if model is not empty # store the model self.connections[tupl]["model"] = model return 0 else: #we could not perform a discovery, so remove connection lib61850.IedConnection_destroy(con) self.connections[tupl]["con"] = None return -1 else: #we have a connection and a model return 0 if not tupl in self.connections: self.connections[tupl] = {} self.connections[tupl]["con"] = None self.connections[tupl]["model"] = {} con = lib61850.IedConnection_create() error = lib61850.IedClientError() lib61850.IedConnection_connect(con,ctypes.byref(error), host, port) if error.value == lib61850.IED_ERROR_OK: # store the active connection self.connections[tupl]["con"] = con # read the model model = iec61850client.discovery(con) if model: #if model is not empty # store the model self.connections[tupl]["model"] = model return 0 else: return -1 else: lib61850.IedConnection_destroy(con) return -1
def printDataDirectory(con, doRef): tmodel = {} if doRef.find("/") == -1: logger.error("invalid datadirecory") return {} error = lib61850.IedClientError() dataAttributes = lib61850.IedConnection_getDataDirectoryFC( con, ctypes.byref(error), doRef) if error.value != 0: logger.error("could not get logical device list, error:%i" % error.value) if dataAttributes: dataAttribute = lib61850.LinkedList_getNext(dataAttributes) while dataAttribute: daName = ctypes.cast( lib61850.LinkedList_getData(dataAttribute), ctypes.c_char_p).value.decode("utf-8") daRef = doRef + "." + daName[:-4] fcName = daName[-3:-1] submodel = iec61850client.printDataDirectory(con, daRef) if submodel: tmodel[daName[:-4]] = submodel else: tmodel[daName[:-4]] = {} tmodel[daName[:-4]]['reftype'] = "DA" tmodel[daName[:-4]]['FC'] = fcName tmodel[daName[:-4]]['value'] = "UNKNOWN" #read DA fc = lib61850.FunctionalConstraint_fromString(fcName) value = lib61850.IedConnection_readObject( con, ctypes.byref(error), daRef, fc) if error.value == 0: tmodel[daName[:-4]]['value'], tmodel[daName[:-4]][ 'type'] = iec61850client.printValue(value) lib61850.MmsValue_delete(value) dataAttribute = lib61850.LinkedList_getNext(dataAttribute) lib61850.LinkedList_destroy(dataAttributes) return tmodel
def writeValue(con, model, ref, value): submodel, path = iec61850client.parseRef(model,ref) if not submodel: logger.error("cannot find ref: %s in model" % ref) return {},-1 if not 'FC' in submodel: logger.error("ref is not DA") return {},-1 fc = lib61850.FunctionalConstraint_fromString(submodel['FC']) mmsvalue = iec61850client.getMMsValue(submodel['type'],value) if not mmsvalue: return model,-1 error = lib61850.IedClientError() lib61850.IedConnection_writeObject(con, ctypes.byref(error), ref, fc, mmsvalue) lib61850.MmsValue_delete(mmsvalue) if error.value == 0: model, err = iec61850client.updateValueInModel(con, model, ref) return model, err return model, error.value
def discovery(con): tmodel = {} error = lib61850.IedClientError() deviceList = lib61850.IedConnection_getLogicalDeviceList(con, ctypes.byref(error)) if error.value != 0: logger.error("could not get logical device list, error:%i" % error) if deviceList: device = lib61850.LinkedList_getNext(deviceList) while device: LD_name=ctypes.cast(lib61850.LinkedList_getData(device),ctypes.c_char_p).value.decode("utf-8") tmodel[LD_name] = {} logicalNodes = lib61850.IedConnection_getLogicalDeviceDirectory(con, ctypes.byref(error), LD_name) if error.value != 0:#ret becomes int if connection is lost lib61850.LinkedList_destroy(deviceList) return model logicalNode = lib61850.LinkedList_getNext(logicalNodes) while logicalNode: LN_name=ctypes.cast(lib61850.LinkedList_getData(logicalNode),ctypes.c_char_p).value.decode("utf-8") tmodel[LD_name][LN_name] = {} #[LNobjects, error] = iec61850.IedConnection_getLogicalNodeVariables(con, LD_name+"/"+LN_name) LNobjects = lib61850.IedConnection_getLogicalNodeDirectory(con, ctypes.byref(error), LD_name+"/"+LN_name,lib61850.ACSI_CLASS_DATA_OBJECT) if error.value != 0:#ret becomes int if connection is lost lib61850.LinkedList_destroy(logicalNodes) lib61850.LinkedList_destroy(deviceList) return model LNobject = lib61850.LinkedList_getNext(LNobjects) while LNobject: Do = ctypes.cast(lib61850.LinkedList_getData(LNobject),ctypes.c_char_p).value.decode("utf-8") tmodel[LD_name][LN_name][Do] = {} doRef = LD_name+"/"+LN_name+"."+Do tmodel[LD_name][LN_name][Do] = iec61850client.printDataDirectory(con, doRef) LNobject = lib61850.LinkedList_getNext(LNobject) lib61850.LinkedList_destroy(LNobjects) LNdss = lib61850.IedConnection_getLogicalNodeDirectory(con, ctypes.byref(error), LD_name+"/"+LN_name, lib61850.ACSI_CLASS_DATA_SET) if error.value != 0:#ret becomes int if connection is lost lib61850.LinkedList_destroy(logicalNodes) lib61850.LinkedList_destroy(deviceList) return tmodel LNds = lib61850.LinkedList_getNext(LNdss) while LNds: DSname = ctypes.cast(lib61850.LinkedList_getData(LNds),ctypes.c_char_p).value.decode("utf-8") tmodel[LD_name][LN_name][DSname] = {} #cannot pass the right type to isDeletable(last arg).. keeps complaining about 'bool *', and isDel = ctypes.pointer(ctypes.c_bool(False)) does not work isDel = ctypes.c_bool(False) dataSetMembers = lib61850.IedConnection_getDataSetDirectory(con, ctypes.byref(error), LD_name+"/"+LN_name+"."+DSname, ctypes.byref(isDel)) if error.value != 0:#ret becomes int if connection is lost lib61850.LinkedList_destroy(LNdss) lib61850.LinkedList_destroy(logicalNodes) lib61850.LinkedList_destroy(deviceList) return tmodel #all DS are assumed not deletable if isDel == True: logger.error(" DS: %s, not Deletable" % DSname) else: logger.error(" DS: %s, is Deletable" % DSname) dataSetMemberRef = lib61850.LinkedList_getNext(dataSetMembers) i = 0 while dataSetMemberRef: dsRef = ctypes.cast(lib61850.LinkedList_getData(dataSetMemberRef),ctypes.c_char_p).value.decode("utf-8") DX = dsRef[:-4] FC = dsRef[-3:-1] tmodel[LD_name][LN_name][DSname][str(i)] = {} tmodel[LD_name][LN_name][DSname][str(i)]['reftype'] = "DX" tmodel[LD_name][LN_name][DSname][str(i)]['type'] = "reference" tmodel[LD_name][LN_name][DSname][str(i)]['value'] = DX tmodel[LD_name][LN_name][DSname][str(i)]['FC'] = FC dataSetMemberRef = lib61850.LinkedList_getNext(dataSetMemberRef) i += 1 lib61850.LinkedList_destroy(dataSetMembers) LNds = lib61850.LinkedList_getNext(LNds) lib61850.LinkedList_destroy(LNdss) logicalNode = lib61850.LinkedList_getNext(logicalNode) lib61850.LinkedList_destroy(logicalNodes) device = lib61850.LinkedList_getNext(device) lib61850.LinkedList_destroy(deviceList) return tmodel