Skip to content

Commit

Permalink
Merge pull request #88 from Jalle19/plus-2pm-pf
Browse files Browse the repository at this point in the history
Add power factor and apparent power for Gen2 PM devices that support it
  • Loading branch information
Jalle19 authored Dec 20, 2024
2 parents 83aebca + 5363c58 commit eda3dcb
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 3 deletions.
6 changes: 5 additions & 1 deletion src/eachwatt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,15 @@ const mainPollerFunc = async (config: Config) => {

// Post-process power sensor data
powerSensorData = powerSensorData.map((data) => {
// Round all numbers to one decimal point
if (data.power !== undefined) {
// Round all numbers to one decimal point
data.power = Number(data.power.toFixed(1))
}

if (data.apparentPower !== undefined) {
data.apparentPower = Number(data.apparentPower.toFixed(1))
}

return data
})

Expand Down
15 changes: 15 additions & 0 deletions src/sensor/shelly.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ type Gen1StatusResult = {

type Gen2SwitchGetStatusResult = {
apower: number
voltage: number
// Not all Gen2 PM devices expose current and power factor
current?: number
pf?: number
}

type Gen2EMGetStatusResult = {
Expand Down Expand Up @@ -83,10 +87,21 @@ const parseGen2PMResponse = async (
): Promise<PowerSensorData> => {
const data = JSON.parse(responseBody) as unknown as Gen2SwitchGetStatusResult

// Not all Gen2 PM devices expose current and power factor
let apparentPower = undefined
let powerFactor = undefined

if (data.pf !== undefined && data.current !== undefined) {
powerFactor = data.pf
apparentPower = data.voltage * data.current
}

return {
timestamp: timestamp,
circuit: circuit,
power: data.apower,
apparentPower,
powerFactor,
}
}

Expand Down
32 changes: 32 additions & 0 deletions tests/sensor/shelly-plus-2pm-pf0.Switch.GetStatus.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"id": 0,
"source": "init",
"output": false,
"apower": 0.0,
"voltage": 237.3,
"freq": 50.0,
"current": 0.000,
"pf": 0.00,
"aenergy": {
"total": 3331.000,
"by_minute": [
0.000,
0.000,
0.000
],
"minute_ts": 1734695160
},
"ret_aenergy": {
"total": 0.000,
"by_minute": [
0.000,
0.000,
0.000
],
"minute_ts": 1734695160
},
"temperature": {
"tC": 34.7,
"tF": 94.5
}
}
32 changes: 32 additions & 0 deletions tests/sensor/shelly-plus-2pm.Switch.GetStatus.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"id": 1,
"source": "WS_in",
"output": true,
"apower": 32.3,
"voltage": 236.4,
"freq": 50.0,
"current": 0.159,
"pf": 0.85,
"aenergy": {
"total": 4.967,
"by_minute": [
572.942,
574.572,
576.372
],
"minute_ts": 1734694200
},
"ret_aenergy": {
"total": 0.000,
"by_minute": [
0.000,
0.000,
0.000
],
"minute_ts": 1734694200
},
"temperature": {
"tC": 40.7,
"tF": 105.3
}
}
44 changes: 44 additions & 0 deletions tests/sensor/shelly.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import fs from 'fs'
const gen1Response = fs.readFileSync('./tests/sensor/shelly-25.status.json')
const gen2emResponse = fs.readFileSync('./tests/sensor/shelly-pro-3m.EM.GetStatus.json')
const gen2pmResponse = fs.readFileSync('./tests/sensor/shelly-plus-1pm.Switch.GetStatus.json')
const gen2pmPfResponse = fs.readFileSync('./tests/sensor/shelly-plus-2pm.Switch.GetStatus.json')
const gen2pmZeroPfResponse = fs.readFileSync('./tests/sensor/shelly-plus-2pm-pf0.Switch.GetStatus.json')

// Mock getDedupedResponse calls to return real-world data
jest.mock('../../src/http/client', () => ({
Expand All @@ -23,6 +25,12 @@ jest.mock('../../src/http/client', () => ({
case 'http://127.0.0.1/rpc/Switch.GetStatus?id=0':
contents = String(gen2pmResponse)
break
case 'http://127.0.0.2/rpc/Switch.GetStatus?id=0':
contents = String(gen2pmZeroPfResponse)
break
case 'http://127.0.0.2/rpc/Switch.GetStatus?id=1':
contents = String(gen2pmPfResponse)
break
}

return Promise.resolve(contents)
Expand Down Expand Up @@ -107,3 +115,39 @@ test('parse gen2-pm response', async () => {
power: 105.7,
})
})

test('parse gen2-pm response with non-zero pf', async () => {
const now = Date.now()
const circuit = createShellyCircuit({
type: ShellyType.Gen2PM,
address: '127.0.0.2',
meter: 1,
})

const sensorData = await getSensorData(now, circuit)
expect(sensorData).toEqual({
timestamp: now,
circuit: circuit,
power: 32.3,
apparentPower: 37.5876,
powerFactor: 0.85,
})
})

test('parse gen2-pm response with zero pf', async () => {
const now = Date.now()
const circuit = createShellyCircuit({
type: ShellyType.Gen2PM,
address: '127.0.0.2',
meter: 0,
})

const sensorData = await getSensorData(now, circuit)
expect(sensorData).toEqual({
timestamp: now,
circuit: circuit,
power: 0,
apparentPower: 0,
powerFactor: 0,
})
})
4 changes: 2 additions & 2 deletions webif/src/routes/Circuits.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@
{/if}
</td>
<td class="cell-right-align">
{#if data.apparentPower }
{#if data.apparentPower !== undefined}
{data.apparentPower}VA
{/if}
</td>
<td class="cell-right-align">
{#if data.powerFactor }
{#if data.powerFactor !== undefined}
{formatPf(data.powerFactor)}
{/if}
</td>
Expand Down

0 comments on commit eda3dcb

Please sign in to comment.