PHP countdown timer without causing a spinlock - php

The problem:
I'm a programming student and currently studying PHP. Apparently Java can designate threads for things like countdown timers; however, I have been told that PHP can have issues with a standard countdown function using delay, or even time() logic, as it will result in a spinlock. How do I go about avoiding a spinlock and having a simple, efficient countdown timer?
Summary of what I am trying to solve:
I need to create a 30 second timer on the backend PHP. Once the timer is completed, PHP will use my Slack API to communicate with a particular Slack channel - letting everyone know that the coffee is done, etc. With this said, I need to be able to start multiple clocks (as there is both coffee and tea) and must avoid a spin lock as it will kill the multi-countdown ability that is required.
Code so far that results in spinlock:
$startTime = time();
$actualTime = (int)$startTime;
$finishTime = ((int)$startTime) + 30;
var_dump($startTime);
var_dump($actualTime);
var_dump($finishTime);
while(($finishTime - $actualTime) > 0) {
usleep(250000);
$actualTime = ((int)time());
if ($actualTime === $finishTime) {
echo "Tea is ready!";
}
}

Related

Frequency of crontab calling a php function - Looking for alternative options

I'm programming my own "smart home" as a learning project.
My code is running fine. I'm looking for help to improve the efficiency and of the code and/or the setup of crontab + php code.
I'm monitoring the energy consumption of my washing machine with a WIFI energy meter. Target is to notify me once the washing machine is completed so I don't forget to clear it.
on my Pi I have a crontab like so:
*/20 7-22 * * * /usr/bin/php '/home/holger/html/plugs/washer.php'
which runs following php code (I simplified for better readability):
[...]/I call the function, of course, but this function does the main task
function loop($maschine, $watt_init, $trashhold){
$max = 75;//max loops to avoid endless runs
$i = 1;//start counter
$tackt = 3;//tact time to check energy consumption
//$trashhold = 4;//ab x Watt kein standby
if ($watt_init < 1 ) {//Machine is switched off if energy consumption < 1 Watt
die;//quit
}
elseif ($watt_init < 2 ) {//Machine is switched off or in standby if energy consumption < 1 Watt
die;//quit
}
else {//Any thing else: Machine is running
while ($i < $max) {//loop as long as max loops are not reached
$watt_current = json_combine(IPplug5);//getting current energy consumption from WIFI energy meter via JSON
sleep(60*$tackt);//sleep and continue every 60s x tact time
$i++;//increase counter +1
//compare actual consumption with defined trashhold
if ($watt_current[0] >= $trashhold) {//continue while energy consumption bigger then trashhold
continue;//repeat loop
}
elseif ($watt_current[0] < $trashhold) {//stop if energy consumption lower then trashhold
break;//stop loop
}
}
echo "Program done. please clear. Runtime: " . $i*$tackt. "Min."
//[...] message me to my telegram bot
}
}
The code is running fine and I'm getting the output I need.
My question is: Is there a better way to do that?
Currently I'm afraid to overload my Pi with too many open php sessions, therefore I'm starting the code only every 20min and also let the while loop sleep for 3 Min. But for improved accuracy I like to run the cronjob more often and also let the while loop sleep only for 30s.
My requirements are to stick to my PI and php code and not to use any available software like Home Assisant.io as it contradicts with my learning approach.
Any ideas or insights welcome.
Ideally it's a not the best approach to handling and measuring power consumption. It would be best if you created an API that accepts events like on/off or threshold hold limit extends from your IP devices.  Further you can create logs and store them in databases.
Although, for your current problem here is one alternate solution.
Set your cron that runs every second.
function get_powerConsumption($machine, $watt_init, $threshold)
{
if ($watt_init < 2) {
exit();
}
$time = date("Y-m-d H:i");
$filename = $machine . '_power_consumption.log'; // expecting some machine identification name here. otherwise ignore prefix
$watt_current = json_combine(IPplug5);
if ($watt_current[0] >= $threshold) {
$data = array(
$time,
$watt_current[0]
);
file_put_contents($filename, json_encode($data) . "\n", FILE_APPEND);
} elseif ($watt_current[0] < $threshold) {
$data = array(
$time,
'stopped'
);
file_put_contents($filename, json_encode($data) . "\n", FILE_APPEND);
}
}
Create another cron to look up for stopped events logged in the file. if found process the calculation based on logged data like time and consumption. You can set this cron to run based on your need like every second or minute or after some interval.
Also, handle code to delete old logs, once stopped events found.

