示例#1
0
        /// <summary>
        /// The main calculation method for the accounting period in Taf-1.
        /// </summary>
        /// <param name="supplier">Contains the calculation data.</param>
        /// <param name="meterReading">The MeterReading instance with the raw data.</param>
        /// <param name="startReading">The intervalReading at the beginning of the section.</param>
        /// <param name="endReading">The intervalReading at the end of the section.</param>
        /// <param name="tariffId">The valid tariffId.</param>
        /// <returns>The calculated AccountingSection</returns>
        public AccountingMonth GetSection(UsagePointLieferant supplier, MeterReading meterReading, IntervalReading startReading, IntervalReading endReading, ushort tariffId)
        {
            var registers = supplier.GetRegister();

            this.UpdateReadingTypeFromOriginalValueList(registers);

            var section = new AccountingMonth(registers)
            {
                Reading = new Reading()
                {
                    Amount = startReading.Value, ObisCode = new ObisId(meterReading.ReadingType.ObisCode)
                }
            };

            var  start  = startReading.TargetTime.Value;
            var  end    = endReading.TargetTime.Value;
            long amount = (long)(endReading.Value - startReading.Value);

            var range = new MeasuringRange(start, end, tariffId, amount);

            section.Add(range);
            section.Start = start;

            return(section);
        }
示例#2
0
        // Check whether all referenced DayIds in SpecialDayProfiles are valid DayIds
        private static void ValidateSupplierModelDayProfileOccurence(UsagePointLieferant supplier, List <Exception> exceptions)
        {
            var dayProfileIds = new List <ushort?>();

            foreach (DayProfile profile in supplier.AnalysisProfile.TariffChangeTrigger.TimeTrigger.DayProfiles)
            {
                dayProfileIds.Add(profile.DayId);
            }

            foreach (SpecialDayProfile spProfile in supplier.AnalysisProfile.TariffChangeTrigger.TimeTrigger.SpecialDayProfiles)
            {
                bool match = false;
                foreach (var id in dayProfileIds)
                {
                    if (id == spProfile.DayId)
                    {
                        match = true;
                        break;
                    }
                }
                if (!match)
                {
                    exceptions.Add(new InvalidOperationException("TAF-7: Das Element \"DayProfile\" im Element \"SpecialDayProfile\" ist ungültig."));
                }
            }
        }
示例#3
0
        /// <summary>
        /// Returns the SpecialDayProfiles which are needed.
        /// </summary>
        /// <param name="supplier">The supplier object which contains the SpecialDayProfiles</param>
        /// <param name="dayProfile">The dayId</param>
        /// <returns>The SpecialDayProfiles corresponding to the dayProfile</returns>
        public List <SpecialDayProfile> GetSpecialDayProfiles(UsagePointLieferant supplier, ushort dayProfile)
        {
            var trigger = supplier.AnalysisProfile.TariffChangeTrigger.TimeTrigger;

            return(trigger.SpecialDayProfiles.Where(s => s.DayId == dayProfile)
                   .OrderBy(s => s.SpecialDayDate.GetDate()).ToList());
        }
示例#4
0
        // Check whether all referenced tarif stages which are used in the DayTimeProfiles are valid
        private static void ValidateTarifStageOccurence(UsagePointLieferant supplier, List <Exception> exceptions)
        {
            var tarifStages = new List <ushort>();

            foreach (TariffStage stage in supplier.AnalysisProfile.TariffStages)
            {
                tarifStages.Add(stage.TariffNumber);
            }

            foreach (DayProfile dayProfile in supplier.AnalysisProfile.TariffChangeTrigger.TimeTrigger.DayProfiles)
            {
                foreach (DayTimeProfile dtProfile in dayProfile.DayTimeProfiles)
                {
                    bool match = false;
                    foreach (int stage in tarifStages)
                    {
                        if (stage == dtProfile.TariffNumber)
                        {
                            match = true;
                            break;
                        }
                    }
                    if (!match)
                    {
                        exceptions.Add(new InvalidOperationException($"TAF-7: Ungültige Tarif-Nummer innerhalb eines Tagesprofils: {dtProfile.TariffNumber}"));
                    }
                }
            }
        }
示例#5
0
        // Taf-7: Validate if the supplier periods have a duration of 15 minutes
        private static void ValidateTaf7SupplierDayProfiles(UsagePointLieferant supplier, List <Exception> exceptions)
        {
            var profiles = supplier.AnalysisProfile.TariffChangeTrigger.TimeTrigger.DayProfiles;

            foreach (DayProfile profile in profiles)
            {
                var dtProfiles = profile.DayTimeProfiles;
                for (int i = 0; i < dtProfiles.Count; i++)
                {
                    if (i + 1 == dtProfiles.Count)
                    {
                        break;
                    }

                    var current = new TimeSpan((int)dtProfiles[i].StartTime.Hour, (int)dtProfiles[i].StartTime.Minute, 0);
                    var next    = new TimeSpan((int)dtProfiles[i + 1].StartTime.Hour, (int)dtProfiles[i + 1].StartTime.Minute, 0);

                    if ((int)(next - current).TotalSeconds == 900)
                    {
                        continue;
                    }

                    exceptions.Add(new InvalidOperationException($"TAF-7: Die Tarifschaltzeiten für Tagesprofil {profile.DayId} in der Tarifdatei des Lieferanten sind nicht für jede 15-Minuten-Messperiode angegeben: {current} zu {next}"));
                }
            }
        }
示例#6
0
        /// <summary>
        /// In Taf 1 a tariff change is not allowed. This will be checked in this method.
        /// </summary>
        /// <param name="supplier">The supplier object which is checked</param>
        /// <param name="dayProfile">The current day profile number</param>
        public void CheckValidSupplierFile(UsagePointLieferant supplier, ushort dayProfile, ushort tariff)
        {
            var profiles = this.GetSpecialDayProfiles(supplier, dayProfile);

            var days = (int)(billingPeriodEnd - billingPeriodStart).TotalDays;

            if (profiles.Count % days != 0)
            {
                throw new InvalidOperationException($"Die Anzahl der SpecialDayProfile Objekte muss einem vielfachen von {days} entsprechen.");
            }
        }
