-
Notifications
You must be signed in to change notification settings - Fork 7
EntitiesBlocks Základní úvod do knihovny VEDriversLite.EntitiesBlocks
Knihovna VEDriversLite.EntitiesBlocks obsahuje obecné jádro, které umí počítat s časově ohraničenými bloky vyjadřujícími určitou hodnotu. První fáze vývoje knihovny je trochu více zaměřená na výpočty distribuce energií, nicméně základní model jako takový je obecný. Knihovnu lze použít například i pro plánovnání cashflow, časů projektu či jeho nákladů, distribuci vzduchu, vody či dat, apod.
Základní objekty v knihovně a jejich vazby jsou následující:
classDiagram
IEntity <|-- IConsumer
IEntity <|-- ISource
IEntity <-- CommonEntity
class IEntityHandler {
+List IEntitities
}
IEntityHandler <-- CommonEntityHandler
class CommonEntityHandler {
}
class IBlock {
}
IBlock <-- CommonBlock
class CommonBlock{
}
class IEntity {
+List Children
+List Simulators
+List Blocks
}
class CommonEntity {
}
class IConsumer {
+ Type
}
IConsumer <-- CommonConsumer
CommonEntity <-- CommonConsumer
class CommonConsumer {
}
CommonConsumer <-- Device
class Device {
}
CommonConsumer <-- DeviceGroup
class DeviceGroup {
}
CommonConsumer <-- GroupNetwork
class GroupNetwork {
}
class ISource {
+ Type
}
ISource <-- CommonSource
CommonEntity <-- CommonSource
class CommonSource {
}
CommonSource <-- PVESource
class PVESource {
}
CommonSource <-- BatteryStorage
class BatteryStorage {
}
CommonSource <-- PowerGridSupplier
class PowerGridSupplier {
}
class ISimulator {
}
ISimulator <-- CommonSimulator
class CommonSimulator {
}
CommonSimulator <-- ConsumerTDDSimulator
class ConsumerTDDSimulator {
}
CommonSimulator <-- PVPanelsGroupsHandler
class PVPanelsGroupsHandler {
}
CommonSimulator <-- BatteryBlockHandler
class BatteryBlockHandler {
}
Diaram je zjednodušený. Neobsahuje všechny třídy a také třídy PVE Simulátoru a Battery storage budou vysvětleny v samostatném článku.
V diagramu je již vidět, že knihovna pracuje se stromem entit. Každá entita může obsahovat dceřiné entity. Strom je možné větvit libovolně. Knihovna obsahuje i funkce pro zpětné dohledání struktury stromu (více bude uvedeno v jiných článcích). Každá entita může obsahovat bloky a simulátory. Bloky jsou jasně časově a hodnotou definované úseky "hodnoty" (v příkladech je to kWh). Simulátory dokážou vygenerovat hodnotu pro daný start-end datum/čas na request.
IEntity je interface a nemůžu vytvořit jeho instanci. Pro to slouží buď BaseEntity (implementace abstraktní třídy CommonEntity) a nebo ideálně specifičnější "Source" nebo "Consumer". To jsou nádstavbové interfacy pro vytváření různých druhů zdrojů nebo spotřebičů ve stromě. Pro vytvoření Source nebo Consumer existují konkrétní Factory. Jejich použití je vidět v následujícím kódu:
var eGrid = new BaseEntitiesHandler();
var id = Guid.NewGuid().ToString();
var source = SourceFactory.GetSource(SourceType.PVE, sourceName, "", id);
var res = eGrid.AddEntity(source, sourceName, owner);
sourceId = string.Empty;
if (res.Item1)
sourceId = res.Item2.Item2;
id = Guid.NewGuid().ToString();
var consumer = ConsumerFactory.GetConsumer(ConsumerType.Device, "device1", "", id);
res = eGrid.AddEntity(consumer, "device1", owner);
device1Id = string.Empty;
if (res.Item1)
device1Id = res.Item2.Item2;
id = Guid.NewGuid().ToString();
consumer = ConsumerFactory.GetConsumer(ConsumerType.Device, "device2", "", id);
res = eGrid.AddEntity(consumer, "device2", owner);
device2Id = string.Empty;
if (res.Item1)
device2Id = res.Item2.Item2;
id = Guid.NewGuid().ToString();
source = SourceFactory.GetSource(SourceType.Battery, "devicegroupbattery", "", id);
res = eGrid.AddEntity(source, "devicegroupbattery", owner);
devicegroupbatteryId = string.Empty;
if (res.Item1)
devicegroupbatteryId = res.Item2.Item2;
V příkladu je vidět také přidání entity do "eGrid" objektu. Tento objekt je typu IEntitiesHandler.
Všechny výše uvedené IEntity by ideálně měli spadnout pod nějakou společnou entitu či skupinu entit. Zde je vidět přidání vytvořených entit do společné DeviceGroup:
id = Guid.NewGuid().ToString();
consumer = ConsumerFactory.GetConsumer(ConsumerType.DevicesGroup, "devicegroup", "", id);
res = eGrid.AddEntity(consumer, "devicegroup", owner);
devicegroup = string.Empty;
if (res.Item1)
{
devicegroup = res.Item2.Item2;
eGrid.AddSubEntityToEntity(devicegroup, device1Id);
eGrid.AddSubEntityToEntity(devicegroup, device2Id);
// add battery which is placed in this group as backup source to reduce spikes
eGrid.AddSubEntityToEntity(devicegroup, devicegroupbatteryId);
}
id = Guid.NewGuid().ToString();
consumer = ConsumerFactory.GetConsumer(ConsumerType.GroupNetwork, "network", "", id);
res = eGrid.AddEntity(consumer, "network", owner);
// create object for whole network
networkId = string.Empty;
if (res.Item1)
{
networkId = res.Item2.Item2;
eGrid.AddSubEntityToEntity(networkId, devicegroup);
eGrid.AddSubEntityToEntity(networkId, devicegroup2);
// add common sources in network
eGrid.AddSubEntityToEntity(networkId, sourceId);
eGrid.AddSubEntityToEntity(networkId, batteryId);
}
Celý příklad vygenerování testovací sítě je možné najít v rámci testů v tomto helperu.
Už jedna entita může tvořit celou síť, nicméně je vhodné si udělat strukturu. Pokud již je vše ready, je možné přidat do entity bloky a nebo simulátor. Přidání bloků je vidět v tomto testu. Postup je jednoduchý:
var Block = new BaseBlock();
// add some custom blocks of simulated consumption
var blockstoadd = new List<IBlock>();
var starttime = new DateTime(2022, 1, 3, 5, 0, 0);
var timeframe = new TimeSpan(160, 0, 0);
var endtime = starttime + timeframe;
//device which consume 1kW and run 160 hours, started on 3rd of January in 5am, for example PC
blockstoadd.Add(Block.GetBlockByPower(BlockType.Simulated,
BlockDirection.Consumed,
starttime,
timeframe,
1,
egth.sourceName,
egth.device2Id));
//device which consume 1kW and run 160 hours, started on 3rd of January in 5am, for example PC
blockstoadd.Add(Block.GetBlockByPower(BlockType.Simulated,
BlockDirection.Consumed,
starttime,
timeframe,
1,
egth.sourceName,
egth.device2Id));
//device which consume 1kW and run 160 hours, started on 3rd of January in 5am, for example PC
blockstoadd.Add(Block.GetBlockByPower(BlockType.Simulated,
BlockDirection.Consumed,
starttime,
timeframe,
1,
egth.sourceName,
egth.device1Id));
// add three blocks into device2 (network/devicegroup/device2)
eGrid.AddBlocksToEntity(egth.device2Id, blockstoadd);
Ve vizuální podobě vypadají bloky vložené do entity následovně:
Pokud je vybrána entita, která má více dceřinných entit, tak pak vypadá zobrazení všech bloků v entitě+subentitách takto:
Poznámka: Tyto vizuální komponenty jsou součástí knihovny VEFramework.VEBlazor.EntitiesBlocks.
Jakmile jsou bloky v entitě, můžu se zeptat entity na přepočet spotřeby v rámci určitého časového úseku. Při volání funkce GetConsumptionOfEntity lze nastavit i formát bloků, které budou reprezentovat data po přepočtu. To znamená, že i když mám v entitě, jeden blok o délce x dní, lze získat jako výsledek zpět seznam bloků, kdy každý má 1h timeframe. Příkladem je toto volání:
var device = eGrid.GetEntity(egth.devicegroup, EntityType.Consumer);
if (device != null)
{
var consumption = eGrid.GetConsumptionOfEntity(egth.devicegroup, BlockTimeframe.Hour, starttime, endtime);
var total = 0.0;
if (consumption != null)
{
foreach (var frame in consumption)
total += frame.Amount;
}
Assert.Equal(160 * 3, total);
}
Pokud potřebuji získat ještě hodnoty jen v rámci určitého okna (například pro každý den spotřebu jen mezi 7:00am a 6:00pm, tak lze použít funkci GetConsumptionOfEntityWithWindow. Tímto lze například získat spotřebu v rámci denního a nočního tarifu. Tento usecase je ukázán v tomto testu.
int windowHourStart = 8;
int windowHourEnd = 20;
// day consumption only
if (devicegroup != null)
{
var res = eGrid.GetConsumptionOfEntityWithWindow(devicegroup.Id,
BlockTimeframe.Day,
starttime,
endtime2,
DateTime.MinValue.AddHours(windowHourStart),
DateTime.MinValue.AddHours(windowHourEnd));
var total = 0.0;
foreach (var b in res)
total += b.Amount;
Assert.Equal(1 * 12 * 7 + 50, total);
}
// night consumption only
if (devicegroup != null)
{
var res = eGrid.GetConsumptionOfEntityWithWindow(devicegroup.Id,
BlockTimeframe.Day,
starttime,
endtime2,
DateTime.MinValue.AddHours(windowHourStart),
DateTime.MinValue.AddHours(windowHourEnd),
true);
var total = 0.0;
foreach (var b in res)
total += b.Amount;
Assert.Equal(1 * 12 * 7 + 20 + 20, total);
}
Kombinací, jak tyto (a různé další) funkce knihovny použít dohromady je mnoho. Knihovna je dosti flexibilní. Více příkladů a funkcí bude popsaných v dalších článcích.