mirror of
https://github.com/meshcore-dev/meshcore.js.git
synced 2026-04-20 22:13:49 +00:00
824 lines
28 KiB
JavaScript
824 lines
28 KiB
JavaScript
import BufferWriter from "../buffer_writer.js";
|
|
import BufferReader from "../buffer_reader.js";
|
|
import Constants from "../constants.js";
|
|
import EventEmitter from "../events.js";
|
|
|
|
class Connection extends EventEmitter {
|
|
|
|
onConnected() {
|
|
this.emit("connected");
|
|
}
|
|
|
|
onDisconnected() {
|
|
this.emit("disconnected");
|
|
}
|
|
|
|
async close() {
|
|
throw new Error("This method must be implemented by the subclass.");
|
|
}
|
|
|
|
async sendToRadioFrame(data) {
|
|
throw new Error("This method must be implemented by the subclass.");
|
|
}
|
|
|
|
async sendCommandAppStart() {
|
|
const data = new BufferWriter();
|
|
data.writeByte(Constants.CommandCodes.AppStart);
|
|
data.writeByte(1); // appVer
|
|
data.writeBytes(new Uint8Array(6)); // reserved
|
|
data.writeString("test"); // appName
|
|
await this.sendToRadioFrame(data.toBytes());
|
|
}
|
|
|
|
async sendCommandSendTxtMsg(txtType, attempt, senderTimestamp, pubKeyPrefix, text) {
|
|
const data = new BufferWriter();
|
|
data.writeByte(Constants.CommandCodes.SendTxtMsg);
|
|
data.writeByte(txtType);
|
|
data.writeByte(attempt);
|
|
data.writeUInt32LE(senderTimestamp);
|
|
data.writeBytes(pubKeyPrefix.slice(0, 6)); // only the first 6 bytes of pubKey are sent
|
|
data.writeString(text);
|
|
await this.sendToRadioFrame(data.toBytes());
|
|
}
|
|
|
|
async sendCommandSendChannelTxtMsg(txtType, channelIdx, senderTimestamp, text) {
|
|
const data = new BufferWriter();
|
|
data.writeByte(Constants.CommandCodes.SendChannelTxtMsg);
|
|
data.writeByte(txtType);
|
|
data.writeByte(channelIdx);
|
|
data.writeUInt32LE(senderTimestamp);
|
|
data.writeString(text);
|
|
await this.sendToRadioFrame(data.toBytes());
|
|
}
|
|
|
|
async sendCommandGetContacts(since) {
|
|
const data = new BufferWriter();
|
|
data.writeByte(Constants.CommandCodes.GetContacts);
|
|
if(since){
|
|
data.writeUInt32LE(since);
|
|
}
|
|
await this.sendToRadioFrame(data.toBytes());
|
|
}
|
|
|
|
async sendCommandGetDeviceTime() {
|
|
const data = new BufferWriter();
|
|
data.writeByte(Constants.CommandCodes.GetDeviceTime);
|
|
await this.sendToRadioFrame(data.toBytes());
|
|
}
|
|
|
|
async sendCommandSetDeviceTime(epochSecs) {
|
|
const data = new BufferWriter();
|
|
data.writeByte(Constants.CommandCodes.SetDeviceTime);
|
|
data.writeUInt32LE(epochSecs);
|
|
await this.sendToRadioFrame(data.toBytes());
|
|
}
|
|
|
|
async sendCommandSendSelfAdvert(type) {
|
|
const data = new BufferWriter();
|
|
data.writeByte(Constants.CommandCodes.SendSelfAdvert);
|
|
data.writeByte(type);
|
|
await this.sendToRadioFrame(data.toBytes());
|
|
}
|
|
|
|
async sendCommandSetAdvertName(name) {
|
|
const data = new BufferWriter();
|
|
data.writeByte(Constants.CommandCodes.SetAdvertName);
|
|
data.writeString(name);
|
|
await this.sendToRadioFrame(data.toBytes());
|
|
}
|
|
|
|
async sendCommandAddUpdateContact(publicKey, type, flags, outPathLen, outPath, advName, lastAdvert, advLat, advLon) {
|
|
const data = new BufferWriter();
|
|
data.writeByte(Constants.CommandCodes.AddUpdateContact);
|
|
data.writeBytes(publicKey);
|
|
data.writeByte(type);
|
|
data.writeByte(flags);
|
|
data.writeByte(outPathLen); // todo writeInt8
|
|
data.writeBytes(outPath); // 64 bytes
|
|
data.writeCString(advName, 32); // 32 bytes
|
|
data.writeUInt32LE(lastAdvert);
|
|
data.writeUInt32LE(advLat);
|
|
data.writeUInt32LE(advLon);
|
|
await this.sendToRadioFrame(data.toBytes());
|
|
}
|
|
|
|
async sendCommandSyncNextMessage() {
|
|
const data = new BufferWriter();
|
|
data.writeByte(Constants.CommandCodes.SyncNextMessage);
|
|
await this.sendToRadioFrame(data.toBytes());
|
|
}
|
|
|
|
async sendCommandSetRadioParams(radioFreq, radioBw, radioSf, radioCr) {
|
|
const data = new BufferWriter();
|
|
data.writeByte(Constants.CommandCodes.SetRadioParams);
|
|
data.writeUInt32LE(radioFreq);
|
|
data.writeUInt32LE(radioBw);
|
|
data.writeByte(radioSf);
|
|
data.writeByte(radioCr);
|
|
await this.sendToRadioFrame(data.toBytes());
|
|
}
|
|
|
|
async sendCommandSetTxPower(txPower) {
|
|
const data = new BufferWriter();
|
|
data.writeByte(Constants.CommandCodes.SetTxPower);
|
|
data.writeByte(txPower);
|
|
await this.sendToRadioFrame(data.toBytes());
|
|
}
|
|
|
|
async sendCommandResetPath(pubKey) {
|
|
const data = new BufferWriter();
|
|
data.writeByte(Constants.CommandCodes.ResetPath);
|
|
data.writeBytes(pubKey); // 32 bytes
|
|
await this.sendToRadioFrame(data.toBytes());
|
|
}
|
|
|
|
async sendCommandSetAdvertLatLon(lat, lon) {
|
|
const data = new BufferWriter();
|
|
data.writeByte(Constants.CommandCodes.SetAdvertLatLon);
|
|
data.writeInt32LE(lat);
|
|
data.writeInt32LE(lon);
|
|
await this.sendToRadioFrame(data.toBytes());
|
|
}
|
|
|
|
async sendCommandRemoveContact(pubKey) {
|
|
const data = new BufferWriter();
|
|
data.writeByte(Constants.CommandCodes.RemoveContact);
|
|
data.writeBytes(pubKey); // 32 bytes
|
|
await this.sendToRadioFrame(data.toBytes());
|
|
}
|
|
|
|
async sendCommandShareContact(pubKey) {
|
|
const data = new BufferWriter();
|
|
data.writeByte(Constants.CommandCodes.ShareContact);
|
|
data.writeBytes(pubKey); // 32 bytes
|
|
await this.sendToRadioFrame(data.toBytes());
|
|
}
|
|
|
|
// provide a public key to export that contact
|
|
// not providing a public key will export local identity as a contact instead
|
|
async sendCommandExportContact(pubKey = null) {
|
|
const data = new BufferWriter();
|
|
data.writeByte(Constants.CommandCodes.ExportContact);
|
|
if(pubKey){
|
|
data.writeBytes(pubKey); // 32 bytes
|
|
}
|
|
await this.sendToRadioFrame(data.toBytes());
|
|
}
|
|
|
|
async sendCommandImportContact(advertPacketBytes) {
|
|
const data = new BufferWriter();
|
|
data.writeByte(Constants.CommandCodes.ImportContact);
|
|
data.writeBytes(advertPacketBytes); // raw advert packet bytes
|
|
await this.sendToRadioFrame(data.toBytes());
|
|
}
|
|
|
|
onFrameReceived(frame) {
|
|
|
|
// emit received frame
|
|
this.emit("rx", frame);
|
|
|
|
const bufferReader = new BufferReader(frame);
|
|
const responseCode = bufferReader.readByte();
|
|
|
|
if(responseCode === Constants.ResponseCodes.Ok){
|
|
this.onOkResponse(bufferReader);
|
|
} else if(responseCode === Constants.ResponseCodes.Err){
|
|
this.onErrResponse(bufferReader);
|
|
} else if(responseCode === Constants.ResponseCodes.SelfInfo){
|
|
this.onSelfInfoResponse(bufferReader);
|
|
} else if(responseCode === Constants.ResponseCodes.CurrTime){
|
|
this.onCurrTimeResponse(bufferReader);
|
|
} else if(responseCode === Constants.ResponseCodes.NoMoreMessages){
|
|
this.onNoMoreMessagesResponse(bufferReader);
|
|
} else if(responseCode === Constants.ResponseCodes.ContactMsgRecv){
|
|
this.onContactMsgRecvResponse(bufferReader);
|
|
} else if(responseCode === Constants.ResponseCodes.ChannelMsgRecv){
|
|
this.onChannelMsgRecvResponse(bufferReader);
|
|
} else if(responseCode === Constants.ResponseCodes.ContactsStart){
|
|
this.onContactsStartResponse(bufferReader);
|
|
} else if(responseCode === Constants.ResponseCodes.Contact){
|
|
this.onContactResponse(bufferReader);
|
|
} else if(responseCode === Constants.ResponseCodes.EndOfContacts){
|
|
this.onEndOfContactsResponse(bufferReader);
|
|
} else if(responseCode === Constants.ResponseCodes.Sent){
|
|
this.onSentResponse(bufferReader);
|
|
} else if(responseCode === Constants.ResponseCodes.ExportContact){
|
|
this.onExportContactResponse(bufferReader);
|
|
} else if(responseCode === Constants.PushCodes.Advert){
|
|
this.onAdvertPush(bufferReader);
|
|
} else if(responseCode === Constants.PushCodes.PathUpdated){
|
|
this.onPathUpdatedPush(bufferReader);
|
|
} else if(responseCode === Constants.PushCodes.SendConfirmed){
|
|
this.onSendConfirmedPush(bufferReader);
|
|
} else if(responseCode === Constants.PushCodes.MsgWaiting){
|
|
this.onMsgWaitingPush(bufferReader);
|
|
} else {
|
|
console.log("unhandled frame", frame);
|
|
}
|
|
|
|
}
|
|
|
|
onAdvertPush(bufferReader) {
|
|
this.emit(Constants.PushCodes.Advert, {
|
|
publicKey: bufferReader.readBytes(32),
|
|
});
|
|
}
|
|
|
|
onPathUpdatedPush(bufferReader) {
|
|
this.emit(Constants.PushCodes.PathUpdated, {
|
|
publicKey: bufferReader.readBytes(32),
|
|
});
|
|
}
|
|
|
|
onSendConfirmedPush(bufferReader) {
|
|
this.emit(Constants.PushCodes.SendConfirmed, {
|
|
ackCode: bufferReader.readUInt32LE(),
|
|
roundTrip: bufferReader.readUInt32LE(),
|
|
});
|
|
}
|
|
|
|
onMsgWaitingPush(bufferReader) {
|
|
this.emit(Constants.PushCodes.MsgWaiting, {
|
|
|
|
});
|
|
}
|
|
|
|
onOkResponse(bufferReader) {
|
|
this.emit(Constants.ResponseCodes.Ok, {
|
|
|
|
});
|
|
}
|
|
|
|
onErrResponse(bufferReader) {
|
|
this.emit(Constants.ResponseCodes.Err, {
|
|
|
|
});
|
|
}
|
|
|
|
onContactsStartResponse(bufferReader) {
|
|
this.emit(Constants.ResponseCodes.ContactsStart, {
|
|
count: bufferReader.readUInt32LE(),
|
|
});
|
|
}
|
|
|
|
onContactResponse(bufferReader) {
|
|
this.emit(Constants.ResponseCodes.Contact, {
|
|
publicKey: bufferReader.readBytes(32),
|
|
type: bufferReader.readByte(),
|
|
flags: bufferReader.readByte(),
|
|
outPathLen: bufferReader.readInt8(),
|
|
outPath: bufferReader.readBytes(64),
|
|
advName: bufferReader.readCString(32),
|
|
lastAdvert: bufferReader.readUInt32LE(),
|
|
advLat: bufferReader.readUInt32LE(),
|
|
advLon: bufferReader.readUInt32LE(),
|
|
lastMod: bufferReader.readUInt32LE(),
|
|
});
|
|
}
|
|
|
|
onEndOfContactsResponse(bufferReader) {
|
|
this.emit(Constants.ResponseCodes.EndOfContacts, {
|
|
mostRecentLastmod: bufferReader.readUInt32LE(),
|
|
});
|
|
}
|
|
|
|
onSentResponse(bufferReader) {
|
|
this.emit(Constants.ResponseCodes.Sent, {
|
|
result: bufferReader.readInt8(),
|
|
expectedAckCrc: bufferReader.readUInt32LE(),
|
|
estTimeout: bufferReader.readUInt32LE(),
|
|
});
|
|
}
|
|
|
|
onExportContactResponse(bufferReader) {
|
|
this.emit(Constants.ResponseCodes.ExportContact, {
|
|
advertPacketBytes: bufferReader.readRemainingBytes(),
|
|
});
|
|
}
|
|
|
|
onSelfInfoResponse(bufferReader) {
|
|
this.emit(Constants.ResponseCodes.SelfInfo, {
|
|
type: bufferReader.readByte(),
|
|
txPower: bufferReader.readByte(),
|
|
maxTxPower: bufferReader.readByte(),
|
|
publicKey: bufferReader.readBytes(32),
|
|
advLat: bufferReader.readInt32LE(),
|
|
advLon: bufferReader.readInt32LE(),
|
|
reserved: bufferReader.readBytes(4),
|
|
radioFreq: bufferReader.readUInt32LE(),
|
|
radioBw: bufferReader.readUInt32LE(),
|
|
radioSf: bufferReader.readByte(),
|
|
radioCr: bufferReader.readByte(),
|
|
name: bufferReader.readString(),
|
|
});
|
|
}
|
|
|
|
onCurrTimeResponse(bufferReader) {
|
|
this.emit(Constants.ResponseCodes.CurrTime, {
|
|
epochSecs: bufferReader.readUInt32LE(),
|
|
});
|
|
}
|
|
|
|
onNoMoreMessagesResponse(bufferReader) {
|
|
this.emit(Constants.ResponseCodes.NoMoreMessages, {
|
|
|
|
});
|
|
}
|
|
|
|
onContactMsgRecvResponse(bufferReader) {
|
|
this.emit(Constants.ResponseCodes.ContactMsgRecv, {
|
|
pubKeyPrefix: bufferReader.readBytes(6),
|
|
pathLen: bufferReader.readByte(),
|
|
txtType: bufferReader.readByte(),
|
|
senderTimestamp: bufferReader.readUInt32LE(),
|
|
text: bufferReader.readString(),
|
|
});
|
|
}
|
|
|
|
onChannelMsgRecvResponse(bufferReader) {
|
|
this.emit(Constants.ResponseCodes.ChannelMsgRecv, {
|
|
channelIdx: bufferReader.readInt8(), // reserved (0 for now, ie. 'public')
|
|
pathLen: bufferReader.readByte(), // 0xFF if was sent direct, otherwise hop count for flood-mode
|
|
txtType: bufferReader.readByte(),
|
|
senderTimestamp: bufferReader.readUInt32LE(),
|
|
text: bufferReader.readString(),
|
|
});
|
|
}
|
|
|
|
getSelfInfo(timeoutMillis = null) {
|
|
return new Promise(async (resolve, reject) => {
|
|
|
|
// listen for response
|
|
this.once(Constants.ResponseCodes.SelfInfo, (selfInfo) => {
|
|
resolve(selfInfo);
|
|
});
|
|
|
|
// timeout after provided milliseconds if device did not respond
|
|
if(timeoutMillis != null){
|
|
setTimeout(reject, timeoutMillis);
|
|
}
|
|
|
|
// request self info
|
|
await this.sendCommandAppStart();
|
|
|
|
});
|
|
}
|
|
|
|
async sendAdvert(type) {
|
|
return new Promise(async (resolve, reject) => {
|
|
try {
|
|
|
|
// resolve promise when we receive ok
|
|
const onOk = () => {
|
|
this.off(Constants.ResponseCodes.Ok, onOk);
|
|
this.off(Constants.ResponseCodes.Err, onErr);
|
|
resolve();
|
|
}
|
|
|
|
// reject promise when we receive err
|
|
const onErr = () => {
|
|
this.off(Constants.ResponseCodes.Ok, onOk);
|
|
this.off(Constants.ResponseCodes.Err, onErr);
|
|
reject();
|
|
}
|
|
|
|
// listen for events
|
|
this.once(Constants.ResponseCodes.Ok, onOk);
|
|
this.once(Constants.ResponseCodes.Err, onErr);
|
|
|
|
// send advert
|
|
await this.sendCommandSendSelfAdvert(type);
|
|
|
|
} catch(e) {
|
|
reject(e);
|
|
}
|
|
});
|
|
}
|
|
|
|
async sendFloodAdvert() {
|
|
return await this.sendAdvert(Constants.SelfAdvertTypes.Flood);
|
|
}
|
|
|
|
async sendZeroHopAdvert() {
|
|
return await this.sendAdvert(Constants.SelfAdvertTypes.ZeroHop);
|
|
}
|
|
|
|
setAdvertName(name) {
|
|
return new Promise(async (resolve, reject) => {
|
|
try {
|
|
|
|
// resolve promise when we receive ok
|
|
const onOk = () => {
|
|
this.off(Constants.ResponseCodes.Ok, onOk);
|
|
this.off(Constants.ResponseCodes.Err, onErr);
|
|
resolve();
|
|
}
|
|
|
|
// reject promise when we receive err
|
|
const onErr = () => {
|
|
this.off(Constants.ResponseCodes.Ok, onOk);
|
|
this.off(Constants.ResponseCodes.Err, onErr);
|
|
reject();
|
|
}
|
|
|
|
// listen for events
|
|
this.once(Constants.ResponseCodes.Ok, onOk);
|
|
this.once(Constants.ResponseCodes.Err, onErr);
|
|
|
|
// set advert name
|
|
await this.sendCommandSetAdvertName(name);
|
|
|
|
} catch(e) {
|
|
reject(e);
|
|
}
|
|
});
|
|
}
|
|
|
|
setAdvertLatLong(latitude, longitude) {
|
|
return new Promise(async (resolve, reject) => {
|
|
try {
|
|
|
|
// resolve promise when we receive ok
|
|
const onOk = () => {
|
|
this.off(Constants.ResponseCodes.Ok, onOk);
|
|
this.off(Constants.ResponseCodes.Err, onErr);
|
|
resolve();
|
|
}
|
|
|
|
// reject promise when we receive err
|
|
const onErr = () => {
|
|
this.off(Constants.ResponseCodes.Ok, onOk);
|
|
this.off(Constants.ResponseCodes.Err, onErr);
|
|
reject();
|
|
}
|
|
|
|
// listen for events
|
|
this.once(Constants.ResponseCodes.Ok, onOk);
|
|
this.once(Constants.ResponseCodes.Err, onErr);
|
|
|
|
// set advert lat lon
|
|
await this.sendCommandSetAdvertLatLon(latitude, longitude);
|
|
|
|
} catch(e) {
|
|
reject(e);
|
|
}
|
|
});
|
|
}
|
|
|
|
setTxPower(txPower) {
|
|
return new Promise(async (resolve, reject) => {
|
|
try {
|
|
|
|
// resolve promise when we receive ok
|
|
const onOk = () => {
|
|
this.off(Constants.ResponseCodes.Ok, onOk);
|
|
this.off(Constants.ResponseCodes.Err, onErr);
|
|
resolve();
|
|
}
|
|
|
|
// reject promise when we receive err
|
|
const onErr = () => {
|
|
this.off(Constants.ResponseCodes.Ok, onOk);
|
|
this.off(Constants.ResponseCodes.Err, onErr);
|
|
reject();
|
|
}
|
|
|
|
// listen for events
|
|
this.once(Constants.ResponseCodes.Ok, onOk);
|
|
this.once(Constants.ResponseCodes.Err, onErr);
|
|
|
|
// set tx power
|
|
await this.sendCommandSetTxPower(txPower);
|
|
|
|
} catch(e) {
|
|
reject(e);
|
|
}
|
|
});
|
|
}
|
|
|
|
setRadioParams(radioFreq, radioBw, radioSf, radioCr) {
|
|
return new Promise(async (resolve, reject) => {
|
|
try {
|
|
|
|
// resolve promise when we receive ok
|
|
const onOk = () => {
|
|
this.off(Constants.ResponseCodes.Ok, onOk);
|
|
this.off(Constants.ResponseCodes.Err, onErr);
|
|
resolve();
|
|
}
|
|
|
|
// reject promise when we receive err
|
|
const onErr = () => {
|
|
this.off(Constants.ResponseCodes.Ok, onOk);
|
|
this.off(Constants.ResponseCodes.Err, onErr);
|
|
reject();
|
|
}
|
|
|
|
// listen for events
|
|
this.once(Constants.ResponseCodes.Ok, onOk);
|
|
this.once(Constants.ResponseCodes.Err, onErr);
|
|
|
|
// set tx power
|
|
await this.sendCommandSetRadioParams(radioFreq, radioBw, radioSf, radioCr);
|
|
|
|
} catch(e) {
|
|
reject(e);
|
|
}
|
|
});
|
|
}
|
|
|
|
getContacts() {
|
|
return new Promise(async (resolve, reject) => {
|
|
|
|
// add contacts we receive to a list
|
|
const contacts = [];
|
|
const onContactReceived = (contact) => {
|
|
contacts.push(contact);
|
|
}
|
|
|
|
// listen for contacts
|
|
this.on(Constants.ResponseCodes.Contact, onContactReceived);
|
|
|
|
// there's no more contacts to receive, stop listening and resolve the promise
|
|
this.once(Constants.ResponseCodes.EndOfContacts, () => {
|
|
this.off(Constants.ResponseCodes.Contact, onContactReceived);
|
|
resolve(contacts);
|
|
});
|
|
|
|
// request contacts from device
|
|
await this.sendCommandGetContacts();
|
|
|
|
});
|
|
}
|
|
|
|
sendTextMessage(contactPublicKey, text) {
|
|
return new Promise(async (resolve, reject) => {
|
|
try {
|
|
|
|
// resolve promise when we receive sent response
|
|
const onSent = (response) => {
|
|
this.off(Constants.ResponseCodes.Sent, onSent);
|
|
this.off(Constants.ResponseCodes.Err, onErr);
|
|
resolve(response);
|
|
}
|
|
|
|
// reject promise when we receive err
|
|
const onErr = () => {
|
|
this.off(Constants.ResponseCodes.Sent, onSent);
|
|
this.off(Constants.ResponseCodes.Err, onErr);
|
|
reject();
|
|
}
|
|
|
|
// listen for events
|
|
this.once(Constants.ResponseCodes.Sent, onSent);
|
|
this.once(Constants.ResponseCodes.Err, onErr);
|
|
|
|
// compose message
|
|
const txtType = Constants.TxtTypes.Plain;
|
|
const attempt = 0;
|
|
const senderTimestamp = Math.floor(Date.now() / 1000);
|
|
|
|
// send message
|
|
await this.sendCommandSendTxtMsg(txtType, attempt, senderTimestamp, contactPublicKey, text);
|
|
|
|
} catch(e) {
|
|
reject(e);
|
|
}
|
|
});
|
|
}
|
|
|
|
sendChannelTextMessage(channelIdx, text) {
|
|
return new Promise(async (resolve, reject) => {
|
|
try {
|
|
|
|
// resolve promise when we receive ok
|
|
const onOk = () => {
|
|
this.off(Constants.ResponseCodes.Ok, onOk);
|
|
this.off(Constants.ResponseCodes.Err, onErr);
|
|
resolve();
|
|
}
|
|
|
|
// reject promise when we receive err
|
|
const onErr = () => {
|
|
this.off(Constants.ResponseCodes.Ok, onOk);
|
|
this.off(Constants.ResponseCodes.Err, onErr);
|
|
reject();
|
|
}
|
|
|
|
// listen for events
|
|
this.once(Constants.ResponseCodes.Ok, onOk);
|
|
this.once(Constants.ResponseCodes.Err, onErr);
|
|
|
|
// compose message
|
|
const txtType = Constants.TxtTypes.Plain;
|
|
const senderTimestamp = Math.floor(Date.now() / 1000);
|
|
|
|
// send message
|
|
await this.sendCommandSendChannelTxtMsg(txtType, channelIdx, senderTimestamp, text);
|
|
|
|
} catch(e) {
|
|
reject(e);
|
|
}
|
|
});
|
|
}
|
|
|
|
syncNextMessage() {
|
|
return new Promise(async (resolve, reject) => {
|
|
|
|
// resolve promise when we receive a contact message
|
|
const onContactMessageReceived = (message) => {
|
|
this.off(Constants.ResponseCodes.ContactMsgRecv, onContactMessageReceived);
|
|
this.off(Constants.ResponseCodes.ChannelMsgRecv, onChannelMessageReceived);
|
|
this.off(Constants.ResponseCodes.NoMoreMessages, onNoMoreMessagesReceived);
|
|
resolve({
|
|
contactMessage: message,
|
|
});
|
|
}
|
|
|
|
// resolve promise when we receive a channel message
|
|
const onChannelMessageReceived = (message) => {
|
|
this.off(Constants.ResponseCodes.ContactMsgRecv, onContactMessageReceived);
|
|
this.off(Constants.ResponseCodes.ChannelMsgRecv, onChannelMessageReceived);
|
|
this.off(Constants.ResponseCodes.NoMoreMessages, onNoMoreMessagesReceived);
|
|
resolve({
|
|
channelMessage: message,
|
|
});
|
|
}
|
|
|
|
// resolve promise when we have no more messages to receive
|
|
const onNoMoreMessagesReceived = () => {
|
|
this.off(Constants.ResponseCodes.ContactMsgRecv, onContactMessageReceived);
|
|
this.off(Constants.ResponseCodes.ChannelMsgRecv, onChannelMessageReceived);
|
|
this.off(Constants.ResponseCodes.NoMoreMessages, onNoMoreMessagesReceived);
|
|
resolve(null);
|
|
}
|
|
|
|
// listen for events
|
|
this.once(Constants.ResponseCodes.ContactMsgRecv, onContactMessageReceived);
|
|
this.once(Constants.ResponseCodes.ChannelMsgRecv, onChannelMessageReceived);
|
|
this.once(Constants.ResponseCodes.NoMoreMessages, onNoMoreMessagesReceived);
|
|
|
|
// sync next message from device
|
|
await this.sendCommandSyncNextMessage();
|
|
|
|
});
|
|
}
|
|
|
|
getDeviceTime() {
|
|
return new Promise(async (resolve, reject) => {
|
|
try {
|
|
|
|
// resolve promise when we receive sent response
|
|
const onCurrTime = (response) => {
|
|
this.off(Constants.ResponseCodes.CurrTime, onCurrTime);
|
|
this.off(Constants.ResponseCodes.Err, onErr);
|
|
resolve(response);
|
|
}
|
|
|
|
// reject promise when we receive err
|
|
const onErr = () => {
|
|
this.off(Constants.ResponseCodes.CurrTime, onCurrTime);
|
|
this.off(Constants.ResponseCodes.Err, onErr);
|
|
reject();
|
|
}
|
|
|
|
// listen for events
|
|
this.once(Constants.ResponseCodes.CurrTime, onCurrTime);
|
|
this.once(Constants.ResponseCodes.Err, onErr);
|
|
|
|
// get device time
|
|
await this.sendCommandGetDeviceTime();
|
|
|
|
} catch(e) {
|
|
reject(e);
|
|
}
|
|
});
|
|
}
|
|
|
|
setDeviceTime(epochSecs) {
|
|
return new Promise(async (resolve, reject) => {
|
|
try {
|
|
|
|
// resolve promise when we receive ok
|
|
const onOk = (response) => {
|
|
this.off(Constants.ResponseCodes.Ok, onOk);
|
|
this.off(Constants.ResponseCodes.Err, onErr);
|
|
resolve(response);
|
|
}
|
|
|
|
// reject promise when we receive err
|
|
const onErr = () => {
|
|
this.off(Constants.ResponseCodes.Ok, onOk);
|
|
this.off(Constants.ResponseCodes.Err, onErr);
|
|
reject();
|
|
}
|
|
|
|
// listen for events
|
|
this.once(Constants.ResponseCodes.Ok, onOk);
|
|
this.once(Constants.ResponseCodes.Err, onErr);
|
|
|
|
// set device time
|
|
await this.sendCommandSetDeviceTime(epochSecs);
|
|
|
|
} catch(e) {
|
|
reject(e);
|
|
}
|
|
});
|
|
}
|
|
|
|
importContact(advertPacketBytes) {
|
|
return new Promise(async (resolve, reject) => {
|
|
try {
|
|
|
|
// resolve promise when we receive ok
|
|
const onOk = (response) => {
|
|
this.off(Constants.ResponseCodes.Ok, onOk);
|
|
this.off(Constants.ResponseCodes.Err, onErr);
|
|
resolve(response);
|
|
}
|
|
|
|
// reject promise when we receive err
|
|
const onErr = () => {
|
|
this.off(Constants.ResponseCodes.Ok, onOk);
|
|
this.off(Constants.ResponseCodes.Err, onErr);
|
|
reject();
|
|
}
|
|
|
|
// listen for events
|
|
this.once(Constants.ResponseCodes.Ok, onOk);
|
|
this.once(Constants.ResponseCodes.Err, onErr);
|
|
|
|
// import contact
|
|
await this.sendCommandImportContact(advertPacketBytes);
|
|
|
|
} catch(e) {
|
|
reject(e);
|
|
}
|
|
});
|
|
}
|
|
|
|
exportContact(pubKey = null) {
|
|
return new Promise(async (resolve, reject) => {
|
|
try {
|
|
|
|
// resolve promise when we receive export contact response
|
|
const onExportContact = (response) => {
|
|
this.off(Constants.ResponseCodes.ExportContact, onExportContact);
|
|
this.off(Constants.ResponseCodes.Err, onErr);
|
|
resolve(response);
|
|
}
|
|
|
|
// reject promise when we receive err
|
|
const onErr = () => {
|
|
this.off(Constants.ResponseCodes.ExportContact, onExportContact);
|
|
this.off(Constants.ResponseCodes.Err, onErr);
|
|
reject();
|
|
}
|
|
|
|
// listen for events
|
|
this.once(Constants.ResponseCodes.ExportContact, onExportContact);
|
|
this.once(Constants.ResponseCodes.Err, onErr);
|
|
|
|
// export contact
|
|
await this.sendCommandExportContact(pubKey);
|
|
|
|
} catch(e) {
|
|
reject(e);
|
|
}
|
|
});
|
|
}
|
|
|
|
removeContact(pubKey) {
|
|
return new Promise(async (resolve, reject) => {
|
|
try {
|
|
|
|
// resolve promise when we receive ok
|
|
const onOk = () => {
|
|
this.off(Constants.ResponseCodes.Ok, onOk);
|
|
this.off(Constants.ResponseCodes.Err, onErr);
|
|
resolve();
|
|
}
|
|
|
|
// reject promise when we receive err
|
|
const onErr = () => {
|
|
this.off(Constants.ResponseCodes.Ok, onOk);
|
|
this.off(Constants.ResponseCodes.Err, onErr);
|
|
reject();
|
|
}
|
|
|
|
// listen for events
|
|
this.once(Constants.ResponseCodes.Ok, onOk);
|
|
this.once(Constants.ResponseCodes.Err, onErr);
|
|
|
|
// remove contact
|
|
await this.sendCommandRemoveContact(pubKey);
|
|
|
|
} catch(e) {
|
|
reject(e);
|
|
}
|
|
});
|
|
}
|
|
|
|
}
|
|
|
|
export default Connection;
|