Skip to content

Commit

Permalink
feat: read initial battery soc from payload (#8)
Browse files Browse the repository at this point in the history
  • Loading branch information
enell authored Jan 3, 2023
1 parent 245d8d0 commit b4057f8
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 99 deletions.
11 changes: 6 additions & 5 deletions src/fitness.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,12 @@ const calculateChargeScore = (props) => {
batteryMaxInputPower,
averageConsumption,
currentCharge,
batteryCapacity,
batteryMaxEnergy,
} = props
let cost = price * (averageConsumption * duration)

let charge = batteryMaxInputPower * duration
const overCharge = currentCharge + charge - batteryCapacity
const overCharge = currentCharge + charge - batteryMaxEnergy
if (overCharge > 0) {
charge -= overCharge
// apply penalty for overcharge
Expand All @@ -112,13 +112,14 @@ const fitnessFunction = (props) => (phenotype) => {
const {
totalDuration,
priceData,
batteryCapacity,
batteryMaxEnergy,
batteryMaxInputPower,
averageConsumption,
} = props

let score = 0
let currentCharge = 0
const soc = props.soc ?? 0
let currentCharge = (soc / 100) * batteryMaxEnergy

for (const interval of fillInNormalPeriodsGenerator(
totalDuration,
Expand All @@ -130,7 +131,7 @@ const fitnessFunction = (props) => (phenotype) => {
duration: interval.duration / 60,
currentCharge: currentCharge,
totalDuration: totalDuration,
batteryCapacity: batteryCapacity,
batteryMaxEnergy: batteryMaxEnergy,
batteryMaxInputPower: batteryMaxInputPower,
averageConsumption: averageConsumption,
})
Expand Down
11 changes: 10 additions & 1 deletion src/strategy-battery-charging-functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,16 +180,24 @@ const toSchedule = (p, start) => {

const calculateBatteryChargingStrategy = (config) => {
const {
priceData,
populationSize,
numberOfPricePeriods,
generations,
mutationRate,
batteryMaxEnergy,
batteryMaxInputPower,
averageConsumption,
soc,
} = config

let priceData = config.priceData
if (Number.isInteger(soc)) {
let now = Date.now()
now = new Date(now - (now % (60 * 60 * 1000)))

priceData = priceData.filter((v) => new Date(v.start) >= now)
}

if (priceData === undefined || priceData.length === 0) return []

let totalDuration = 0
Expand All @@ -209,6 +217,7 @@ const calculateBatteryChargingStrategy = (config) => {
batteryMaxEnergy,
batteryMaxInputPower,
averageConsumption,
soc,
}),
population: generatePopulation(
totalDuration,
Expand Down
2 changes: 2 additions & 0 deletions src/strategy-battery-charging.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const node = (RED) => {

this.on('input', async (msg, send, done) => {
const priceData = msg.payload?.priceData || []
const soc = msg.payload?.soc ?? 0

const schedule = calculateBatteryChargingStrategy({
priceData,
Expand All @@ -32,6 +33,7 @@ const node = (RED) => {
batteryMaxOutputPower,
batteryMaxInputPower,
averageConsumption,
soc,
})

if (msg.payload) {
Expand Down
118 changes: 33 additions & 85 deletions test/fitness.test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const { expect } = require('@jest/globals')
const {
fitnessFunction,
splitIntoHourIntervals,
Expand Down Expand Up @@ -38,85 +39,6 @@ describe('Fitness - splitIntoHourIntervals', () => {
{ start: 120, activity: 1, duration: 30 },
])
})

// test('should calculate fitness score with no periods', () => {
// const priceData = [
// { value: 1, start: '2022-12-01T00:00:00.000Z' },
// { value: 1, start: '2022-12-01T01:00:00.000Z' },
// ]
// let endTime = 2 * 60
// let batteryMaxEnergy = 1
// let batteryMaxInputPower = 1
// let averageConsumption = 1

// let score = fitnessFunction({
// priceData,
// endTime,
// batteryMaxEnergy,
// batteryMaxInputPower,
// averageConsumption,
// })([])
// expect(score).toBe(-2)
// })

// test('should calculate fitness score with one charge period', () => {
// const priceData = [
// { value: 1, start: '2022-12-01T00:00:00.000Z' },
// { value: 1, start: '2022-12-01T01:00:00.000Z' },
// ]
// let endTime = 2 * 60
// let batteryMaxEnergy = 1
// let batteryMaxInputPower = 1
// let averageConsumption = 1

// let score = fitnessFunction({ priceData, endTime, batteryMaxEnergy, batteryMaxInputPower, averageConsumption })([
// { start: 0, activity: 1, duration: 60 },
// ])
// expect(score).toBe(-3)
// })

// test('should calculate fitness score with one discharge period', () => {
// const priceData = [
// { value: 1, start: '2022-12-01T00:00:00.000Z' },
// { value: 1, start: '2022-12-01T01:00:00.000Z' },
// ]
// let endTime = 2 * 60
// let batteryMaxEnergy = 1
// let batteryMaxInputPower = 1
// let averageConsumption = 1

// let score = fitnessFunction({ priceData, endTime, batteryMaxEnergy, batteryMaxInputPower, averageConsumption })([
// { start: 0, activity: -1, duration: 60 },
// ])
// expect(score).toBe(-2)
// })

// test('should calculate fitness score with charged battery', () => {
// const priceData = [
// { value: 1, start: '2022-12-01T00:00:00.000Z' },
// { value: 2, start: '2022-12-01T01:00:00.000Z' },
// ]
// let endTime = 2 * 60
// let batteryMaxEnergy = 1
// let batteryMaxInputPower = 1
// let averageConsumption = 1

// let fitness = fitnessFunction({ priceData, endTime, batteryMaxEnergy, batteryMaxInputPower, averageConsumption })

// expect(
// fitness([
// { start: 0, activity: 1, duration: 60 },
// { start: 60, activity: -1, duration: 60 },
// ])
// ).toBe(-2)

// expect(
// fitness([
// { start: 0, activity: 1, duration: 90 },
// { start: 90, activity: -1, duration: 30 },
// ])
// ).toBe(-3)
// })
})

describe('Fitness - fillInNormalPeriods', () => {
Expand Down Expand Up @@ -242,7 +164,7 @@ describe('Fitness - calculateChargeScore', () => {
price: 2,
averageConsumption: 1,
currentCharge: 5,
batteryCapacity: 5,
batteryMaxEnergy: 5,
batteryMaxInputPower: 1,
})
).toEqual([2, 0])
Expand All @@ -255,7 +177,7 @@ describe('Fitness - calculateChargeScore', () => {
price: 2,
averageConsumption: 1,
currentCharge: 5,
batteryCapacity: 5,
batteryMaxEnergy: 5,
batteryMaxInputPower: 1,
})
).toEqual([1, 0])
Expand All @@ -268,7 +190,7 @@ describe('Fitness - calculateChargeScore', () => {
price: 2,
averageConsumption: 1,
currentCharge: 0,
batteryCapacity: 5,
batteryMaxEnergy: 5,
batteryMaxInputPower: 1,
})
).toEqual([4, 1])
Expand All @@ -281,7 +203,7 @@ describe('Fitness - calculateChargeScore', () => {
price: 2,
averageConsumption: 1,
currentCharge: 4.5,
batteryCapacity: 5,
batteryMaxEnergy: 5,
batteryMaxInputPower: 1,
})
).toEqual([3, 0.5])
Expand Down Expand Up @@ -311,7 +233,30 @@ describe('Fitness - calculateNormalScore', () => {
})

describe('Fitness', () => {
test('should new fitness', () => {
test('should calculate fitness', () => {
const priceData = [
{ value: 1, start: '2022-12-01T00:00:00.000Z' },
{ value: 1, start: '2022-12-01T01:00:00.000Z' },
]
const totalDuration = 2 * 60
const batteryMaxEnergy = 1
const batteryMaxInputPower = 1
const averageConsumption = 1
const score = fitnessFunction({
priceData,
totalDuration,
batteryMaxEnergy,
batteryMaxInputPower,
batteryMaxEnergy,
averageConsumption,
})([
{ start: 30, duration: 60, activity: 1 },
{ start: 90, duration: 30, activity: -1 },
])
expect(score).toEqual(-2.5)
})

test('should calculate fitness with soc', () => {
const priceData = [
{ value: 1, start: '2022-12-01T00:00:00.000Z' },
{ value: 1, start: '2022-12-01T01:00:00.000Z' },
Expand All @@ -320,16 +265,19 @@ describe('Fitness', () => {
const batteryMaxEnergy = 1
const batteryMaxInputPower = 1
const averageConsumption = 1
const soc = 100
const score = fitnessFunction({
priceData,
totalDuration,
batteryMaxEnergy,
batteryMaxInputPower,
batteryMaxEnergy,
averageConsumption,
soc,
})([
{ start: 30, duration: 60, activity: 1 },
{ start: 90, duration: 30, activity: -1 },
])
console.log(score)
expect(score).toEqual(-1.5)
})
})
32 changes: 24 additions & 8 deletions test/strategy-battery-charging-functions.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,25 @@ describe('Crossover', () => {

describe('Calculate', () => {
test('calculate', () => {
let now = Date.now()
now = now - (now % (60 * 60 * 1000))
const priceData = [
{ value: 1, start: '2022-12-01T00:00:00.000Z' },
{ value: 2, start: '2022-12-01T01:00:00.000Z' },
{ value: 5, start: '2022-12-01T02:00:00.000Z' },
{ value: 1, start: new Date(now).toString() },
{ value: 500, start: new Date(now + 60 * 60 * 1000).toString() },
{ value: 500, start: new Date(now + 60 * 60 * 1000 * 2).toString() },
]
const populationSize = 100
const numberOfPricePeriods = 8
const numberOfPricePeriods = 2
const generations = 500
const mutationRate = 0.03

const batteryMaxEnergy = 5 // kWh
const batteryMaxOutputPower = 2.5 // kW
const batteryMaxInputPower = 2.5 // kW
const batteryMaxEnergy = 3 // kWh
const batteryMaxOutputPower = 3 // kW
const batteryMaxInputPower = 3 // kW
const averageConsumption = 1.5 // kW

const soc = 0

const config = {
priceData,
populationSize,
Expand All @@ -65,7 +69,19 @@ describe('Calculate', () => {
batteryMaxOutputPower,
batteryMaxInputPower,
averageConsumption,
soc,
}
console.log(calculateBatteryChargingStrategy(config))
const schedule = calculateBatteryChargingStrategy(config)
console.log(schedule)

expect(schedule.length).toBeGreaterThan(0)
expect(schedule[1]).toMatchObject({
activity: 1,
name: 'charging',
})
expect(schedule[3]).toMatchObject({
activity: -1,
name: 'discharging',
})
})
})

0 comments on commit b4057f8

Please sign in to comment.