1: using System;
2: using System.Collections.Generic;
3: using System.Configuration;
4: using System.Linq;
5: using System.Text;
6: using static Ia.Ngn.Cl.Model.Business.NetworkDesignDocument;
7:
8: namespace Ia.Ngn.Cl.Model.Business.Nokia
9: {
10: ////////////////////////////////////////////////////////////////////////////
11:
12: /// <summary publish="true">
13: /// Optical Fiber Network's Operations Support System Management Intranet (OFN OSS) support class for Nokia's Optical Fiber Network (OFN) business model.
14: /// </summary>
15: ///
16: /// <value>
17: /// <appSettings>
18: /// <add key="sdcServerHost" value="https://*" />
19: /// <add key="sdcServerPort" value="*" />
20: /// <add key="sdcServerServiceUrl" value="*" />
21: /// <add key="sdcServerUser" value="*" />
22: /// <add key="sdcServerUserPassword" value="*" />
23: /// </appSettings>
24: /// </value>
25: ///
26: /// <remarks>
27: /// Copyright © 2018-2022 Jasem Y. Al-Shamlan (info@ia.com.kw), Integrated Applications - Kuwait. All Rights Reserved.
28: ///
29: /// This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
30: /// the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
31: ///
32: /// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
33: /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
34: ///
35: /// You should have received a copy of the GNU General Public License along with this library. If not, see http://www.gnu.org/licenses.
36: ///
37: /// Copyright notice: This notice may not be removed or altered from any source distribution.
38: /// </remarks>
39: public class Sdc
40: {
41: private static List<string> ponNameList;
42:
43: private static List<Ia.Ngn.Cl.Model.Business.NetworkDesignDocument.Pon> ponList;
44:
45: /// <summary/>
46: public static string BaseAddress { get { return ConfigurationManager.AppSettings["sdcServerHost"].ToString() + ":" + ConfigurationManager.AppSettings["sdcServerPort"].ToString(); } }
47: /// <summary/>
48: public static string ServiceUrl { get { return ConfigurationManager.AppSettings["sdcServerServiceUrl"].ToString(); } }
49: /// <summary/>
50: public static string UserName { get { return ConfigurationManager.AppSettings["sdcServerUser"].ToString(); } }
51: /// <summary/>
52: public static string Password { get { return ConfigurationManager.AppSettings["sdcServerUserPassword"].ToString(); } }
53:
54: public enum Transaction { Receive, Transmit }
55:
56: /// <summary/>
57: public static List<TimeSpan> ScaleList
58: {
59: get
60: {
61: return new List<TimeSpan> { TimeSpan.FromHours(1), TimeSpan.FromDays(1), TimeSpan.FromDays(7), TimeSpan.FromDays(30), TimeSpan.FromDays(365) };
62: }
63: }
64:
65: ////////////////////////////////////////////////////////////////////////////
66:
67: /// <summary>
68: ///
69: /// </summary>
70: public Sdc()
71: {
72: }
73:
74: ////////////////////////////////////////////////////////////////////////////
75:
76: /// <summary>
77: ///
78: /// </summary>
79: public class TransactionTimestampValue
80: {
81: /// <summary/>
82: public Transaction Transaction { get; set; }
83:
84: /// <summary/>
85: public DateTime Timestamp { get; set; }
86:
87: /// <summary/>
88: public long Value { get; set; }
89:
90: ////////////////////////////////////////////////////////////////////////////
91:
92: /// <summary>
93: ///
94: /// </summary>
95: public TransactionTimestampValue(Transaction transaction, DateTime timestamp, long value)
96: {
97: this.Transaction = transaction;
98:
99: this.Timestamp = timestamp;
100:
101: this.Value = value;
102: }
103:
104: ////////////////////////////////////////////////////////////////////////////
105:
106: /// <summary>
107: ///
108: /// </summary>
109: public override string ToString()
110: {
111: return this.Transaction.ToString() + ": " + this.Timestamp + ": " + this.Value;
112: }
113:
114: ////////////////////////////////////////////////////////////////////////////
115: }
116:
117: ////////////////////////////////////////////////////////////////////////////
118:
119: /// <summary>
120: /// Response of Nokia SDC server
121: /// </summary>
122: public class Response
123: {
124: public string Author { get; set; }
125:
126: /// <summary/>
127: public string Version { get; set; }
128:
129: /// <summary/>
130: public string Tmf854Version { get; set; }
131:
132: /// <summary/>
133: public string ActivityName { get; set; }
134:
135: /// <summary/>
136: public string MessageName { get; set; }
137:
138: /// <summary/>
139: public string MessageType { get; set; }
140:
141: /// <summary/>
142: public string SenderUri { get; set; }
143:
144: /// <summary/>
145: public string DestinationUri { get; set; }
146:
147: /// <summary/>
148: public string CommunicationPattern { get; set; }
149:
150: /// <summary/>
151: public string CommunicationStyle { get; set; }
152:
153: /// <summary/>
154: public string ActivityStatus { get; set; }
155:
156: /// <summary/>
157: public DateTime Timestamp { get; set; }
158:
159: /// <summary/>
160: public string BodyText { get; set; }
161:
162: /// <summary/>
163: public Dictionary<string, string> ParameterDictionary;
164:
165: /// <summary/>
166: public bool IsSuccessfull { get { return ReturnCode == Ia.Ngn.Cl.Model.Client.Nokia.Sdc.ResultCode.Successful; } }
167:
168: /// <summary/>
169: public Ia.Ngn.Cl.Model.Client.Nokia.Sdc.ResultCode ReturnCode { get; set; }
170:
171: /// <summary/>
172: public Response() { }
173: }
174:
175: ////////////////////////////////////////////////////////////////////////////
176:
177: /// <summary>
178: ///
179: /// </summary>
180: public static void EnableSdcPerformanceMonitoringDataOfAllPons(Ia.Ngn.Cl.Model.Client.Nokia.Sdc sdc, out Ia.Cl.Model.Result result)
181: {
182: StringBuilder sb;
183:
184: result = new Ia.Cl.Model.Result();
185:
186: if (ponList == null) ponList = (from p in Ia.Ngn.Cl.Model.Data.NetworkDesignDocument.PonList
187: where p.PonGroup.Olt.Odf.Vendor == Ia.Ngn.Cl.Model.Business.NetworkDesignDocument.Vendor.Nokia
188: select p).ToList();
189:
190: sb = new StringBuilder();
191:
192: foreach (var pon in ponList)
193: {
194: Ia.Ngn.Cl.Model.Business.Nokia.Sdc.EnableSdcPerformanceMonitoringDataForPon(sdc, pon, out result);
195:
196: result.AddResult(result);
197:
198: sb.AppendLine(result.Message);
199: }
200: }
201:
202: ////////////////////////////////////////////////////////////////////////////
203:
204: /// <summary>
205: ///
206: /// </summary>
207: public static void EnableSdcPerformanceMonitoringDataForPon(Ia.Ngn.Cl.Model.Client.Nokia.Sdc sdc, Ia.Ngn.Cl.Model.Business.NetworkDesignDocument.Pon pon, out Ia.Cl.Model.Result result)
208: {
209: string s;
210:
211: result = new Ia.Cl.Model.Result();
212:
213: sdc.EnablePerformanceMonitoringDataOverPon(pon, out Cl.Model.Business.Nokia.Sdc.Response response);
214:
215: s = response.Timestamp + ": " + response.ActivityName + ": " + response.ActivityStatus;
216: s += "\r\n";
217:
218: if (response != null && response.ParameterDictionary != null)
219: {
220: if (response.ParameterDictionary.Count > 0)
221: {
222: foreach (KeyValuePair<string, string> kvp in response.ParameterDictionary)
223: {
224: s += kvp.Key + ": " + kvp.Value + "\r\n";
225: }
226: }
227: }
228:
229: if (response.IsSuccessfull) result.AddSuccess(s);
230: else result.AddError(s);
231: }
232:
233: ////////////////////////////////////////////////////////////////////////////
234:
235: /// <summary>
236: ///
237: /// </summary>
238: public static Ia.Cl.Model.Result ReadPerformanceMonitoringDataOfEnabledPon(Ia.Ngn.Cl.Model.Client.Nokia.Sdc sdc, Ia.Ngn.Cl.Model.Business.NetworkDesignDocument.Pon pon)
239: {
240: var result = new Ia.Cl.Model.Result();
241:
242: var response = sdc.GetPerformanceMonitoringDataOverPon(pon);
243:
244: var text = string.Empty;
245:
246: if (response.IsSuccessfull)
247: {
248: // Tx
249: if (response.ParameterDictionary.ContainsKey("pmParameterName0"))
250: {
251: var gponOltSidePonUtilTxPmIntervalTotalBytesPmParameterName = response.ParameterDictionary["pmParameterName0"];
252:
253: if (response.ParameterDictionary.ContainsKey("pmParameterValue0"))
254: {
255: var gponOltSidePonUtilTxPmIntervalTotalBytesPmParameterValue = response.ParameterDictionary["pmParameterValue0"];
256:
257: if (gponOltSidePonUtilTxPmIntervalTotalBytesPmParameterValue.Length > 0)
258: {
259: var list = gponOltSidePonUtilTxPmIntervalTotalBytesPmParameterValue.Split(',');
260:
261: if (list.Length > 0)
262: {
263: var valueList = new List<long>();
264:
265: foreach (var s in list)
266: {
267: if (long.TryParse(s, out long l)) valueList.Add(l);
268: else text += pon.Name + ": transmit: " + response.Timestamp + ": Error: can't parse s: " + s;
269: }
270:
271: Ia.Ngn.Cl.Model.Data.Nokia.Sdc.SaveTransactionTimestampValueListOfPon(pon, Ia.Ngn.Cl.Model.Business.Nokia.Sdc.Transaction.Transmit, response.Timestamp, valueList);
272:
273: text += pon.Name + ": transmit: " + response.Timestamp + ": " + string.Join(",", valueList);
274: }
275: else
276: {
277: text += pon.Name + ": transmit: " + response.Timestamp + ": Error: list is empty";
278: }
279: }
280: else
281: {
282: text += pon.Name + ": transmit: " + response.Timestamp + ": Error: gponOltSidePonUtilTxPmIntervalTotalBytesPmParameterValue is empty";
283: }
284:
285: result.AddSuccess(text);
286: }
287: else
288: {
289: text += pon.Name + ": transmit: " + response.Timestamp + ": Error: response.ParameterDictionary does not contain key pmParameterValue0";
290:
291: result.AddError(text);
292: }
293: }
294: else
295: {
296: text += pon.Name + ": transmit: " + response.Timestamp + ": Error: response.ParameterDictionary does not contain key pmParameterName0";
297:
298: result.AddError(text);
299: }
300:
301:
302: text = string.Empty;
303:
304: // Rx
305: if (response.ParameterDictionary.ContainsKey("pmParameterName1"))
306: {
307: var gponOltSidePonUtilRxPmIntervalTotalBytesPmParameterName = response.ParameterDictionary["pmParameterName1"];
308:
309: if (response.ParameterDictionary.ContainsKey("pmParameterValue1"))
310: {
311: var gponOltSidePonUtilRxPmIntervalTotalBytesPmParameterValue = response.ParameterDictionary["pmParameterValue1"];
312:
313: if (gponOltSidePonUtilRxPmIntervalTotalBytesPmParameterValue.Length > 0)
314: {
315: var list = gponOltSidePonUtilRxPmIntervalTotalBytesPmParameterValue.Split(',');
316:
317: if (list.Length > 0)
318: {
319: var valueList = new List<long>();
320:
321: foreach (var s in list)
322: {
323: if (long.TryParse(s, out long l)) valueList.Add(l);
324: else text += pon.Name + ": receive: " + response.Timestamp + ": Error: can't parse s: " + s;
325: }
326:
327: Ia.Ngn.Cl.Model.Data.Nokia.Sdc.SaveTransactionTimestampValueListOfPon(pon, Ia.Ngn.Cl.Model.Business.Nokia.Sdc.Transaction.Receive, response.Timestamp, valueList);
328:
329: text += pon.Name + ": receive: " + response.Timestamp + ": " + string.Join(",", valueList);
330: }
331: else
332: {
333: text += pon.Name + ": receive: " + response.Timestamp + ": Error: list is empty";
334: }
335: }
336: else
337: {
338: text += pon.Name + ": receive: " + response.Timestamp + ": Error: gponOltSidePonUtilRxPmIntervalTotalBytesPmParameterValue is empty";
339: }
340:
341: result.AddSuccess(text);
342: }
343: else
344: {
345: text += pon.Name + ": receive: " + response.Timestamp + ": Error: response.ParameterDictionary does not contain key pmParameterValue1";
346:
347: result.AddError(text);
348: }
349: }
350: else
351: {
352: text += pon.Name + ": receive: " + response.Timestamp + ": Error: response.ParameterDictionary does not contain key pmParameterName1";
353:
354: result.AddError(text);
355: }
356: }
357: else result.AddError(text);
358:
359: return result;
360: }
361:
362: ////////////////////////////////////////////////////////////////////////////
363:
364: /// <summary>
365: ///
366: /// </summary>
367: public static List<Ia.Ngn.Cl.Model.Business.Nokia.Sdc.TransactionTimestampValue> AdjustTransactionTimestampHourlyValueList(Ia.Ngn.Cl.Model.Business.Nokia.Sdc.Transaction transaction, List<Ia.Ngn.Cl.Model.Business.Nokia.Sdc.TransactionTimestampValue> timestampValueList)
368: {
369: long l;
370: List<Ia.Ngn.Cl.Model.Business.Nokia.Sdc.TransactionTimestampValue> adjustedTimestampValueList;
371:
372: adjustedTimestampValueList = new List<Ia.Ngn.Cl.Model.Business.Nokia.Sdc.TransactionTimestampValue>();
373:
374: //previous = 0;
375:
376: foreach (var timestampValue in timestampValueList)
377: {
378: if (timestampValue.Transaction == transaction)
379: {
380: l = ConvertHourlyByteCountToMegaBitsPerSecond(timestampValue.Value);
381:
382: adjustedTimestampValueList.Add(new Ia.Ngn.Cl.Model.Business.Nokia.Sdc.TransactionTimestampValue(transaction, timestampValue.Timestamp, l));
383: }
384: }
385:
386: return adjustedTimestampValueList;
387: }
388:
389: ////////////////////////////////////////////////////////////////////////////
390:
391: /// <summary>
392: ///
393: /// </summary>
394: public static long ConvertHourlyByteCountToMegaBitsPerSecond(long l)
395: {
396: // from Nokia support:.. these are byte counters and five minute interval means that you will have to divide the value with 300 to get bytes per second.
397: // ... one byte is eight bits, thus, 10 MB/s = 80 Mb/s.
398: // I say: to get the hourly *rate* in Mb/s I will need to divide by 3600 (seconds in an hour)
399:
400: return l / 3600 * 8 / 1000000;
401: }
402:
403: ////////////////////////////////////////////////////////////////////////////
404:
405: /// <summary>
406: ///
407: /// </summary>
408: public static void ReadPerformanceMonitoringDataOfEnabledPon(Ia.Ngn.Cl.Model.Client.Nokia.Sdc sdc, out Ia.Cl.Model.Result result)
409: {
410: if (ponList == null)
411: {
412: ponList = (from p in Ia.Ngn.Cl.Model.Data.NetworkDesignDocument.PonList
413: where p.PonGroup.Olt.Odf.Vendor == Ia.Ngn.Cl.Model.Business.NetworkDesignDocument.Vendor.Nokia
414: select p).ToList();
415: }
416:
417: var pon = ponList.Next();
418:
419: result = Ia.Ngn.Cl.Model.Business.Nokia.Sdc.ReadPerformanceMonitoringDataOfEnabledPon(sdc, pon);
420: }
421:
422: /*
423: ////////////////////////////////////////////////////////////////////////////
424:
425: /// <summary>
426: ///
427: /// </summary>
428: public static List<Ia.Ngn.Cl.Model.Business.Nokia.Sdc.PonNameTimestampValue> AdjusteStatisticDistributionAndCountAndAverageAccordingToTimeScaleToStatisticsListToMakeMoreResonableStorageList(List<Ia.Ngn.Cl.Model.Business.Nokia.Sdc.PonNameTimestampValue> statisticList)
429: {
430: //int i, numberOfSamplesPerTimeScale;
431: //TimeSpan timeSpan;
432: //DateTime startTime, endTime;
433: List<Ia.Ngn.Cl.Model.Business.Nokia.Sdc.PonNameTimestampValue> oldList, adjustedStatisticsList;
434:
435: /*
436: Dictionary<TimeSpan, List<Ia.Ngn.Cl.Model.Business.Nokia.Sdc.Statistic>> timeSpanToStatisticListDictionary;
437: Dictionary<TimeSpan, List<Ia.Ngn.Cl.Model.Business.Nokia.Sdc.Statistic>> timeScaleToStatisticsListDictionary;
438:
439: numberOfSamplesPerTimeScale = 100;
440:
441: timeScaleToStatisticsListDictionary = new Dictionary<TimeSpan, List<Ia.Ngn.Cl.Model.Business.Nokia.Sdc.Statistic>>();
442:
443: timeSpanToStatisticListDictionary = new Dictionary<TimeSpan, List<Ia.Ngn.Cl.Model.Business.Nokia.Sdc.Statistic>>();
444: */
445: //adjustedStatisticsList = new List<Ia.Ngn.Cl.Model.Business.Nokia.Sdc.PonNameTimestampValue>();
446:
447: /*
448: oldList = new List<Ia.Ngn.Cl.Model.Business.Nokia.Sdc.Statistic>();
449:
450: foreach (var scale in Ia.Ngn.Cl.Model.Business.Nokia.Sdc.ScaleList.OrderBy(u => u.TotalSeconds))
451: {
452: timeScaleToStatisticsListDictionary[scale] = FilterAccordingToScaleTimeSpan(scale, statisticList).Except(oldList).ToList();
453:
454: oldList.AddRange(timeScaleToStatisticsListDictionary[scale]);
455: }
456:
457:
458: foreach (var timeScaleToStatisticsList in timeScaleToStatisticsListDictionary.OrderBy(u => u.Key.TotalSeconds))
459: {
460: timeSpan = new TimeSpan(timeScaleToStatisticsList.Key.Ticks / numberOfSamplesPerTimeScale);
461:
462: startTime = DateTime.UtcNow.AddHours(3) - timeScaleToStatisticsList.Key;
463: endTime = startTime + timeSpan;
464:
465: foreach (var statistic in timeScaleToStatisticsList.Value)
466: {
467: for (i = 0; i < numberOfSamplesPerTimeScale; i++)
468: {
469: if (statistic.Timestamp >= startTime && statistic.Timestamp < endTime)
470: {
471: if (timeSpanToStatisticListDictionary.ContainsKey(timeSpan))
472: {
473: timeSpanToStatisticListDictionary[timeSpan].Add(statistic);
474: }
475: else
476: {
477: timeSpanToStatisticListDictionary[timeSpan] = new List<Ia.Ngn.Cl.Model.Business.Nokia.Sdc.Statistic>();
478:
479: timeSpanToStatisticListDictionary[timeSpan].Add(statistic);
480: }
481:
482: break;
483: }
484:
485: startTime = endTime;
486: endTime = startTime + timeSpan;
487: }
488: }
489:
490: statisticList = new List<Ia.Ngn.Cl.Model.Business.Nokia.Sdc.Statistic>();
491:
492: foreach (KeyValuePair<TimeSpan, List<Ia.Ngn.Cl.Model.Business.Nokia.Sdc.Statistic>> timeSpanToStatisticList in timeSpanToStatisticListDictionary)
493: {
494: if (timeScaleToStatisticsList.Value.Count > 0)
495: {
496: statisticList.Add(new Ia.Ngn.Cl.Model.Business.Nokia.Sdc.Statistic(timeScaleToStatisticsList.Value[0].Pon, startTime, (long)timeSpanToStatisticList.Value.Average(u => u.Count)));
497: }
498: }
499:
500: adjustedStatisticsList.AddRange(statisticList);
501: }
502: * /
503:
504: foreach (var v in statisticList)
505: {
506: if (v.Timestamp >= DateTime.UtcNow.AddHours(3).AddDays(-7))
507: {
508: adjustedStatisticsList.Add(v);
509: }
510: }
511:
512: return adjustedStatisticsList.OrderBy(u => u.Timestamp.Ticks).ToList();
513: }
514: */
515:
516: ////////////////////////////////////////////////////////////////////////////
517:
518: /// <summary>
519: ///
520: /// </summary>
521: public static List<Ia.Ngn.Cl.Model.Business.Nokia.Sdc.TransactionTimestampValue> FilterAndKeepDataFromNDays(List<Ia.Ngn.Cl.Model.Business.Nokia.Sdc.TransactionTimestampValue> timestampValuelist)
522: {
523: var dataToKeepFromPastNDays = 30;
524: var now = DateTime.UtcNow.AddHours(3);
525: var list = new List<Ia.Ngn.Cl.Model.Business.Nokia.Sdc.TransactionTimestampValue>(timestampValuelist.Count);
526:
527: foreach (var timestampValue in timestampValuelist)
528: {
529: if (now.AddDays(-dataToKeepFromPastNDays) < timestampValue.Timestamp) list.Add(timestampValue);
530: }
531:
532: return list;
533: }
534:
535: ////////////////////////////////////////////////////////////////////////////
536: ////////////////////////////////////////////////////////////////////////////
537: }
538:
539: ////////////////////////////////////////////////////////////////////////////
540: ////////////////////////////////////////////////////////////////////////////
541: }