pws_gsm
Version:
gsm modem api for sms and gprs
280 lines (248 loc) • 7.27 kB
JavaScript
/**
* 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;