Set Bluetooth Listener on Tizen Wearable - javascript

I'm using Tizen's Wearable SDK to create a watch face, and while I am able to retrieve the Bluetooth's power state by using blueAdapter = tizen.bluetooth.getDefaultAdapter(); and bluetoothPowered = blueAdapter.powered;, I'd rather use a Bluetooth listener instead of constantly calling blueAdapter.powered.
The problem I'm having is that although I did a straight forward copy and paste of the sample code (although I did change the adapter's name, see below) from Tizen's Bluetooth API webpage, I'm getting the following error: 'undefined' is not a function (evaluating 'blueAdapter.setChangeListener(changeListener)').
This is the code I am using:
var blueAdapter = tizen.bluetooth.getDefaultAdapter();
var changeListener = {
onstatechanged: function(powered) {
console.log ("Power state is changed into: " + powered);
},
onnamechanged: function( name) {
console.log("Name is changed to: " + name);
},
onvisibilitychanged: function(visible) {
console.log("Visibility is changed into: " + visible);
}
};
blueAdapter.setChangeListener(changeListener);
Not sure if it helps, but I am using the following the privileges:
http://tizen.org/privilege/bluetooth.admin
http://tizen.org/privilege/bluetooth.gap
Any help would be appreciated.

Although it's been a while now, have you tried changing the syntax like below?
function changeListener(handler) {
handler.onstatechanged = function(powered) {
console.log ("Power state is changed into: " + powered);
}
handler.onnamechanged = function(name) {
console.log("Name is changed to: " + name);
}
handler.onvisibilitychanged = function(visible) {
console.log("Visibility is changed into: " + visible);
}
};
this replaces your listener object by a function, which should then declare the needed functions in the listener. It is just an idea, i did not test it yet.

Related

Capture an event and re-emit with modification using EventEmitter2

I am using the ROS JavaScript Library (CDN) which uses EventEmitter2 (CDN) to listen to a topic. Please see the following code snippet:
var ros = new ROSLIB.Ros({ url: "ws://localhost:9090" });
class Subscriber extends EventEmitter2 {
constructor(element) {
super();
this.element = element;
this.listener = new ROSLIB.Topic({
ros: ros,
name: "/listener",
messageType: "std_msgs/String",
});
this.listener.subscribe(this.handleCallback);
}
handleCallback(message) {
this.emit("update", message.data, this.element);
// just for debugging. access a property of our element
console.log("callback" + message.data + " " + this.element.innerHTML);
}
}
Upon receiving a message, an event is fired which is handled by the handleCallback. Here, using console.log("callback" + message.data), the message (string) is visible.
My goal is to receive the new callback as shown below:
var element = document.getElementById("hello");
var subscriber = new Subscriber(element);
subscriber.on("update", (data, element) => {
console.log("received" + data + " " + element.innerHTML);
});
However, there are two problems mentioned below:
Accessing the element using this.element is throwing the following error:
Uncaught TypeError: Cannot read properties of undefined (reading 'innerHTML')
To avoid the above error temporarily, I removed it from the emit call as this.emit("update", message.data) but no success. Furthermore, I used this.emit("update", "my static message") but didn't receive a callback.

eventDrop, oldResource and newResource in fullcalendar scheduler v4

