22using Newtonsoft . Json ;
33using Newtonsoft . Json . Linq ;
44using Opc . Ua . Cloud . Client . Models ;
5- using System . Collections . Concurrent ;
65using System . Net . Http . Headers ;
76using System . Text ;
87
98namespace Opc . Ua . Data . Processor
109{
11- public class ProductCarbonFootprintService
10+ public class PCFProcessor
1211 {
1312 private readonly ADXDataService _adxDataService = new ADXDataService ( ) ;
1413 private readonly DynamicsDataService _dynamicsDataService = new DynamicsDataService ( ) ;
@@ -21,15 +20,21 @@ public class ProductCarbonFootprintService
2120 }
2221 } ;
2322
24- public void GeneratePCFs ( )
23+ public PCFProcessor ( )
24+ {
25+ _adxDataService . Connect ( ) ;
26+ _dynamicsDataService . Connect ( ) ;
27+ }
28+
29+ public void Process ( )
2530 {
2631 // we have two production lines in the manufacturing ontologies production line simulation and they are connected like so:
2732 // assembly -> test -> packaging
28- GeneratePCFForProductionLine ( "Munich" , "48.1375" , "11.575" , 6 ) ;
29- GeneratePCFForProductionLine ( "Seattle" , "47.609722" , "-122.333056" , 10 ) ;
33+ CalcPCFForProductionLine ( "Munich" , "48.1375" , "11.575" , 6 ) ;
34+ CalcPCFForProductionLine ( "Seattle" , "47.609722" , "-122.333056" , 10 ) ;
3035 }
3136
32- private void GeneratePCFForProductionLine ( string productionLineName , string latitude , string longitude , int idealCycleTime )
37+ private void CalcPCFForProductionLine ( string productionLineName , string latitude , string longitude , int idealCycleTime )
3338 {
3439 try
3540 {
@@ -39,21 +44,21 @@ private void GeneratePCFForProductionLine(string productionLineName, string lati
3944 {
4045 // check if a new product was produced (last machine in the production line, i.e. packaging, is in state 2 ("done") with a passed QA)
4146 // and get the products serial number and energy consumption at that time
42- ConcurrentDictionary < string , object > latestProductProduced = ADXQueryForSpecificValue ( "packaging" , productionLineName , "Status" , 2 ) ;
47+ Dictionary < string , object > latestProductProduced = ADXQueryForSpecificValue ( "packaging" , productionLineName , "Status" , 2 ) ;
4348 if ( ( latestProductProduced != null ) && ( latestProductProduced . Count > 0 ) )
4449 {
45- ConcurrentDictionary < string , object > serialNumberResult = ADXQueryForSpecificTime ( "packaging" , productionLineName , "ProductSerialNumber" , ( ( DateTime ) latestProductProduced [ "Timestamp" ] ) . ToString ( "yyyy-MM-dd HH:mm:ss" ) , idealCycleTime ) ;
50+ Dictionary < string , object > serialNumberResult = ADXQueryForSpecificTime ( "packaging" , productionLineName , "ProductSerialNumber" , ( ( DateTime ) latestProductProduced [ "Timestamp" ] ) . ToString ( "yyyy-MM-dd HH:mm:ss" ) , idealCycleTime ) ;
4651 double serialNumber = ( double ) serialNumberResult [ "OPCUANodeValue" ] ;
4752
48- ConcurrentDictionary < string , object > timeItWasProducedPackaging = ADXQueryForSpecificValue ( "packaging" , productionLineName , "ProductSerialNumber" , serialNumber ) ;
49- ConcurrentDictionary < string , object > energyPackaging = ADXQueryForSpecificTime ( "packaging" , productionLineName , "EnergyConsumption" , ( ( DateTime ) timeItWasProducedPackaging [ "Timestamp" ] ) . ToString ( "yyyy-MM-dd HH:mm:ss" ) , idealCycleTime ) ;
53+ Dictionary < string , object > timeItWasProducedPackaging = ADXQueryForSpecificValue ( "packaging" , productionLineName , "ProductSerialNumber" , serialNumber ) ;
54+ Dictionary < string , object > energyPackaging = ADXQueryForSpecificTime ( "packaging" , productionLineName , "EnergyConsumption" , ( ( DateTime ) timeItWasProducedPackaging [ "Timestamp" ] ) . ToString ( "yyyy-MM-dd HH:mm:ss" ) , idealCycleTime ) ;
5055
5156 // check each other machine for the time when the product with this serial number was in the machine and get its energy comsumption at that time
52- ConcurrentDictionary < string , object > timeItWasProducedTest = ADXQueryForSpecificValue ( "test" , productionLineName , "ProductSerialNumber" , serialNumber ) ;
53- ConcurrentDictionary < string , object > energyTest = ADXQueryForSpecificTime ( "test" , productionLineName , "EnergyConsumption" , ( ( DateTime ) timeItWasProducedTest [ "Timestamp" ] ) . ToString ( "yyyy-MM-dd HH:mm:ss" ) , idealCycleTime ) ;
57+ Dictionary < string , object > timeItWasProducedTest = ADXQueryForSpecificValue ( "test" , productionLineName , "ProductSerialNumber" , serialNumber ) ;
58+ Dictionary < string , object > energyTest = ADXQueryForSpecificTime ( "test" , productionLineName , "EnergyConsumption" , ( ( DateTime ) timeItWasProducedTest [ "Timestamp" ] ) . ToString ( "yyyy-MM-dd HH:mm:ss" ) , idealCycleTime ) ;
5459
55- ConcurrentDictionary < string , object > timeItWasProducedAssembly = ADXQueryForSpecificValue ( "assembly" , productionLineName , "ProductSerialNumber" , serialNumber ) ;
56- ConcurrentDictionary < string , object > energyAssembly = ADXQueryForSpecificTime ( "assembly" , productionLineName , "EnergyConsumption" , ( ( DateTime ) timeItWasProducedAssembly [ "Timestamp" ] ) . ToString ( "yyyy-MM-dd HH:mm:ss" ) , idealCycleTime ) ;
60+ Dictionary < string , object > timeItWasProducedAssembly = ADXQueryForSpecificValue ( "assembly" , productionLineName , "ProductSerialNumber" , serialNumber ) ;
61+ Dictionary < string , object > energyAssembly = ADXQueryForSpecificTime ( "assembly" , productionLineName , "EnergyConsumption" , ( ( DateTime ) timeItWasProducedAssembly [ "Timestamp" ] ) . ToString ( "yyyy-MM-dd HH:mm:ss" ) , idealCycleTime ) ;
5762
5863 // calculate the total energy consumption for the product by summing up all the machines' energy consumptions (in Ws), divide by 3600 to get seconds and multiply by the ideal cycle time (which is in seconds)
5964 double energyTotal = ( ( double ) energyAssembly [ "OPCUANodeValue" ] + ( double ) energyTest [ "OPCUANodeValue" ] + ( double ) energyPackaging [ "OPCUANodeValue" ] ) / 3600 * idealCycleTime ;
@@ -77,7 +82,7 @@ private void GeneratePCFForProductionLine(string productionLineName, string lati
7782 }
7883 catch ( Exception ex )
7984 {
80- Console . WriteLine ( "GeneratePCFForProductionLine : " + ex . Message ) ;
85+ Console . WriteLine ( "CalcPCFForProductionLine : " + ex . Message ) ;
8186 }
8287 }
8388
@@ -132,17 +137,15 @@ private float RetrieveScope3Emissions()
132137 {
133138 try
134139 {
135- DynamicsQueryResponse response = _dynamicsDataService . RunDynamicsQuery ( new DynamicsQuery ( ) {
136- tracingDirection = "Backward" ,
137- company = Environment . GetEnvironmentVariable ( "DYNAMICS_COMPANY_NAME" ) ,
138- itemNumber = Environment . GetEnvironmentVariable ( "DYNAMICS_PRODUCT_NAME" ) ,
139- serialNumber = Environment . GetEnvironmentVariable ( "DYNAMICS_BATCH_NAME" ) ,
140- shouldIncludeEvents = true
141- } ) . GetAwaiter ( ) . GetResult ( ) ;
142-
143- if ( response != null )
140+ string query = "Backward" + "\r \n "
141+ + Environment . GetEnvironmentVariable ( "DYNAMICS_COMPANY_NAME" ) + "\r \n "
142+ + Environment . GetEnvironmentVariable ( "DYNAMICS_PRODUCT_NAME" ) + "\r \n "
143+ + Environment . GetEnvironmentVariable ( "DYNAMICS_BATCH_NAME" ) + "\r \n " ;
144+
145+ Dictionary < string , object > response = _dynamicsDataService . RunQuery ( query ) ;
146+ if ( response . ContainsKey ( query ) && ( response [ query ] != null ) && response [ query ] is DynamicsQueryResponse dynamicsResponse )
144147 {
145- return FindPcf ( response . root ) ;
148+ return FindPcf ( dynamicsResponse . root ) ;
146149 }
147150 else
148151 {
@@ -191,7 +194,7 @@ private float FindPcf(ErpNode node)
191194 return 0.0f ;
192195 }
193196
194- private ConcurrentDictionary < string , object > ADXQueryForSpecificValue ( string stationName , string productionLineName , string valueToQuery , double desiredValue )
197+ private Dictionary < string , object > ADXQueryForSpecificValue ( string stationName , string productionLineName , string valueToQuery , double desiredValue )
195198 {
196199 string query = "opcua_metadata_lkv\r \n "
197200 + "| where Name contains \" " + stationName + "\" \r \n "
@@ -203,13 +206,10 @@ private ConcurrentDictionary<string, object> ADXQueryForSpecificValue(string sta
203206 + "| distinct Timestamp, OPCUANodeValue = todouble(Value)\r \n "
204207 + "| sort by Timestamp desc" ;
205208
206- ConcurrentDictionary < string , object > values = new ConcurrentDictionary < string , object > ( ) ;
207- _adxDataService . RunADXQuery ( query , values ) ;
208-
209- return values ;
209+ return _adxDataService . RunQuery ( query ) ;
210210 }
211211
212- private ConcurrentDictionary < string , object > ADXQueryForSpecificTime ( string stationName , string productionLineName , string valueToQuery , string timeToQuery , int idealCycleTime )
212+ private Dictionary < string , object > ADXQueryForSpecificTime ( string stationName , string productionLineName , string valueToQuery , string timeToQuery , int idealCycleTime )
213213 {
214214 string query = "opcua_metadata_lkv\r \n "
215215 + "| where Name contains \" " + stationName + "\" \r \n "
@@ -222,10 +222,7 @@ private ConcurrentDictionary<string, object> ADXQueryForSpecificTime(string stat
222222 + "| where around(Timestamp, datetime(" + timeToQuery + "), " + idealCycleTime . ToString ( ) + "s)\r \n "
223223 + "| sort by Timestamp desc" ;
224224
225- ConcurrentDictionary < string , object > values = new ConcurrentDictionary < string , object > ( ) ;
226- _adxDataService . RunADXQuery ( query , values ) ;
227-
228- return values ;
225+ return _adxDataService . RunQuery ( query ) ;
229226 }
230227 }
231228}
0 commit comments