Issue reading structs containing BIT datatype
Closed this issue · 6 comments
Hi,
I'm having an issue where I cannot subscribe to structures containing BITs. I can subscribe to everything else just fine.
For example, I cannot subscribe to the struct below:
TYPE ST_SYSTEM_STATE :
STRUCT
//all subsystems
bStateMachineRunning : BIT;
bMotorsPowered : BIT;
bInitComplete : BIT;
bIsHoming : BIT;
bHasHomed : BIT;
bIsReady : BIT;
bIsBusy : BIT;
bMotorsMoving : BIT;
bHasStopped : BIT;
bHasPaused : BIT;
END_STRUCT
END_TYPE
Turning on debugging in ads-client, I receive the following message:
at async \node_modules\ads-client\src\ads-client.js:6325:35 { code: 'ERR_BUFFER_OUT_OF_BOUNDS' } +4ms
ads-client:details IO in <------ 68 bytes +494ms
ads-client:details _parseAmsTcpHeader(): Starting to parse AMS/TCP header +1ms
ads-client:details _parseAmsTcpHeader(): AMS/TCP header parsed: { command: 0, commandStr: 'AMS_TCP_PORT_AMS_CMD', dataLength: 62 } +0ms
ads-client:details _parseAmsHeader(): Starting to parse AMS header +1ms
ads-client:details _parseAmsHeader(): AMS header parsed: { targetAmsNetId: '192.168.200.1.1.1', targetAdsPort: 33242, sourceAmsNetId: '192.168.11.2.1.1', sourceAdsPort: 851, adsCommand: 8, adsCommandStr: 'Notification', stateFlags: 4, stateFlagsStr: 'AdsCommand, Tcp, Request', dataLength: 30, errorCode: 0, invokeId: 0, error: false, errorStr:
ads-client:details _getDataTypeInfo(): Data type requested for BIT +0ms
ads-client:details _getDataTypeInfo(): Data type info found from cache for BIT +0ms
ads-client:details _getDataTypeInfo(): Data type requested for BIT +0ms ads-client:details _getDataTypeInfo(): Data type info found from cache for BIT +1ms
ads-client _onAdsCommandReceived(): Ads notification received but parsing Javascript object failed: RangeError [ERR_BUFFER_OUT_OF_BOUNDS]: Attempt to access memory outside buffer bounds
Any help would be greatly appreciated.
Thanks!
Isaac
Hi!
Actually the BIT data type is not available/working at the moment. I thought that I had it in README but I didn't.. Basically it is in the code however handled like a BOOL and it would require some extra effort to be handled correctly.
So I would suggest to use BOOL instead if possible, or just a single WORD and then get the bits yourself. Personally I never use BITs with TwinCAT as the support is not that good.
Edit: I will keep this issue open as this certainly should work some day if it's technically doable.
Hi jisotalo,
Thanks very much for the quick reply. Good to know I wasn't going crazy! We initially were using BITs instead of BOOLs to reduce the size of the overall packets over the network, but it's not a big deal for us to change over to using BOOLs instead. I'll keep it in mind for future development not to use BITs.
Once again, I very much appreciate the time and effort you've put into this library.
Thanks!
Isaac
If you really need to read struct with BITs it's possible but needs a little work. I tested the following and it works fine!
PLC side
TYPE ST_Bits:
STRUCT
Bit_0 : BIT;
Bit_1 : BIT;
Bit_2 : BIT;
Bit_3 : BIT;
Bit_4 : BIT;
Bit_5 : BIT;
Bit_6 : BIT;
Bit_7 : BIT;
END_STRUCT
END_TYPE
//GVL_BitTest
{attribute 'qualified_only'}
VAR_GLOBAL
Bits : ST_Bits;
END_VAR
Node.js side
const ads = require('ads-client');
const client = new ads.Client({
targetAmsNetId: 'localhost',
targetAdsPort: 851
});
client.connect()
.then(async res => {
console.log(`Connected to the ${res.targetAmsNetId}`);
console.log(`Router assigned us AmsNetId ${res.localAmsNetId} and port ${res.localAdsPort}`);
//First getting the symbol info for this variable
const info = await client.getSymbolInfo('GVL_BitTest.Bits');
//Using symbol info to subscribe to raw data
const sub = await client.subscribeRaw(info.indexGroup, info.indexOffset, info.size, (data, sub) => {
//Converting Buffer to byte
const value = data.value.readUint8();
const converted = {
bit_0: !!(value & (0x01 << 0)),
bit_1: !!(value & (0x01 << 1)),
bit_2: !!(value & (0x01 << 2)),
bit_3: !!(value & (0x01 << 3)),
bit_4: !!(value & (0x01 << 4)),
bit_5: !!(value & (0x01 << 5)),
bit_6: !!(value & (0x01 << 6)),
bit_7: !!(value & (0x01 << 7)),
}
console.log(converted);
/* Should print something like:
{
bit_0: true,
bit_1: false,
bit_2: true,
bit_3: false,
bit_4: true,
bit_5: false,
bit_6: true,
bit_7: false
}
*/
});
})
.catch(err => {
console.log('Something failed:', err);
})
Thanks again and have a nice christmas!
Adding this to version 2.0 milestone. Let's see if it's possible easily or not.