示例#7
0
        /// <summary>
        /// Looks for SpecialDayProfiles which have the right dayProfile and are between
        /// the begin and end time.
        /// </summary>
        /// <param name="supplier">The supplier object which contains the SpecialDayProfiles.</param>
        /// <param name="dayProfiles">The valid dayProfiles for the current day.</param>
        /// <param name="begin">The start timestamp.</param>
        /// <param name="end">The end timestamp.</param>
        /// <returns>A list of all valid SpecialDayProfiles.</returns>
        public List <SpecialDayProfile> GetSpecialDayProfiles(UsagePointLieferant supplier, List <ushort?> dayProfiles, DateTime begin, DateTime end)
        {
            // Needed if Begin or End are in the middle of a day
            var open  = begin.Date;
            var close = end.Date;

            return(supplier.AnalysisProfile.TariffChangeTrigger.TimeTrigger
                   .SpecialDayProfiles
                   .Where(s => dayProfiles.Contains(s.DayId) && s.SpecialDayDate.GetDate() >= open && s.SpecialDayDate.GetDate() <= close)
                   .OrderBy(s => s.SpecialDayDate.GetDate()).ToList());
        }
示例#8
0
        // Validation of additional requirements with additional supplier xml (only Taf-7)
        public static void ValidateContext(UsagePointAdapterTRuDI usagePoint, UsagePointLieferant supplierModel, AdapterContext ctx)
        {
            ValidateContext(usagePoint, ctx);

            var exceptions = new List <Exception>();

            ValidateTaf7ModelSupplierCompatibility(usagePoint, supplierModel, exceptions);
            ValidateSupplierModelTariffStageCount(supplierModel, exceptions);
            ValidateSpecialDayProfilesWithinBillingPeriod(supplierModel, exceptions);
            ValidateSupplierModelCompletelyEnrolledCalendar(usagePoint, supplierModel, exceptions);
            ValidateTarifStageOccurence(supplierModel, exceptions);
            ValidateSupplierModelDayProfileOccurence(supplierModel, exceptions);

            if (exceptions.Any())
            {
                throw new AggregateException("Taf-7 Context error:>", exceptions);
            }
        }
示例#9
0
        // Check if any SpecialDayProfiles are within the billing period
        private static void ValidateSpecialDayProfilesWithinBillingPeriod(UsagePointLieferant supplier, List <Exception> exceptions)
        {
            var begin   = supplier.AnalysisProfile.BillingPeriod.Start;
            var end     = supplier.AnalysisProfile.BillingPeriod.GetEnd();
            var counter = 0;

            foreach (SpecialDayProfile profile in supplier.AnalysisProfile.TariffChangeTrigger.TimeTrigger.SpecialDayProfiles)
            {
                if (profile.SpecialDayDate.GetDate() >= begin && profile.SpecialDayDate.GetDate() <= end)
                {
                    counter++;
                }
            }

            if (counter == 0)
            {
                exceptions.Add(new InvalidOperationException("Die Abrechnungsperiode in der Tarifdatei des Lieferanten umfasst keinen vollen Tagesprofil."));
            }
        }
示例#10
0
 // Validates the maximum amount of tariff stages
 private static void ValidateSupplierModelTariffStageCount(UsagePointLieferant supplier, List <Exception> exceptions)
 {
     if (supplier.AnalysisProfile.TariffStages.Count > 20)
     {
         var stages             = supplier.AnalysisProfile.TariffStages;
         int errorRegisterCount = 0;
         foreach (TariffStage stage in stages)
         {
             var obisId = new ObisId(stage.ObisCode);
             if (obisId.E == 63)
             {
                 errorRegisterCount++;
             }
         }
         if (stages.Count - errorRegisterCount > 20)
         {
             exceptions.Add(new InvalidOperationException("Es sind maximal 20 Tarifstuffen zulässig."));
         }
     }
 }
示例#11
0
        // The public method for the validation of the supplier model
        public static UsagePointLieferant ValidateSupplierModel(UsagePointLieferant usagePoint)
        {
            var exceptions = new List <Exception>();

            CommonModelValidation(usagePoint, exceptions);

            if (usagePoint.Certificates.Count >= 1)
            {
                foreach (Certificate cert in usagePoint.Certificates)
                {
                    ValidateCertificate(cert, exceptions);
                }
            }

            ValidateAnalysisProfile(usagePoint.AnalysisProfile, exceptions);
            ValidateTaf7SupplierDayProfiles(usagePoint, exceptions);

            if (exceptions.Any())
            {
                throw new AggregateException("Supplier Model error:>", exceptions);
            }

            return(usagePoint);
        }
