dufourgilles / knx-ip

KNX IP Gateway protocol implementation
30 stars 9 forks source link

Raw write data to bus #17

Closed buuuudzik closed 2 years ago

buuuudzik commented 3 years ago

Because there is no full support for all existing datatypes I think more useful would be open api by introducing some raw method to write data to bus with simple interface like: write(groupAddress, valueAsBuffer)

If it is about listening bus communication the library is good and probably I can say that it is reliable which not all knx libraries for node offer.

But writing is not very useful for me because of above issue. I think this library have very good communication reliability but should has minimum api, without datapoints. Datapoints and encoding/decoding buffered data should be in other lib and this part could change in the future but raw communication more probably no.

buuuudzik commented 3 years ago

I've found a way:

const knxSocket = new KNXTunnelSocket("1.0.16");

const write = (ga, value) => new Promise((resolve, reject) => {
    const buffer = encode(ga, value);
    const knxDataBuffer = new KNXDataBuffer(buffer);
    const srcAddress = KNXAddress.createFromString('7.0.2', KNXAddress.TYPE_GROUP);
    const destAddress = KNXAddress.createFromString(ga, KNXAddress.TYPE_GROUP);
    knxSocket._knxClient.sendWriteRequest(srcAddress, destAddress, knxDataBuffer, (err) => {
        if (err) {
            console.log({err});
            reject(err);
        } else {
            resolve();
        }
    });
});
dufourgilles commented 3 years ago

Thanks for your feedback. I will add a generic write function.

buuuudzik commented 3 years ago

If this is not a problem then please add also read and response. Then the telegram queue would be handled in one place.

Thank you for this library

dufourgilles commented 3 years ago

I pushed a new version with generic DataPoint. See the README for an example. Let me know if modifications are required.

buuuudzik commented 3 years ago

I will test it later, after work, but it looks very good.

What about read and response request?

I have a little question about library which could be in README in reliability context: How this library will react on disconnection of ip router? Is it try to reconnect after reconnecting or I must build knx tunnel object once again?

Unfortunately I cannot now test it by myself because I test connection remotely. But what is the idea?

Thank you very much for response and help. For me now this is the best and reliable app for KNX connection.

buuuudzik commented 3 years ago

I've tried and it not works. genericDatapoint still expect encode in its _type. Only works when I pass something like this:

const buffer = encode(ga, value);
        const knxDataBuffer = new KNXDataBuffer(buffer);
        const destAddress = KNXAddress.createFromString(ga, KNXAddress.TYPE_GROUP);
        const genericDatapoint = new DataPoints.DataPoint(destAddress);
        genericDatapoint._type = {
            encode: value => encode(ga, value),
            decode: buffer => decode(ga, buffer),
        };
        genericDatapoint.bind(knxClient);
        await genericDatapoint.write(knxDataBuffer);
        return true;

But the goal should to pass only ready data buffer from value.

dufourgilles commented 2 years ago

_type should not be required. If _type is null, we either crash if you pass something else than a KNXDataBuffer ... or we use the KNXDataBuffer without further encoding.

Same for read, if no _type, we just return the KNXDataBuffer.

buuuudzik commented 2 years ago

Unfortunately it is required as you see below in Datapoint.write method:

async write(val: string|number|DPT10Value|DPT3Value|Date|DPT18Value|KNXDataBuffer|null = null): Promise<void> {
        if (this._knxTunnelSocket == null) {
            throw new Error('Datapoint not binded');
        }
        if (this._type == null && !(val instanceof KNXDataBuffer)) {
            throw new Error('Datapoint type not specified. Expecting KNXDataBuffer value');
        }
        const value = val == null ? this._value : val;
        const buf =  this._type ? new KNXDataBuffer(this._type.encode(value), this) : <KNXDataBuffer>val;
        await this._knxTunnelSocket.writeAsync(this._ga, buf);
    }

Same with this line, it needs to pass this or other Datapoint interface: new KNXDataBuffer(this._type.encode(value), this)

dufourgilles commented 2 years ago

this._type is not required if the value passed to write is a KNXBuffer.

Tested at home. It works. See below the log where I print the generic DataPoint _type value.

gdufour@gdnet2:/mnt/raid/Node/test$ node t.js _sendSearchRequestMessage 192.168.1.2 null Connecting to 192.168.1.46 3671 Connected through channel id 42 Reading lamp status Lamp status: 0 Generic DP Write null ^C

                .then(() => {
                **console.log("Generic DP Write", genericDP._type);**
                const buf = Buffer.alloc(1);
                buf.writeUInt8(1, 0);
                const kbuf = new KNXDataBuffer(buf);
                return genericDP.write(kbuf);
         })