Skip to content

Commit

Permalink
Merge pull request #34 from svrooij/feature/new-socket-comms
Browse files Browse the repository at this point in the history
Feature/new socket comms
  • Loading branch information
svrooij committed Aug 30, 2021
2 parents e0fa1ee + 3000d12 commit 808f227
Show file tree
Hide file tree
Showing 24 changed files with 333 additions and 107 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-and-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 12
node-version: 16
- name: Install depencencies
run: npm ci
- name: Run tests
Expand Down
3 changes: 2 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"request": "launch",
"name": "Launch Program",
"program": "${workspaceFolder}/bin/run",
"preLaunchTask": "tsc: build - tsconfig.json",
// "preLaunchTask": "tsc: build - tsconfig.json",
"preLaunchTask": "Build",
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
"envFile": "${workspaceFolder}/.env"
},
Expand Down
15 changes: 15 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "Build",
"type": "shell",
"command": "npm run prepack",
"windows": {
"command": "npm run prepack-win"
}
}
]
}
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:14-alpine as node-original
FROM node:16-alpine as node-original
FROM node-original as install
WORKDIR /usr/src/app
COPY package*.json ./
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

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

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@
"scripts": {
"compile": "tsc",
"copy-www": "cp -r ./src/output/wwwroot ./dist/output/wwwroot",
"copy-www-win": "xcopy .\\src\\output\\wwwroot .\\dist\\output\\wwwroot /E/H/C/I/d/Y",
"coverage": "jest --coverage",
"jest": "jest",
"lint": "eslint ./src --ext .js,.jsx,.ts,.tsx",
"lint-fix": "eslint ./src --ext .js,.jsx,.ts,.tsx --fix",
"test": "npm run lint && jest",
"prepack": "npm run compile && npm run copy-www"
"prepack": "npm run compile && npm run copy-www",
"prepack-win": "npm run compile && npm run copy-www-win"
},
"repository": {
"type": "git",
Expand Down
19 changes: 19 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export interface MqttConfig {
distinctFields: Array<string>;
prefix: string;
url: string;
last_reset?: string;
last_reset_solar?: string;
}

const defaultMqttConfig: Partial<MqttConfig> = {
Expand All @@ -35,13 +37,15 @@ const defaultMqttConfig: Partial<MqttConfig> = {
export interface SunspecConfig {
host: string;
port: number;
interval?: number;
}

export interface OutputConfig {
debug: boolean;
influx?: InfluxOutputOptions;
jsonSocket?: number;
mqtt?: MqttConfig;
mqttSocket?: number;
post?: HttpPostConfig;
rawSocket?: number;
webserver?: number;
Expand Down Expand Up @@ -120,20 +124,28 @@ export class ConfigLoader {
.describe('mqtt-discovery', 'Emit auto-discovery message')
.boolean('mqtt-discovery')
.describe('mqtt-discovery-prefix', 'Autodiscovery prefix')
.describe('mqtt-last-reset', 'If set, this value is added to mqtt as \'last_reset\'')
.string('mqtt-last-reset')
.describe('mqtt-last-reset-solar', 'If set, this value is added to mqtt as \'last_reset\'')
.string('mqtt-last-reset-solar')
.describe('influx-url', 'Influxdb server url')
.describe('influx-token', 'Influxdb server token')
.describe('influx-bucket', 'Influx bucket')
.describe('influx-org', 'Influx organization')
.describe('tcp-server', 'Expose JSON TCP socket on this port')
.describe('tcp-server-mqtt', 'Expose JSON TCP socket on this port')
.describe('raw-tcp-server', 'Expose RAW TCP socket on this port')
.conflicts('port', 'socket')
.describe('debug', 'Enable debug output')
.boolean('debug')
.describe('sunspec-modbus', 'IP of solar inverter with modbus TCP enabled')
.describe('sunspec-modbus-port', 'modbus TCP port')
.describe('sunspec-interval', 'Interval for solar reading')
.number('sunspec-modbus-port')
.number('sunspec-modbus-interval')
.number('web-server')
.number('tcp-server')
.number('tcp-server-mqtt')
.number('raw-tcp-server')
.number('post-interval')
.describe('enc-aad', 'Additional authentication data, if your meter encrypts data (eg. Luxemburg)')
Expand Down Expand Up @@ -167,6 +179,10 @@ export class ConfigLoader {
config.outputs.jsonSocket = args['tcp-server'];
}

if (args['tcp-server-mqtt']) {
config.outputs.mqttSocket = args['tcp-server-mqtt'];
}

if (typeof args['mqtt-url'] === 'string') {
config.outputs.mqtt = {
discovery: args['mqtt-discovery'] === true,
Expand All @@ -175,6 +191,8 @@ export class ConfigLoader {
distinctFields: args['mqtt-distinct-fields']?.split(',') ?? defaultMqttConfig.distinctFields ?? [],
prefix: args['mqtt-topic'] ?? 'smartmeter',
url: args['mqtt-url'],
last_reset: args['mqtt-last-reset'],
last_reset_solar: args['mqtt-last-reset-solar'],
};
}

Expand Down Expand Up @@ -208,6 +226,7 @@ export class ConfigLoader {
config.solar = {
host: args['sunspec-modbus'],
port: args['sunspec-modbus-port'],
interval: args['sunspec-interval'],
} as SunspecConfig;
}

Expand Down
36 changes: 0 additions & 36 deletions src/modbus-solar-input.ts

This file was deleted.

7 changes: 7 additions & 0 deletions src/output/debug-output.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import P1Reader from '../p1-reader';
import BaseSolarReader from '../solar/base-solar-input';
import { Output } from './output';

/**
Expand All @@ -24,6 +25,12 @@ export default class DebugOutput implements Output {
});
}

addSolar(solarReader: BaseSolarReader): void {
solarReader.on('solar', (data) => {
console.log(' - solar %s', JSON.stringify(data));
});
}

close(): Promise<void> {
// You should stop the started servers here, when building your own output.
return Promise.resolve();
Expand Down
4 changes: 4 additions & 0 deletions src/output/http-output.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ export default class HttpOutput extends IntervalOutput {
}));
}

// addSolar(solarReader: BaseSolarReader): void {

// }

private sendEvent(data: DsmrMessage): Promise<Response> {
const flatData = this.config.fields
? this.filterData(HttpOutput.flatten(data))
Expand Down
13 changes: 13 additions & 0 deletions src/output/influx-output.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { InfluxDB, Point, WriteApi } from '@influxdata/influxdb-client';
import P1Reader from '../p1-reader';
import BaseSolarReader from '../solar/base-solar-input';
import { Output } from './output';

export interface InfluxOutputOptions {
Expand Down Expand Up @@ -51,6 +52,18 @@ export class InfluxOutput implements Output {
});
}

addSolar(solarReader: BaseSolarReader): void {
solarReader.on('solar', (data) => {
const solarPoint = new Point('solar');
if (data.serial) solarPoint.tag('invertor', data.serial);
if (data.acPower && data.lifetimeProduction) {
solarPoint.intField('lifetime-production', data.lifetimeProduction);
solarPoint.floatField('ac-power', data.acPower);
this.writeApi.writePoint(solarPoint);
}
});
}

async close(): Promise<void> {
await this.writeApi.flush();
await this.writeApi.close();
Expand Down
11 changes: 9 additions & 2 deletions src/output/interval-output.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import EventEmitter from 'events';
import { EventEmitter } from 'events';
import TypedEmitter from 'typed-emitter';
import { SunspecResult } from '@svrooij/sunspec/lib/sunspec-result';
import P1Reader, { Usage } from '../p1-reader';
import { Output } from './output';
import DsmrMessage from '../dsmr-message';
import BaseSolarReader from '../solar/base-solar-input';


interface IntervalOutputEvents {
dsmr: (result: DsmrMessage) => void;
gasUsage: (usage: Usage) => void;
usage: (usage: Usage) => void;
solar: (solar: Partial<SunspecResult>) => void;
}

export default abstract class IntervalOutput extends (EventEmitter as unknown as new () => TypedEmitter<IntervalOutputEvents>) implements Output {
export default abstract class IntervalOutput extends (EventEmitter as new () => TypedEmitter<IntervalOutputEvents>) implements Output {
private timer?: NodeJS.Timeout;

private publishNextEvent: boolean;
Expand Down Expand Up @@ -46,6 +49,10 @@ export default abstract class IntervalOutput extends (EventEmitter as unknown as
}, (this.interval ?? 60) * 1000);
}

addSolar(solarReader: BaseSolarReader): void {
solarReader.on('solar', (data) => { this.emit('solar', data); });
}

close(): Promise<void> {
if (this.timer) {
clearInterval(this.timer);
Expand Down

0 comments on commit 808f227

Please sign in to comment.