Skip to content

Commit

Permalink
Refactor http/client to return response body instead of full response
Browse files Browse the repository at this point in the history
This means we don't have to use clone() to access the body, which closes #85
  • Loading branch information
Jalle19 committed Dec 8, 2024
1 parent 4463405 commit a1d2213
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 27 deletions.
13 changes: 9 additions & 4 deletions src/http/client.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { createLogger } from '../logger'

const logger = createLogger('http')
type BodyPromise = Promise<string>

const logger = createLogger('http')
let requestTimeout = 0
let lastTimestamp = 0
const promiseCache = new Map<string, Promise<Response>>()
const promiseCache = new Map<string, BodyPromise>()

const createRequestParams = (): RequestInit => {
return {
Expand All @@ -20,7 +21,11 @@ export const setRequestTimeout = (timeoutMs: number) => {
logger.info(`Using ${timeoutMs} millisecond timeout for HTTP requests`)
}

export const getDedupedResponse = async (timestamp: number, url: string): Promise<Response> => {
const resolveBody = async (request: Request): BodyPromise => {
return (await fetch(request)).text()
}

export const getDedupedResponseBody = async (timestamp: number, url: string): BodyPromise => {
// Clear the cache whenever the timestamp changes
if (timestamp !== lastTimestamp) {
lastTimestamp = timestamp
Expand All @@ -35,7 +40,7 @@ export const getDedupedResponse = async (timestamp: number, url: string): Promis

const request = new Request(url, createRequestParams())
logger.debug(`GET ${url}`)
const promise = fetch(request)
const promise = resolveBody(request)
promiseCache.set(key, promise)

return promise
Expand Down
14 changes: 7 additions & 7 deletions src/sensor/iotawatt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
PowerSensorPollFunction,
} from '../sensor'
import { Circuit } from '../circuit'
import { getDedupedResponse } from '../http/client'
import { getDedupedResponseBody } from '../http/client'
import { Characteristics } from '../characteristics'
import { createLogger } from '../logger'

Expand Down Expand Up @@ -114,10 +114,10 @@ export const getSensorData: PowerSensorPollFunction = async (
const sensor = circuit.sensor as IotawattSensor

try {
const configurationResult = (await getDedupedResponse(timestamp, getConfigurationUrl(sensor))).clone()
const configuration = (await configurationResult.json()) as IotawattConfiguration
const statusResult = (await getDedupedResponse(timestamp, getStatusUrl(sensor))).clone()
const status = (await statusResult.json()) as IotawattStatus
const configurationResult = await getDedupedResponseBody(timestamp, getConfigurationUrl(sensor))
const configuration = JSON.parse(configurationResult) as unknown as IotawattConfiguration
const statusResult = await getDedupedResponseBody(timestamp, getStatusUrl(sensor))
const status = JSON.parse(statusResult) as unknown as IotawattStatus

return {
timestamp: timestamp,
Expand All @@ -142,8 +142,8 @@ export const getCharacteristicsSensorData: CharacteristicsSensorPollFunction = a
const sensor = characteristics.sensor as IotawattCharacteristicsSensor

try {
const queryResult = (await getDedupedResponse(timestamp, getQueryUrl(sensor))).clone()
const query = (await queryResult.json()) as IotawattCharacteristicsQuery
const queryResult = await getDedupedResponseBody(timestamp, getQueryUrl(sensor))
const query = JSON.parse(queryResult) as unknown as IotawattCharacteristicsQuery

return {
timestamp: timestamp,
Expand Down
26 changes: 13 additions & 13 deletions src/sensor/shelly.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
ShellyType,
} from '../sensor'
import { Circuit } from '../circuit'
import { getDedupedResponse } from '../http/client'
import { getDedupedResponseBody } from '../http/client'
import { Characteristics } from '../characteristics'
import { createLogger } from '../logger'

Expand Down Expand Up @@ -64,10 +64,10 @@ const getSensorDataUrl = (sensor: ShellySensor | ShellyCharacteristicsSensor): s
const parseGen1Response = async (
timestamp: number,
circuit: Circuit,
httpResponse: Response,
responseBody: string,
): Promise<PowerSensorData> => {
const sensor = circuit.sensor as ShellySensor
const data = (await httpResponse.json()) as Gen1StatusResult
const data = JSON.parse(responseBody) as unknown as Gen1StatusResult

return {
timestamp: timestamp,
Expand All @@ -79,9 +79,9 @@ const parseGen1Response = async (
const parseGen2PMResponse = async (
timestamp: number,
circuit: Circuit,
httpResponse: Response,
responseBody: string,
): Promise<PowerSensorData> => {
const data = (await httpResponse.json()) as Gen2SwitchGetStatusResult
const data = JSON.parse(responseBody) as unknown as Gen2SwitchGetStatusResult

return {
timestamp: timestamp,
Expand All @@ -93,10 +93,10 @@ const parseGen2PMResponse = async (
const parseGen2EMResponse = async (
timestamp: number,
circuit: Circuit,
httpResponse: Response,
responseBody: string,
): Promise<PowerSensorData> => {
const sensor = circuit.sensor as ShellySensor
const data = (await httpResponse.json()) as Gen2EMGetStatusResult
const data = JSON.parse(responseBody) as unknown as Gen2EMGetStatusResult

let power = 0
let apparentPower = 0
Expand Down Expand Up @@ -136,16 +136,16 @@ export const getSensorData: PowerSensorPollFunction = async (
const url = getSensorDataUrl(sensor)

try {
const httpResponse = (await getDedupedResponse(timestamp, url)).clone()
const responseBody = await getDedupedResponseBody(timestamp, url)

// Parse the response differently depending on what type of Shelly we're dealing with
switch (sensor.shelly.type as ShellyType) {
case ShellyType.Gen1:
return await parseGen1Response(timestamp, circuit, httpResponse)
return await parseGen1Response(timestamp, circuit, responseBody)
case ShellyType.Gen2PM:
return await parseGen2PMResponse(timestamp, circuit, httpResponse)
return await parseGen2PMResponse(timestamp, circuit, responseBody)
case ShellyType.Gen2EM:
return await parseGen2EMResponse(timestamp, circuit, httpResponse)
return await parseGen2EMResponse(timestamp, circuit, responseBody)
}
} catch (e) {
logger.error(e)
Expand All @@ -166,8 +166,8 @@ export const getCharacteristicsSensorData: CharacteristicsSensorPollFunction = a
}

try {
const httpResponse = (await getDedupedResponse(timestamp, url)).clone()
const data = (await httpResponse.json()) as Gen2EMGetStatusResult
const result = await getDedupedResponseBody(timestamp, url)
const data = JSON.parse(result) as unknown as Gen2EMGetStatusResult

let voltage = 0
let frequency = 0
Expand Down
6 changes: 3 additions & 3 deletions tests/sensor/shelly.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ const gen2pmResponse = fs.readFileSync('./tests/sensor/shelly-plus-1pm.Switch.Ge

// Mock getDedupedResponse calls to return real-world data
jest.mock('../../src/http/client', () => ({
getDedupedResponse: async (timestamp: number, url: string) => {
let contents: string | null = null
getDedupedResponseBody: async (timestamp: number, url: string): Promise<string> => {
let contents = ''

switch (url) {
case 'http://127.0.0.1/status':
Expand All @@ -25,7 +25,7 @@ jest.mock('../../src/http/client', () => ({
break
}

return Promise.resolve(new Response(contents))
return Promise.resolve(contents)
},
}))

Expand Down

0 comments on commit a1d2213

Please sign in to comment.