示例#12
0
        public void TestGetRegister()
        {
            var supplier        = new UsagePointLieferant();
            var analysisProfile = new AnalysisProfile();

            var obisId181  = "0100010801FF";
            var obisId182  = "0100010802FF";
            var obisId183  = "0100010803FF";
            var obisId1863 = "010001083FFF";

            var obisId281  = "0100020801FF";
            var obisId282  = "0100020802FF";
            var obisId2863 = "010002083FFF";

            var tariffStage1 = new TariffStage()
            {
                Description = "T1", ObisCode = obisId181, TariffNumber = 1
            };
            var tariffStage2 = new TariffStage()
            {
                Description = "T2", ObisCode = obisId182, TariffNumber = 2
            };
            var tariffStage3 = new TariffStage()
            {
                Description = "T3", ObisCode = obisId183, TariffNumber = 3
            };
            var tariffStage4 = new TariffStage()
            {
                Description = "T4", ObisCode = obisId1863, TariffNumber = 4
            };
            var tariffStage5 = new TariffStage()
            {
                Description = "T5", ObisCode = obisId281, TariffNumber = 5
            };
            var tariffStage6 = new TariffStage()
            {
                Description = "T6", ObisCode = obisId282, TariffNumber = 6
            };
            var tariffStage7 = new TariffStage()
            {
                Description = "T7", ObisCode = obisId2863, TariffNumber = 7
            };

            analysisProfile.TariffStages.Add(tariffStage1);
            analysisProfile.TariffStages.Add(tariffStage2);
            analysisProfile.TariffStages.Add(tariffStage3);
            analysisProfile.TariffStages.Add(tariffStage4);
            analysisProfile.TariffStages.Add(tariffStage5);
            analysisProfile.TariffStages.Add(tariffStage6);
            analysisProfile.TariffStages.Add(tariffStage7);

            supplier.AnalysisProfile = analysisProfile;
            var target = supplier.GetRegister();

            Assert.AreEqual(7, target.Count);

            foreach (Register reg in target)
            {
                Assert.AreEqual(0, reg.Amount);
            }

            Assert.AreEqual("0100010801FF", target[0].ObisCode.ToHexString());
            Assert.AreEqual("0100010802FF", target[1].ObisCode.ToHexString());
            Assert.AreEqual("0100010803FF", target[2].ObisCode.ToHexString());
            Assert.AreEqual("010001083FFF", target[3].ObisCode.ToHexString());
            Assert.AreEqual("0100020801FF", target[4].ObisCode.ToHexString());
            Assert.AreEqual("0100020802FF", target[5].ObisCode.ToHexString());
            Assert.AreEqual("010002083FFF", target[6].ObisCode.ToHexString());

            Assert.AreEqual(1, target[0].TariffId);
            Assert.AreEqual(2, target[1].TariffId);
            Assert.AreEqual(3, target[2].TariffId);
            Assert.AreEqual(4, target[3].TariffId);
            Assert.AreEqual(5, target[4].TariffId);
            Assert.AreEqual(6, target[5].TariffId);
            Assert.AreEqual(7, target[6].TariffId);

            supplier.AnalysisProfile.TariffUseCase = HanAdapter.Interface.TafId.Taf2;

            target = supplier.GetRegister();

            Assert.AreEqual(1, target[0].TariffId);
            Assert.AreEqual(2, target[1].TariffId);
            Assert.AreEqual(3, target[2].TariffId);
            Assert.AreEqual(63, target[3].TariffId);
            Assert.AreEqual(5, target[4].TariffId);
            Assert.AreEqual(6, target[5].TariffId);
            Assert.AreEqual(63, target[6].TariffId);

            var analysisProfile2 = new AnalysisProfile
            {
                TariffUseCase = HanAdapter.Interface.TafId.Taf2
            };

            analysisProfile2.TariffStages.Add(tariffStage1);
            analysisProfile2.TariffStages.Add(tariffStage2);
            analysisProfile2.TariffStages.Add(tariffStage3);
            analysisProfile2.TariffStages.Add(tariffStage5);
            analysisProfile2.TariffStages.Add(tariffStage6);

            supplier.AnalysisProfile = analysisProfile2;

            target = supplier.GetRegister();

            foreach (Register reg in target)
            {
                Assert.AreEqual(0, reg.Amount);
            }

            Assert.AreEqual(7, target.Count);

            Assert.AreEqual("0100010801FF", target[0].ObisCode.ToHexString());
            Assert.AreEqual("0100010802FF", target[1].ObisCode.ToHexString());
            Assert.AreEqual("0100010803FF", target[2].ObisCode.ToHexString());
            Assert.AreEqual("0100020801FF", target[3].ObisCode.ToHexString());
            Assert.AreEqual("0100020802FF", target[4].ObisCode.ToHexString());
            Assert.AreEqual("010001083FFF", target[5].ObisCode.ToHexString());
            Assert.AreEqual("010002083FFF", target[6].ObisCode.ToHexString());

            Assert.AreEqual(1, target[0].TariffId);
            Assert.AreEqual(2, target[1].TariffId);
            Assert.AreEqual(3, target[2].TariffId);
            Assert.AreEqual(5, target[3].TariffId);
            Assert.AreEqual(6, target[4].TariffId);
            Assert.AreEqual(63, target[5].TariffId);
            Assert.AreEqual(63, target[6].TariffId);

            var analysisProfile3 = new AnalysisProfile
            {
                TariffUseCase = HanAdapter.Interface.TafId.Taf2
            };

            var obisId381 = "0100030801FF";
            var obisId481 = "0100040801FF";
            var obisId482 = "0100040802FF";

            var tariffStage8 = new TariffStage()
            {
                Description = "T8", ObisCode = obisId381, TariffNumber = 8
            };
            var tariffStage9 = new TariffStage()
            {
                Description = "T9", ObisCode = obisId481, TariffNumber = 9
            };
            var tariffStage10 = new TariffStage()
            {
                Description = "T10", ObisCode = obisId482, TariffNumber = 10
            };

            analysisProfile3.TariffStages.Add(tariffStage1);
            analysisProfile3.TariffStages.Add(tariffStage2);
            analysisProfile3.TariffStages.Add(tariffStage3);
            analysisProfile3.TariffStages.Add(tariffStage5);
            analysisProfile3.TariffStages.Add(tariffStage6);
            analysisProfile3.TariffStages.Add(tariffStage8);
            analysisProfile3.TariffStages.Add(tariffStage9);
            analysisProfile3.TariffStages.Add(tariffStage10);

            supplier.AnalysisProfile = analysisProfile3;

            target = supplier.GetRegister();

            foreach (Register reg in target)
            {
                Assert.AreEqual(0, reg.Amount);
            }

            Assert.AreEqual(12, target.Count);

            Assert.AreEqual("0100010801FF", target[0].ObisCode.ToHexString());
            Assert.AreEqual("0100010802FF", target[1].ObisCode.ToHexString());
            Assert.AreEqual("0100010803FF", target[2].ObisCode.ToHexString());
            Assert.AreEqual("0100020801FF", target[3].ObisCode.ToHexString());
            Assert.AreEqual("0100020802FF", target[4].ObisCode.ToHexString());
            Assert.AreEqual("0100030801FF", target[5].ObisCode.ToHexString());
            Assert.AreEqual("0100040801FF", target[6].ObisCode.ToHexString());
            Assert.AreEqual("0100040802FF", target[7].ObisCode.ToHexString());
            Assert.AreEqual("010001083FFF", target[8].ObisCode.ToHexString());
            Assert.AreEqual("010002083FFF", target[9].ObisCode.ToHexString());
            Assert.AreEqual("010003083FFF", target[10].ObisCode.ToHexString());
            Assert.AreEqual("010004083FFF", target[11].ObisCode.ToHexString());

            Assert.AreEqual(1, target[0].TariffId);
            Assert.AreEqual(2, target[1].TariffId);
            Assert.AreEqual(3, target[2].TariffId);
            Assert.AreEqual(5, target[3].TariffId);
            Assert.AreEqual(6, target[4].TariffId);
            Assert.AreEqual(8, target[5].TariffId);
            Assert.AreEqual(9, target[6].TariffId);
            Assert.AreEqual(10, target[7].TariffId);
            Assert.AreEqual(63, target[8].TariffId);
            Assert.AreEqual(63, target[9].TariffId);
            Assert.AreEqual(63, target[10].TariffId);
            Assert.AreEqual(63, target[11].TariffId);
        }
