UNPKG

pws_gsm

Version:

gsm modem api for sms and gprs

280 lines (248 loc) 7.27 kB
/** * Project: PWS_GSM * Created Date: Monday, June 4th 2018, 7:43:43 pm * Author: Thomas.Li * E-Mail: leeyinghui@hotmail.com * Intro: Modem class * ----- * Last Modified: Wed Jun 13 2018 * Modified By: Thomas.Li * ----- * Copyright (c) 2018 pareact * ------------------------------------ * Always bet on Javascript! */ const SerialPort = require('serialport'); const async = require('async'); const pduParser = require('./pdu'); let defaults = { timeout: 15000, parity: 'none', //校验 dataBits: 8, stopBits: 1, baudRate: 9600, // rtscts: true, autoOpen: true, }; const regexp = /(\r?(.+)\r)?\r\n(.+)\r\n$/;//初始化正则 const cmdRegexp = /(\r?(.+)\r)?(\r\n([\s\S]*)\r\n)?\r\n([A-Za-z]+)\r\n$/;//发送命令正则 class Modem extends SerialPort { constructor(url, opt) { for (var k in opt) defaults[k] = opt[k]; super(url, defaults, (err) => { if (err) { throw new Error(err); } else { console.log('connected ok!'); } }); this.options = defaults; this.buf = ''; //缓冲区 this.sendSta = false;//发送状态 this.hasData = true;//是否有返回数据,而非只有结果 this.on('error', function (err) { throw new Error(err); }); this.on('readable', () => { this.buf += this.read(); // console.log(this.sendSta); // console.log(Buffer.from(this.buf)); // console.log(this.sendSta + ':' + this.buf); if (this.sendSta) { if (/>/.test(this.buf)) { this.emit('message', ['OK', this.buf]); this.buf = ''; } if (cmdRegexp.test(this.buf)) { var m = cmdRegexp.exec(this.buf); this.emit('message', [m[5], m[4]]); this.buf = ''; } } else { // console.log(this.buf); if (regexp.test(this.buf)) { var m = regexp.exec(this.buf); this.emit('inComingMessage', m[3]); this.buf = ''; } } }); this.on('inComingMessage', mes => { var p = mes.split(/:\s?/); if (p.length === 2) { this.emit(p[0], p[1]) } else { console.log('value:' + mes); } }); this.queue = async.queue((task, done) => { this.sendSta = true; this.clear(); this.write(task.data + '\r', () => this.drain()); function onMessage(message) { clearTimeout(this.timeout); if (message[0] == 'OK') { task.accept(message[1] ? message[1] : message[0]); } else { task.reject(message[1]); } this.removeListener('message', onMessage); done(); } this.on('message', onMessage); // to temporary disable timeout use: null, 0, false if (this.options.timeout) { this.timeout = setTimeout(() => { task.reject(new Error('Sexy Timeout exceeded')); this.removeListener('message', onMessage); done(); }, +this.options.timeout); } }); this.queue.drain = () => { this.sendSta = false; console.log('Send work has been finished!'); } } // isOpen() { return this.port.isOpen } clear() { this.buf = '' } send(data) { let command = Object.assign({ data }, {}); command.promise = new Promise((accept, reject) => { command.accept = accept; command.reject = reject; }); this.queue.push(command); return command.promise; }; //查询 test(cmd) { return this.send(`AT+${cmd}?`); }; //执行并返回值 exec(cmd) { return this.send(`AT+${cmd}`); }; //设置或读取短信 set(name, value) { return this.send(`AT+${name}=${value}`); }; //查询并返回值 get(name) { return this.send(`AT+${name}=?`); }; async imei() { return this.exec('CGSN'); } async imsi() { return this.exec('CIMI'); } async sms_center() { return new Promise((resolve, reject) => { this.test('CSCA').then(res => { var p = res.split(/\"/); if (p.length === 3) { resolve(p[1]); } else { reject('ERROR'); } }) }); } async signal_length() { return new Promise((resolve, reject) => { this.exec('CSQ').then(res => { var p = res.split(/:\s?/); if (p.length === 2) { resolve(p[1]); } else { reject('ERROR'); } }); }) } async sms_read(index) { return new Promise((resolve, reject) => { this.set('CMGR', index).then(res => { try { let ss = res.split(/\r\n/); resolve(pduParser.parse(ss[1])); } catch (error) { reject(error); } }); }) } async sms_read_all(index) { return new Promise((resolve, reject) => { this.set('CMGL', index).then(res => { try { let ss = res.split(/\+CMGL/ig); let result = []; ss.forEach(element => { if (element.length > 5) { let si = element.split(/\r\n/); result.push(pduParser.parse(si[1])) } }); resolve(result); } catch (error) { reject(error); } }); }) } async sms_delete(index) { return this.set('CMGD', index); } async sms_mode(mode) { return this.set('CMGF', mode || 0); }; async set_sms_center(mode) { return this.set('CSCA', mode || '+8613800100500'); }; async set_gsm() { return this.set('CSCS', "GSM"); }; async sms_simple_send(number, content) { return new Promise((resolve, reject) => { this.set('CMGS', `"${number}"`).then(res => { this.send(content + '\u001a').then(res => resolve(res)).catch(e => reject(e)); }).catch(e => reject(e)); }) }; async sms_send(number, content, sc) { let addr = sc.replace('+', '') + 'F'; addr = '0891' + Buffer.from(addr, 'hex').map(bt => bt % 16 * 16 + (bt >> 4)).toString('hex'); let phone = number.replace('+', '') + 'F'; phone = '11000D91' + Buffer.from(phone, 'hex').map(bt => bt % 16 * 16 + (bt >> 4)).toString('hex'); let msg = content.split('').map(c => c.charCodeAt(0).toString(16).padStart(4, '0')).join(''); msg = (msg.length / 2).toString(16).padStart(2, '0') + msg; phone = phone + '000800' + msg; let count = (phone.length / 2); return new Promise((resolve, reject) => { this.set('CMGS', `${count}`).then(res => { this.send(addr + phone + '\u001a').then(res => resolve(res)).catch(e => reject(e)); }).catch(e => { reject(e); }); }) } async request() { return new Promise((resolve, reject) => { this.set('HTTPACTION', 0).then(res => { resolve(res); }).catch(e => reject(e)); }) }; async get_request() { return new Promise((resolve, reject) => { this.exec('HTTPREAD').then(res => { resolve(res); }).catch(e => reject(e)); }) }; } module.exports = Modem;