Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,10 @@ The Energy Management System operates on multiple time scales:
4. **Fault Detection**: Identifies and logs device issues

### Energy Optimization (15-minute intervals, configurable)
1. **Price Updates**: Fetches current and forecasted electricity prices
1. **Price Updates**: Fetches current and forecasted electricity prices at 15-minute intervals
2. **Weather Forecast**: Updates solar production forecast
3. **MPC Optimization**: Calculates optimal battery and load schedules for next 24-48 hours
4. **Schedule Execution**: Implements optimized decisions for current period
3. **MPC Optimization**: Calculates optimal battery and load schedules for next 24-48 hours using exact 15-minute price data (not hourly averages)
4. **Schedule Execution**: Implements optimized decisions for current 15-minute period
5. **Load Management**:
- **Price below threshold**: Activate loads, prioritize self-consumption
- **Price above threshold**: Deactivate non-essential loads, maximize export
Expand Down
49 changes: 0 additions & 49 deletions entsoe/energy_prices_decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,17 +325,6 @@ func (pmd *PublicationMarketData) LookupPriceByTime(t time.Time) (float64, bool)
return 0, false
}

// LookupAveragePriceInHourByTime searches all TimeSeries in the market data for the average price within the hour containing the given time.
// Returns the first matching average price found and true, or 0 and false if no price is found in any TimeSeries for that hour.
func (pmd *PublicationMarketData) LookupAveragePriceInHourByTime(t time.Time) (float64, bool) {
for _, timeSeries := range pmd.TimeSeries {
if avg, found := timeSeries.Period.averagePriceInHourByTime(t); found {
return avg, true
}
}
return 0, false
}

// GetPriceByTime returns the price for a specific time.
// The price corresponds to the interval that contains the given time.
// For example, if the period starts at 22:00 with hourly resolution:
Expand Down Expand Up @@ -412,44 +401,6 @@ func (p *Period) GetTimeRangeForPosition(position int) (start, end time.Time, va
return start, end, true
}

// averagePriceInHourByTime returns the average price for all intervals within the hour containing the given time.
// If no intervals overlap with the hour, returns (0, false).
func (p *Period) averagePriceInHourByTime(t time.Time) (float64, bool) {
// Find the hour boundaries for the given time
hourStart := t.Truncate(time.Hour)
hourEnd := hourStart.Add(time.Hour)

var sum float64
var count int

var checked *Point

for _, point := range p.Points {
start, end, valid := p.GetTimeRangeForPosition(point.Position)
if !valid {
continue
}
// Check if the interval overlaps with the hour
if (start.Before(hourEnd) && end.After(hourStart)) || (start.Equal(hourStart) && end.After(hourStart)) {
// correctly calculate average even if data point is missed when the price isn't changed
if checked != nil {
for position := checked.Position + 1; position < point.Position; position++ {
sum += checked.PriceAmount
count++
}
}
sum += point.PriceAmount
count++
checked = &point
}
}

if count == 0 {
return 0, false
}
return sum / float64(count), true
}

// DecodeEnergyPricesXML decodes the XML file and returns the parsed data
func DecodeEnergyPricesXML(file io.Reader) (*PublicationMarketData, error) {

Expand Down
Loading