node-enocean-ts
Version:
Typescript full implementation of the enocean protocol (ESP3 + EEP2.6)
289 lines (277 loc) • 13.9 kB
JavaScript
;
// This file is part of node-enocean.
Object.defineProperty(exports, "__esModule", { value: true });
// node-enocean. is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// node-enocean. is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with node-enocean. If not, see <http://www.gnu.org/licenses/>.
// # memory implementation.
// this module implements saving and deleting sensors as well as hanbling telegrams from known sensor
// this implementation uses the fiesystem to stor sensor info
var db = undefined;
var EnoceanSensor = undefined;
function getEEP(rorg, rorg_func, rorg_type) {
return (rorg + "-" + rorg_func + "-" + rorg_type).toLowerCase();
}
function getByte(telegram_byte_str, index) {
return telegram_byte_str[index * 2] + telegram_byte_str[index * 2 + 1];
}
class Memory {
constructor(emitters) {
this.emitters = emitters;
this.timerId = null;
this.learnMode = "on";
this.forgetMode = "off";
this.timeout = 30;
}
connect(mongo_path) {
/*mongoose.connect(mongo_path);
db = mongoose.connection;
db.on("error", function(err) {
console.error.bind(console, 'connection error:');
});
db.once('open', function() {
console.log("connection ok");
var EnoceanSensorScheme = mongoose.Schema({
id: String,
eep: String,
manufacturer: String,
title: String,
desc: String,
eepFunc: String,
eepType: String
});
EnoceanSensor = mongoose.model('EnoceanSensor', EnoceanSensorScheme);
app.emitters.forEach( function( emitter ) {
emitter.emit( "sensor-db-open" , {});
});
});
*/
}
/*app.on( "data" , function( data ) {
console.log("having data", data);
EnoceanSensor && EnoceanSensor.findOne({ id: data.senderId }, function (err, sensor) {
if( sensor != undefined) {
if( data.learnBit === 1 || data.choice === "f6" || data.choice === "d1") {
// but only if it is not a learn Telegram (learnBit==1)
data.sensor = sensor // attach that info to the telegram data
data.values = app.getData( sensor.eep , data.raw ) // actually extract the Data
//was also saving last data in db but removed it, useful?
app.emitters.forEach(function(emitter){
emitter.emit("known-data",data) // and emmit an event propagating the extracted Data downstream
} )
} else {
// if it is a learn telegram, check if we are in "teach in"-mode
if( app.learnMode === "on" ) {
// we are in teach in mode
// And we have just received a "tech in" telegram...
// but we allready know this sensor
app.learnMode = "off" // turn of "teach in"-mode to prevent unwanted sensors to be tought in accedently
app.emitters.forEach( function( emitter ) {
emitter.emit( "learn-mode-stop" , { code : 1 , reason : "already known sensor" } ) // tell everyone that we stop the "teach-in"-mode
} )
}
if( app.forgetMode === "on" ) {
// we are in forget mode, and we received a "teach-in" telegram of a known sensor
// this indicates that it should be forgotten.
app.forget( data.senderId ) // delete the sensor
}
}
if( app.forgetMode === "on" && data.choice === "f6" ) {
// we are in forget mode, and we received an RPS telegram form a known sensor
// but the learnBit is not set, as RPS telegramns don't have learnBits...
// this indicates that it should be forgotten.
app.forget( data.senderId ) // delete the sensor
}
} else {
// ???? we don't know this sensor ???
if( data.learnBit === 0 ) {
// but it's a "teach in"-telegram, so it wants to tell us about itself
if( app.learnMode === "on" ) {
// we are in learnMode, so extract the sensor info frm the telegram
// and save that info
if(data.choice==="d5") data.eep="d5-00-01" //its a 1BS Telegram there is currently only 1 defined so assume d5-00-01
app.learn( {
id : data.senderId,
eep : data.eep,
manufacturer : data.manufacturer,
title : "New " + app.eepDesc[data.eep.substring(0,5)], // give it some name
desc : "I'm a new sensor...", // and some description
eepFunc : app.eepDesc[data.eep.substring(0,5)], // finde the func description of the eep
eepType : app.eepDesc[data.eep] // find the Type description of the eep
} )
} else {
// we are not in teach in mode, but this is a "tech in" telegram
if(data.choice !== "f6" ) {
// "RPS" telegrams do not have a lernBit. depending on the Data Byte sometimes the Bit used for indicating "teach-in"-telegrams is set
// prevent false positives
app.emitters.forEach( function( emitter ) {
emitter.emit( "unknown-teach-in" , data ) // tell everyone we received an unknown "teach-in"
} )
}
}
} else {
// we don't know the sender and the leranBit is not set
if( data.choice === "f6" && app.learnMode === "on" ) {
// but this is an "RPS" signal ( remeber RPS don't have learn bits ), and we are in teach in mode
// so treat every RPS received during teach in a a request to be tought in
// do so...
app.learn( {
id : data.senderId,
eep : "f6-02-03",
manufacturer : "unknown",
title : "New RPS Switch", // give it some name
desc : "I'm a new sensor...", // and some description
eepFunc : app.eepDesc["f6-02"], // finde the func description of the eep
eepType : app.eepDesc["f6-02-03"] // find the Type description of the eep
} )
} else {
// we are not in learnMode and the sensor of this telegram is not known.
// neither is this a learn telegram.
//retrieve eep to be sure about the device
var rorg = getByte(data.rawByte, 6);
var rorg_func = getByte(data.rawByte, 6 + 6);
var rorg_type = getByte(data.rawByte, 6 + 7);
var eep = getEEP(rorg, rorg_func, rorg_type);
var format = app.getData(eep, data.raw);
if(format == undefined || (format.length == 0 && format[0].type == "unknown")) {
app.emitters.forEach( function( emitter ){
emitter.emit( "unknown-data" , data ) // just tell everyone we received something, but we don't know what to do with it
} )
}else{
console.log("no device found but eep seems correct, no need", eep);
}
}
}
}
});
})
*/
startLearning() {
// start learnMode ("tech-in"-mode)
// the learn mode is here to automaticly learn sensors that send a teach in telegram
this.learnMode = "on";
this.emitters.forEach(function (emitter) {
emitter.emit("learn-mode-start", { timeout: this.timeout }); // propagete that we are ready to learn
});
this.timerId = setTimeout(() => this.stopLearning(), this.timeout * 1000); // make sure we stop learning after timeout
}
stopLearning() {
// stop learnMode
if (this.learnMode == "on") {
// but only if we are still in leranMode
this.learnMode = " off";
this.timerId && clearTimeout(this.timerId);
this.emitters.forEach(function (emitter) {
emitter.emit("learn-mode-stop", { code: 2, reason: "timeout" }); // tell everyone we are not in teach in anymore
});
}
}
startForgetting() {
// start the forget mode
// this is used to delete single sensors, through its teach in telegram.
this.forgetMode = "on";
this.emitters.forEach(function (emitter) {
emitter.emit("forget-mode-start", { timeout: this.timeout }); // tell everyone we are in forget-mode
});
this.timerId = setTimeout(() => this.stopForgetting(), this.timeout * 1000); // make sure we leave stop mode after timeout
}
stopForgetting() {
// stop forget Mode
if (this.forgetMode == "on") {
// but only if we are in forget Mode
this.forgetMode = "off";
this.timerId && clearTimeout(this.timerId);
this.emitters.forEach(function (emitter) {
emitter.emit("forget-mode-stop", { code: 2, reason: "timeout" }); // tell everyone we are not in forget mode anymore
});
}
}
learn(sensor) {
// actually learn a sensor.
// this function can be call from anywhwere.
// the sensor object should have the following fileds: id,eep,manufacturer,title,desc
// this can be used to update sensor info like desc and title...
if (!EnoceanSensor)
return;
/*
var sensor_db = new EnoceanSensor(sensor); //the object is a proper json
sensor_db.save(function (err, user) {
app.learnMode = "off" // stop the learnMode in any case
clearTimeout(this.timerId)
app.emitters.forEach( function( emitter ) {
emitter.emit( "learn-mode-stop" , { code : 0 , reason : "success" } ) // tell everyone we are not in learn mode anymore
} )
if(err === undefined) {
// the file was successfully saved
app.emitters.forEach( function( emitter ) {
emitter.emit( "learned" , sensor ) // let's tell everyone we where successfull attach the sensor info of the sensor we just saved
});
}else{
app.emitters.forEach( function( emitter ) {
emitter.emit( "learn-error" , { err : err, reason: "error saving sensor file to disk" } ) // there was an error saving the file
});
}
});
*/
}
forget(id) {
/*
EnoceanSensor && EnoceanSensor.findOneAndRemove({ id: id }, function (err, sensor) {
app.forgetMode="off" // stop forget Mode
clearTimeout(this.timerId);
app.emitters.forEach( function( emitter ) {
emitter.emit( "forget-mode-stop" , { code : 0 , reason:"success"} ) // and tell the "world" we stoped forget mode
});
if( err === undefined) {
app.emitters.forEach(function(emitter){
emitter.emit("forgotten",tmp) // let's tell everyone we where successfull, attach the sensor info of the just deleted sensor
});
} else {
app.emitters.forEach( function( emitter ) {
emitter.emit( "forget-error" , { err : err, reason: "error saving sensor file to disk" } ) // there was an error saving the file
});
}
});
*/
}
info(id, callback) {
callback(undefined);
/*if(!EnoceanSensor) {
callback(undefined);
return;
}
EnoceanSensor.findOne({ id: id }, function (err, sensor) {
callback(sensor);
});*/
}
getLastValues(id) {
return getLastData(id);
}
getSensors(callback) {
callback([]);
/*if(!EnoceanSensor) {
callback([]);
return;
}
EnoceanSensor.find({}, function(err, sensors) {
callback(sensors);
});*/
}
}
exports.default = Memory;
function getLastData(id) {
return new Promise(function (resolve, reject) {
reject("no data");
//db.get(id,function(err,value){
// if(err){reject(err)}else{resolve(value)}
//})
});
}
//# sourceMappingURL=memory.js.map