I'm trying to eventually create a php script to update mysql. As I go step by step and try to set the variables and have js behave correctly, I'm having difficulty with changing the 'resource' rooms in the scheduler.
If I change the location of the event and change the room, I get a JS alert saying "Title was dropped on to [new time] from [old time]. Old room [oldresource]. New Room [newresource]". That's working well.
However, if I move the event to a location on the same day, I get errors - because info.oldResource and info.newResource are only available IF the event has moved to a NEW resource. If they're moving within the same resource, the object doesn't exist.
I tried working in an IF statement. Console Log shows null, but my if statement is not stopping the processing of the rest of the code. This will eventually (I think) result in the commands not being run correctly - once I pass them to PHP.
I plan on having an 'else' statement that does not include oldResource or newResource dialogue to process changes that stay within the same resource.
My code is as such:
eventDrop: function(info) {
if (typeof info.oldResource !=="null") {
var oll = console.log(info.oldResource);
var nww = console.log(info.newResource);
var oldroom = (info.oldResource.id);
var newroom = (info.newResource.id);
var newtitle = info.event.title;
/*if (oldroom = newroom) {alert ("Same Room");}*/
alert(newtitle + " was dropped on " + info.event.start.toString() + ".Old Time: " + info.oldEvent.start.toString() + ". From: " + oldroom + ". To: " + newroom );
if (!confirm("Are you sure about this change?")) {
info.revert();
}}
},
You don't need typeof here. Just write
if (info.oldResource != null)
instead.
P.s. if you call typeof on a property that's set to null I would expect the typeof call to return "object", not "null". But like I said, it's irrelevant because you don't need it. Just check for the value null directly.

Overriding Console.log

Sup guys, big wall of code incoming
function assertObjectsEqual(actual, expected, testName) {
actual = JSON.stringify(actual);
expected = JSON.stringify(expected);
if ( actual === expected ) {
console.log('PASSED [' + testName + ']');
} else {
console.log('FAILED [' + testName + '], expected "' + expected + '", but got "' + actual + '"')
}
}
/////////////////////////////////
// Tests for "assertObjectsEqual"
/////////////////////////////////
// Note: testing assertion functions is a bit of "Inception"...
// You have to use an assert to test your other assert.
// And since the output is console-logged, you have to trap that too.
// Hence I don't think it's reasonable to expect students to do the negative test on these.
// I think it's sufficient for students to just console log what these assertions do in the failure cases
// and move on...
// But just for illustration, here it is:
function assert(actual, testName) {
if ( actual !== true ) {
console.log('FAILED [' + testName + '] Expected "' + expected + '" to be true.');
} else {
console.log('PASSED [' + testName + ']');
}
}
function testFailureCaseAssertObjectsEqual() {
var objectA = {a: 1};
var objectB = {b: 2};
var originalConsoleLog = console.log; // we're going to override console logger to be able to trap messages.
var trappedMsg;
console.log = function(msg) {
trappedMsg = msg; // trap the message via a closure
}
assertObjectsEqual(objectA, objectB);
console.log = originalConsoleLog; // restore the mocked logger before doing our real assertion
assert(trappedMsg.includes('FAILED'), 'should fail when given two different objects');
}
testFailureCaseAssertObjectsEqual();
So I'm studying to take the Hack Reactor entrance exam and I'm on module 2 right now, which focuses on testing functions. This is a reference solution for applying an assertObjectsEqual testing function. What I'm confused about is in the testFailureCaseAssertObjectsEqual function lines:
var originalConsoleLog = console.log; // we're going to override console logger to be able to trap messages.
var trappedMsg;
console.log = function(msg) {
trappedMsg = msg; // trap the message via a closure
}
assertObjectsEqual(objectA, objectB);
console.log = originalConsoleLog;
I don't really understand what's happening here. What does overriding the console logger to trap messages mean and why do we do it? Also how does the code above accomplish that? Sorry if my post contains a lot of unnecessary info, idk what is and isn't directly relevant to my question so I included all of it. Thank you for taking the time.
They are wanting to intercept the first argument of console.log temporarily for this one use case and not have it printed to console
This is accomplished by storing a reference to original function and assigning a different function to console.log.
Then after they are done - make console.log do what it is normally supposed to do by reassigning the original function to it again
Following simplified demo and comments should help understand process better
function doLog(msg){
console.log(msg)
}
function myTest() {
// store reference to console.log function
var originalConsoleLog = console.log;
// temporarily make console.log do something different than logging to console
// by assigning new function to it
console.log = function(msg) {
alert('Intercepted: ' + msg)
}
// anywhere in here if console.log gets used it will do above alert
doLog('First message');/* log gets called inside this function so will alert instead*/
console.log('Second message');/* will also alert and not print in console */
// override finished, return it to do what it normally does
// by reassigning it's own original function
console.log = originalConsoleLog;
// use console.log again and it will do what it normally does
doLog('Third message should appear normally in console')
}
myTest();
// proceed as if nothing was ever different
doLog('Forth message - back to normal')

