Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vorschlag: node-red-contrib-ccu-jack #75

Closed
guenter-ms opened this issue Jan 5, 2022 · 17 comments
Closed

Vorschlag: node-red-contrib-ccu-jack #75

guenter-ms opened this issue Jan 5, 2022 · 17 comments

Comments

@guenter-ms
Copy link

guenter-ms commented Jan 5, 2022

Hallo,
der ccu-jack ist richtig gut!! Deshalb möchte ich anregen, das XMLAPI basierende nodered addon "node-red-contrib-ccu" (https://flows.nodered.org/node/node-red-contrib-ccu) 1:1 auf der Basis ccu-jack verfügbar zu machen. Ich selbst habe dafür leider das know how nicht, biete aber an, zu testen. M.W. kann/darf man das vorgenannte addon als Basis kopieren? Das addon ist eine Komponente von redmatic.de, wo es seit 10 Monaten still geworden ist und wohl keine Betreuung mehr erfolgt.
Eine solche 1:1 Umstellung wäre einechter Knaller und würde vermutlich von sehr vielen Anwendern extrem begrüßt werden.
Comments?
Grüße von Guenni

@ptweety
Copy link

ptweety commented Jan 10, 2022

Hallo @guenter-ms,

verstehe ich das richtig, dass du ein drop-in Replacement vorschlägst?

Dazu habe ich folgende Anmerkungen/Gedanken:

  • CCU-Jack ist kein NodeRed Projekt, daher könnte das hier out-of-scope sein und ggfs. ein eigenes Projekt darstellen
  • node-red-contrib-ccu besteht aus insgesamt 16 nodes. Welche davon würden denn überhaupt Sinn machen?
  • CCU-Jack bietet schon jetzt Information zu den Geräten über die VEAP-Schnittstelle, die man in NodeRed über http-request abfragen kann
  • CCU-Jack bietet schon jetzt Ereignisse der Geräte über die MQTT-Schnittstelle, welche über mqtt-in empfangen werden
  • CCU-Jack bietet schon jetzt Steuerung der Geräte über die MQTT-Schnittstelle, welche über mqtt-out durchgeführt werden
  • in NodeRed kann man sich eine selber zusammen basteln. Hast du das schon mal probiert und kannst ggfs. einen Prototypen zeigen?
  • Ein kleines Design für einen solche Entwicklung wäre sicher auch hilfreich.

@guenter-ms
Copy link
Author

Hallo Matthias,

hier meine Überlegungen zu Deinen Punkten:

  • ja, könnte out-of-scope sein, muss aber nicht sein, ist ja alles nur Software.... :-)
  • Die 16 nodes von node-red-contrib-ccu kommunizieren und nutzen alle den zentralen node "CCU-connection", siehe screenshot. Wenn man diesen erweitern würde mit einer checkbox "connect to CCU-Jack" (und dann die vielen unnötigen XMLAPI Konfigurationspunke ausblendet), dann wäre das die Lösung und der Hammer! Ich nehme an, es gibt ein zentrales Modul, das die Kommunikation und den Transport der Datenpunkte übernimmt, und genau da wäre die Weiche einzusetzen und alles andere könnte bleiben. Richtig?
  • Korrekt, http Abfragen gingen über die VEAP Schnittstelle und auch mqtt geht (habe ich schon ausprobiert), aber dann geht die gesamte (hohe!) Funktionalität der 16 nodes von node-red-contrib-ccu verloren, und genau das wäre sehr schade und extrem aufwändig nachzubilden für die Benutzer.

Bin leider kein Programmierer, aber die zentrale "CCU-Jack-Weiche" klingt für mich logisch...
Viele Grüße
Günni

Bildschirmfoto 2022-01-10 um 17 41 51

@mdzio
Copy link
Owner

mdzio commented Feb 20, 2022

@mdzio
Copy link
Owner

mdzio commented Feb 20, 2022