示例#13
0
        /// <summary>
        /// The main calculation method for every day in the billing period.
        /// </summary>
        /// <param name="profile">The current SpecialDayProfile</param>
        /// <param name="dayProfiles">A List of all DayProfiles</param>
        /// <param name="meterReading">The MeterReading instance with the raw data.</param>
        /// <param name="supplier">Contains the calculation data.</param>
        /// <param name="latestReading">The last valid value of an IntervalReading.</param>
        /// <param name="latestTariffId">The last vaild tariff.</param>
        /// <returns>The calculated AccountingSection</returns>
        public (AccountingDay day, long latestReading, ushort tariffId) GetDayData(SpecialDayProfile profile, List <DayProfile> dayProfiles,
                                                                                   MeterReading meterReading, UsagePointLieferant supplier, long latestReading, ushort latestTariffId)
        {
            var registers = supplier.GetRegister();

            this.UpdateReadingTypeFromOriginalValueList(registers);

            var currentDay = new AccountingDay(registers);

            // Every SpecialDayProfile is linked to a dayProfile which contains dayTimeProfiles.
            // This dayTimeProfiles are needed because they contain the tariff change information of the day.
            var dayTimeProfiles = GetValidDayTimeProfiles(dayProfiles, profile);

            var start        = ModelExtensions.GetDateTimeFromSpecialDayProfile(profile, dayTimeProfiles[0]);
            var index        = 1;
            var startReading = meterReading.GetIntervalReadingFromDate(start);

            // If the current day has a gap at 00:00
            if (startReading == null || !IsStatusValid(startReading))
            {
                var startData = this.GetStartReading(start, dayTimeProfiles, profile,
                                                     meterReading, currentDay, index, latestReading, latestTariffId);

                index          = startData.index;
                startReading   = startData.startReading;
                start          = startData.startReading != null && IsStatusValid(startData.startReading) ? startData.startReading.TargetTime.Value : start;
                latestTariffId = startData.tariffId;
                latestReading  = startData.latestReading;
            }

            // Check whether dayTimeProfiles is null or empty
            this.CheckInitSettings(dayTimeProfiles);

            if (startReading != null && IsStatusValid(startReading))
            {
                currentDay.Reading = new Reading()
                {
                    Amount = startReading.Value, ObisCode = new ObisId(meterReading.ReadingType.ObisCode)
                };
                currentDay.Start = profile.SpecialDayDate.GetDate();
            }

            var endReading = SetConcreteIntervalReading(null, DateTime.MinValue);

            for (var i = index; i < dayTimeProfiles.Count; i++)
            {
                DateTime end;
                // Check if the tariff number changes
                if (dayTimeProfiles[i - 1].TariffNumber != dayTimeProfiles[i].TariffNumber)
                {
                    // Set the end of the current range
                    end        = ModelExtensions.GetDateTimeFromSpecialDayProfile(profile, dayTimeProfiles[i]);
                    endReading = SetIntervalReading(meterReading, end, i, dayTimeProfiles.Count);

                    var rangeData = GetNextRange(endReading.reading, endReading.end,
                                                 startReading, start, end,
                                                 dayTimeProfiles, meterReading, profile, currentDay, i, latestReading, latestTariffId);


                    latestReading  = rangeData.latestReading;
                    start          = rangeData.reading.TargetTime.Value;
                    startReading   = rangeData.reading;
                    i              = rangeData.index;
                    latestTariffId = rangeData.range.TariffId;
                    latestReading  = this.GetLatestReading(latestReading, rangeData.reading);

                    if (!this.IsRangeEmpty(rangeData.range))
                    {
                        currentDay.Add(rangeData.range, new ObisId(meterReading.ReadingType.ObisCode));
                    }
                }
                // If there is no tariff change at the current timestamp
                else
                {
                    //  Check if it is the last value of the current day
                    if (i == dayTimeProfiles.Count - 1)
                    {
                        end        = ModelExtensions.GetDateTimeFromSpecialDayProfile(profile, dayTimeProfiles[i]);
                        endReading = SetIntervalReading(meterReading, end, i, dayTimeProfiles.Count);

                        var rangeData = GetNextRange(endReading.reading, endReading.end,
                                                     startReading, start, end,
                                                     dayTimeProfiles, meterReading, profile, currentDay, i, latestReading, latestTariffId);


                        latestReading  = rangeData.latestReading;
                        start          = end;
                        startReading   = rangeData.reading;
                        i              = rangeData.index;
                        latestTariffId = rangeData.range.TariffId;
                        latestReading  = this.GetLatestReading(latestReading, rangeData.reading);

                        if (!this.IsRangeEmpty(rangeData.range))
                        {
                            currentDay.Add(rangeData.range, new ObisId(meterReading.ReadingType.ObisCode));
                        }
                    }
                }
            }

            return(currentDay, latestReading, latestTariffId);
        }
