i am new in express.js, i´ve only built some small client/server apps.
Now i want to create a temperature-controller with a PID-component. I don´t understand the architecture of express.js enough to decide where to place what.
I have a router to get the targetvalue from my Web-Client - that works. And
I have a router to get the current temperature-value. And third have a router to control the heatingelement.
Now i need somewhat of a loop, in which for every some seconds i can compare this values and calculate my output-value and send that value to my heatingelement.
Where to place what?
Greets, Freisei.
In Javascript you don't use a loop for this kind of thing, you use an Interval, set up with setInterval().
function doTheControlOperation() {
const setPoint = //get the temp set point
const current = //get the most recent temperature reading
const diff = current - setPoint
if (diff < 0) // turn on the element
else // turn off the element
}
var howOften = 10000 //ten seconds in milliseconds
setInterval (doTheControlOperation, howOften)
This code calls doTheControlOperation() every ten seconds.
I'm sure you know this kind of control system usually contains some hysteresis and protection against short-cycling. My example doesn't do any of that, obviously.
Related
I've been trying to figure this out for the past day or two with minimal results. Essentially what I want to do is send my selected comps in After Effects to Adobe Media Encoder via script, and using information about them (substrings of their comp name, width, etc - all of which I already have known and figured out), and specify the appropriate AME preset based on the conditions met. The current two methods that I've found won't work for what I'm trying to do:
https://www.youtube.com/watch?v=K8_KWS3Gs80
https://blogs.adobe.com/creativecloud/new-changed-after-effects-cc-2014/?segment=dva
Both of these options more or less rely on the output module/render queue, (with the first option allowing sending it to AME without specifying preset) which, at least to my knowledge, won't allow h.264 file-types anymore (unless you can somehow trick render queue with a created set of settings prior to pushing queue to AME?).
Another option that I've found involves using BridgeTalk to bypass the output module/render queue and go directly to AME...BUT, that primarily involves specifying a file (rather than the currently selected comps), and requires ONLY having a single comp (to be rendered) at the root level of the project: https://community.adobe.com/t5/after-effects/app-project-renderqueue-queueiname-true/td-p/10551189?page=1
Now as far as code goes, here's the relevant, non-working portion of code:
function render_comps(){
var mySelectedItems = [];
for (var i = 1; i <= app.project.numItems; i++){
if (app.project.item(i).selected)
mySelectedItems[mySelectedItems.length] = app.project.item(i);
}
for (var i = 0; i < mySelectedItems.length; i++){
var mySelection = mySelectedItems[i];
//~ front = app.getFrontend();
//~ front.addItemToBatch(mySelection);
//~ enc = eHost.createEncoderForFormat("H.264");
//~ flag = enc.loadPreset("HD 1080i 25");
//app.getFrontend().addItemToBatch(mySelection);
var bt = new BridgeTalk();
bt.appName = "ame";
bt.target = "ame";
//var message = "alert('Hello')";
//bt.body = message;
bt.body="app.getFrontend().addCompToBatch(mySelection)";
bt.send();
}
}
Which encapsulates a number of different attempts and things that I've tried.
I've spent about 4-5 hours trying to scour the internet and various resources but so far have come up short. Thanks in advance for the help!
I have a Google Spreadsheet with internal AppsScript code which process each row of the sheet and perform an urlfetch with the row data. The url will provide a value which will be added to the values returned by each row processing..
For now the code is processing 1 row at a time with a simple for:
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadsheet.getActiveSheet();
var range = sheet.getDataRange();
for(var i=1 ; i<range.getValues().length ; i++) {
var payload = {
// retrieve data from the row and make payload object
};
var options = {
"method":"POST",
"payload" : payload
};
var result = UrlFetchApp.fetch("http://.......", options);
var text = result.getContentText();
// Save result for final processing
// (with multi-thread function this value will be the return of the function)
}
Please note that this is only a simple example, in the real case the working function will be more complex (like 5-6 http calls, where the output of some of them are used as input to the next one, ...).
For the example let's say that there is a generic "function" which executes some sort of processing and provides a result as output.
In order to speed up the process, I'd like to try to implement some sort of "multi-thread" processing, so I can process multiple rows in the same time.
I already know that javascript does not offer a multi-thread handling, but I read about WebWorker which seems to create an async processing of a function.
My goal is to obtain some sort of ThreadPool (like 5 threads at a time) and send every row that need to be processed to the pool, obtaining as output the result of each function.
When all the rows finished the processing, a final action will be performed gathering all the results of each function.
So the capabilities I'm looking for are:
managed "ThreadPool" where I can submit an N amount of tasks to be performed
possibility to obtain a resulting value from each task processed by the pool
possibility to determine that all the tasks has been processed, so a final "event" can be executed
I already see that there are some ready-to-use libraries like:
https://www.hamsters.io/wiki#thread-pool
http://threadsjs.readthedocs.io/en/latest/
https://github.com/andywer/threadpool-js
but they work with NodeJS. Due to AppsScript nature, I need a more simplier approach, which is provided by native JS. Also, it seems that minified JS are not accepted by AppsScript editor, so I also need the "expanded" version.
Do you know a simple ThreadPool in JS where I can submit a function to be execute and I get back a Promise for the result?
This question already has answers here:
Sync JS time between multiple devices
(5 answers)
Closed 5 years ago.
On my server I call two emits at the same time, which looks like this.
if (songs.length > 0) {
socket.emit('data loaded', songs);
socket.broadcast.to(opponent).emit('data loaded', songs);
}
The one is for opponent and the other for himself.
Once the data is loaded a countdown should appear for both players on my android app. For me it is important that they see the same number at the same time on their screen. To be precise it should run synchronized. How can I do this?
As far as js timers are concerned the will be a small amount of difference. We can reduce the difference in time with reduce of latency time, with the difference between the request and response time from the server.
function syncTime() {
console.log("syncing time")
var currentTime = (new Date).getTime();
res.open('HEAD', document.location, false);
res.onreadystatechange = function()
{
var latency = (new Date).getTime() - currentTime;
var timestring = res.getResponseHeader("DATE");
systemtime = new Date(timestring);
systemtime.setMilliseconds(systemtime.getMilliseconds() + (latency / 2))
};
res.send(null);
}
Elapsed time between sending the request and getting back the response need to be calculated, divide that value by 2. That gives you a rough value of latency. If you add that to the time value from the server, you'll be closer to the true server time (The difference will be in microseconds)
Reference: http://ejohn.org/blog/accuracy-of-javascript-time/
Hope this helps.
I have made an application and I had the same problem. In That case I solved the problem leaving the time control to the server. The server send to the client and the client increases the time. Maybe in your case you could have problem with connection. If the problem exists you can leave clients to increase time by yourself and some times send a tick with correct time for sync.
I could give you something like bellow but I am not tested.
This solution have these steps:
Synchronize timers for client and server. all users have the same difference with server timer.
For the desired response/request get clients time and find the differences with server time.
Consider the smallest as first countdown which will be started.
For each response(socket) subtract the difference from smallest and let the client counter starts after waiting as much as this time.
The client that gets 0 in response data will start immediately.
and the main problem that you may will have is broadcast method which you can't use if you think this solution will be helpful.
This is a post may will help you.
Add time into emit message.
Let's say that songs is an object with {"time" : timeString, "songs" : songsList}.
If we consider devices time is correct You can calculate the time needed for information to travel and then just use server timer as a main calculator.
The client would get the time when countdown should start:
var start = false;
var startTime = 0;
var myTime = new Date().getMilliseconds();
var delay = 1000 - myTime;
setTimeout(function(){
intervalID = setInterval(function(){
myTime = new Date().getTime();
//console.log(myTime); to check if there is round number of milliseconds
if (startTime <= myTime && start = true) {startCountdown();}
}, 100); //put 1000 to check every second if second is round
//or put 100 or 200 is second is not round
}, delay);
socket.on('data loaded', data){
startTime = data.time;
start = true;
}
function startCountdown(){
//your time countdown
}
And that works fine when 2 clients are from same time region, therefore You will need "time converter" to check if time is good due to time difference if You strictly need same numbers.
After the countdown has ended You should clearInterval(intervalID);
The idea is to:
Measure usedJSHeapSize before starting the test.
Measure usedJSHeapSize after completing the test.
Comparing values from 1 and 2 and if the size increases above a defined threshold, then fail the scenario.
So far I have tried:
SG Protractor Tools (https://github.com/SunGard-Labs/sg-protractor-tools) which allow to repeat the same scenario several times and find the memory growth. I have discarded it since it does not allow checking memory usage for a single scenario (https://github.com/SunGard-Labs/sg-protractor-tools/issues/3).
Extracting the memory values from the browser object, which does not seem to work (or I could not get to work) to integrate with the specs -> Assign a value returned from a promise to a global variable
Any other ideas?
This can be done by invoking browser.executeScript()
Use window.performance.memory for Chrome to fetch the performance parameters
The below code worked all good for me.
https://docs.webplatform.org/wiki/apis/timing/properties/memory
it('Dummy Test', function(){
//Fetch the browser memory parameters before execution
browser.executeScript('return window.performance.memory').then(function(memoryInfo){
console.log(memoryInfo)
var beforejsHeapSizeLimit = memoryInfo.jsHeapSizeLimit;
var beforeusedJSHeapSize = memoryInfo.usedJSHeapSize;
var beforetotalJSHeapSize = memoryInfo.totalJSHeapSize;
// Have all your code to open browser .. navigate pages etc
browser.driver.get("https://wordpress.com/");
browser.driver.get("http://www.adobe.com/software/flash/about/");
// Once you are done compare before and after values
//Fetch the browser memory parameters after execution and compare
browser.executeScript('return window.performance.memory').then(function(aftermemoryInfo) {
console.log(aftermemoryInfo)
var afterjsHeapSizeLimit = aftermemoryInfo.jsHeapSizeLimit;
var afterusedJSHeapSize = aftermemoryInfo.usedJSHeapSize;
var aftertotalJSHeapSize = aftermemoryInfo.totalJSHeapSize;
expect((parseInt(afterusedJSHeapSize)-parseInt(beforeusedJSHeapSize))<10000000).toBe.true;
});
});
});
I run my bot in a public channel with hundreds of users. Yesterday a person came in and just abused it.
I would like to let anyone use the bot, but if they spam commands consecutively and if they aren't a bot "owner" like me when I debug then I would like to add them to an ignored list which expires in an hour or so.
One way I'm thinking would be to save all commands by all users, in a dictionary such as:
({
'meder#freenode': [{command:'.weather 20851', timestamp: 209323023 }],
'jack#efnet': [{command:'.seen john' }]
})
I would setup a cron job to flush this out every 24 hours, but I would basically determine if a person has made X number of commands in a duration of say, 15 seconds and add them to an ignore list.
Actually, as I'm writing this answer I thought of a better idea.. maybe instead of storing each users commands, just store the the bot's commands in a list and keep on pushing until it reaches a limit of say, 15.
lastCommands = [], limit = 5;
function handleCommand( timeObj, action ) {
if ( lastCommands.length < limit ) {
action();
} else {
// enumerate through lastCommands and compare the timestamps of all 5 commands
// if the user is the same for all 5 commands, and...
// if the timestamps are all within the vicinity of 20 seconds
// add the user to the ignoreList
}
}
watch_for('command', function() {
handleCommand({timestamp: 2093293032, user: user}, function(){ message.say('hello there!') })
});
I would appreciate any advice on the matter.
Here's a simple algorithm:
Every time a user sends a command to the bot, increment a number that's tied to that user. If this is a new user, create the number for them and set it to 1.
When a user's number is incremented to a certain value (say 15), set it to 100.
Every <period> seconds, run through the list and decrement all the numbers by 1. Zero means the user's number can be freed.
Before executing a command and after incrementing the user's counter, check to see if it exceeds your magic max value (15 above). If it does, exit before executing the command.
This lets you rate limit actions and forgive excesses after a while. Divide your desired ban length by the decrement period to find the number to set when a user exceeds your threshold (100 above). You can also add to the number if a particular user keeps sending commands after they've been banned.
Well Nathon has already offered a solution, but it's possible to reduce the code that's needed.
var user = {};
user.lastCommandTime = new Date().getTime(); // time the user send his last command
user.commandCount = 0; // command limit counter
user.maxCommandsPerSecond = 1; // commands allowed per second
function handleCommand(obj, action) {
var user = obj.user, now = new Date().getTime();
var timeDifference = now - user.lastCommandTime;
user.commandCount = Math.max(user.commandCount - (timeDifference / 1000 * user.maxCommandsPerSecond), 0) + 1;
user.lastCommandTime = now;
if (user.commandCount <= user.maxCommandsPerSecond) {
console.log('command!');
} else {
console.log('flooding');
}
}
var obj = {user: user};
var e = 0;
function foo() {
handleCommand(obj, 'foo');
e += 250;
setTimeout(foo, 400 + e);
}
foo();
In this implementation, there's no need for a list or some global callback every X seconds, instead we just reduce the commandCount every time there's a new message, based on time difference to the last command, it's also possible to allow different command rates for specific users.
All we need are 3 new properties on the user object :)
Redis
I would use the insanely fast advanced key-value store redis to write something like this, because:
It is insanely fast.
There is no need for cronjob because you can set expire on keys.
It has atomic operations to increment key
You could use redis-cli for prototyping.
I myself really like node_redis as redis client. It is a really fast redis client, which can easily be installed using npm.
Algorithme
I think my algorithme would look something like this:
For each user create a unique key which counts the commands consecutively executed. Also set expire to the time when you don't flag a user as spammer anymore. Let's assume the spammer has nickname x and the expire 15.
Inside redis-cli
incr x
expire x 15
When you do a get x after 15 seconds then the key does not exist anymore.
If value of key is bigger then threshold then flag user as spammer.
get x
These answers seem to be going the wrong way about this.
IRC Servers will disconnect your client regardless of whether you're "debugging" or not if the client or bot is flooding a channel or the server in general.
Make a blanket flood control, using the method #nmichaels has detailed, but on the bot's network connection to the server itself.