php continue execution after leaving the page

I have a simple script that counts from 1 to 5000 with a for loop. It flushes output in real time to browser and shows a progress bar with %.
What I have: If I leave the page, the process interrupts. If I come back, it starts from 0.
What I want to achieve: If I leave the page, the process continues and, If I come back , it shows the right percentage.
Example: I run the process, it counts till 54, I leave the page for 10 seconds, when I come back it shows me 140 and continues to flush.
Is it possible?
I would suggest you to use server workers - scripts which are intended to run independently from webserver context.
The most common way of doing it - usage of message queues (RabbitMQ, Qless, etc). Event should be initiated by the script in web context, but the actual task should be executed by queue listener in a different context.
What you have asked seems quite simple to do with a session. (Purely assuming on the use case given). This is not running any process in the background, it just simply keep track of the time and show the progress. That's why I said "based on what you asked". If you want to keep track of any real background tasks, then I believe the case would be totally different, and you will have to change the wordings of your question as well ;)
Something like this would do.
<?php
session_start();
$s = &$_SESSION;
$sleep = 1; //seconds
//check if we have a value set in session before, if not set default = 0.
if(!isset($s['last'])){
$s['last'] = 0;
}
//check if we have a last time set in session before. if not set a default = curret time.
if(!isset($s['time'])){
$s['time'] = time();
}
//get the idle time of the user.
$idle = time() - $s['time'];
//start the loop..and set starting point.
$start = $s['last'] + ($idle / $sleep);
for( $i = $start; $i < 100; $i++){
echo $i . '<br />';
$s['last']++;
$s['time'] = time();
flush();
sleep($sleep);
}
Hope it helps!!

Php Timer with a Pause Function

I'm trying to figure out a way to create a function to have the user be able to start a project by clicking a button and the timer would start. At the same time, I would like the user to be able to pause as well as stop the timer. When finished with a task, they can then hit 'Finished' to record the total amount of recorded time, minus any paused time, for the task to a variable in which I can record.
I have been researching and found that a Javascript timer wouldn't be very reliable which is why I wanted to go with Php. I figured I could take a Timestamp on 'Start' and 'Stop', but since I'm needing a 'Pause' as well, it's throwing a whole new kink into my plans.
Anyone know of a good way to accomplish this? I know that one Timestamp to another will get the total time, but how can you calculate one to another if the process had been paused?
I don't think "Javascript timer wouldn't be very accurate" is an accurate statement.
However, if you decide to use PHP, you will not be having the script running for the whole duration of the project. What you need is simply a number of markers in an object. You can store the object in a database table or as JSON string in a file. Here's an example using JSON:
[
[1440264185, "start"],
[1440280217, "pause"],
[1440288349, "resume"],
[1440292161, "pause"],
[1440317465, "resume"],
[1440325597, "stop"]
]
The object is built progressively with each event adding the timestamp of the signal received with the signal type (start, pause, resume, stop).
Then, when you want to calculate the amount of time spent working on the project/task you can use code like this:
$markers = json_decode($json_markers, true);
$num_markers = count($markers);
$markers[] = $markers[$num_markers-1];
$time_worked = 0;
for($i = 0; $i < $num_markers; $i++) {
if(in_array($markers[$i][1], array("start","resume"))) {
$time_worked += $markers[$i+1][0] - $markers[$i][0];
}
}
var_dump($time_worked); // int(27976)
Here's the code above.