示例#14
0
        /// <inheritdoc />
        /// <summary>
        /// Calculates the derived register for Taf1.
        /// </summary>
        /// <param name="device">Date from the SMGW. There should be just original value lists.</param>
        /// <param name="supplier">The calculation data from the supplier.</param>
        /// <returns>An ITaf2Data instance. The object contains the calculated data.</returns>
        public TafAdapterData Calculate(UsagePointAdapterTRuDI device, UsagePointLieferant supplier)
        {
            this.originalValueLists =
                device.MeterReadings.Where(mr => mr.IsOriginalValueList()).Select(mr => new OriginalValueList(mr, device.ServiceCategory.Kind ?? Kind.Electricity)).ToList();

            if (!this.originalValueLists.Any())
            {
                throw new InvalidOperationException("Es ist keine originäre Messwertliste verfügbar.");
            }

            this.ValidateOriginalValueLists(originalValueLists, supplier, device.MeterReadings.Count);

            var registers = supplier.GetRegister();

            this.UpdateReadingTypeFromOriginalValueList(registers);

            var accountingPeriod = new Taf1Data(registers, supplier.AnalysisProfile.TariffStages);

            accountingPeriod.SetDate(supplier.AnalysisProfile.BillingPeriod.Start, supplier.AnalysisProfile.BillingPeriod.GetEnd());
            this.SetTotalBillingPeriod(accountingPeriod);

            ValidateBillingPeriod();

            var dayProfiles = supplier.AnalysisProfile.TariffChangeTrigger.TimeTrigger.DayProfiles;

            foreach (OriginalValueList ovl in originalValueLists)
            {
                var startReading = ovl.MeterReading.GetIntervalReadingFromDate(billingPeriodStart);
                var endReading   = ovl.MeterReading.GetIntervalReadingFromDate(billingPeriodEnd);

                if (startReading == null || !IsStatusValid(startReading))
                {
                    throw new InvalidOperationException($"Zu dem Zeitpunkt {billingPeriodStart} ist kein Wert vorhanden oder der Status kritisch oder fatal.");
                }

                if (endReading == null || !IsStatusValid(endReading))
                {
                    throw new InvalidOperationException($"Zu dem Zeitpunkt {billingPeriodEnd} ist kein Wert vorhanden oder der Status kritisch oder fatal.");
                }

                var dayProfile = this.GetDayProfileNumber(dayProfiles, new ObisId(ovl.MeterReading.ReadingType.ObisCode),
                                                          supplier.AnalysisProfile);

                var tariffStages = supplier.AnalysisProfile.TariffStages;
                var tariffId     = this.GetTariffId(tariffStages, dayProfiles, dayProfile);

                CheckValidSupplierFile(supplier, dayProfile, tariffId);

                var result = this.GetSection(supplier, ovl.MeterReading, startReading, endReading, tariffId);

                accountingPeriod.Add(result);

                accountingPeriod.AddInitialReading(new Reading()
                {
                    Amount   = accountingPeriod.AccountingSections.First(s => s.Reading.ObisCode == ovl.MeterReading.ReadingType.ObisCode).Reading.Amount,
                    ObisCode = new ObisId(ovl.MeterReading.ReadingType.ObisCode)
                });
            }

            return(new TafAdapterData(typeof(Taf2SummaryView), typeof(Taf2DetailView), accountingPeriod));
        }
示例#15
0
        /// <summary>
        /// The method provides the derrived register for the Taf7 calculation.
        /// </summary>
        /// <param name="supplier">The supplier model which contains the needed tariff data for the register.</param>
        /// <returns>A list of all register which are needed for the calculation.</returns>
        public static List <Register> GetRegister(this UsagePointLieferant supplier)
        {
            var register     = new List <Register>();
            var tariffStages = supplier.AnalysisProfile.TariffStages;

            foreach (TariffStage stage in tariffStages)
            {
                var reg = new Register()
                {
                    ObisCode = new ObisId(stage.ObisCode),
                    TariffId = stage.TariffNumber,
                    Amount   = 0
                };
                register.Add(reg);
            }

            if (supplier.AnalysisProfile.TariffUseCase == HanAdapter.Interface.TafId.Taf2)
            {
                var errorRegister = register.Where(r => r.ObisCode.E == 63).ToList() ?? new List <Register>();

                if (errorRegister.Count > 0)
                {
                    foreach (Register reg in errorRegister)
                    {
                        reg.TariffId = 63;
                    }
                }
                else
                {
                    var first   = true;
                    var seccond = true;
                    var next    = 2;

                    foreach (Register reg in register.ToList())
                    {
                        if (first && reg.ObisCode.C == 1)
                        {
                            var oc          = reg.ObisCode.ToHexString();
                            var errRegister = new Register()
                            {
                                ObisCode = new ObisId(oc)
                                {
                                    E = 63
                                },
                                TariffId = 63,
                                Amount   = 0
                            };

                            register.Add(errRegister);
                            first = false;
                        }
                        else if (seccond && reg.ObisCode.C == 2)
                        {
                            var oc          = reg.ObisCode.ToHexString();
                            var errRegister = new Register()
                            {
                                ObisCode = new ObisId(oc)
                                {
                                    E = 63
                                },
                                TariffId = 63,
                                Amount   = 0
                            };

                            register.Add(errRegister);
                            seccond = false;
                        }
                        else if (reg.ObisCode.C != 1 && reg.ObisCode.C != 2 && reg.ObisCode.C > next)
                        {
                            var oc          = reg.ObisCode.ToHexString();
                            var errRegister = new Register()
                            {
                                ObisCode = new ObisId(oc)
                                {
                                    E = 63
                                },
                                TariffId = 63,
                                Amount   = 0
                            };
                            next++;
                            register.Add(errRegister);
                        }
                    }
                }
            }
            return(register);
        }
