xiot-core-xcp-ts
Version:
217 lines (216 loc) • 7.35 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.XcpClientBase = void 0;
const XcpClientVerifierImpl_1 = require("./XcpClientVerifierImpl");
const WebSocketBinaryFrameCodecImpl_1 = require("../codec/WebSocketBinaryFrameCodecImpl");
const xiot_core_spec_ts_1 = require("xiot-core-spec-ts");
const StanzaCodec_1 = require("../../stanza/codec/StanzaCodec");
const IQResult_1 = require("../../stanza/typedef/iq/IQResult");
const IQError_1 = require("../../stanza/typedef/iq/IQError");
const IQQuery_1 = require("../../stanza/typedef/iq/IQQuery");
const XcpFrameCodecType_1 = require("../common/XcpFrameCodecType");
const Uint8ArrayUtils_1 = require("../utils/Uint8ArrayUtils");
const IQ_1 = require("../../stanza/typedef/iq/IQ");
const IQType_1 = require("../../stanza/typedef/iq/IQType");
class XcpClientBase {
constructor(serialNumber, productId, type, cipher, codec) {
this.cipher = cipher;
this.codec = codec;
this.ws = null;
this.verifier = null;
this.verified = false;
this.frameCodec = null;
this.messageId = 1;
this.verifyHandler = () => { };
this.disconnectHandler = () => { };
this.did = serialNumber + '@' + productId;
this.type = type;
this.messageCodec = new StanzaCodec_1.StanzaCodec();
this.resultHandlers = new Map();
this.queryHandlers = new Map();
}
createWebSocket(url) {
// this.ws = new WebSocket(url);
throw Error('createWebSocket failed !');
}
connect(host, port, uri) {
const url = 'ws://' + host + ':' + port + uri;
console.log('connect: ' + url);
this.ws = this.createWebSocket(url);
if (this.ws == null) {
throw Error('new WebSocket Failed!');
}
this.ws.addEventListener('open', () => this.onConnected());
this.ws.addEventListener('close', () => this.onDisconnect());
this.ws.addEventListener('error', () => this.onError());
this.ws.addEventListener('message', message => this.onMessage(message));
return new Promise((resolve, reject) => {
this.verifyHandler = (result, err) => {
if (result) {
resolve();
return;
}
reject(err);
};
});
}
disconnect() {
if (this.ws != null) {
this.ws.close();
}
}
getDeviceId() {
return this.did;
}
getDeviceType() {
return this.type;
}
getNextStanzaId() {
return Date.now() + '#' + this.messageId++;
}
addQueryHandler(method, handler) {
console.log('addQueryHandler: ', method);
this.queryHandlers.set(method, handler);
}
addDisconnectHandler(handler) {
this.disconnectHandler = handler;
}
sendQuery(query) {
this.write(this.messageCodec.encode(query));
return new Promise((resolve, reject) => {
this.resultHandlers.set(query.id, (result, error) => {
if (error != null) {
reject(error);
return;
}
if (result == null) {
return;
}
resolve(result);
});
});
}
sendResult(result) {
this.write(this.messageCodec.encode(result));
}
sendError(error) {
this.write(this.messageCodec.encode(error));
}
sendMessage(message) {
this.write(this.messageCodec.encode(message));
}
onConnected() {
console.log('onConnected');
this.startVerify('1.0')
.then(() => this.verifyHandler(true))
.catch(e => this.verifyHandler(false, e));
}
onDisconnect() {
console.log('onDisconnect');
this.ws = null;
this.disconnectHandler();
}
onError() {
console.log('onError');
this.ws = null;
}
onMessage(message) {
let msg = null;
if (this.frameCodec == null) {
console.log(Date() + ' recv text frame: ', message.data);
msg = this.messageCodec.decode(message.data);
}
else {
const data = this.frameCodec.decrypt(message.data);
if (data != null) {
const s = Uint8ArrayUtils_1.Utf8ArrayToStr(data);
console.log(Date() + ' recv binary frame: ', s);
msg = this.messageCodec.decode(s);
}
}
if (msg == null) {
return;
}
this.handleMessage(msg);
}
handleMessage(message) {
if (message instanceof IQ_1.IQ) {
switch (message.type) {
case IQType_1.IQType.QUERY:
this.handleQuery(message);
break;
case IQType_1.IQType.RESULT:
this.handleResult(message);
break;
case IQType_1.IQType.ERROR:
this.handleError(message);
break;
default:
console.log('invalid message: ', message);
break;
}
}
else {
console.log('message not IQ: ', message);
}
}
handleQuery(query) {
if (!(query instanceof IQQuery_1.IQQuery)) {
return;
}
const handler = this.queryHandlers.get(query.method);
if (handler != null) {
handler(query);
}
else {
this.sendError(query.error(xiot_core_spec_ts_1.Status.UNDEFINED, 'Query Handler not found'));
}
}
handleResult(result) {
if (!(result instanceof IQResult_1.IQResult)) {
return;
}
const handler = this.resultHandlers.get(result.id);
if (handler != null) {
handler(result, null);
this.resultHandlers.delete(result.id);
}
else {
console.log('handle for result not found: ', result.id);
}
}
handleError(error) {
if (!(error instanceof IQError_1.IQError)) {
return;
}
const handler = this.resultHandlers.get(error.id);
if (handler != null) {
this.verifyHandler(false, error);
handler(null, error);
this.resultHandlers.delete(error.id);
}
else {
console.log('handle for error not found: ', error.id);
}
}
startVerify(version) {
this.verifier = new XcpClientVerifierImpl_1.XcpClientVerifierImpl(this, version, this.cipher, this.codec);
return this.verifier.start().then(x => this.setXcpSessionKey(x));
}
setXcpSessionKey(key) {
console.log('setXcpSessionKey, codec: ', key.codec);
if (key.codec !== XcpFrameCodecType_1.XcpFrameCodecType.NOT_CRYPT) {
this.frameCodec = new WebSocketBinaryFrameCodecImpl_1.WebSocketBinaryFrameCodecImpl(key.deviceToServer, key.serverToDevice);
}
console.log('verify succeed!');
this.verified = true;
}
write(o) {
const s = JSON.stringify(o);
console.log(Date() + ' write: ', s);
if (this.ws != null) {
this.ws.send(s);
}
}
}
exports.XcpClientBase = XcpClientBase;