Das weitere Vorgehen ist nun von den Maintainern von Node-Red-Contrib-CCU abhängig. Daher schließe ich das Thema hier. Vielen Dank an gnark/realgnark für den Pull-Request.

@mdzio mdzio closed this as completed Feb 20, 2022
@guenter-ms
Copy link
Author

Hallo mdzio

Maintainer von Node-Red-Contrib-CCU gibt es leider nicht mehr. Das war ja der Hauptgrund für den Vorschlag....

gruß guenni

@ptweety
Copy link

ptweety commented Feb 21, 2022

Hi @guenter-ms:

ich habe mal mit einem function node rumgespielt, welcher einen Cache für Abfragen an den CCU-Jack implementiert und das Ergebnis der Abfragen etwas aufbereitet (analog zu ccu-connection) herausgibt.

Eingesetzt wird das Ganze als einzelner Knoten hinter allen anderen MQTT-Knoten, welche Topics des CCU-Jack abonniert haben. Wenn du magst, dann kannst du gerne dazu ein Feedback geben. Es fehlen insbesondere eine Dokumentation und die Implementierung von Programmen und Systemvariablen.

Die Konfiguration erfolgt im Knoten selbst. Und dort ist die Lasche Start anzupassen:

Bildschirmfoto 2022-02-21 um 15 35 39

