Raspberry PI/PHP + Arduino serial communication - php

I'll try to give a brief summary of the project and then the current code approach.
I have a RPi all set up with the latest Stretch OS.
I have installed MySQL, PHP, APahce and PhpMyAdmin and it working correctly.
I have it booting up to the default (locally hosted) webpage and in full screen (KIOSK) mode.
DB created, tables populated, queries in place.. and the webpage (drink menu) is displaying correctly as expected.
I have my Arduino UNO connected to the RPI via USB
The webpage displays a bunch of menu options.. each with its own 'order' button.
When any order button is clicked.. I save this button data to a hidden field, and use jQuery to submit/post the form (to itself)
Upon $_POST I grab this submitted data, and send it out via PHP over serial comm 1.
And here is where I am currently.
Since my Arduino is connected via USB to the RPi. I can not use the serial monitor to debug things.... do I have any other options here?
When I submit the webpage.. I -do- see the RX/TX lights on the Arduino blinking (leading me to believe it is receiving the serial data).. I can/will check if it is correct tonight by hooking up the stepper motor again and see if ti moves to the correct position(s)...
Here is where I am stuck/stumped a bit.. and could use some discussion to get me on the right path.
So after the Arduino 'does its magic'.. it is supposed to send a confirmation message back to the RPi.. saying the drink is complete.. and I can go back to the main drink menu awaiting another order
Because the webpage has already $_POSTed..and the serial data sent to the connected Arduino.. .. I then leave the page displaying a 'please wait' message... but because the page is already parse on the server side of things, I am left with the need on how to 'listen' to the serial posrt via PHP now.
I figured.. I could use some AJAX to call/load an external php script.. that will just wait/listen to the serial port.. and return the data to the AJAX 'success' callback.
But as I have never done this before.. I'm kind of leery if this will work.. or if this is even the correct way to do so.
Also random questions about the best place(s) to open and close the port.. especially if there is 2 separate scripts? (ie: can I open the port in one script.. and still access it in another? or does that file accessing it.. need to be the one that opens it?)
Here is my current snippet to handle the sending and waiting/listening of the serial port:
[code]
<?
if ($mode == 'submit') {
//grab posted data (save to var)
$drinkRecipe = $_POST['selectedDrink'];
//set-up com port
exec("mode /dev/ttyACM0 BAUD=9600 PARITY=N data=8 stop=1 xon=off");
//saw this on several RPi posts? (but not sure of the difference? or why one would be used over the other?)
//stty -F /dev/ttyACM0 cs8 9600 ignbrk -brkint -imaxbel -opost -onlcr -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke noflsh -ixon -crtscts
//open serial port
$fp = fopen("/dev/ttyACM0", "w+"); //w = write w+ = read/write
//check if open
if (!$fp) {
echo "Not open";
//die();
} else {
//if open send data (via PHP) to connected Arduino on serial comm port 1 (ttyACM0)
fwrite($fp, '<' . $drinkRecipe . '>');
//arduino takes serial data, parsed it.. does it duty,
//and is supposed to reply back via serial to the awaiting (listening)
//PHP script executed via AJAX, since the front end needs to display
//a 'waiting' type message.. and the callback 'success' will
//re-direct back to menu/initial state
?>
<script type="text/JavaScript" language="JavaScript">
$.ajax({
//async: false,
//type: "POST",
url: "serial_listener.php",
//define success handler actions
success: function(response) {
//alert("PHP RETURN CHECK: "+response);
if($.trim(response) == 'complete'){
alert("Drink making is complete... return to main menu");
//do redirect here
}else{
alert("Some value other than 'complete' was returned... look into it!");
//not sure what to do? (back to main menu anyways?)
}
},
//define error handler actions
error: function(response) {
alert("PHP SERIAL READ FAIL: "+ 'Ready State: '+ response.readyState + ' Status: ' + response.status);
}
});
</script>
<?
//close connection
fclose($fp); //needed? //should this go in the external php script instead now?
}
}
Not even sure what should go into the: serial_listener.php script yet... just a while loop or something? Waiting for data? or end of file or something? (not sure how that works using fread() on serial port?)
Any suggestions to try and wrap my head around this is appreciated.
Update: I'm not sure if I am not explaining things correctly/clearly?
But when the page submits (to itself).. that is when the OUTGOING serial data is sent to the connected (via USB to the RPi) Arduino....
When the page 'posts' it sends the above data OUT.. and then displays a 'please wait' type of message.
At this point (as far as I understand it).. the server side script/parse is now COMPLETE... and I am left with a page saying 'please wait'...
There is no more parsing/server side ANYTHING going at this point..
That is why I thought/brought up the use an AJAX call to an external script that can sit and 'wait' (listen) to the serial port (un-clear as to how best going about this... a while() loop or something?)...
and then when the data eventually comes back...
*
(which there is no telling how long it will take for this 'serial
feedback' from the Arduino.. as each drink takes different amounts of
time to create).........
*
it will use the AJAX 'success' callback function to then update the page.. and ultimately just re-direct it back to the main drink menu page again.. to start all over.
I dont feel the use of timeout() or delay() on the Arduino is not only bad advice (ie: never use delay() if can help it)..... but I dont even see where/why that makes any sense?
Update:
And the contents of the serial_listener.php script: (script the AJAX snippet calls)
//set-up com port
exec("mode /dev/ttyACM0 BAUD=9600 PARITY=N data=8 stop=1 xon=off");
//open serial port
$fp = fopen("/dev/ttyACM0", "w+"); //w = write w+ = read/write
//check if open
if (!$fp) {
echo "Not open";
//die();
} else {
while(!feof($fp)){
$response = fread($fp, 10);
}
echo $response;
fclose($fp);
}
Final update:
I re-wrote things to use the AJAX call to SEND my data.. and also wait for the response.
The external php script the AJAX call executes is the ONLY place the port gets opened now (and I am not closing it)
Here is the SUBMIT state of the PHP form that has the AJAX call:
The sending of data works 100% of the time.. but I can NOT read my response.
if ($mode == 'submit') {
//grab posted data (save to var)
$drinkRecipe = $_POST['selectedDrink'];
?>
<div id="waitingContainer">
<p>Please wait, your brink is being made.</p>
</div>
<script type="text/JavaScript" language="JavaScript">
console.log("ajax routine hit");
//var drinkRecipe = "<?php echo $drinkRecipe ?>";
var drinkRecipe = "<?=$drinkRecipe?>";
var xhr = $.ajax({
//async: false,
type: "POST",
url: "serial_listener.php",
//datatype: "html",
datatype: "text",
data:({"drinkData":drinkRecipe}),
//define success handler actions
success:function(response) {
//alert("PHP RETURN CHECK: "+response);
if($.trim(response) == 'complete'){
console.log("Drink making is complete... return to main menu");
//do redirect here
}else{
console.log("Some value other than 'complete' was returned... look into it!");
console.log("RESPONSE SENT WAS: " + response);
//not sure what to do? (back to main menu anyways?)
}
//kill the request
xhr.abort();
},
//define error handler actions
error: function(response) {
console.log("PHP SERIAL READ FAIL: "+ 'Ready State: '+ response.readyState + ' Status: ' + response.status);
//kill the request
xhr.abort();
}
});
</script>
<?
}
Here are the contents of the serial_listener.php script the AJAX call executes:
//data sent from AJAX call (works)
$drinkData = $_POST['drinkData'];
//open serial port
$fp = fopen("/dev/ttyACM0", "w+"); //w = write w+ = read/write (works)
//$fp = fopen("/dev/ttyUSB0", "w+"); //w = write w+ = read/write //tried with USB-TTL cable too.. couldnt even send data)
//check if open
if (!$fp) {
echo "Not open";
//die();
} else {
if($drinkData != ''){
//send drink data
fwrite($fp, '<' . $drinkData . '>');
//wait for response
$chars = "";
do{
$char = fread($fp, 1);
$chars .= $char;
}while(strlen($char) < 1);
echo $char;
}else{
echo 'drink recipe is empty';
}
}

