Skip to content

Commit

Permalink
Merge pull request #57 from Jalle19/modbus-tcp
Browse files Browse the repository at this point in the history
Add basic Modbus support
  • Loading branch information
Jalle19 authored May 10, 2024
2 parents 7c7cc82 + db4b78f commit 8032aa7
Show file tree
Hide file tree
Showing 12 changed files with 375 additions and 8 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ to any number of different targets, such as databases or MQTT.
* Supports _**multiple different power sensors**_
* [IotaWatt](http://iotawatt.com/)
* [Shelly](https://www.shelly.com/) (both Gen 1 and Gen 2)
* Generic Modbus sensors (limited support)
* Supports _**virtual power sensors**_
* A virtual power sensor gets its values from other configured sensors, enabling the user to calculate the total
power usage of three-phase devices or three-phase mains power
Expand Down
13 changes: 13 additions & 0 deletions examples/config.sample.full.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ circuits:
- Vägg vardagsrum
- Vägg kök
- Vägg arbetsrum
clamp: positive # Don't allow negative values
# A IotaWatt main circuit, phase A/L1
- name: Main L1
type: main
Expand Down Expand Up @@ -133,6 +134,18 @@ circuits:
type: gen2-em
meter: 0
phase: a
# A circuit with a Modbus sensor
- name: Inverter/chargers
type: circuit
sensor:
type: modbus
modbus:
address: 10.112.4.250
port: 502
unit: 100
register: 866
type: int16
clamp: positive

#
# Characteristics. Characteristics mean voltage and frequency, and potentially other non-power related readings.
Expand Down
241 changes: 241 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"dependencies": {
"@influxdata/influxdb-client": "^1.33.2",
"axios": "^1.6.0",
"modbus-serial": "^8.0.16",
"mqtt": "^5.1.2",
"slugify": "^1.6.6",
"winston": "^3.11.0",
Expand Down
4 changes: 4 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
getCharacteristicsSensorData as getIotawattCharacteristicsSensorData,
getSensorData as getIotawattSensorData,
} from './sensor/iotawatt'
import { getSensorData as getModbusSensorData } from './sensor/modbus'
import { getSensorData as getVirtualSensorData } from './sensor/virtual'
import { getSensorData as getUnmeteredSensorData } from './sensor/unmetered'
import {
Expand Down Expand Up @@ -153,6 +154,9 @@ export const resolveAndValidateConfig = (config: Config): Config => {
case SensorType.Iotawatt:
circuit.sensor.pollFunc = getIotawattSensorData
break
case SensorType.Modbus:
circuit.sensor.pollFunc = getModbusSensorData
break
case SensorType.Virtual:
circuit.sensor.pollFunc = getVirtualSensorData
break
Expand Down
17 changes: 13 additions & 4 deletions src/eachwatt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import { WebSocketPublisherImpl } from './publisher/websocket'
import { PublisherType } from './publisher'
import { pollCharacteristicsSensors } from './characteristics'
import { createLogger } from './logger'
import { setRequestTimeout } from './http/client'
import { setRequestTimeout as setHttpRequestTimeout } from './http/client'
import { setRequestTimeout as setModbusRequestTimeout } from './modbus/client'

// Set up a signal handler, so we can exit on Ctrl + C when run from Docker
process.on('SIGINT', () => {
Expand Down Expand Up @@ -52,10 +53,16 @@ const mainPollerFunc = async (config: Config) => {
// Poll characteristics sensors
const characteristicsSensorData = await pollCharacteristicsSensors(now, config.characteristics)

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

// Optionally clamp values
if (data.circuit.sensor.clamp === 'positive') {
data.power = Math.max(0, data.power)
}
}
}

Expand Down Expand Up @@ -101,10 +108,12 @@ const mainPollerFunc = async (config: Config) => {
publisherImpl: webSocketServer,
})

// Adjust the HTTP timeout to be half that of the polling interval
// Adjust request timeouts to be half that of the polling interval
const pollingInterval = config.settings.pollingInterval
logger.info(`Polling sensors with interval ${pollingInterval} milliseconds`)
setRequestTimeout((pollingInterval as number) / 2)
const timeoutMs = (pollingInterval as number) / 2
setHttpRequestTimeout(timeoutMs)
setModbusRequestTimeout(timeoutMs)

// Start polling sensors
await mainPollerFunc(config)
Expand Down
Loading

0 comments on commit 8032aa7

Please sign in to comment.