UNPKG

@zandor300/jsmodbus

Version:

Implementation for the Serial/TCP Modbus protocol.

164 lines (163 loc) 5.94 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const OUT_OF_SYNC = 'OutOfSync'; const OFFLINE = 'Offline'; const MODBUS_EXCEPTION = 'ModbusException'; const MANUALLY_CLEARED = 'ManuallyCleared'; const Debug = require("debug"); const debug = Debug('client-request-handler'); const exception_js_1 = __importDefault(require("./response/exception.js")); const user_request_error_1 = require("./user-request-error"); const user_request_js_1 = __importDefault(require("./user-request.js")); class MBClientRequestHandler { get state() { return this._state; } get requestCount() { return this._requests.length; } constructor(socket, timeout) { if (new.target === MBClientRequestHandler) { throw new TypeError('Cannot instantiate ModbusClientRequestHandler directly.'); } this._socket = socket; this._timeout = timeout; this._state = 'offline'; } registerRequest(request) { const userRequest = new user_request_js_1.default(request, this._timeout); this._requests.push(userRequest); this._flush(); return userRequest.promise; } handle(response) { debug('incoming response'); if (!response) { debug('well, sorry I was wrong, no response at all'); return; } const userRequest = this._currentRequest; if (!userRequest) { debug('no current request, no idea where this came from'); return; } const request = userRequest.request; if (response.body.isException === false && response.body.fc !== request.body.fc) { debug('something is weird, request fc and response fc do not match.'); userRequest.reject(new user_request_error_1.UserRequestError({ err: OUT_OF_SYNC, message: 'request fc and response fc does not match.', request })); this._clearAllRequests(); return; } if (response.body instanceof exception_js_1.default) { debug('response is a exception'); userRequest.reject(new user_request_error_1.UserRequestError({ err: MODBUS_EXCEPTION, message: `ModbusException: ${response.body.message} (Code ${response.body.code}) (Device Address ${response.address})`, request, response })); this._clearCurrentRequest(); this._flush(); return; } debug('resolving request'); userRequest.resolve(response); this._clearCurrentRequest(); this._flush(); } manuallyRejectCurrentRequest() { if (this._currentRequest) { this._currentRequest.reject(new user_request_error_1.UserRequestError({ err: MANUALLY_CLEARED, message: 'the request was manually cleared', request: this._currentRequest.request })); this._flush(); } } manuallyRejectRequests(numRequests) { for (let i = 0; i < numRequests; i++) { this.manuallyRejectCurrentRequest(); } } manuallylRejectAllRequests() { this.manuallyRejectRequests(this.requestCount); } customErrorRequest(err) { if (this._currentRequest) { this._currentRequest.reject(err); } } _clearCurrentRequest() { if (!this._currentRequest) { return; } this._currentRequest.done(); this._currentRequest = null; } _clearAllRequests() { this._clearCurrentRequest(); while (this._requests.length > 0) { const req = this._requests.shift(); if (req) { req.reject(new user_request_error_1.UserRequestError({ err: OUT_OF_SYNC, message: 'rejecting because of earlier OutOfSync error', request: req.request })); } } } _onConnect() { this._state = 'online'; } _onClose() { this._state = 'offline'; this._currentRequest && this._currentRequest.reject(new user_request_error_1.UserRequestError({ err: OFFLINE, message: 'connection to modbus server closed', request: this._currentRequest.request })); this._clearAllRequests(); } _flush() { debug('flushing'); if (this._currentRequest !== null) { debug('executing another request, come back later'); return; } if (this._requests.length === 0) { debug('no request to be executed'); return; } this._currentRequest = this._requests.shift(); if (this._state === 'offline') { debug('rejecting request immediatly, client offline'); this._currentRequest && this._currentRequest.reject(new user_request_error_1.UserRequestError({ err: OFFLINE, message: 'no connection to modbus server', request: this._currentRequest.request })); this._clearCurrentRequest(); setTimeout(this._flush.bind(this), 0); return; } const payload = this._currentRequest && this._currentRequest.createPayload(); debug('flushing new request', payload); this._currentRequest && this._currentRequest.start(() => { this._clearCurrentRequest(); this._flush(); }); this._socket.write(payload, (err) => { debug('request fully flushed, ( error:', err, ')'); }); } } exports.default = MBClientRequestHandler;