log object in log4javascript

I want to log objects using log4javascript. For example consider the following code:
function LogObject() {
var blah = {
one: 42,
two: "486"
};
logger.Info(blah);
Assuming that logger is instance of log4javascript logger that is properly set up:
var logger = log4javascript.getLogger("InternalLogger");
var ajaxAppender = new log4javascript.AjaxAppender(url),
jsonLayout = new log4javascript.JsonLayout(false, false);
ajaxAppender.setLayout(jsonLayout);
ajaxAppender.addHeader("Content-Type", "application/json");
logger.addAppender(ajaxAppender);
I am expecting the result to the following: request payload contains array of messages first of which is my object serialized into JSON. What I see is array of messages first of which has string "Object object" (like toString() method was invoked). How can I achieve that?
JsonLayout formats the logging event (which includes log level, timestamp and logger name in addition to the log message(s)) as JSON rather than the log message, which is pretty much assumed to be a string. The reason for this is to avoid a dependency on a JSON library for older browsers; generating JSON for the simple, known data that JsonLayout deals with is no problem without a JSON library but handling arbitrary objects definitely requires one.
The workaround I'd suggest is simply to format the message before you pass it to the logging call:
logger.info( JSON.stringify(blah) );
We were following #Tim Down's suggestion
logger.info( JSON.stringify(blah) );
But we had performance issues since the JSON.stringify happens before logger.info is called, therefore it will always happen even if the logging level is set to ignore this log.
In order to work around this I wrote a new lazy layout so that the stringification only happens if the log is actually output. In order to be more flexible it also alows passing a function, in which case it outputs the result of running said function.
Usage:
logger.trace("Received ", widget, " which has ", () => countFrimbles(widget), ' frimbles');
Implementation:
function LazyFormatLayout() { }
LazyFormatLayout.prototype = new log4javascript.Layout();
LazyFormatLayout.prototype.format = function (loggingEvent) {
var time = loggingEvent.timeStamp.toTimeString().split(/\s/)[0];
var head = time + ' ' + loggingEvent.logger.name + ' [' + loggingEvent.level.name + '] - ';
var body = loggingEvent.messages.map(function (arg) {
try {
switch (typeof (arg)) {
case 'function':
return arg();
case 'object':
return JSON.stringify(arg);
}
}
catch (e) {
return '<<error while logging: ' + e.stack + '>>';
}
return arg;
}).join('');
if (!loggingEvent.exception)
return head + body;
return head + body + ' ==> Exception: ' + loggingEvent.exception.stack;
}
LazyFormatLayout.prototype.ignoresThrowable = function () { return false; };
LazyFormatLayout.prototype.toString = function () { return "LazyFormatLayout"; };
Question is somewhat dated, but a simple google search turned up this question and there seems to be a build-in way to log objects:
var log = log4javascript.getDefaultLogger();
log.info("log following object",{ data:5, text:"bla" });
output
12:49:43 INFO - log following object {
data: 5,
text: bla
}

Hot Code Push NodeJS

I've been trying to figure out this "Hot Code Push" on Node.js. Basically, my main file (that is run when you type node app.js) consists of some settings, configurations, and initializations. In that file I have a file watcher, using chokidar. When I file has been added, I simply require the file. If a file has been changed or updated I would delete the cache delete require.cache[path] and then re-require it. All these modules don't export anything, it just works with the single global Storm object.
Storm.watch = function() {
var chokidar, directories, self = this;
chokidar = require('chokidar');
directories = ['server/', 'app/server', 'app/server/config', 'public'];
clientPath = new RegExp(_.regexpEscape(path.join('app', 'client')));
watcher = chokidar.watch(directories, {
ignored: function(_path) {
if (_path.match(/\./)) {
!_path.match(/\.(js|coffee|iced|styl)$/);
} else {
!_path.match(/(app|config|public)/);
}
},
persistent: true
});
watcher.on('add', function(_path){
self.fileCreated(path.resolve(Storm.root, _path));
//Storm.logger.log(Storm.cliColor.green("File Added: ", _path));
//_console.info("File Updated");
console.log(Storm.css.compile(' {name}: {file}', "" +
"name" +
"{" +
"color: white;" +
"font-weight:bold;" +
"}" +
"hr {" +
"background: grey" +
"}")({name: "File Added", file: _path.replace(Storm.root, ""), hr: "=================================================="}));
});
watcher.on('change', function(_path){
_path = path.resolve(Storm.root, _path);
if (fs.existsSync(_path)) {
if (_path.match(/\.styl$/)) {
self.clientFileUpdated(_path);
} else {
self.fileUpdated(_path);
}
} else {
self.fileDeleted(_path);
}
//Storm.logger.log(Storm.cliColor.green("File Changed: ", _path));
console.log(Storm.css.compile(' {name}: {file}', "" +
"name" +
"{" +
"color: yellow;" +
"font-weight:bold;" +
"}" +
"hr {" +
"background: grey" +
"}")({name: "File Changed", file: _path.replace(Storm.root, ""), hr: "=================================================="}));
});
watcher.on('unlink', function(_path){
self.fileDeleted(path.resolve(Storm.root, _path));
//Storm.logger.log(Storm.cliColor.green("File Deleted: ", _path));
console.log(Storm.css.compile(' {name}: {file}', "" +
"name" +
"{" +
"color: red;" +
"font-weight:bold;" +
"}" +
"hr {" +
"background: grey" +
"}")({name: "File Deleted", file: _path.replace(Storm.root, ""), hr: "=================================================="}));
});
watcher.on('error', function(error){
console.log(error);
});
};
Storm.watch.prototype.fileCreated = function(_path) {
if (_path.match('views')) {
return;
}
try {
require.resolve(_path);
} catch (error) {
require(_path);
}
};
Storm.watch.prototype.fileDeleted = function(_path) {
delete require.cache[require.resolve(_path)];
};
Storm.watch.prototype.fileUpdated = function(_path) {
var self = this;
pattern = function(string) {
return new RegExp(_.regexpEscape(string));
};
if (_path.match(pattern(path.join('app', 'templates')))) {
Storm.View.cache = {};
} else if (_path.match(pattern(path.join('app', 'helpers')))) {
self.reloadPath(path, function(){
self.reloadPaths(path.join(Storm.root, 'app', 'controllers'));
});
} else if (_path.match(pattern(path.join('config', 'assets.coffee')))) {
self.reloadPath(_path, function(error, config) {
//Storm.config.assets = config || {};
});
} else if (_path.match(/app\/server\/(models|controllers)\/.+\.(?:coffee|js|iced)/)) {
var isController, directory, klassName, klass;
self.reloadPath(_path, function(error, config) {
if (error) {
throw new Error(error);
}
});
Storm.serverRefresh();
isController = RegExp.$1 == 'controllers';
directory = 'app/' + RegExp.$1;
klassName = _path.split('/');
klassName = klassName[klassName.length - 1];
klassName = klassName.split('.');
klassName.pop();
klassName = klassName.join('.');
klassName = _.camelize(klassName);
if (!klass) {
require(_path);
} else {
console.log(_path);
self.reloadPath(_path)
}
} else if (_path.match(/config\/routes\.(?:coffee|js|iced)/)) {
self.reloadPath(_path);
} else {
this.reloadPath(_path);
}
};
Storm.watch.prototype.reloadPath = function(_path, cb) {
_path = require.resolve(path.resolve(Storm.root, path.relative(Storm.root, _path)));
delete require.cache[_path];
delete require.cache[path.resolve(path.join(Storm.root, "server", "application", "server.js"))];
//console.log(require.cache[path.resolve(path.join(Storm.root, "server", "application", "server.js"))]);
require("./server.js");
Storm.App.use(Storm.router);
process.nextTick(function(){
Storm.serverRefresh();
var result = require(_path);
if (cb) {
cb(null, result);
}
});
};
Storm.watch.prototype.reloadPaths = function(directory, cb) {
};
Some of the code is incomplete / not used as I'm trying a lot of different methods.
What's Working:
For code like the following:
function run() {
console.log(123);
}
Works perfectly. But any asynchronous code fails to update.
Problem = Asynchronous Code
app.get('/', function(req, res){
// code here..
});
If I then update the file when the nodejs process is running, nothing happens, though it goes through the file watcher and the cache is deleted, then re-established. Another instance where it doesn't work is:
// middleware.js
function hello(req, res, next) {
// code here...
}
// another file:
app.use(hello);
As app.use would still be using the old version of that method.
Question:
How could I fix the problem? Is there something I'm missing?
Please don't throw suggestions to use 3rd party modules like forever. I'm trying to incorporate the functionality within the single instance.
EDIT:
After studying meteors codebase (there's surprisingly little resources on "Hot Code Push" in node.js or browser.) and tinkering around with my own implementation I've successfully made a working solution. https://github.com/TheHydroImpulse/Refresh.js . This is still at an early stage of development, but it seems solid right now. I'll be implementing a browser solution too, just for sake of completion.
Deleting require's cache doesn't actually "unload" your old code, nor does it undo what that code did.
Take for example the following function:
var callbacks=[];
registerCallback = function(cb) {
callbacks.push(cb);
};
Now let's say you have a module that calls that global function.
registerCallback(function() { console.log('foo'); });
After your app starts up, callbacks will have one item. Now we'll modify the module.
registerCallback(function() { console.log('bar'); });
Your 'hot patching' code runs, deletes the require.cached version and re-loads the module.
What you must realize is that now callbacks has two items. First, it has a reference to the function that logs foo (which was added on app startup) and a reference to the function that logs bar (which was just added).
Even though you deleted the cached reference to the module's exports, you can't actually delete the module. As far as the JavaScript runtime is concerned, you simply removed one reference out of many. Any other part of your application can still be hanging on to a reference to something in the old module.
This is exactly what is happening with your HTTP app. When the app first starts up, your modules attach anonymous callbacks to routes. When you modify those modules, they attach a new callback to the same routes; the old callbacks are not deleted. I'm guessing that you're using Express, and it calls route handlers in the order they were added. Thus, the new callback never gets a chance to run.
To be honest, I wouldn't use this approach to reloading you app on modification. Most people write app initialization code under the assumption of a clean environment; you're violating that assumption by running initialization code in a dirty environment – that is, one which is already up and running.
Trying to clean up the environment to allow your initialization code to run is almost certainly more trouble than it's worth. I'd simply restart the entire app when your underlying files have changed.
Meteor solves this problem by allowing modules to "register" themselves as part of the hot code push process.
They implement this in their reload package:
https://github.com/meteor/meteor/blob/master/packages/reload/reload.js#L105-L109
I've seen that Meteor.reload API used in some plugins on GitHub, but they also use it in the session package:
https://github.com/meteor/meteor/blob/master/packages/session/session.js#L103-L115
if (Meteor._reload) {
Meteor._reload.onMigrate('session', function () {
return [true, {keys: Session.keys}];
});
(function () {
var migrationData = Meteor._reload.migrationData('session');
if (migrationData && migrationData.keys) {
Session.keys = migrationData.keys;
}
})();
}
So basically, when the page/window loads, meteor runs a "migration", and it's up to the package to define the data/methods/etc. that get recomputed when a hot code push is made.
It's also being used by their livedata package (search reload).
Between refreshes they're saving the "state" using window.sessionStorage.

Categories

Resources