From e02ceb8c560efbb9b31f149ede6d5a65656387b8 Mon Sep 17 00:00:00 2001 From: Kazeem Oladipupo <67549739+Kaz040@users.noreply.github.com> Date: Wed, 18 Sep 2024 10:58:22 +0200 Subject: [PATCH] Refactoring of code --- BackendFlask/InterfaceSetup.py | 327 ++------- BackendFlask/Models.py | 688 ++++++++++++++++++ .../InterfaceSetup.cpython-311.pyc | Bin 17103 -> 16526 bytes 3 files changed, 750 insertions(+), 265 deletions(-) create mode 100644 BackendFlask/Models.py diff --git a/BackendFlask/InterfaceSetup.py b/BackendFlask/InterfaceSetup.py index 5a49ee9..e437398 100644 --- a/BackendFlask/InterfaceSetup.py +++ b/BackendFlask/InterfaceSetup.py @@ -5,6 +5,7 @@ import string import pandas from io import StringIO +from Models import Models ''' TODOs -- Creat a method that extract asset, work on it and return it back. @@ -15,145 +16,6 @@ def update datapoint(assetId, datapointId) #if anything changes from the datapoint (e.g, value, new sink registration e.t.c), # it should be updated. ''' -class Models(): - def __init__(self): - self.interfaces = { - "endpoints" : {}, - - "assets" : [] - } - - self.endpoint = { - "submodel-endpoint" : "none", - "registry-endpoint" : "none", - } - - self.asset = { - - "assetId" : "", - "aasId":"", - "aasDescriptor" : {}, - "datapoints" : [] - - } - - self.datapoint = { - - "source-endpoint": { - "id" : 0, - "name" : "", - "url" : "", - "method" : "", - "content-type" : "", - "data-type" : "number", - "value" : "NaN" - - }, - - "sink-endpoint" : [] - - } - self.sinkEndpoint = { - "sink-created": False, - "submodel" : {}, - "submodelId" : "", - "submodelIdBase64" : "", - "submodelElementPath" : "", - "submodelElementType" : "", - "payloadMappingKeys" : "" - } - - self.Submodel = { - "idShort": "", - "id": "", - "semanticId": { - "type": "ModelReference", - "keys": [ - { - "type": "Submodel", - "value": "https://admin-shell.io/sinksubmodel" - } - ] - }, - "submodelElements": [], - "modelType": "Submodel" - } - - self.BlobSubmodelElement = { - "idShort": "", - "value": "", - "semanticId": { - "type": "ModelReference", - "keys": [ - { - "type": "GlobalReference", - "value": "0173-1#02-AAM556#002" - } - ] - }, - "contentType": "application/csv", - "modelType": "Blob" - } - - self.PropertySubmodelElement = { - "category": "PARAMETER", - "idShort": "", - "description": [], - "semanticId": { - "type": "ModelReference", - "keys": [ - { - "type": "GlobalReference", - "value": "0173-1#02-AAM556#002" - } - ] - }, - "valueType": "xs:string", - "value": "", - "modelType": "Property" - } - - self.aasDescriptor = { - "assetKind" : "Instance", - "idShort" : "", - "id" : "", - "globalAssetId" : " ", - "submodelDescriptors": [ - - ] - } - - self.submodelDescriptor = { - "endpoints" : [ - { - "protocolInformation": { - "href": "https://localhost:1234/api/v3.0/submodels", - "endpointProtocol": "HTTP", - "endpointProtocolVersion": [ - "1.1" - ] - }, - "interface": "AAS-3.0" - } - ], - "idShort" : "data_sink", - "id" : "https://factoryxTP204.com/submodel-for-data-sink" - } - - self.registryHeader = { - 'Content-Type': 'application/json', - 'edc-bpn':'default-tenant' - } - - self.submodelBasicAuth = ("fx","fx-ccm-poc") - - self.assetId = "" - self.id = 0 - self.counter = 0 - self.indexes = { - "assetIndex" : 0, - "datapointIndex" : 0, - } class AasMapper(Models): @@ -279,6 +141,7 @@ def read_datapoint_from_source(self, assetId, id): source = datapoint["source-endpoint"] mappings = datapoint["sink-endpoint"] url = source["url"] + #method at the moment is automatically 'GET' response = httpx.get(url, timeout=15) #find the type of payload @@ -302,12 +165,12 @@ def read_datapoint_from_source(self, assetId, id): updatedMappings= self.write_datapoint_to_sink(source["name"], mappings, csv_payload) - datapoint["source-endpoint"]["value"] = "NaN"+self.counter + datapoint["source-endpoint"]["value"] = f"NaN{self.counter}" datapoint["sink-endpoint"] = updatedMappings asset["datapoints"][self.indexes["datapointIndex"]] = datapoint self.interfaces["assets"][self.indexes["assetIndex"]] = asset self.counter += self.counter - return "NaN"+str(self.counter) + return f"NaN{self.counter}" def write_datapoint_to_sink(self, name, mappings, payload): submodel_url = self.interfaces["endpoints"]["submodel-endpoint"] @@ -327,82 +190,78 @@ def write_datapoint_to_sink(self, name, mappings, payload): #just post to the submodelId and submodel element in mapping elif mappings[mappingIndex]["submodelElementType"].lower() == "property": - submodel = copy.deepcopy(self.Submodel) - submodel["idShort"] = "SourceDataSink_"+' '.join(random.choices(string.ascii_uppercase, k=1)) - submodel["id"] = "https://example.com/ids/sm/5552_0182_8042_"+str(random.randint(1000, 9999)) - propertySME = copy.deepcopy(self.PropertySubmodelElement) - propertySME["value"] = payload - propertySME["idShort"] = name - submodel["submodelElements"].append(propertySME) + submodel = self.set_up_submodel_property(payload, name) - response = httpx.post(submodel_url, auth=self.submodelBasicAuth, json=submodel, timeout=15) - if response.is_success: - #submodel created, turn on the flag, assign the Ids to sink-created and register the submodel in registry - mappings[mappingIndex]["submodel"] = submodel - mappings[mappingIndex]["sink-created"] = True - mappings[mappingIndex]["submodelId"] = submodel["id"] - submodelId_byte = submodel["id"].encode('utf-8') - mappings[mappingIndex]["submodelIdBase64"] = base64.b64encode(submodelId_byte).decode('utf-8') - mappings[mappingIndex]["submodelElementPath"] = name - + if httpx.post(submodel_url, auth=self.submodelBasicAuth, json=submodel, timeout=15).is_success: + #load mappings and register submodel descriptor. + mappings = self.load_mappings(mappings, mappingIndex, submodel, name) - + elif mappings[mappingIndex]["submodelElementType"].lower() == "blob": - if mappings[mappingIndex]["payloadMappingKeys"] == "": - submodel = copy.deepcopy(self.Submodel) - submodel["idShort"] = "SourceDataSink_"+' '.join(random.choices(string.ascii_uppercase, k=1)) - submodel["id"] = "https://example.com/ids/sm/5552_0182_8042_"+str(random.randint(1000, 9999)) - blobSME = copy.deepcopy(self.BlobSubmodelElement) - #convert payload to base64 string. - payload_byte = payload.encode('utf-8') - blobSME["value"] = base64.b64encode(payload_byte).decode('utf-8') - blobSME["idShort"] = name - submodel["submodelElements"].append(blobSME) - if httpx.post(submodel_url, auth=self.submodelBasicAuth, json=submodel, timeout=15).is_success: - mappings[mappingIndex]["submodel"] = submodel - mappings[mappingIndex]["sink-created"] = True - mappings[mappingIndex]["submodelId"] = submodel["id"] - submodelId_byte = submodel["id"].encode('utf-8') - mappings[mappingIndex]["submodelIdBase64"] = base64.b64encode(submodelId_byte).decode('utf-8') - mappings[mappingIndex]["submodelElementPath"] = name - else: #payloadMapping is not empty - submodel = copy.deepcopy(self.Submodel) - submodel["idShort"] = "SourceDataSink_"+' '.join(random.choices(string.ascii_uppercase, k=1)) - submodel["id"] = "https://example.com/ids/sm/5552_0182_8042_"+str(random.randint(1000, 9999)) - blobSME = copy.deepcopy(self.BlobSubmodelElement) - #columns extraction - mapping_keys = mappings[mappingIndex]["payloadMappingKeys"] - mapping_keys = mapping_keys.replace(' ', '') - keys = mapping_keys.split(',') - csv_payload = StringIO(payload) - csv_dataFrame = pandas.read_csv(csv_payload, usecols=keys) - #convert csv to string - csv_string = csv_dataFrame.to_csv(index=False) - #convert csv_string to base64 string. - payload_byte = csv_string.encode('utf-8') - blobSME["value"] = base64.b64encode(payload_byte).decode('utf-8') - blobSME["idShort"] = name - submodel["submodelElements"].append(blobSME) - if httpx.post(submodel_url, auth=self.submodelBasicAuth, json=submodel, timeout=15).is_success: - mappings[mappingIndex]["submodel"] = submodel - mappings[mappingIndex]["sink-created"] = True - mappings[mappingIndex]["submodelId"] = submodel["id"] - submodelId_byte = submodel["id"].encode('utf-8') - mappings[mappingIndex]["submodelIdBase64"] = base64.b64encode(submodelId_byte).decode('utf-8') - mappings[mappingIndex]["submodelElementPath"] = name + + submodel = self.set_up_submodel_blob(payload, name, mappings[mappingIndex]["payloadMappingKeys"]) + + if httpx.post(submodel_url, auth=self.submodelBasicAuth, json=submodel, timeout=15).is_success: + #load mappings and register submodel descriptor. + mappings = self.load_mappings(mappings, mappingIndex, submodel, name) + return mappings - #method at the moment is automatically 'GET' + def set_up_submodel_property(self,value, idShort): + submodel = copy.deepcopy(self.Submodel) + submodel["idShort"] = "SourceDataSink_"+' '.join(random.choices(string.ascii_uppercase, k=1)) + submodel["id"] = "https://example.com/ids/sm/5552_0182_8042_"+str(random.randint(1000, 9999)) + propertySME = copy.deepcopy(self.PropertySubmodelElement) + propertySME["value"] = value + propertySME["idShort"] = idShort + submodel["submodelElements"].append(propertySME) + return submodel + + def set_up_submodel_blob(self, value, idShort, mappingKeys): + submodel = copy.deepcopy(self.Submodel) + submodel["idShort"] = "SourceDataSink_"+' '.join(random.choices(string.ascii_uppercase, k=1)) + submodel["id"] = "https://example.com/ids/sm/5552_0182_8042_"+str(random.randint(1000, 9999)) + blobSME = copy.deepcopy(self.BlobSubmodelElement) + blobSME["idShort"] = idShort + if mappingKeys == "": + #convert payload to base64 string. + payload_byte = value.encode('utf-8') + else: + mappingKeys = mappingKeys.replace(' ', '') + keys = mappingKeys.split(',') + csv_payload = StringIO(value) + csv_dataFrame = pandas.read_csv(csv_payload, usecols=keys) + #convert csv to string + csv_string = csv_dataFrame.to_csv(index=False) + payload_byte = csv_string.encode('utf-8') + + blobSME["value"] = base64.b64encode(payload_byte).decode('utf-8') + submodel["submodelElements"].append(blobSME) + + return submodel + def load_mappings(self, mappings, mappingIndex, submodel, idShortPath): + #submodel created, turn on the flag, assign the Ids to sink-created and register the submodel in registry + mappings[mappingIndex]["submodel"] = submodel + mappings[mappingIndex]["sink-created"] = True + mappings[mappingIndex]["submodelId"] = submodel["id"] + submodelId_byte = submodel["id"].encode('utf-8') + mappings[mappingIndex]["submodelIdBase64"] = base64.b64encode(submodelId_byte).decode('utf-8') + mappings[mappingIndex]["submodelElementPath"] = idShortPath + + return mappings + #create submodel descriptor and post it + def extract_asset(self,assetId): for assetIndex in range(len(self.interfaces["assets"])): #using indexing here to be able to update the asset array and datapoint array asset = self.interfaces["assets"][assetIndex] if asset['assetId'] == assetId: self.indexes["assetIndex"] = assetIndex + self.indexes["aasId"] = asset["aasId"] return asset @@ -422,66 +281,4 @@ def push_payload_to_submodelElement(self, submodel, name, payload): return submodel return submodel - - -''' - { - "source-endpoint": - { - "submodelCreated" : False, - "id" : 1, - "name" : "count", - "url" : "http://asset:8500/counter/properties/count", - "method" : "get", - "content-type" : "text/plain", - "data-type" : "number", - "value" : "Factory X" - - }, - - "sink-endpoint" : - [ - { - "submodelId" : "", - "submodelElementPath" : "", - "submodelElementType" : "", - "payloadMappingKeys" : "Time,Sensor1,Sensor2" - } - ] - - } - - - - -descritor = { - "kind" : "instance", - "idshort" : "ComponentA", - "id" : "https://example.com/ids/sm/5552_0182_8042_7251", - "submodelDescriptors": [ - { - "endpoints" : [ - { - "protocolInformation": { - "href": "https://localhost:1234/api/v3.0/submodels", - "endpointProtocol": "HTTP", - "endpointProtocolVersion": [ - "1.1" - ] - }, - "interface": "AAS-3.0" - } - ], - "idShort" : "Nameplate", - "id" : "https://admin-shell.io/zvei/nameplate/1/0/Nameplate" - } - ] - -} - -''' - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/BackendFlask/Models.py b/BackendFlask/Models.py new file mode 100644 index 0000000..d02c3e4 --- /dev/null +++ b/BackendFlask/Models.py @@ -0,0 +1,688 @@ +class Models(): + def __init__(self): + self.interfaces = { + "endpoints" : {}, + + "assets" : [] + } + + self.endpoint = { + "submodel-endpoint" : "none", + "registry-endpoint" : "none", + } + + self.asset = { + + "assetId" : "", + "aasId":"", + "aasDescriptor" : {}, + "datapoints" : [] + + } + + self.datapoint = { + + "source-endpoint": { + "id" : 0, + "name" : "", + "url" : "", + "method" : "", + "content-type" : "", + "data-type" : "number", + "value" : "NaN" + + }, + + "sink-endpoint" : [] + + } + self.sinkEndpoint = { + "sink-created": False, + "submodel" : {}, + "submodelId" : "", + "submodelIdBase64" : "", + "submodelElementPath" : "", + "submodelElementType" : "", + "payloadMappingKeys" : "" + } + + self.TimeSeries_Submodel = { + "idShort": "TimeSeries", + "description": [ + { + "language": "de", + "text": "Enth\u00E4lt Zeitreihendaten und Referenzen auf Zeitreihendaten, um diese entlang des Asset Lebenszyklus aufzufinden und semantisch zu beschreiben." + }, + { + "language": "en", + "text": "Contains time series data and references to time series data to discover and semantically describe them along the asset lifecycle." + } + ], + "administration": { + "version": "1", + "revision": "1" + }, + "id": "https://admin-shell.io/idta/SubmodelTemplate/TimeSeries/1/1_", + "kind": "Instance", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "https://admin-shell.io/idta/TimeSeries/1/1" + } + ] + }, + "submodelElements": [ + { + "idShort": "Metadata", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "https://admin-shell.io/idta/TimeSeries/Metadata/1/1" + } + ] + }, + "value": [ + { + "category": "PARAMETER", + "idShort": "Name", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "https://admin-shell.io/idta/TimeSeries/Metadata/Name/1/1" + } + ] + }, + "value": [ + { + "language": "en", + "text": "Meaningful name for labeling" + } + ], + "modelType": "MultiLanguageProperty" + }, + { + "category": "PARAMETER", + "idShort": "Description", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "https://admin-shell.io/idta/TimeSeries/Metadata/Description/1/1" + } + ] + }, + "qualifiers": [ + { + "type": "Cardinality", + "valueType": "xs:string", + "value": "ZeroToOne" + } + ], + "value": [ + { + "language": "en", + "text": "Short description of the time series segment." + } + ], + "modelType": "MultiLanguageProperty" + }, + { + "idShort": "Record", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "https://admin-shell.io/idta/TimeSeries/Record/1/1" + } + ] + }, + "qualifiers": [ + { + "type": "Cardinality", + "valueType": "xs:string", + "value": "One" + } + ], + "value": [ + { + "category": "VARIABLE", + "idShort": "Time", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "https://admin-shell.io/idta/TimeSeries/RelativePointInTime/1/1" + } + ] + }, + "qualifiers": [ + { + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "https://admin-shell.io/SubmodelTemplates/Cardinality/1/0" + } + ] + }, + "type": "Cardinality", + "valueType": "xs:string", + "value": "OneToMany" + }, + { + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "https://admin-shell.io/SubmodelTemplates/AllowedIdShort/1/0" + } + ] + }, + "type": "AllowedIdShort", + "valueType": "xs:string", + "value": "Time[\\d{2,3}]" + } + ], + "valueType": "xs:long", + "modelType": "Property" + }, + { + "category": "VARIABLE", + "idShort": "sampleAccelerationX", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "https://sample.com/AccelerationX/1/1" + } + ] + }, + "qualifiers": [ + { + "type": "Cardinality", + "valueType": "xs:string", + "value": "ZeroToOne" + } + ], + "valueType": "xs:long", + "modelType": "Property" + }, + { + "category": "VARIABLE", + "idShort": "sampleAccelerationY", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "https://sample.com/AccelerationY/1/1" + } + ] + }, + "qualifiers": [ + { + "type": "Cardinality", + "valueType": "xs:string", + "value": "ZeroToOne" + } + ], + "valueType": "xs:long", + "modelType": "Property" + }, + { + "category": "VARIABLE", + "idShort": "sampleAccelerationZ", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "https://sample.com/AccelerationZ/1/1" + } + ] + }, + "qualifiers": [ + { + "type": "Cardinality", + "valueType": "xs:string", + "value": "ZeroToOne" + } + ], + "valueType": "xs:long", + "modelType": "Property" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "SubmodelElementCollection" + }, + { + "idShort": "Segments", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "https://admin-shell.io/idta/TimeSeries/Segments/1/1" + } + ] + }, + "qualifiers": [ + { + "type": "Cardinality", + "valueType": "xs:string", + "value": "One" + } + ], + "value": [ + { + "idShort": "ExternalSegment", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "https://admin-shell.io/idta/TimeSeries/Segments/ExternalSegment/1/1" + } + ] + }, + "qualifiers": [ + { + "type": "Cardinality", + "valueType": "xs:string", + "value": "ZeroToMany" + } + ], + "value": [ + { + "category": "PARAMETER", + "idShort": "Name", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "https://admin-shell.io/idta/TimeSeries/Segment/Name/1/1" + } + ] + }, + "qualifiers": [ + { + "type": "Cardinality", + "valueType": "xs:string", + "value": "ZeroToOne" + } + ], + "value": [ + { + "language": "en", + "text": "Meaningful name for labeling." + } + ], + "modelType": "MultiLanguageProperty" + }, + { + "category": "PARAMETER", + "idShort": "Description", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "https://admin-shell.io/idta/TimeSeries/Segment/Description/1/1" + } + ] + }, + "qualifiers": [ + { + "type": "Cardinality", + "valueType": "xs:string", + "value": "ZeroToOne" + } + ], + "value": [ + { + "language": "en", + "text": "Short description of the time series segment." + } + ], + "modelType": "MultiLanguageProperty" + }, + { + "category": "VARIABLE", + "idShort": "RecordCount", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "https://admin-shell.io/idta/TimeSeries/Segment/RecordCount/1/1" + } + ] + }, + "qualifiers": [ + { + "type": "Cardinality", + "valueType": "xs:string", + "value": "ZeroToOne" + } + ], + "valueType": "xs:long", + "modelType": "Property" + }, + { + "category": "VARIABLE", + "idShort": "StartTime", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "https://admin-shell.io/idta/TimeSeries/Segment/StartTime/1/1" + } + ] + }, + "qualifiers": [ + { + "type": "Cardinality", + "valueType": "xs:string", + "value": "ZeroToOne" + } + ], + "valueType": "xs:string", + "modelType": "Property" + }, + { + "category": "VARIABLE", + "idShort": "EndTime", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "https://admin-shell.io/idta/TimeSeries/Segment/EndTime/1/1 " + } + ] + }, + "qualifiers": [ + { + "type": "Cardinality", + "valueType": "xs:string", + "value": "ZeroToOne" + } + ], + "valueType": "xs:string", + "modelType": "Property" + }, + { + "category": "VARIABLE", + "idShort": "Duration", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "https://admin-shell.io/idta/TimeSeries/Segment/Duration/1/1" + } + ] + }, + "qualifiers": [ + { + "type": "Cardinality", + "valueType": "xs:string", + "value": "ZeroToOne" + } + ], + "valueType": "xs:string", + "modelType": "Property" + }, + { + "category": "PARAMETER", + "idShort": "SamplingInterval", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "https://admin-shell.io/idta/TimeSeries/Segment/SamplingInterval/1/1" + } + ] + }, + "qualifiers": [ + { + "type": "Cardinality", + "valueType": "xs:string", + "value": "ZeroToOne" + } + ], + "valueType": "xs:long", + "modelType": "Property" + }, + { + "category": "PARAMETER", + "idShort": "SamplingRate", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "https://admin-shell.io/idta/TimeSeries/Segment/SamplingRate/1/1" + } + ] + }, + "qualifiers": [ + { + "type": "Cardinality", + "valueType": "xs:string", + "value": "ZeroToOne" + } + ], + "valueType": "xs:long", + "modelType": "Property" + }, + { + "category": "PARAMETER", + "idShort": "State", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "https://admin-shell.io/idta/TimeSeries/Segment/State/1/1" + } + ] + }, + "qualifiers": [ + { + "type": "Cardinality", + "valueType": "xs:string", + "value": "ZeroToOne" + } + ], + "valueType": "xs:string", + "modelType": "Property" + }, + { + "category": "VARIABLE", + "idShort": "LastUpdate", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "https://admin-shell.io/idta/TimeSeries/Segment/LastUpdate/1/1" + } + ] + }, + "qualifiers": [ + { + "type": "Cardinality", + "valueType": "xs:string", + "value": "ZeroToOne" + } + ], + "valueType": "xs:string", + "modelType": "Property" + }, + { + "category": "PARAMETER", + "idShort": "File", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "https://admin-shell.io/idta/TimeSeries/File/1/1" + } + ] + }, + "qualifiers": [ + { + "type": "Cardinality", + "valueType": "xs:string", + "value": "ZeroToOne" + } + ], + "contentType": "application/json", + "modelType": "File" + }, + { + "category": "VARIABLE", + "idShort": "Blob", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "https://admin-shell.io/idta/TimeSeries/Blob/1/1" + } + ] + }, + "qualifiers": [ + { + "type": "Cardinality", + "valueType": "xs:string", + "value": "ZeroToOne" + } + ], + "contentType": "application/json", + "modelType": "Blob" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "SubmodelElementCollection" + } + ], + "modelType": "Submodel" + } + + self.Submodel = { + "idShort": "", + "id": "", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "https://admin-shell.io/sinksubmodel" + } + ] + }, + "submodelElements": [], + "modelType": "Submodel" + } + + self.BlobSubmodelElement = { + "idShort": "", + "value": "", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAM556#002" + } + ] + }, + "contentType": "application/csv", + "modelType": "Blob" + } + + self.PropertySubmodelElement = { + "category": "PARAMETER", + "idShort": "", + "description": [], + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAM556#002" + } + ] + }, + "valueType": "xs:string", + "value": "", + "modelType": "Property" + } + + self.aasDescriptor = { + "assetKind" : "Instance", + "idShort" : "", + "id" : "", + "globalAssetId" : " ", + "submodelDescriptor": [ + + ] + } + + self.submodelDescriptor = { + "endpoints" : [ + { + "protocolInformation": { + "href": "", + "endpointProtocol": "HTTP", + "endpointProtocolVersion": [ + "1.1" + ] + }, + "interface": "AAS-3.0" + } + ], + "idShort" : "data_sink", + "id" : "https://factoryxTP204.com/submodel-for-data-sink", + "semanticId" : [ + + ] + } + + self.registryHeader = { + 'Content-Type': 'application/json', + 'edc-bpn':'default-tenant' + } + + self.submodelBasicAuth = ("fx","fx-ccm-poc") + + self.assetId = "" + self.id = 0 + self.counter = 0 + self.indexes = { + "assetIndex" : 0, + "datapointIndex" : 0, + "aasId" : "" + } diff --git a/BackendFlask/__pycache__/InterfaceSetup.cpython-311.pyc b/BackendFlask/__pycache__/InterfaceSetup.cpython-311.pyc index e797dda903424777e011bf57278032f96bef75df..5f3a903ac822d2535355e8d961387ba7b38cd81a 100644 GIT binary patch delta 4672 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 Z-hE6rL&M7Nk5k&u<etyJqF;Wg{{u4ba>xJx delta 5202 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 E0Sd$c)Bpeg