Can't comment to make a suggestion (no reputation)
I have no knowledge on Ajax , jquery, Raspberry Pi or PHP but...
If you have a Serial to USB TTL device like this you can use the SoftwareSerial library. Set up SoftwareSerial on a couple of unused digital pins on the arduino and send debugging info out there.
Not an answer, but a suggestion.
*********Edit***********
Come to think of it, doesn't the Raspberry Pi have a serial port?
If so you don't need the USB converter. Just set up a softwareSerial port on the Arduino and use that to connect to the Pi. Taht way you can use the USB port to send debug coms to your computer.

First, I dont have expirience with Raspberry nor Arduino, but do have played with serial communication in the past.
You are making things waay too complicated. Serial communication is not some strange animal from history channel - take it as a data layer. You would easely create needed front- and backend IF data would come from/go to database? Now, implement your system exactly same way, just instead of database connection use Serial communication.
Your serial_listener is simple:
create/configure port
send data
read data
close port
So, whole case:
frontend --post(d)--> serial_listener::COM1::send(d) ... COM1::read('OK') -->reply 'success'
PS.
with those small controllers... timeout() is your real friend ;)
And for serial communication I would suggest to use some library (e.g. php_serial.class)
I try to clarify with a code. I try to keep it as simple, just to illustrate the system as a whole.
Frontend, pure js/html and AJAX request:
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body onLoad="$('#loading-image').hide();">
<div width="100%" style="text-align: center;">
<div id="demo">
<h2>Content: forms/scripts/...</h2>
</div>
<div>
<button type="button"
onclick="makeSerialCall('serial.php')">order (send AJAX call to php script)
</button>
</div>
</div>
<img id='loading-image' src='https://media.tenor.com/images/011ebf9c192d1c9b26f242d526ee24bb/tenor.gif'></img>
<script>
var string = 'data which is collected from content above';
function makeSerialCall(url) {
$('#loading-image').show();
$.ajax({
type: "POST",
url: url,
data: string,
cache: false,
success: function(response){
$('#loading-image').hide();
console.log(JSON.stringify(response['info']));
//and whatever else you want to do afterwards...
}
});
}
</script>
</body>
Serverside:
<?php
if(!empty($_POST))
$data = $_POST["data"];
include "php_serial.class.php";
$serial = new phpSerial();
$serial->deviceSet("/dev/ttyUSB0");
$serial->confBaudRate(9600);
$serial->confParity("none");
$serial->confCharacterLength(8);
$serial->confStopBits(1);
$serial->confFlowControl("none");
$serial->deviceOpen();
$serial->sendMessage($data);
$read = $serial->readPort();
$serial->deviceClose();
header('Content-type: application/json');
$response_array['status'] = 'success';
$response_array['info'] = 'some additional info:'.$read;
echo json_encode($response_array);
?>
This way you have "loading.." image on the screen until response. Initial rendered page is there all the time. Ofcourse, you need alot of (error)checking, solution when there's no response from serial etc.etc. But basic system is not "rocket science".

