lwm2m
Version:
Library for developing servers and client of OMA Lightweight M2M
199 lines (165 loc) • 4.7 kB
JavaScript
/*
* Copyright 2017 Alexandre Moreno <alex_moreno@tutk.com>
*
* This file is part of node-lwm2m
*
* node-lwm2m is free software: you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* node-lwm2m is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with node-lwm2m.
* If not, seehttp://www.gnu.org/licenses/.
*
* For those usages not covered by the GNU Affero General Public License
* please contact with::[contacto@tid.es]
*
*/
;
var debug = require('debug')('lwm2m');
var utils = require('./utils');
function serializeToString(obj, schema) {
var result = { e: [] },
keys = Object.keys(obj);
schema.validate(obj);
function append(arr, key, value, type) {
var types = {
String: function() {
arr.push({ n: key, sv: value });
},
Integer: function() {
arr.push({ n: key, v: value });
},
Float: function() {
arr.push({ n: key, v: value });
},
Boolean: function() {
arr.push({ n: key, bv: value });
},
Opaque: function() {
arr.push({
n: key,
sv: value.toString('base64'),
});
},
Time: function() {
var timestamp = value.getTime() / 1e3 >> 0;
arr.push({ n: key, v: timestamp });
},
};
function skip () {
debug('Skipping resource with invalid type %s', typeof value);
}
if (Array.isArray(type)) {
value.forEach(function(val, i) {
append(arr, key + '/' + i, val, type[0]);
});
return arr;
}
(types[type] || skip)();
return arr;
}
for (var i = 0; i < keys.length; ++i) {
var key = keys[i],
res = schema.resources[key];
// skip resources not defined in schema
if (!res) {
debug('Resource not defined in schema: %s', key);
continue;
}
append(result.e, String(res.id), obj[key], res.type);
}
if (schema.basename) {
result.bn = schema.basename;
}
return JSON.stringify(result);
}
function parse(payload, schema) {
var result = {},
obj = {};
function append(obj, key, attr, data, i) {
var types = {
String: function() {
obj[key] = data[i].sv;
},
Integer: function() {
obj[key] = data[i].v;
},
Float: function() {
obj[key] = data[i].v;
},
Boolean: function() {
obj[key] = data[i].bv;
},
Opaque: function() {
obj[key] = Buffer.from(data[i].sv, 'base64');
},
Time: function() {
obj[key] = new Date(data[i].v * 1e3);
},
Objlnk: function() {
var path = data[i].ov.split(':').join('/');
var elems = data.filter(function(elem) {
return elem.n.startsWith(path);
});
var inSchema = attr.schema;
obj[key] = {};
elems.forEach(function(elem, j) {
var inKey = inSchema.id[elem.n.split('/')[2]];
// skip resources not defined in schema.
if (!inKey) {
return;
}
append(obj[key], inKey, inSchema.resources[inKey], elems, j);
});
},
};
if (Array.isArray(attr.type)) {
var id = data[i].n.split('/').slice(-1)[0];
if (!obj[key]) {
obj[key] = [];
}
append(obj[key], id, { type: attr.type[0] }, data, i);
} else {
(types[attr.type])();
}
if (obj[key] === undefined) {
throw new Error('JSON payload does not match ' +
schema.name + ' definition');
}
return obj;
}
obj = JSON.parse(payload.toString('utf8'));
if (!Array.isArray(obj.e)) {
throw new Error('Invalid JSON payload');
}
var offset = 0;
if (obj.bn) {
if (obj.bn === '/') {
offset = 2;
} else if (utils.isObject(obj.bn)) {
offset = 1;
} else if (utils.isInstance(obj.bn)) {
offset = 0;
} else {
throw new Error('Invalid JSON payload');
}
}
for (var i = 0; i < obj.e.length; ++i) {
var key = schema.id[obj.e[i].n.split('/')[offset]];
// skip resources not defined in schema.
if (!key) {
continue;
}
append(result, key, schema.resources[key], obj.e, i);
}
return result;
}
exports.serialize = serializeToString;
exports.parse = parse;