Skip to content

Commit

Permalink
Add support for using Shelly EM devices as characteristics sensors
Browse files Browse the repository at this point in the history
  • Loading branch information
Jalle19 committed Oct 13, 2023
1 parent bbf38e5 commit 4c43032
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 3 deletions.
8 changes: 7 additions & 1 deletion src/config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import YAML from 'yaml'
import { getSensorData as getShellySensorData } from './shelly'
import {
getCharacteristicsSensorData as getShellyCharacteristicsSensorData,
getSensorData as getShellySensorData,
} from './shelly'
import {
getCharacteristicsSensorData as getIotawattCharacteristicsSensorData,
getSensorData as getIotawattSensorData,
Expand Down Expand Up @@ -106,6 +109,9 @@ export const parseConfig = (configFileContents: string): Config => {
case CharacteristicsSensorType.Iotawatt:
c.sensor.pollFunc = getIotawattCharacteristicsSensorData
break
case CharacteristicsSensorType.Shelly:
c.sensor.pollFunc = getShellyCharacteristicsSensorData
break
}
}

Expand Down
6 changes: 6 additions & 0 deletions src/sensor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export enum ShellyType {

export enum CharacteristicsSensorType {
Iotawatt = 'iotawatt',
Shelly = 'shelly',
}

export type PowerSensorPollFunction = (
Expand Down Expand Up @@ -58,6 +59,11 @@ export interface ShellySensor extends PowerSensor {
shelly: ShellySensorSettings
}

export interface ShellyCharacteristicsSensor extends CharacteristicsSensor {
type: CharacteristicsSensorType.Shelly
shelly: ShellySensorSettings
}

interface IotawattSensorSettings {
address: string
name: string
Expand Down
66 changes: 64 additions & 2 deletions src/shelly.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
import { emptySensorData, PowerSensorData, PowerSensorPollFunction, ShellySensor, ShellyType } from './sensor'
import {
CharacteristicsSensorData,
CharacteristicsSensorPollFunction,
emptyCharacteristicsSensorData,
emptySensorData,
PowerSensorData,
PowerSensorPollFunction,
ShellyCharacteristicsSensor,
ShellySensor,
ShellyType,
} from './sensor'
import { Circuit } from './circuit'
import { getDedupedResponse } from './http/client'
import { AxiosResponse } from 'axios'
import { Characteristics } from './characteristics'

type Gen1MeterResult = {
power: number
Expand All @@ -17,11 +28,17 @@ type Gen2SwitchGetStatusResult = {

type Gen2EMGetStatusResult = {
a_act_power: number
a_voltage: number
a_freq: number
b_act_power: number
b_voltage: number
b_freq: number
c_act_power: number
c_voltage: number
c_freq: number
}

const getSensorDataUrl = (sensor: ShellySensor): string => {
const getSensorDataUrl = (sensor: ShellySensor | ShellyCharacteristicsSensor): string => {
const address = sensor.shelly.address
const meter = sensor.shelly.meter

Expand Down Expand Up @@ -105,3 +122,48 @@ export const getSensorData: PowerSensorPollFunction = async (
return emptySensorData(timestamp, circuit)
}
}

export const getCharacteristicsSensorData: CharacteristicsSensorPollFunction = async (
timestamp: number,
characteristics: Characteristics,
): Promise<CharacteristicsSensorData> => {
const sensor = characteristics.sensor as ShellyCharacteristicsSensor
const url = getSensorDataUrl(sensor)

// Only support gen2-em sensors
if (sensor.shelly.type !== ShellyType.Gen2EM) {
throw new Error(`Shelly sensor type ${sensor.shelly.type} not supported as characteristics sensor`)
}

try {
const httpResponse = await getDedupedResponse(timestamp, url)
const data = httpResponse.data as Gen2EMGetStatusResult

let voltage = 0
let frequency = 0
switch (sensor.shelly.phase) {
case 'a':
voltage = data.a_voltage
frequency = data.a_freq
break
case 'b':
voltage = data.b_voltage
frequency = data.b_freq
break
case 'c':
voltage = data.c_voltage
frequency = data.c_freq
break
}

return {
timestamp: timestamp,
characteristics: characteristics,
voltage: voltage,
frequency: frequency,
}
} catch (e) {
console.error((e as Error).message)
return emptyCharacteristicsSensorData(timestamp, characteristics)
}
}

0 comments on commit 4c43032

Please sign in to comment.