[
    {
        "id": "e4865d213c50805e",
        "type": "function",
        "z": "62591c5e2ae416a5",
        "name": "Jack Cache",
        "func": "const ts = Date.now();\n\nconst sortObject = context.get('util').sortObject;\nconst jackAPI = context.get('util').jackAPI;\nconst getLinks = context.get('util').getLinks;\n\n/**\n * cache: add root, domains & vendor/config information\n */\nconst root = await jackAPI('/', 1000 * 60 * 60 * 24); // 1d\n\nif (root) {\n    await Promise.all(getLinks(root, 'domain').map(async (link) => {\n        const ret = await jackAPI(link.url, 1000 * 60 * 60 * 4); // 4h\n    }));\n}\n\nconst config = await jackAPI('/~vendor/config/~pv', 1000 * 60 * 60 * 4); // 4h\n\n/**\n * msg: split, analyze and add additional data (either from cache or api call)\n */\n\nlet message = {}\nlet ids = msg.topic.split('/');\n\nswitch (ids[0]) {\n    case 'device': {\n        // mqtt topic example: device/status/${device}/${channel}/${datapoint}\n        \n        const device = await jackAPI(`/device/${ids[2]}`, 1000 * 60 * 60 * 2); // 2h\n        const channel = await jackAPI(`/device/${ids[2]}/${ids[3]}`, 1000 * 60 * 1); // 1h\n        const datapoint = await jackAPI(`/device/${ids[2]}/${ids[3]}/${ids[4]}`, 1000 * 60 * 10); // 10min\n\n        return {\n                topic: msg.topic,\n                ['~pv']: msg.payload,\n                payload: msg.payload.v,\n                qos: msg.qos,\n                retain: msg.retain,\n                ['~config']: config,\n                ccu: config.v.CCU.Address,\n                iface: device.interfaceType,\n                ['~device']: device,\n                device: device.address,\n                deviceName: device.title,\n                deviceType: device.type,\n                ['~channel']: channel,\n                channel: channel.address,\n                channelName: channel.title,\n                channelType: channel.type,\n                channelIndex: channel.index,\n                ['~datapoint']: datapoint,\n                datapoint: datapoint.id,\n                datapointName: device.interfaceType + '.' + channel.address + '.' + datapoint.id,\n                datapointType: datapoint.type,\n                datapointMin: datapoint.minimum,\n                datapointMax: datapoint.maximum,\n                datapointDefault: datapoint.default,\n                datapointControl: datapoint.control,\n                rooms: channel['~links'].filter( it => it.rel == 'room').map(x => x.title),\n                room: channel['~links'].filter( it => it.rel == 'room').map(x => x.title)[0],\n                functions: channel['~links'].filter( it => it.rel == 'function').map(x => x.title),\n                function: channel['~links'].filter( it => it.rel == 'function').map(x => x.title)[0],\n                ts: ts,\n                uncertain: (msg.payload.s !== 0),\n                value: msg.payload.v,\n            };\n        //break;\n    }\n    default: {\n        return msg;\n    }\n}\n\n/**\n * msg: output\n */\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "// Der Code hier wird ausgeführt,\n// wenn der Node gestartet wird\n\n// Please enter your <ip>, <user> & <password> below\n\n// IMPORTANT: if you use https on port 2122\n// please change <proto> & <port> as well\n// Also, you must include propper <key> & <cert>\n// This might be self-signed ones from ccu-jack\n\nnode.status({\n                fill: 'blue',\n                shape: 'dot',\n                text: 'configuration required',\n            });\n\nconst config = {\n    cache: 'jack-cache',\n    proto: 'http',\n    ip: '192.168.1.12',\n    port: 2121,\n    user: 'youruser',\n    password: 'yoursecret',\n    key: `-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----`,\n    cert: `-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\n..\n-----END CERTIFICATE-----`,\n}\n\n// no changes below this comment required\n\n//context.set('jack', config);\n\nlet cache = global.get(config.cache) || {};\n\nconst util = {\n    sortObject: obj => Object.keys(obj).sort().reduce((res, key) => (res[key] = obj[key], res), {}),\n\n\n    jackAPI: async (url, ttl) => {\n        const ts = Date.now();\n        if ( !cache[url] || cache[url].ts < (ts - ttl) ) {\n            try {\n                const { data } = await axios.get(url, {\n                    baseURL: `${config.proto}://${config.ip}:${config.port}`,\n                    auth: { username: config.user, password: config.password },\n                    httpsAgent: new https.Agent({ rejectUnauthorized: false, key: config.key, cert: config.cert }),\n                }).catch( (err) => { } ); // node.warn({url: url, error: err, ...msg})\n                cache[url] = data;\n                cache[url].ts = ts;\n                cache[url].ttl = ttl;\n                global.set(config.cache, cache);\n                cache = global.get(config.cache);\n            } catch(error) {}\n        }\n        return cache[url] || {};\n    },\n\n    getLinks: (obj, rel, ...args) => {\n        let ret = [];\n\n        obj['~links']\n        .sort((a, b) => { return a.href.localeCompare(b.href) })\n        .filter( link => link.href !== '..')\n        .filter( link => link.href !== '$MASTER')\n        .filter( link => rel !== null ? link.rel === rel : true)\n        .forEach( (link, ind, arr) => {\n            ret.push({\n                url: args.length > 0 ? '/' + args[0] + '/' + link.href : '/' + link.href,\n                request: args.length > 1 ? args[1] : link.href,\n            });\n        })\n        \n        return ret;\n    }\n}\n\ncontext.set('util', util);",
        "finalize": "",
        "libs": [
            {
                "var": "axios",
                "module": "axios"
            },
            {
                "var": "https",
                "module": "https"
            }
        ],
        "x": 810,
        "y": 1060,
        "wires": [
            []
        ]
    }
]

@guenter-ms
Copy link
Author

Hi Matthias,

puuhh das ist high sofisticated.... respekt!

Wenn ich es richtig verstanden habe, bringt der function node abonnierte mqtt topics des CCU-jacks "in Form", heisst man bekommt als output ein mit CCU-connection vergleichbares array.

Das entspräche dann in etwa der Funktionalität des RPC-Event Nodes von nodered-contrib-ccu. Also ein output bei einer Status Änderung eines CCU Objektes. Korrekt?

Zurückschreiben geht damit sicherlich noch nicht oder das gezielte (realtime) abfragen des aktuellen status, den könnte man eigentlich dafür doch in dem function node direkt in global.context variablen (name=msg.topic) speichern, oder?