Related

Never-ending ajax request, good idea / bad idea?

For the backend of my site, visible only to a few people, I have a system whereby I communicate with a php via ajax like so:
function ajax(url, opts) {
var progress = false, all_responses = [], previousResponseLength = "";
var ajaxOptions = {
dataType: "json",
type: "POST",
url: url,
xhrFields: {
onprogress: function(e) {
if (!e.target.responseText.endsWith("\n")) return;
var response = e.target.responseText.substring(previousResponseLength).trim();
previousResponseLength = e.target.responseText.length;
var responses = response.split(/[\r\n]+/g);
var last_response;
for (var k in responses) {
if (responses[k] === "---START PROGRESS---") {
progress = true;
if (opts.onProgressInit) opts.onProgressInit();
} else if (responses[k] === "---END PROGRESS---") progress = false;
else all_responses.push(last_response = responses[k]);
}
if (progress && last_response !== undefined) opts.onProgress(JSON.parse(all_responses[all_responses.length-1]));
}
},
dataFilter: function(data){
return all_responses[all_responses.length-1];
}
}
$.extend(ajaxOptions, {
onProgress: function(data){
console.log(data);
}
});
return $.ajax(ajaxOptions);
}
And an example of a never-ending php script (until the user closes the connection):
const AJAX_START_PROGRESS = "---START PROGRESS---";
const AJAX_END_PROGRESS = "---END PROGRESS---";
session_write_close(); //fixes problem of stalling entire php environment while script runs
set_time_limit(0); //allows to the script to run indefinitely
output(AJAX_START_PROGRESS);
while(true) {
output(json_encode(["asdasd" => "asasdas"]));
sleep(1);
}
function output($msg) {
echo preg_replace("`[\r\n]+`", "", $msg).PHP_EOL;
ob_flush(); flush();
}
This allows me through 1 ajax request to 'poll' (am I using that term correctly?)
So if I want to execute a very long php script I can now check its progress, and the last response is delivered via jqhxr.done(callback).
Or, as in the example php script, I can open a connection and leave it open. Using sleep(1); It issues an update to the $.ajax object every 1 second.
Every response has to be json encoded, and if the response is 1 very long json that comes over multiple 'onprogress' calls, it waits until the end of the message (if responseText.endsWith("\n")) we're ready!)
My remote shared server didn't allow websockets so I made this. If the user closes the connection, so does the php script.
It's only got to work for a few admins with special privileges, and I don't need to worry about old browsers.
Can anyone see anything wrong with this script? Through googling I haven't found anybody else with this kind of method, so I expect something is wrong with it.
Extensive testing tells me it works just fine.
You invented long polling request, actually it's wide used as fallback to websockets, so nothing wrong with it.
About your code it's hard to say without testing, but when using such methods as long-polling, you need to double check memory leaks on browser side and on server side.

