-
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 více zaměřena na výpočty distribuce energií, nicméně základní model jako takový je obecný. Knihovnu lze použít například pro plánovnání cashflow, zaznamenávání časů na projektu či jeho nákladů, distribuci vzduchu, vody, 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 {
}
Diagram je zjednodušený a neobsahuje všechny třídy.
V diagramu je vidět, že knihovna pracuje se stromem entit. Každá entita může obsahovat dceřiné entity. Strom je možné jakkoli větvit. Knihovna obsahuje i funkce pro zpětné dohledání struktury stromu (o tom více v dalších článcích). Každá entita může obsahovat bloky a simulátory. Bloky jsou jasně časově a hodnotou definované úseky "hodnoty" (např. kWh). Simulátory dokážou vygenerovat hodnotu pro daný start-end datum/čas na request.
IEntity
je interface, díky čemuž nelze vytvořit jeho instanci. K tomu slouží buď BaseEntity
(implementace abstraktní třídy CommonEntity
) a nebo specifičtější Source
nebo Consumer
. To jsou nadstavbové interfacy pro vytváření různých druhů zdrojů nebo spotřebičů ve stromě. Pro vytvoření Source
nebo Consumer
existují konkrétní factories. 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 také vidět 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.
I jedna entita může tvořit celou síť, nicméně je vhodné si udělat strukturu. Pokud je vše připravené, 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 zobrazení všech bloků v entitě a subentitách vypadá takto:
Poznámka: Tyto vizuální komponenty jsou součástí knihovny VEFramework.VEBlazor.EntitiesBlocks.
Jakmile jsou bloky v entitě, je možné se entity zeptat 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ž je v entitě jeden blok o délce x dní, lze získat jako výsledek 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 je potřeba získat hodnoty jen v rámci určitého okna (například pro každý den spotřebu 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 dost flexibilní. Více příkladů a funkcí bude popsáno v dalších článcích.