PHP: Check mysql database every 10 seconds for any new rows

I am making a php chat and am starting the php checking database part. So when a user types something into the chat, it gets recorded in the MySQL database, how would I check the database every 10 seconds so that one user's chat would update with new messages from other users. I know that you can use an ajax request to a page with an interval, but I want the php to be on the same page, instead of having to use numerous pages. This is the code for checking the database
<?php
$con = mysqli_connect('host','user','pass','database');
$query = mysqli_query($con,"SELECT * FROM `messages`");
while ($row=mysqli_fetch_assoc($query)) {
$user = $row['user'];
$message = $row['message'];
echo 'User: ',$user,' Message: ',$message;
}
?>
Thanks in advance anyone!
Use MySQL Event Scheduler.
Below link will guide you through .
http://www.9lessons.info/2012/10/mysql-event-scheduler.html.
I think best option in your case .
AJAX is probably the simplest solution. You can perform an AJAX request on the same page your PHP code is executing on if you really want to.
(function check() {
$.get('mypage.php', function(data) {
doSomethingWith(data);
setTimeout(check, 5000); // every 5 seconds
});
})();
PHP doesn't have a setInterval function. While I'm sure you can use a crontask to automate it on the server, you can also achieve this with some simple Javascript.
The concept you are trying to achieve is known as Short Polling. What you want to do is to have a setInterval function in Javascript that constantly makes AJAX requests to your PHP file which performs the check to the database for new messages. Your PHP should return that information to your script where you can then simply populate the user's screen.
There is also Long Polling where you simply maintain the connection and have a setTimeout to wait for messages to come in. You can find more information yourself and if you have questions, you can come back here.
A good video about this:
https://www.youtube.com/watch?v=wHmSqFor1HU
Hope this helps.
This is what you need. We need set time for ajax auto reload. Don't put everything in one page. Because you must reload page to refresh data. That is bad solution.
Call jQuery Ajax Request Each X Minutes
Make a while for 30 seconds, and check the db every second, once you find a record the while is being broken, also it is being broken when 30 secs are expired.
$sec = 1;
while($sec <= 30) {
if(has record)
Send to the user;
$sec++;
sleep(one sec here);
}
Use sleep for 10 secs in order to check every 10 secs...

PHP: Most efficient way to make multiple fsockopen(); connections?

Hey guys i'm making a website where you submit a server for advertising. When the user goes to the index page of my website it grabs the ip's of all the servers submitted and then tests to see if it is online using fsockopen() like so:
while($row = mysql_fetch_assoc($rs)) {
$ip = $row['ip'];
$info = #fsockopen($ip, 25565, $errno, $errstr, 0.5);
if($info) {
$status = "<div><img width='32px' height='32px'
title='$name is online!' src='images/online.png'/></div>";
$online = true;
} else {
$status = "<div><img width='32px' height='32px'
title='$name is offline!' src='images/offline.png'/></div>";
$online = false;
}
}
}
This way works fine, but the only downside is when you load the site it takes a good 2-4 seconds to start loading the website due to the fsockopen() methods being called. I want to know if there is a better way to do this that will reduce the amount of wait time before the website loads.
Any information will be appreciated, thanks.
Store the online status and last check time in a database, if the last check time is longer than 15 minutes for example, update it. I am pretty sure you don't need to get the status on EVERY pageload? It's the time it takes to connect to each server that slows down the website.
Then again, you would probably wanna move the update process to a cronjob instead of relying on someone visiting your website to update the server statuses.
Looking at your example, I'd make all the $status bits be javascript calls to another php page that checks that individual server.
However, the idea to move the status checks to cron job or use some kind of status caching is very good too. Maybe store statuses in a database only only check the ones that have expired (time limit set by you).

Categories