Der Ansatz gefällt mir, zumal er so weit schon generisch ist, also nicht auf jeden geräte typ angepasst werden muss. sind denn RF, wired, IP und cuxd Objekte schon drin?

Der function node könnte später ein "richtiger" Node werden oder zumindest ein subflow https://nodered.org/docs/user-guide/editor/workspace/subflows dann können die config items gut als sub flow properties eingerichtet werden.

Ein Beispiel flow mit z.B. 2 MQTT Nodes und debug nodes wäre schon hilfreich das mal zu testen.

Gefällt mir!

Gruß guenni

@mdzio
Copy link
Owner

mdzio commented Feb 21, 2022

Maintainer von Node-Red-Contrib-CCU gibt es leider nicht mehr. Das war ja der Hauptgrund für den Vorschlag....

Ist denn just-grizzle kein Maintainer? Er wollte sich doch den CCU-Jack anschauen und sich dann zurückmelden.

Ansonsten muss ein Fork von dem Projekt erstellt und gepflegt werden. Das kann ich aber nicht leisten.

@guenter-ms
Copy link
Author

Meines Wissens ist node-red-contrib-ccu eine Komponente von https://github.com/rdmtc/RedMatic#readme
Der Autor ist Sebastian Raff alias hobbyquaker, der da einen super Job gemacht hat. Leider steht er wohl seit 12+ Monaten nicht mehr zur Verfügung, was man ihm natürlich niemand vorwirft.
Wenn es einen neuen maintainer gibt, wäre das sehr gut, denn redmatic ist mittlerweile veraltet, u.a. weil issues nicht mehr bearbeitet werden und die dependencies schon lange überholt sind. Bestes Beispiel ist das integrierte nodered.
Mir selbst fehlt das know how, am Interesse fehlt es da nicht.

@ptweety
Copy link

ptweety commented Oct 13, 2022

Hi @guenter-ms,

ich habe die letzten Tag an einem Fork von node-red-contrig-ccu gearbeitet und dort u.a. auch die hier angesprochene Integration umgesetzt: ptweety/node-red-contrib-ccu#6

@mdzio
Copy link
Owner

mdzio commented Oct 13, 2022

Vielen Dank für das Einbauen und den Fork!

@guenter-ms
Copy link
Author

guenter-ms commented Oct 14, 2022 via email

@ptweety
Copy link

ptweety commented Oct 14, 2022

Hi @guenter-ms,

da würde ich gerne helfen und habe auch bereits ein entsprechendes issue offen: ptweety/node-red-contrib-ccu#3

Da ich nicht weiß, in welcher Umgebung du Node-RED laufen hast, können wir im genannten issue gerne was gemeinsam erarbeiten.

@guenter-ms
Copy link
Author

guenter-ms commented Oct 14, 2022 via email

@ptweety
Copy link

ptweety commented Oct 14, 2022

Hi @guenter-ms,

ein erster Versuch eines Migrationsleitfadens ist nun verfügbar: ptweety/node-red-contrib-ccu@da8e3a2

@guenter-ms
Copy link
Author

Hi Mathias,

ich habe unter redmatic mal alle flows gelöscht (vorher gesichert), dann contrib-ccu gelöscht und deine version installiert, siehe install-log.

Anschließend konnte ich keinen ccu-configuration-node erfolgreich einrichten, siehe screenshot. Die Auswahlliste im Feld "Listen Adress" ist leer, man kann nichts eintragen.

Werde jetzt mal dein migration Konzept probieren.

Grüße G
Bildschirmfoto 2022-10-19 um 11 31 24
Bildschirmfoto 2022-10-19 um 11 30 38

@mdzio
Copy link
Owner

mdzio commented Oct 19, 2022

Fragen zu node-red-contrib-ccu stellst Du am besten in dem zugehörigen Projekt . Dann lesen auch die richtigen Leute mit. Hier geht es primär um den CCU-Jack.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants