node-red-contrib-senec-cloud-v2 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,94 @@
1
+ <script type="text/javascript">
2
+ RED.nodes.registerType('senec-image', {
3
+ category: 'SENEC',
4
+ color: '#00A0E3',
5
+ defaults: {
6
+ name: { value: '' },
7
+ width: { value: 800, validate: RED.validators.number() },
8
+ height: { value: 480, validate: RED.validators.number() },
9
+ layout: { value: 'default' }
10
+ },
11
+ inputs: 1,
12
+ outputs: 1,
13
+ icon: 'font-awesome/fa-image',
14
+ label: function() {
15
+ return this.name || 'SENEC Image';
16
+ },
17
+ labelStyle: function() {
18
+ return this.name ? 'node_label_italic' : '';
19
+ }
20
+ });
21
+ </script>
22
+
23
+ <script type="text/html" data-template-name="senec-image">
24
+ <div class="form-row">
25
+ <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
26
+ <input type="text" id="node-input-name" placeholder="SENEC Image">
27
+ </div>
28
+ <div class="form-row">
29
+ <label for="node-input-width"><i class="fa fa-arrows-h"></i> Width</label>
30
+ <input type="number" id="node-input-width" placeholder="800" min="100">
31
+ </div>
32
+ <div class="form-row">
33
+ <label for="node-input-height"><i class="fa fa-arrows-v"></i> Height</label>
34
+ <input type="number" id="node-input-height" placeholder="480" min="100">
35
+ </div>
36
+ <div class="form-row">
37
+ <label for="node-input-layout"><i class="fa fa-th-large"></i> Layout</label>
38
+ <select id="node-input-layout">
39
+ <option value="default">Default</option>
40
+ <option value="compact">Compact</option>
41
+ <option value="trmnl">TRMNL Display</option>
42
+ </select>
43
+ </div>
44
+ </script>
45
+
46
+ <script type="text/html" data-help-name="senec-image">
47
+ <p>Generates a PNG image visualization of SENEC system data.</p>
48
+
49
+ <h3>Inputs</h3>
50
+ <dl class="message-properties">
51
+ <dt>payload <span class="property-type">object</span></dt>
52
+ <dd>SENEC data object (from senec-data node)</dd>
53
+ </dl>
54
+
55
+ <h3>Outputs</h3>
56
+ <dl class="message-properties">
57
+ <dt>payload <span class="property-type">buffer</span></dt>
58
+ <dd>PNG image as a Buffer</dd>
59
+
60
+ <dt>contentType <span class="property-type">string</span></dt>
61
+ <dd>Set to "image/png"</dd>
62
+
63
+ <dt>filename <span class="property-type">string</span></dt>
64
+ <dd>Suggested filename for the image</dd>
65
+ </dl>
66
+
67
+ <h3>Configuration</h3>
68
+ <dl class="message-properties">
69
+ <dt>Width</dt>
70
+ <dd>Image width in pixels (default: 800)</dd>
71
+
72
+ <dt>Height</dt>
73
+ <dd>Image height in pixels (default: 480)</dd>
74
+
75
+ <dt>Layout</dt>
76
+ <dd>Image layout template:
77
+ <ul>
78
+ <li><b>Default</b> - Standard layout with all data</li>
79
+ <li><b>Compact</b> - Minimal layout for small displays</li>
80
+ <li><b>TRMNL Display</b> - Optimized for TRMNL e-ink display (800x480)</li>
81
+ </ul>
82
+ </dd>
83
+ </dl>
84
+
85
+ <h3>Details</h3>
86
+ <p>This node generates a PNG image visualization of your SENEC system data.</p>
87
+ <p>Connect it after a senec-data node to visualize the data graphically.</p>
88
+ <p>The generated image can be saved to file, sent via HTTP, or displayed on e-ink displays like TRMNL.</p>
89
+
90
+ <h3>Example Flow</h3>
91
+ <pre>
92
+ [senec-data] → [senec-image] → [file out]
93
+ </pre>
94
+ </script>
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ module.exports = function (RED) {
4
+ function SenecImageNode(config) {
5
+ RED.nodes.createNode(this, config);
6
+ const node = this;
7
+ node.width = config.width || 800;
8
+ node.height = config.height || 480;
9
+ node.layout = config.layout || 'default';
10
+ node.on('input', async function (msg) {
11
+ try {
12
+ if (!msg.payload || typeof msg.payload !== 'object') {
13
+ node.error('Input payload must be a SENEC data object');
14
+ return;
15
+ }
16
+ node.status({ fill: 'blue', shape: 'dot', text: 'generating...' });
17
+ // TODO: Implement image generation using pureimage
18
+ // For now, send a placeholder response
19
+ const imageBuffer = Buffer.from('PNG image generation not yet implemented', 'utf-8');
20
+ msg.payload = imageBuffer;
21
+ msg.contentType = 'image/png';
22
+ msg.filename = `senec-${Date.now()}.png`;
23
+ node.send(msg);
24
+ node.status({ fill: 'green', shape: 'dot', text: 'success' });
25
+ }
26
+ catch (error) {
27
+ node.error('Failed to generate image: ' + error.message);
28
+ node.status({ fill: 'red', shape: 'ring', text: 'error' });
29
+ }
30
+ });
31
+ }
32
+ RED.nodes.registerType('senec-image', SenecImageNode);
33
+ };
34
+ //# sourceMappingURL=senec-image.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"senec-image.js","sourceRoot":"","sources":["../../src/nodes/senec-image.ts"],"names":[],"mappings":";;AAiBA,MAAM,CAAC,OAAO,GAAG,UAAS,GAAQ;IAChC,SAAS,cAAc,CAAuB,MAAyB;QACrE,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAEnC,MAAM,IAAI,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,GAAG,CAAC;QACjC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC;QACnC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,SAAS,CAAC;QAEzC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,WAAU,GAAQ;YACtC,IAAI,CAAC;gBACH,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;oBACpD,IAAI,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;oBACxD,OAAO;gBACT,CAAC;gBAED,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC,CAAC;gBAEnE,mDAAmD;gBACnD,uCAAuC;gBACvC,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,0CAA0C,EAAE,OAAO,CAAC,CAAC;gBAErF,GAAG,CAAC,OAAO,GAAG,WAAW,CAAC;gBAC1B,GAAG,CAAC,WAAW,GAAG,WAAW,CAAC;gBAC9B,GAAG,CAAC,QAAQ,GAAG,SAAS,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC;gBAEzC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACf,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;YAEhE,CAAC;YAAC,OAAO,KAAU,EAAE,CAAC;gBACpB,IAAI,CAAC,KAAK,CAAC,4BAA4B,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;gBACzD,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;YAC7D,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;AACxD,CAAC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "node-red-contrib-senec-cloud-v2",
3
+ "version": "0.2.0",
4
+ "description": "Node-RED nodes for SENEC Cloud API integration - supports new API, CCU RedMatic optimized",
5
+ "main": "dist/index.js",
6
+ "scripts": {
7
+ "build": "tsc && npm run copy-html",
8
+ "copy-html": "node -e \"const fs=require('fs');const path=require('path');const src='src/nodes';const dst='dist/nodes';fs.mkdirSync(dst,{recursive:true});fs.readdirSync(src).filter(f=>f.endsWith('.html')).forEach(f=>fs.copyFileSync(path.join(src,f),path.join(dst,f)));console.log('HTML files copied to dist/nodes');\"",
9
+ "watch": "tsc --watch",
10
+ "test": "jest",
11
+ "test:watch": "jest --watch",
12
+ "test:coverage": "jest --coverage",
13
+ "lint": "eslint src/**/*.ts",
14
+ "lint:fix": "eslint src/**/*.ts --fix",
15
+ "prepublishOnly": "npm run build && npm test"
16
+ },
17
+ "keywords": [
18
+ "node-red",
19
+ "senec",
20
+ "solar",
21
+ "battery",
22
+ "energy",
23
+ "home-automation",
24
+ "ccu",
25
+ "redmatic",
26
+ "photovoltaics",
27
+ "energy-storage"
28
+ ],
29
+ "node-red": {
30
+ "nodes": {
31
+ "senec-config": "dist/nodes/senec-config.js",
32
+ "senec-data": "dist/nodes/senec-data.js",
33
+ "senec-image": "dist/nodes/senec-image.js"
34
+ }
35
+ },
36
+ "author": "aunovis-fitting",
37
+ "license": "MIT",
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "https://github.com/aunovis-fitting/node-red-contrib-senec-cloud-v2.git"
41
+ },
42
+ "bugs": {
43
+ "url": "https://github.com/aunovis-fitting/node-red-contrib-senec-cloud-v2/issues"
44
+ },
45
+ "homepage": "https://github.com/aunovis-fitting/node-red-contrib-senec-cloud-v2#readme",
46
+ "engines": {
47
+ "node": ">=14.0.0"
48
+ },
49
+ "dependencies": {
50
+ "axios": "^1.6.0",
51
+ "pureimage": "^0.4.0"
52
+ },
53
+ "devDependencies": {
54
+ "@types/jest": "^29.5.0",
55
+ "@types/node": "^20.0.0",
56
+ "@types/node-red": "^0.20.7",
57
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
58
+ "@typescript-eslint/parser": "^6.0.0",
59
+ "eslint": "^8.50.0",
60
+ "jest": "^29.7.0",
61
+ "nock": "^13.3.0",
62
+ "node-red": "^5.0.1",
63
+ "node-red-node-test-helper": "^0.3.0",
64
+ "ts-jest": "^29.1.0",
65
+ "typescript": "^5.2.0"
66
+ },
67
+ "peerDependencies": {
68
+ "node-red": "^5.0.1"
69
+ },
70
+ "optionalDependencies": {
71
+ "canvas": "^2.11.0"
72
+ }
73
+ }