How do you password protect a blogger post?

I've seen this question a number of times - just not here in SO. The answers to this point have all said to use use credentials in javascript (and we all know clientside credentials is no way to do authentication :)
The scenario is that I want to control a certain page on my blog - until such time as I let it loose to everyone. I have my own domain, so I can host php scripts. I've already tried Blogger's reader filter - it's great, but for viewers without a gmail account, it's a real pain in the
Here's my solution (using Javascript - but without user+password verification on the client). It's a hack - but I've got other fish to catch and miles to go before I eat.
The initial page call is this:
http://YOUR.DOMAIN.COM/manager.php?p=login
That prompts for the username and password
- ala this: http://www.php.net/manual/en/features.http-auth.php
After login some encryption is done on an authentication cookie
- ala this: http://php.net/manual/en/function.mcrypt-decrypt.php
- or this: http://php.net/manual/en/function.openssl-decrypt.php
The cookie is set
- ala this: http://www.php.net/manual/en/function.setcookie.php
And then the php file calls this present page via the following
- header('Location: http://YOUR2.DOMAIN.COM/p/page.html');
* YOUR2.DOMAIN.COM points to blogger; the page is this file here which will grab the file data and insert it into a div on the page
- see info here: http://support.google.com/blogger/bin/static.py?hl=en&ts=1233381&page=ts.cs
Based on the param and confirming that the cookie is valid, manager.php gets the real file data and sends it out
- ala this: http://php.net/manual/en/function.file-get-contents.php
Just drop the following into a blank Blogger page - taking care to replace the instances of YOUR.DOMAIN.COM
<script type="text/javascript" src="http://YOUR.DOMAIN.COM/scripts/jquery-1.8.3.min.js"></script>
<script type='text/javascript'>
var $pageUrl = "http://YOUR.DOMAIN.COM/manager.php?p=page1"; // so cool how you could setup your own domain!
function doInitStuff()
{
if ($alreadyInited) return;
$alreadyInited = true;
// a little hack - because though I said share cookies among (*) ".DOMAIN.COM" it wasn't getting sent
// although it's obviously there since we get it here on YOUR2.DOMAIN.COM (originally set on YOUR.DOMAIN.COM)
$cookies = document.cookie;
$result = $.ajax
({
type: "GET",
url: $pageUrl,
dataType: 'json', // or whatever
async: false, // force this to complete before moving on (should be quick though - since already logged in)
// username: 'username', // would get these from a prompt/html form - but should have already gone directly to the site to authenticate
// password: 'password', // did it that way, because wasn't able to get the u/p to be properly sent... this new way is better anyway
data: $cookies, // send along the cookies - they should show up in $_GET
success: function (result, status, jqXHR){
// good - but for some reason wasn't getting result - just move on...
},
error: function (){
// not good
}
});
if ($result.status == 200)
{
// insert our data into our nice Div
$('#realpageinfo').html($result.responseText);
}
// grrrrrr. ie strikes again! use iframes instead
var isMSIE = eval("/*#cc_on!#*/!1");
if ($('#realpageinfo').html() == '' || isMSIE)
{
//$('#realpageinfo').replaceWith("<div id='realpageinfo' style='font-weight:bold;color:red'>Internet Explorer? Sorry, but please use a different Browser.</div>");
$('#realpageinfo').replaceWith("<div id='realpageinfo'><iframe id='realpageframe' style='width:100%;height:700px' src='" + $pageUrl + "'></iframe></div>");
}
}
// Don't mind this - multiple ways to ensure the main worker function is called
var $alreadyInited = false;
$(document).ready(function() { doInitStuff(); });
window.addEventListener('DOMContentLoaded',function() { doInitStuff(); });
</script>
<div id='realpageinfo'></div>
Now for the server side
<?php
$cookieName = 'my_auth_cookie';
$loggedInCookieVal = $_COOKIE[$cookieName];
if (!isset($loggedInCookieVal))
{
$loggedInCookieVal = $_GET[$cookieName]; // was it passed in instead of coming through the Cookie channel?
}
// if $loggedInCookieVal is set, decrypt it and pull username + pwd from it - if succeeds, set $cookieValsDecrypted
// otherwise see if the user just sent them back in response to a challenge
// these are empty before login - and set in response to the challenge
$curUser = $_SERVER['PHP_AUTH_USER'];
$curPswd = $_SERVER['PHP_AUTH_PW'];
if (!$cookieValsDecrypted && (!isset($curUser) || !isset($curPswd)))
{
// ask the user to authenticate (again if have to)
header('WWW-Authenticate: Basic realm="YOUR.DOMAIN.COM"');
header('HTTP/1.0 401 Unauthorized');
echo "You gotta login bud - but you canceled instead";
exit;
} else {
// check $curUser and $curPswd against a db or .htpasswd file, etc - or check $cookieValsDecrypted
// if all good then send the file
if ($matched)
{
switch($_GET['p'])
{
case 'login': // just came here to login - now done, go on to the real page that pulls the value
header('Location: http://YOUR2.DOMAIN.COM/p/page.html');
break;
case 'page1':
echo file_get_contents ('./page1.txt'); // show the date
break;
}
} else {
// else send the auth request again
header('WWW-Authenticate: Basic realm="YOUR.DOMAIN.COM"');
header('HTTP/1.0 401 Unauthorized');
echo "Try something else, maybe";
}
}
?>
That's it... feel free to improve. See it in action here ClyntonCaines.Com

Best way to check the connection to my database js

I work on a web interface which receives and send informations to a distant PostGreSQL database.
From what I found on the internet it seems that the best way is to create a small php script in an external .php file.
I followed that idea,
so I have that script pg_connection.php which tests the connectivity to my database (with a pg_connect) in that style :
$db = pg_connect("host=localhost port=5432 dbname=**** user=**** password=****")
or die("Not Connected");
if ($db) {echo (Connected);} else {echo (Not Connected);}
If I launch only that pg_connection.php in my webbrowser, it works fine (I just have wrotten Connected with the correct login infos entered in my script or Not connected if I put a random ip address).
Then in my .js(+jquery) external script I use :
$(document).ready(function(){
$("#dbstatus").load("php-services/pg_connection.php");
var dbstatus = new String();
dbstatus = $("#dbstatus").val();
if (dbstatus == "Connected")
{ /*jquery code to show a green light on a section in my html page*/}
else { /*jquery code to show a red light*/}
}
And that works partially :
In my $("#dbstatus") object it will replace the default text by Connected or Not Connected,
But it doesn't produce any effect on the green/red light in my conditionnal
Then I went in my Chrome console and type dbstatus, and I realized that the content of my var is
<div id=​"dbstatus" class=​"span3">​Connected​</div>​
when I expected it to be just "Connected".
Any idea on how to clean that var from all these extra html stuffs ?
Is there more simple method implemented in js or Jquery to check a postgreSQL database status ?
Try to modify your code to:
$db = pg_connect("host=localhost port=5432 dbname=**** user=**** password=****") or die("0");
if ($db) {echo "1";} else {echo "0"}
And in JS:
$(document).ready(function(){
$.ajax({
url: "http://fullpathto/php-services/pg_connection.php",
cache: false
}).done(function( result ) {
if(result=="1") {
/*jquery code to show a green light on a section in my html page*/
}
else
{
/*jquery code to show a red light*/}
}
});
});
Instead of $("#dbstatus").val(); use $("#dbstatus").html();.

Why my server freezes when using long pull with Ajax?

When I'm taking my query using Ajax on jQuery, o try use the method of long pull but my server is shutdown or dont response, my website becomes too slow like in stanby, or freezed what can i do?
MY PHP;
session_start();
$chat=new chat;
$class=new tools;
$idenvia=isset($_GET['idenvia'])? $_GET['idenvia']: '';
$idreceptor=isset($_GET['idreceptor'])? $_GET['idreceptor']: '';
$cantidad= isset($_GET['cantidad'])? $_GET['cantidad']: '';
$control=$_GET['control'];
//$ultima_modif=isset($_SESSION['fecha'])?$_SESSION['fecha']:0;
if($control==1){
echo json_encode($chat->leer_chat($idreceptor,$idenvia,$control,$cantidad,NULL));
}
if($control==2){
$dir='log/log_'.$_SESSION['id'].'.txt';
$ultima_modif=filemtime($dir);
$modifica_actual=isset($_GET['tiempo'])? $_GET['tiempo']: 0;//0
set_time_limit(0);
while($ultima_modif<=$modifica_actual){
clearstatcache();
$ultima_modif=filemtime($dir);
sleep(1);
//echo '{"0":{"activo":2}}';
//flush();
}
$res=$chat->leer_chat($_SESSION['id'],NULL,$control,$ultima_modif);
echo json_encode($res);
//unlink($dir);
flush();
}
This is my JQUERY code, here i take th response of my php with AJAX
function leer_chat_interval(){
$.ajax({
url:enlace,
type:'GET',
async:true,
data:{'control': 2,'tiempo':tiempo},
success:function(dato){
eval('var json='+dato);
if(json[0].activo==1){
//if(json.length!=0){
leer_chat(json[0].idenvia,json[0].idrecibe,1,json[0].nombre,json[0].mifoto,1,1);
$('#msg_chat'+json[0].idrecibe).attr('name',"{'recibe':'"+json[0].idenvia+"','envia':'"+json[0].idrecibe+"','foto':'"+json[0].mifoto+"'}");
setTimeout(function(){
$('#header_chat'+json[0].idenvia).css('background-color','#09C')
setTimeout(function(){
$('#header_chat'+json[0].idenvia).css('background-color','#F90')
},1000)
},1000);
tiempo=json[0].tiempo;
noerror=true;
}else{noerror=false;}
},
datatype:"json",
complete:function(dato){
if(!noerror){
setTimeout(function(){
leer_chat_interval()
},5000)
}else{
leer_chat_interval();
noerror=false;
}
},
timeout:30000
});
}
Your problem is this:
while(1)
You are not supposed to have a script looping infinitely to handle your ajax "long polling"; instead each ajax call runs through a finite request, collects the result, and repeat. What is happening in your example is that everytime your ajax request fires, a new infinitely running script is started; naturally the server collapses after a accumulating several of these.

Ajax call to php script returns 404 error

I'm a WordPress designer, I developed a contact form for one of my themes that's validated via jQuery.
Please check the code below, then read the notes beneath.
$('.submitemail') .click(function() {
//VALIDATION CODE GOES HERE
if ( /*VALIDATED SUCCESSFULLY*/ ) {
$.ajax({
type: 'POST',
url: templatePath+'/lib/scripts/sendEmail.php',
data: 'visitorname=' + visitorname + '&visitoremail=' + visitoremail + '&visitormessage=' + visitormessage,
success: function(contactResults) {
//SUCCESS CODE
}
});
}
});
Notes:
sendEmail.php is a correct script that sends email using PHPmailer class.
templatePath variable has the value of the full template path which looks like this: http://somedomain.com/wp-content/themes/themename
The jQuery code above is located in lib/scripts/jfunctions.js (same directory of the php script)
The whole process (ajax and php) works perfectly as expected in many servers, (tested in two servers by me and other servers by my theme users).
The Problem:
In SOME servers, the success handler is not triggered while the ajax call to sendEmail.php is actually passed successfully and the php script is processed and email is sent.
When I check with firebug to see why the success handler is not triggered, firebug shows "not found 404 error", It's like a false alarm.
Possible causes:
I think some servers is configured to block such ajax calls.
What might be the cause for this weird issue? How to fix it?
Thanks in advance.
#nowk: sendEmail.php code is:
<?php
// Code for loading WordPress environment goes here //
$themeName_optionTree = get_option('option_tree');
$name = trim($_POST['visitorname']);
$email = $_POST['visitoremail'];
$message = $_POST['visitormessage'];
$site_owners_email = $themeName_optionTree['owner_email'];
$site_owners_name = $themeName_optionTree['owner_name'];
$email_subject = $themeName_optionTree['email_subject'];
$success_message = '<p class="success-box">' . $themeName_optionTree['success_message'] . '</p>';
if (strlen($name) < 2) {
$error['name'] = 1;
}
if (!preg_match('/^[a-z0-9&\'\.\-_\+]+#[a-z0-9\-]+\.([a-z0-9\-]+\.)*+[a-z]{2}/is', $email)) {
$error['email'] = 1;
}
if (strlen($message) < 2) {
$error['message'] = 1;
}
if (!$error) {
require_once('PHPMailer_v5.1/class.phpmailer.php');
$mail = new PHPMailer(true);
try {
$mail->From = $email;
$mail->FromName = $name;
$mail->Subject = $email_subject;
$mail->AddAddress($site_owners_email, $site_owners_name);
$mail->Body = $message;
$mail->Send();
echo $success_message;
} catch (phpmailerException $e) {
echo '<p class="warning-box">' . $e->errorMessage() . '</p>';
} catch (Exception $e) {
echo '<p class="warning-box">' . $e->getMessage() . '</p>';
}
}
?>
Please note that the above code executes perfectly even when ajax returns 404, weird huh!.
Since the server sends a 404 (for god knows what reason), there are two ways to fix/circumvent this:
Ignore the HTTP response code and change success to complete in the jQuery ajax call, so that the handler is executed when the request is done no matter the server response. You know the server response (it always works). The HTML should still be available in the jQuery complete handler.
Overwrite the 404 that something sends on the server (probably something Wordpress) by executing (before printing any output): header('HTTP/1.1 200 OK'). Since the script is executed, this will overwrite the crazy 404 and jQuery will receive that 200 and execute the success handler.
You could try both =) I'm pretty sure the first one will work (but that's not so clean). I'm also pretty sure the 2nd will work, but I don't know Wordpress well enough to make promises =)
I'm guessing it's because Wordpress already has an AJAX mechanism built in and it stops you from implementing it on your own. This page explains how to add AJAX to plugins:
http://codex.wordpress.org/AJAX_in_Plugins
Here's a snippet from the page:
Ajax on the Administration Side
Since Ajax is already built into the core WordPress administration screens, adding more administration-side Ajax functionality to your plugin is fairly straightforward, and this section describes how to do it.
Here's a short example. All this will be in one file.
First, add some javascript that will trigger the AJAX request:
<?php
add_action('admin_print_scripts', 'my_action_javascript');
function my_action_javascript() {
?>
<script type="text/javascript" >
jQuery(document).ready(function($) {
var data = {
action: 'my_action',
whatever: 1234
};
// since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php
$.post(ajaxurl, data, function(response) {
alert('Got this from the server: ' + response);
});
});
</script>
<?php
}
Then, set up a PHP function that will handle that request:
<?php
add_action('wp_ajax_my_action', 'my_action_callback');
function my_action_callback() {
global $wpdb; // this is how you get access to the database
$whatever = intval( $_POST['whatever'] );
$whatever += 10;
echo $whatever;
die(); // this is required to return a proper result
}
That's it! You will need to add a few details, such as error checking and verifying that the request came from the right place ( using check_ajax_referer() ), but hopefully the example above will be enough to get you started on your own administration-side Ajax plugin.
NOTE: Since Version 2.8, The javascript global variable ajaxurl can be used in case you want to separate your javascript code from php files into javascript only files. This is true on the administration side only.
As seen here https://cooltrainer.org/fixing-false-404-headers-on-external-pages-including-wp-blog-header-php/ this solution tested and works well:
require_once("path/to/wp-config.php");
$wp->init();
$wp->parse_request();
$wp->query_posts();
$wp->register_globals();
$wp->send_headers();
Without digging into the problem, you might check that the ajax request is actually going where you think it is going. There could be several things going on here, such as the server is set up to redirect any requests to /wp-content/ somewhere else.
Capture some header information using firebug, and perhaps livehttp headers.

Categories