canopen
Version:
CANopen implementation for Javascript
384 lines (325 loc) • 12.9 kB
JavaScript
const chai = require('chai');
const chaiAsPromised = require('chai-as-promised');
const { Device, AccessType, DataType } = require('../../index');
const expect = chai.expect;
chai.use(chaiAsPromised);
const shortTypes = [
['BOOLEAN', true],
['INTEGER8', -0x12],
['INTEGER16', -0x1234],
['INTEGER24', -0x123456],
['INTEGER32', -0x12345678],
['UNSIGNED8', 0x12],
['UNSIGNED16', 0x1234],
['UNSIGNED24', 0x123456],
['UNSIGNED32', 0x12345678],
['VISIBLE_STRING', 'test'],
['OCTET_STRING', Buffer.from([1, 2, 3, 4])],
['UNICODE_STRING', '\u03b1'],
['REAL32', 1.0],
];
const longTypes = [
['INTEGER40', -0x1234567890],
['INTEGER48', -0x1234567890AB],
['INTEGER64', -1n],
['UNSIGNED40', 0x1234567890],
['UNSIGNED48', 0x1234567890AB],
['UNSIGNED64', 1n],
['VISIBLE_STRING', 'long visible string'],
['OCTET_STRING', Buffer.from([1, 2, 3, 4, 5, 6, 7, 8])],
['UNICODE_STRING', '\u03b1\u03b2\u03b3\u03b4\u03b5\u03b6'],
['REAL64', Math.PI],
['TIME_OF_DAY', new Date()],
['TIME_DIFFERENCE', new Date()],
];
describe('Sdo', function () {
it('should emit start once', function (done) {
const device = new Device({ id: 0xA});
device.sdo.on('start', () => done());
device.sdo.start();
device.sdo.start();
});
it('should emit stop once', function (done) {
const device = new Device({ id: 0xA});
device.sdo.start();
device.sdo.on('stop', () => done());
device.sdo.stop();
device.sdo.stop();
});
it('should transfer using the deprecated API', async function() {
const device = new Device({ id: 0xA, loopback: true });
device.sdo.addServer(device.id);
device.sdoServer.addClient(device.id);
device.init();
await device.sdo.download({
serverId: device.id,
data: 0xc0ffee,
dataType: DataType.UNSIGNED32,
index: 7,
});
const result = await device.sdo.upload({
serverId: device.id,
index: 7,
dataType: DataType.UNSIGNED32,
});
expect(result).to.equal(0xc0ffee);
device.stop();
});
describe('Expediated transfer', function () {
for (let [type, value] of shortTypes) {
it('should transfer ' + type, async function () {
const device = new Device({ id: 0xA, loopback: true });
device.eds.addSdoClientParameter(device.id);
device.eds.addSdoServerParameter(device.id);
device.start();
const index = DataType[type];
await device.sdo.download({
serverId: device.id,
data: value,
dataType: type,
index: index,
});
const result = await device.sdo.upload({
serverId: device.id,
index: index,
dataType: type,
});
if (Buffer.isBuffer(result))
expect(Buffer.compare(result, value)).to.equal(0);
else
expect(result).to.equal(value);
device.stop();
});
}
it('should transfer to any valid node id [1 - 127]', async function () {
let device;
for(let id = 1; id < 0x7F; ++id) {
device = new Device({ id, loopback: true });
device.eds.addSdoClientParameter(device.id);
device.eds.addSdoServerParameter(device.id);
device.start();
await device.sdo.download({
serverId: device.id,
data: 0xc0ffee,
dataType: DataType.UNSIGNED32,
index: 7,
});
const result = await device.sdo.upload({
serverId: device.id,
index: 7,
dataType: DataType.UNSIGNED32,
});
expect(result).to.equal(0xc0ffee);
device.stop();
}
});
});
describe('Segmented transfer', function () {
for (let [type, value] of longTypes) {
it('should transfer ' + type, async function () {
const device = new Device({ id: 0xA, loopback: true });
device.eds.addSdoClientParameter(device.id);
device.eds.addSdoServerParameter(device.id);
device.start();
const index = DataType[type];
await device.sdo.download({
serverId: device.id,
data: value,
dataType: type,
index: index,
});
const result = await device.sdo.upload({
serverId: device.id,
index: index,
dataType: type,
});
if (result instanceof Date)
expect(result.getTime()).to.equal(value.getTime());
else if (Buffer.isBuffer(result))
expect(Buffer.compare(result, value)).to.equal(0);
else if (typeof result == 'bigint')
expect(Number(result)).to.equal(Number(value));
else
expect(result).to.equal(value);
device.stop();
});
}
it('should transfer subindexes >= 1', async function () {
const device = new Device({ id: 0xA, loopback: true });
device.eds.addSdoClientParameter(device.id);
device.eds.addSdoServerParameter(device.id);
device.start();
const testString = 'I am a long string that will take multiple messages to transfer';
device.eds.addEntry(0x1234, {
parameterName: 'Test entry',
objectType: 6,
subNumber: 1
});
device.eds.addSubEntry(0x1234, 0, {
parameterName: 'A long name',
dataType: DataType.VISIBLE_STRING,
accessType: AccessType.READ_WRITE,
defaultValue: testString,
});
const result = await device.sdo.upload({
serverId: device.id,
index: 0x1234,
subIndex: 0,
dataType: DataType.VISIBLE_STRING
});
expect(result).to.equal(testString);
await device.sdo.download({
serverId: device.id,
data: result,
dataType: DataType.VISIBLE_STRING,
index: 0x1234,
subIndex: 0
});
device.stop();
});
it('should transfer to any valid node id [1 - 127]', async function () {
let device;
for(let id = 1; id < 0x7F; ++id) {
device = new Device({ id, loopback: true });
device.eds.addSdoClientParameter(id);
device.eds.addSdoServerParameter(id);
device.start();
await device.sdo.download({
serverId: device.id,
data: 'long visible string',
dataType: DataType.VISIBLE_STRING,
index: 9,
});
const result = await device.sdo.upload({
serverId: device.id,
index: 9,
dataType: DataType.VISIBLE_STRING,
});
expect(result).to.equal('long visible string');
device.stop();
}
});
it('should handle large transfers', async function () {
const device = new Device({ id: 0xA, loopback: true });
device.eds.addSdoClientParameter(device.id);
device.eds.addSdoServerParameter(device.id);
device.start();
const data = Buffer.alloc(65*1024);
for (let i = 0; i < data.length; ++i)
data[i] = Math.floor(Math.random() * 0xff);
device.eds.addEntry(0x1234, {
parameterName: 'A long buffer',
dataType: DataType.DOMAIN,
accessType: AccessType.READ_WRITE,
});
await device.sdo.download({
serverId: device.id,
data: data,
dataType: DataType.DOMAIN,
index: 0x1234,
blockTransfer: false,
});
const result = await device.sdo.upload({
serverId: device.id,
dataType: DataType.DOMAIN,
index: 0x1234,
blockTransfer: false,
});
expect(Buffer.compare(data, result)).to.equal(0);
device.stop();
});
});
describe('Block transfer', function () {
for (let [type, value] of shortTypes) {
it('should transfer ' + type, async function () {
const device = new Device({ id: 0xA, loopback: true });
device.eds.addSdoClientParameter(device.id);
device.eds.addSdoServerParameter(device.id);
device.start();
const index = DataType[type];
await device.sdo.download({
serverId: device.id,
data: value,
dataType: type,
index: index,
blockTransfer: true,
});
const result = await device.sdo.upload({
serverId: device.id,
index: index,
dataType: type,
blockTransfer: true,
});
if (Buffer.isBuffer(result))
expect(Buffer.compare(result, value)).to.equal(0);
else
expect(result).to.equal(value);
device.stop();
});
}
for (let [type, value] of longTypes) {
it('should transfer ' + type, async function () {
const device = new Device({ id: 0xA, loopback: true });
device.eds.addSdoClientParameter(device.id);
device.eds.addSdoServerParameter(device.id);
device.start();
const index = DataType[type];
await device.sdo.download({
serverId: device.id,
data: value,
dataType: type,
index: index,
blockTransfer: true,
});
const result = await device.sdo.upload({
serverId: device.id,
index: index,
dataType: type,
blockTransfer: true,
});
if (result instanceof Date)
expect(result.getTime()).to.equal(value.getTime());
else if (Buffer.isBuffer(result))
expect(Buffer.compare(result, value)).to.equal(0);
else if (typeof result == 'bigint')
expect(Number(result)).to.equal(Number(value));
else
expect(result).to.equal(value);
device.stop();
});
}
it('should handle large transfers', async function () {
const device = new Device({ id: 0xA, loopback: true });
device.eds.addSdoClientParameter(device.id);
device.eds.addSdoServerParameter(device.id);
device.start();
const data = Buffer.alloc(65*1024);
for (let i = 0; i < data.length; ++i)
data[i] = Math.floor(Math.random() * 0xff);
device.sdo.setBlockSize(127);
device.sdoServer.setBlockSize(127);
device.sdoServer.setBlockInterval(0);
device.eds.addEntry(0x1234, {
parameterName: 'A long buffer',
dataType: DataType.DOMAIN,
accessType: AccessType.READ_WRITE,
});
await device.sdo.download({
serverId: device.id,
data: data,
dataType: DataType.DOMAIN,
index: 0x1234,
blockTransfer: true,
blockInterval: 0,
});
const result = await device.sdo.upload({
serverId: device.id,
dataType: DataType.DOMAIN,
index: 0x1234,
blockTransfer: true,
});
expect(Buffer.compare(data, result)).to.equal(0);
device.stop();
});
});
});