mischroe / klf-200-api Goto Github PK
View Code? Open in Web Editor NEWThis module provides a wrapper to the REST API of a KLF-200 interface. Supporting the new API with firmware version 0.2.0.0.71 is in progress.
License: MIT License
This module provides a wrapper to the REST API of a KLF-200 interface. Supporting the new API with firmware version 0.2.0.0.71 is in progress.
License: MIT License
Documentation was corrected -> fix that frame, so that it will work.
One-way remote controlls don't trigger a refresh of the data, therefore it should be possible to refresh the data by the user.
The refres() method should be implemented for
Calling the refresh() method triggers a GW_GET_<NODE|GROUP|SCENE>_INFORMATION_REQ request.
Hello!
I'm very glad you made this module as this allowed me to interact with my KLF 200 and manipulate my Somfy IO blinds.
I have one problem though, I can't get the currentPosition from any Product, it's undefined.
Here's my code :
const { Connection, Products, Product } = require('klf-200-api');
async function main() {
const c = new Connection('192.168.0.7');
await c.loginAsync('xxx', 10000);
const blinds = await Products.createProductsAsync(c);
const cuisine = blinds.findByName('Volet cuisine');
const amis = blinds.findByName('Volet chambre amis');
const chambre = blinds.findByName('Volet chambre');
await cuisine.setTargetPositionAsync(1);
console.log(cuisine);
await c.logoutAsync();
}
main().catch(err => console.log(err));
Here's what I get when I console.log(cuisine):
Product {
propertyChangedEvent: TypedEvent {
listeners: [],
listenersOncer: [],
on: [Function (anonymous)],
once: [Function (anonymous)],
off: [Function (anonymous)],
emit: [Function (anonymous)],
pipe: [Function (anonymous)]
},
Connection: Connection {
host: '192.168.0.7',
CA: <Buffer 2d 2d 2d 2d 2d 42 45 47 49 4e 20 43 45 52 54 49 46 49 43 41 54 45 2d 2d 2d 2d 2d 0a 4d 49 49 44 46 54 43 43 41 66 32 67 41 77 49 42 41 67 49 4a 41 4a ... 1081 more bytes>,
fingerprint: '02:8C:23:A0:89:2B:62:98:C4:99:00:5B:D2:E7:2E:0A:70:3D:71:6A',
_onFrameSent: TypedEvent {
listeners: [],
listenersOncer: [],
on: [Function (anonymous)],
once: [Function (anonymous)],
off: [Function (anonymous)],
emit: [Function (anonymous)],
pipe: [Function (anonymous)]
},
keepAliveInterval: 600000,
sckt: TLSSocket {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
secureConnecting: false,
_SNICallback: null,
servername: false,
alpnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object: null prototype],
_eventsCount: 5,
connecting: false,
_hadError: false,
_parent: null,
_host: null,
_readableState: [ReadableState],
_maxListeners: undefined,
_writableState: [WritableState],
allowHalfOpen: false,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: [TLSWrap],
_requestCert: true,
_rejectUnauthorized: true,
[Symbol(res)]: [TLSWrap],
[Symbol(verified)]: true,
[Symbol(pendingSession)]: null,
[Symbol(async_id_symbol)]: 3,
[Symbol(kHandle)]: [TLSWrap],
[Symbol(kSetNoDelay)]: false,
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: null,
[Symbol(kBuffer)]: null,
[Symbol(kBufferCb)]: null,
[Symbol(kBufferGen)]: null,
[Symbol(kCapture)]: false,
[Symbol(kBytesRead)]: 0,
[Symbol(kBytesWritten)]: 0,
[Symbol(connect-options)]: [Object]
},
klfProtocol: KLF200SocketProtocol {
socket: [TLSSocket],
_onFrameReceived: [TypedEvent],
_onDataSent: [TypedEvent],
_onDataReceived: [TypedEvent],
_onError: [TypedEvent],
state: 0,
queue: []
}
},
_runStatus: 0,
_statusReply: 1,
NodeID: 0,
_name: 'Volet cuisine',
_TypeID: 2,
_SubType: 0,
_order: 0,
_placement: 0,
_velocity: 1,
_nodeVariation: 0,
_PowerSaveMode: 0,
_SerialNumber: <Buffer 00 00 00 00 00 00 00 00>,
_ProductType: 0,
_state: 255,
_currentPositionRaw: 25691,
_targetPositionRaw: 63487,
_fp1CurrentPositionRaw: 63487,
_fp2CurrentPositionRaw: 63487,
_fp3CurrentPositionRaw: 63487,
_fp4CurrentPositionRaw: 63487,
_remainingTime: 0,
_timeStamp: 2012-01-01T12:19:30.000Z,
_ProductAlias: [],
_limitationMinRaw: [
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0
],
_limitationMaxRaw: [
51200, 51200, 51200,
51200, 51200, 51200,
51200, 51200, 51200,
51200, 51200, 51200,
51200, 51200, 51200,
51200, 51200
]
}
I suppose I can deduce the currentPosition from the Raw one which seems to go from 65535 to 0 but I wanted to tell you about the missing properties.
The setTargetPositionAsync(0.5) works fine and the blind moves as expected to the right position :)
I'm running on the right KLF 200 firmware so I'm wondering if I'm missing something or if there's a bug somewhere?
Thank you so much for this library!
Not sure this is an issue with the code here, but I've noticed I'm not able to connect to the KLF-200 unit after a while until rebooting it. (port 51200 is closed)
~ » sudo nmap -sT -p- 10.0.90.191 terafin@home
Alias tip: _ nmap -sT -p- 10.0.90.191
[sudo] password for XXXXXX:
Starting Nmap 7.80 ( https://nmap.org ) at 2024-02-25 12:31 PST
Nmap scan report for velux.XXXXXXXX (10.0.90.191)
Host is up (0.00045s latency).
Not shown: 65533 closed ports
PORT STATE SERVICE
1900/tcp filtered upnp
60000/tcp filtered unknown
Nmap done: 1 IP address (1 host up) scanned in 6.02 seconds
Has anyone observed this behavior?
Note: You can see my connect usage of your library here:
https://github.com/terafin/mqtt-velux-bridge/blob/a0c044d6ca3b8a5450fe07b2ebf313e977b5d333/index.js#L108
Aside: Should I be using the cert/fingerprint instead? (Why one vs the other?)
See MiSchroe/ioBroker.klf200#129 for details.
Hi,
While using this library on Node.js it works fine (within the limits of the KLF 200 firmware). However, while running in a browser I got errors parsing the JSON result of the /auth call. Further investigation showed that the resulting JSON was indeed invalid. It turned out to be reproducible using curl:
$ curl -d '{"action":"login","params":{"password":"<passwd>"}}' -H "Content-Type: application/json" -X POST http://<ip>/api/v1/auth
Results in:
)]}', {"token":"<base64 string>","result":true,"deviceStatus":"IDLE","data":{},"errors":[]}
Note the preamble before the actual JSON. Have you seen similar behaviour?
Thanks,
Adriaan
I'm trying to run this from within a docker container, and I get an error which I don't fully understand. It is during the call to loginAsync.
await conn.loginAsync('mypassword');
The error message is as follows:
/app/node_modules/klf-200-api/dist/connection.js:277
(_b = this.sckt) === null || _b === void 0 ? void 0 : _b.off("error", loginErrorHandler);
^
TypeError: _b.off is not a function
at TLSSocket.sckt.tls_1.connect (/app/node_modules/klf-200-api/dist/connection.js:277:90)
at Object.onceWrapper (events.js:313:30)
at emitNone (events.js:106:13)
at TLSSocket.emit (events.js:208:7)
at TLSSocket.<anonymous> (_tls_wrap.js:1126:14)
at emitNone (events.js:106:13)
at TLSSocket.emit (events.js:208:7)
at TLSSocket._finishInit (_tls_wrap.js:639:8)
at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:469:38)
Am I missing some dependencies? Or something else?
I did have this all working in a non-dockerized environment. I hope to get it running also from within a docker container.
I've installed FHEM on a loxberry system. After placing the both files in the right folder and restarting the FHEM Server i procced with the input
define Velux KLF200 192.168.x.xx
After pressing ENTER i get the response: Cannot load module KLF200
This I think is the relevant part of the logfile
2019.01.15 20:36:49 0: Excessively long <> operator at ./FHEM/83_KLF200.pm line 21. 2019.01.15 20:37:22 1: reload: Error:Modul 83_KLF200 deactivated: Excessively long <> operator at ./FHEM/83_KLF200.pm line 21. 2019.01.15 20:37:22 0: Excessively long <> operator at ./FHEM/83_KLF200.pm line 21.
I there any hint what could be the problem?
KR, Roman
In the example code snippet in README.md, the web password is referenced. But for logging in (conn.loginAsync()), the WIFI password should be used. I'm sure it will be helpful for future users to correct this in the documentation.
I've been able to use the API with very rudimentary open/close of blinds and windows. I want to improve the functionality, but in order to do that I would need to read the current positions of the devices.
My ts skills are close to none, but I figure that something like below should work. Output from running the below is: NaN
.
Could anyone give me a hint on what I'm doing wrong? I'd really appreciate it.
const window = myProducts.findByName("Window left");
if (window) {
var p = window.CurrentPosition;
console.log(p);
} else {
throw(new Error("Could not find window left."));
}
Hi i have this error when i try to change position
(node:5021) UnhandledPromiseRejectionWarning: Error: Invalid frame structure. at cfmHandler.klfProtocol.on (/Users/spichtj/Desktop/velux/node_modules/klf-200-api/dist/connection.js:162:40) at listeners.forEach (/Users/spichtj/Desktop/velux/node_modules/klf-200-api/dist/utils/TypedEvent.js:25:50)
I'm logged in but this command fails, could you help me ?
Thanks
The LimitationOriginator and the remaining LimitationTime that comes with GW_LIMITATION_STATUS_NTF should be available as properties at a product.
refreshAsync only reads the stored values from the KLF-200. We have to request the status from the product additionally.
Hi
First of all, thank you for the library! I'm using it in a Node-RED flow and it works well. One issue is present though: The KLF-200 does not support execution of multiple concurrent scenes (or even logins). Currently, it doesn't seem that the library handles this case, at least I get the following error (after a timeout):
Error: socket hang up at createHangUpError (_http_client.js:331:15) at Socket.socketOnEnd (_http_client.js:423:23) at emitNone (events.js:111:20) at Socket.emit (events.js:208:7) at endReadableNT (_stream_readable.js:1064:12) at _combinedTickCallback (internal/process/next_tick.js:138:11) at process._tickCallback (internal/process/next_tick.js:180:9)
If I retry quickly I get (probably the multiple login limitation):
Error: Forbidden at Request.callback (/root/node_modules/superagent/lib/node/index.js:696:15) at parser (/root/node_modules/superagent/lib/node/index.js:906:18) at IncomingMessage.<anonymous> (/root/node_modules/klf-200-api/src/connection.js:129:13) at emitNone (events.js:111:20) at IncomingMessage.emit (events.js:208:7) at endReadableNT (_stream_readable.js:1064:12) at _combinedTickCallback (internal/process/next_tick.js:138:11) at process._tickCallback (internal/process/next_tick.js:180:9)
After another retry it usually works.
Currently, I'm providing basic retry capability within my Node-RED flow, but it would be great if the library would mitigate this limitation using some sort of queuing.
If you try to connect without a connection possible, e.g. the box is not connected at all, the resulting exception isn't handled which leads to an uncaught exception.
Velux released a new firmware (0.2.0.0.71.0) for the KLF-200. Unfortunately, there are no release notes. It would be important to know, if this library is still compatible with the new firmware.
The timestamp of a product is delivered wrongly by the KLF in the GW_NODE_STATE_POSITION_CHANGED_NTF
frame.
Therefore it should not be used to set the timestamp of the product.
refreshLimitationAsync() should wait for the GW_SESSION_FINISHED_NTF notification, otherwise it could result in timeout issues.
Hi @MiSchroe
i am new to this typescript, i do have the klf200 , and i am interested in the rainsensor state, i was told the state could be retrieved wit the limitations requests?
GW_GET_LIMITATION_STATUS_REQ
GW_GET_LIMITATION_STATUS_CFM
seems if the result !=0 its raining
but i am not sure how i can use that command in a ts script? can you make me an example for it?
thnx, appreciated in advance!!
E.g. the runAsync() method in the scenes class could be enhanced to provide additional parameters that are defaulted at the moment. By this change it would be possible to run a scene at another speed (e.g. in silent mode).
All methods should be enhanced like this. To prevent breaking current using the parameters should be defaulted to the same values that are used to call the KLF200.
Hi,
I tried to look up the API under this link
But it seems they removed it. Is this available anywhere else?
Limitations limit the movement of a node to a given range for a period of time.
Limitiation should be stored at the product and should be queried for each product.
According to the latest official documentation the GW_GET_NODE_INFORMATION_NTF frame has an additional property "ProductGroup".
Include this property in the frame.
Same change has to be done at GW_GET_ALL_NODES_INFORMATION_NTF.
In addition to user-defined groups the Group classes should support the GroupType parameter as optional parameter.
That wouldn't break the existing functionality but it would support the rooms (and also house and all groups).
Some of the timeout tests doesn't use fake timers and have a longer runtime than they should have.
The timeout for the tests are set high enough, but still they are flagged as slow in the log (and they are slow of course).
Hello,
running the install of klf-200-api on raspberry pi is not successful. Are there missing bits in my installation ?
Thank you
See below the output of installation.
sudo npm install klf-200-api --save
(node:9174) [DEP0022] DeprecationWarning: os.tmpDir() is deprecated. Use os.tmpdir() instead.
npm ERR! Error: Method Not Allowed
npm ERR! at errorResponse (/usr/share/npm/lib/cache/add-named.js:260:10)
npm ERR! at /usr/share/npm/lib/cache/add-named.js:203:12
npm ERR! at saved (/usr/share/npm/node_modules/npm-registry-client/lib/get.js:167:7)
npm ERR! at FSReqWrap.oncomplete (fs.js:135:15)
npm ERR! If you need help, you may report this entire log,
npm ERR! including the npm and node versions, at:
npm ERR! http://github.com/npm/npm/issues
npm ERR! System Linux 4.19.42-v7+
npm ERR! command "/usr/bin/node" "/usr/bin/npm" "install" "klf-200-api" "--save"
npm ERR! cwd /home/pi/script
npm ERR! node -v v8.11.1
npm ERR! npm -v 1.4.21
npm ERR! code E405
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR! /home/pi/script/npm-debug.log
npm ERR! not ok code 0
When new products are added, the Products
class tries to read the new products after receiving the GW_CS_SYSTEM_TABLE_UPDATE_NTF
notification.
This results in receiving a GW_ERROR_NTF
notification with error code 7 = Busy.
A reconnect should be possible, when the underlying connection was closed due to any circumstances.
Currently, if the connection is lost (plug out the network cable to test), the underlying socket closes the connection, but the Connection class doesn't handle this.
Add a handler that is called whenever a frame is sent via sendFrameAsync.
That handler can be used for logging purposes.
Hi,
with the "display remote" I can open my window even if it's raining. Is there a possibility to do this with klf-200-api?
First analysis:
The frame GW_GET_SCENE_INFORMATION_NTF doesn't contain the SceneID as stated in the documentation. That field is always 0.
In Line 145 we filter by the SceneID. Probably that additional check has to be removed.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.