示例#16
0
        public static UsagePointLieferant ParseSupplierModel(IEnumerable <XElement> elements)
        {
            UsagePointLieferant usagePoint = null;
            var exceptions         = new List <Exception>();
            var dayIdAlreadyExists = false;

            foreach (XElement e in elements)
            {
                switch (e.Name.LocalName)
                {
                case "UsagePoint":
                    usagePoint = new UsagePointLieferant();
                    break;

                case "usagePointId":
                    usagePoint.UsagePointId = e.Value;
                    break;

                case "tariffName":
                    usagePoint.TariffName = e.Value;
                    break;

                case "Customer":
                    usagePoint.Customer = new Customer();
                    break;

                case "customerId":
                    usagePoint.Customer.CustomerId = e.Value;
                    break;

                case "InvoicingParty":
                    usagePoint.InvoicingParty = new InvoicingParty();
                    break;

                case "invoicingPartyId":
                    usagePoint.InvoicingParty.InvoicingPartyId = e.Value;
                    break;

                case "ServiceCategory":
                    usagePoint.ServiceCategory = new ServiceCategory();
                    break;

                case "kind":
                    usagePoint.ServiceCategory.Kind = (Kind)Convert.ToInt32(e.Value);
                    break;

                case "SMGW":
                    usagePoint.Smgw = new SMGW();
                    break;

                case "certId":
                    if (e.Parent.Name.LocalName == "SMGW")
                    {
                        usagePoint.Smgw.CertIds.Add(Convert.ToByte(e.Value));
                    }
                    else if (e.Parent.Name.LocalName == "Certificate")
                    {
                        usagePoint.Certificates.LastOrDefault().CertId = Convert.ToByte(e.Value);
                    }

                    break;

                case "smgwId":
                    usagePoint.Smgw.SmgwId = e.Value;
                    break;

                case "Certificate":
                    usagePoint.Certificates.Add(new Certificate());
                    break;

                case "certType":
                    usagePoint.Certificates.LastOrDefault().CertType = (CertType)Convert.ToByte(e.Value);
                    break;

                case "parentCertId":
                    usagePoint.Certificates.LastOrDefault().ParentCertId = Convert.ToByte(e.Value);
                    break;

                case "certContent":
                    if (e.Value.ValidateHexString())
                    {
                        usagePoint.Certificates.LastOrDefault().HexStringToByteArray(e.Value);
                    }
                    else
                    {
                        exceptions.Add(new InvalidOperationException("Das Element \"certContent\" enthält keinen gültigen Wert."));
                    }

                    break;

                case "AnalysisProfile":
                    usagePoint.AnalysisProfile = new AnalysisProfile();
                    break;

                case "tariffUseCase":
                    usagePoint.AnalysisProfile.TariffUseCase = (TafId)Convert.ToUInt16(e.Value);
                    break;

                case "tariffId":
                    usagePoint.AnalysisProfile.TariffId = e.Value;
                    break;

                case "defaultTariffNumber":
                    usagePoint.AnalysisProfile.DefaultTariffNumber = Convert.ToUInt16(e.Value);
                    break;

                case "billingPeriod":
                    usagePoint.AnalysisProfile.BillingPeriod = new Interval();
                    break;

                case "duration":
                    usagePoint.AnalysisProfile.BillingPeriod.Duration = Convert.ToUInt32(e.Value);
                    break;

                case "start":
                    usagePoint.AnalysisProfile.BillingPeriod.Start = Convert.ToDateTime(e.Value);
                    break;

                case "TariffStage":
                    usagePoint.AnalysisProfile.TariffStages.Add(new TariffStage());
                    break;

                case "tariffNumber":
                    if (e.Parent.Name.LocalName == "TariffStage")
                    {
                        usagePoint.AnalysisProfile.TariffStages.LastOrDefault().TariffNumber = Convert.ToUInt16(e.Value);
                    }
                    else if (e.Parent.Name.LocalName == "DayTimeProfile")
                    {
                        usagePoint.AnalysisProfile.TariffChangeTrigger.TimeTrigger.DayProfiles.LastOrDefault()
                        .DayTimeProfiles.LastOrDefault().TariffNumber = Convert.ToUInt16(e.Value);
                    }

                    break;

                case "description":
                    usagePoint.AnalysisProfile.TariffStages.LastOrDefault().Description = e.Value;
                    break;

                case "obisCode":
                    usagePoint.AnalysisProfile.TariffStages.LastOrDefault().ObisCode = e.Value;
                    break;

                case "TariffChangeTrigger":
                    usagePoint.AnalysisProfile.TariffChangeTrigger = new TariffChangeTrigger();
                    break;

                case "TimeTrigger":
                    usagePoint.AnalysisProfile.TariffChangeTrigger.TimeTrigger = new TimeTrigger();
                    break;

                case "DayProfile":
                    usagePoint.AnalysisProfile.TariffChangeTrigger.TimeTrigger.DayProfiles.Add(new DayProfile());
                    dayIdAlreadyExists = false;
                    break;

                case "dayId":
                    if (e.Parent.Name.LocalName == "DayProfile")
                    {
                        if (dayIdAlreadyExists)
                        {
                            exceptions.Add(new InvalidOperationException("Es ist nur ein Element \"dayId\" innerhalb des Elements \"DayProfile\" erlaubt."));
                        }
                        else
                        {
                            usagePoint.AnalysisProfile.TariffChangeTrigger.TimeTrigger.DayProfiles.LastOrDefault()
                            .DayId = Convert.ToUInt16(e.Value);
                            dayIdAlreadyExists = true;
                        }
                    }
                    else if (e.Parent.Name.LocalName == "SpecialDayProfile")
                    {
                        var id = Convert.ToUInt16(e.Value);
                        usagePoint.AnalysisProfile.TariffChangeTrigger.TimeTrigger.SpecialDayProfiles
                        .LastOrDefault().DayId = id;
                        try
                        {
                            usagePoint.AnalysisProfile.TariffChangeTrigger.TimeTrigger.SpecialDayProfiles
                            .LastOrDefault().DayProfile = usagePoint.AnalysisProfile.TariffChangeTrigger.TimeTrigger
                                                          .DayProfiles.Single(dp => dp.DayId == id);
                        }
                        catch (Exception ex)
                        {
                            exceptions.Add(ex);
                        }
                    }
                    break;

                case "DayTimeProfile":
                    usagePoint.AnalysisProfile.TariffChangeTrigger.TimeTrigger.DayProfiles.LastOrDefault()
                    .DayTimeProfiles.Add(new DayTimeProfile());
                    usagePoint.AnalysisProfile.TariffChangeTrigger.TimeTrigger.DayProfiles.LastOrDefault()
                    .DayTimeProfiles.LastOrDefault().DayProfile = usagePoint.AnalysisProfile
                                                                  .TariffChangeTrigger.TimeTrigger.DayProfiles.LastOrDefault();
                    break;

                case "startTime":
                    usagePoint.AnalysisProfile.TariffChangeTrigger.TimeTrigger.DayProfiles.LastOrDefault()
                    .DayTimeProfiles.LastOrDefault().StartTime = new TimeVarType();
                    break;

                case "hour":
                    usagePoint.AnalysisProfile.TariffChangeTrigger.TimeTrigger.DayProfiles.LastOrDefault()
                    .DayTimeProfiles.LastOrDefault().StartTime.Hour = Convert.ToByte(e.Value);
                    break;

                case "minute":
                    usagePoint.AnalysisProfile.TariffChangeTrigger.TimeTrigger.DayProfiles.LastOrDefault()
                    .DayTimeProfiles.LastOrDefault().StartTime.Minute = Convert.ToByte(e.Value);
                    break;

                case "second":
                    usagePoint.AnalysisProfile.TariffChangeTrigger.TimeTrigger.DayProfiles.LastOrDefault()
                    .DayTimeProfiles.LastOrDefault().StartTime.Second = Convert.ToByte(e.Value);
                    break;

                case "hundreds":
                    usagePoint.AnalysisProfile.TariffChangeTrigger.TimeTrigger.DayProfiles.LastOrDefault()
                    .DayTimeProfiles.LastOrDefault().StartTime.Hundreds = Convert.ToByte(e.Value);
                    break;

                case "SpecialDayProfile":
                    usagePoint.AnalysisProfile.TariffChangeTrigger.TimeTrigger.SpecialDayProfiles.Add(new SpecialDayProfile());
                    break;

                case "specialDayDate":
                    usagePoint.AnalysisProfile.TariffChangeTrigger.TimeTrigger.SpecialDayProfiles.LastOrDefault()
                    .SpecialDayDate = new DayVarType();
                    break;

                case "year":
                    usagePoint.AnalysisProfile.TariffChangeTrigger.TimeTrigger.SpecialDayProfiles.LastOrDefault()
                    .SpecialDayDate.Year = Convert.ToUInt16(e.Value);
                    break;

                case "month":
                    usagePoint.AnalysisProfile.TariffChangeTrigger.TimeTrigger.SpecialDayProfiles.LastOrDefault()
                    .SpecialDayDate.Month = Convert.ToByte(e.Value);
                    break;

                case "day_of_month":
                    usagePoint.AnalysisProfile.TariffChangeTrigger.TimeTrigger.SpecialDayProfiles.LastOrDefault()
                    .SpecialDayDate.DayOfMonth = Convert.ToByte(e.Value);
                    break;

                default:
                    if (usagePoint == null)
                    {
                        throw new InvalidOperationException("Keine gültige Datei.");
                    }

                    exceptions.Add(new InvalidOperationException($"Das Element \"{e.Name.LocalName}\" wird nicht unterstützt."));
                    break;
                }
            }

            if (exceptions.Any())
            {
                throw new AggregateException("Supplier Parsing error:>", exceptions);
            }

            return(usagePoint);
        }
示例#17
0
        // Validate of all the neccessary ids of the model xml match with the ids in the supplier xml
        private static void ValidateTaf7ModelSupplierCompatibility(UsagePointAdapterTRuDI model, UsagePointLieferant supplier, List <Exception> exceptions)
        {
            if (model.UsagePointId != supplier.UsagePointId)
            {
                exceptions.Add(new InvalidOperationException($"TAF-7: Die ID der Messlokation \"{model.UsagePointId}\" stimmt nicht mit der ID der Messlokation \"{supplier.UsagePointId}\" aus der Tarifdatei des Lieferanten überein."));
            }

            if (model.InvoicingParty.InvoicingPartyId != supplier.InvoicingParty.InvoicingPartyId)
            {
                exceptions.Add(new InvalidOperationException($"TAF-7: Die ID des Rechnungsstellers \"{model.InvoicingParty.InvoicingPartyId}\" stimmt nicht mit der ID des Rechnungssteller \"{supplier.InvoicingParty.InvoicingPartyId}\" aus der Tarifdatei des Lieferanten überein."));
            }

            if (model.ServiceCategory.Kind != supplier.ServiceCategory.Kind)
            {
                exceptions.Add(new InvalidOperationException($"TAF-7: Die Service-Kategory \"{model.ServiceCategory.Kind}\" stimmt nicht mit der Service-Kategory \"{supplier.ServiceCategory.Kind}\" aus der Tarifdatei des Lieferanten überein."));
            }

            if (string.Compare(model.Smgw.SmgwId, supplier.Smgw.SmgwId, StringComparison.OrdinalIgnoreCase) != 0)
            {
                exceptions.Add(new InvalidOperationException($"TAF-7: Die ID des Smart Meter Gateway \"{model.Smgw.SmgwId}\" stimmt nicht mit der ID \"{supplier.Smgw.SmgwId}\" aus der Tarifdatei des Lieferanten überein."));
            }

            if (model.TariffName != supplier.TariffName)
            {
                exceptions.Add(new InvalidOperationException($"TAF-7: Der Tarifname \"{model.TariffName}\" stimmt nicht mit dem Tariffnamen \"{supplier.TariffName}\" aus der Tarifdatei des Lieferanten überein."));
            }
        }
示例#18
0
        /// <summary>
        /// Check if the count of the original value lists are valid and if all meterReadings are original value lists.
        /// The TariffStages count is also checked. The max is one TariffStage per original value list.
        /// </summary>
        /// <param name="originalValueList">The list with all original value lists.</param>
        /// <param name="supplier">raw data from the supplier.</param>
        public void ValidateOriginalValueLists(List <OriginalValueList> originalValueLists, UsagePointLieferant supplier, int meterReadingsCount)
        {
            if (originalValueLists.Count > 3)
            {
                throw new InvalidOperationException("Es werden maximal 3 originäre Messwertlisten unterstützt.");
            }

            if (originalValueLists.Count != meterReadingsCount)
            {
                throw new InvalidOperationException("Es sind nur originäre Messwertlisten zulässig.");
            }


            if (supplier.AnalysisProfile.TariffStages.Count > originalValueLists.Count)
            {
                throw new InvalidOperationException("Die Anzahl der Tarifstufen darf die Anzahl der originären Messwertlisten nicht überschreiten.");
            }
        }
示例#19
0
        // Check if the delivered supplier xml has an completely enrolled calendar
        private static void ValidateSupplierModelCompletelyEnrolledCalendar(UsagePointAdapterTRuDI model, UsagePointLieferant supplier, List <Exception> exceptions)
        {
            var period   = supplier.AnalysisProfile.BillingPeriod;
            var profiles = supplier.AnalysisProfile.TariffChangeTrigger.TimeTrigger.SpecialDayProfiles;

            var sdpCheckList = new Dictionary <DateTime, int>();
            var timestamp    = period.Start;
            var hasCounted   = false;

            while (timestamp <= period.GetEnd().AddDays(-1))
            {
                sdpCheckList.Add(timestamp, 0);

                timestamp = timestamp.AddDays(1);
            }

            foreach (var profile in profiles)
            {
                if (sdpCheckList.ContainsKey(profile.SpecialDayDate.GetDate()))
                {
                    sdpCheckList[profile.SpecialDayDate.GetDate()] += 1;
                    hasCounted = true;
                }
            }

            foreach (var item in sdpCheckList)
            {
                if (item.Value == 0 && hasCounted)
                {
                    exceptions.Add(new InvalidOperationException($"Tagesprofil für Tag {item.Key:dd.MM.yyy} nicht vorhanden."));
                }
            }
        }
示例#20
0
        /// <inheritdoc />
        /// <summary>
        /// Calculates the derived registers for Taf2.
        /// </summary>
        /// <param name="device">Data from the SMGW. There should be just original value lists.</param>
        /// <param name="supplier">The calculation data from the supplier.</param>
        /// <returns>An ITaf2Data instance. The object contains the calculated data.</returns>
        public TafAdapterData Calculate(UsagePointAdapterTRuDI device, UsagePointLieferant supplier)
        {
            this.originalValueLists =
                device.MeterReadings.Where(mr => mr.IsOriginalValueList()).Select(mr => new OriginalValueList(mr, device.ServiceCategory.Kind ?? Kind.Electricity)).ToList();

            if (!this.originalValueLists.Any())
            {
                throw new InvalidOperationException("Es ist keine originäre Messwertliste verfügbar.");
            }

            var registers = supplier.GetRegister();

            this.UpdateReadingTypeFromOriginalValueList(registers);

            var accountingPeriod = new Taf2Data(registers, supplier.AnalysisProfile.TariffStages);
            var dayProfiles      = supplier.AnalysisProfile.TariffChangeTrigger.TimeTrigger.DayProfiles;

            foreach (var ovl in this.originalValueLists)
            {
                var bpStart = ovl.MeterReading.GetFirstReadingTimestamp(supplier.AnalysisProfile.BillingPeriod.Start, supplier.AnalysisProfile.BillingPeriod.GetEnd());
                var bpEnd   = ovl.MeterReading.GetLastReadingTimestamp(supplier.AnalysisProfile.BillingPeriod.Start, supplier.AnalysisProfile.BillingPeriod.GetEnd());
                if (bpEnd == null || bpStart == null || bpStart == bpEnd)
                {
                    throw new InvalidOperationException("Keine Messwerte innerhalb des Abbrechnungszeitraums gefunden.");
                }

                accountingPeriod.SetDates(bpStart.Value, bpEnd.Value);
                this.SetTotalBillingPeriod(accountingPeriod);

                var    validDayProfiles   = dayProfiles.GetValidDayProfilesForMeterReading(ovl.Obis, supplier.AnalysisProfile.TariffStages);
                var    specialDayProfiles = this.GetSpecialDayProfiles(supplier, validDayProfiles, accountingPeriod.Begin, accountingPeriod.End);
                long   latestReading      = 0;
                ushort latestTariffId     = 63;

                // Check if the lists validDayProfiles and special DayProfiles are null or empty
                if (!this.CheckUsedLists(validDayProfiles, specialDayProfiles))
                {
                    continue;
                }

                // Calculation of the single days (latestReading and latestTariffId are needed for days across gap detection)
                foreach (SpecialDayProfile profile in specialDayProfiles)
                {
                    var currentDayData = this.GetDayData(profile, dayProfiles, ovl.MeterReading, supplier, latestReading, latestTariffId);
                    if (!(currentDayData.day.Start == DateTime.MinValue) || currentDayData.day.MeasuringRanges.Count != 0)
                    {
                        accountingPeriod.Add(currentDayData.day);
                    }
                    latestReading  = currentDayData.latestReading;
                    latestTariffId = currentDayData.tariffId;
                }

                // Set the initial overall meter reading
                accountingPeriod.AddInitialReading(new Reading()
                {
                    Amount   = accountingPeriod.AccountingSections.First().Reading.Amount,
                    ObisCode = ovl.Obis
                });
            }

            accountingPeriod.OrderSections();
            return(new TafAdapterData(typeof(Taf2SummaryView), typeof(Taf2DetailView), accountingPeriod));
        }