Connecting a purple air sensor to my server

in the registration page says “To help community science and improve air quality forecasting, share your device’s location and sensor readings with The Weather Company, LLC (includes Weather Underground and The Weather Channel branded platforms).”
last two days i’m trying to send data to my own web server using php.
no good. i can see in my router the sensor opening connection to my web server.
trying to dump data with this php script

<?php
// Configure these
$log_file = 'purpleair_log.json'; // JSON log file
$debug_log = 'purpleair_debug.log'; // Human-readable log

// Get the raw JSON input
$json_input = file_get_contents('php://input');
$data = json_decode($json_input, true);

// Prepare logs
$timestamp = date('Y-m-d H:i:s');
$ip = $_SERVER['REMOTE_ADDR'];

// 1. Save raw JSON data (for machines)
file_put_contents($log_file, $json_input . "\n", FILE_APPEND);

// 2. Create human-readable debug log
$debug_entry = <<<LOG
===== [{$timestamp}] =====
IP: {$ip}
Sensor ID: {$data['SensorId']}
Location: {$data['lat']}, {$data['lon']}
PM2.5 AQI: {$data['pm2.5_aqi']}
Uptime: {$data['uptime']} seconds
RSSI: {$data['rssi']} dBm
Full Data:
LOG;

file_put_contents($debug_log, $debug_entry . print_r($data, true) . "\n\n", FILE_APPEND);

// Required response for PurpleAir
header('Content-Type: application/json');
echo json_encode(['status' => 'success', 'message' => 'Data logged']);
?>

it seems that no connection reaches the web server..
does anyone have a success story on this ?

these are my settings..

really ? none tried to import the data into his own database ?

well, after an evening of tests, i found out that the Data processor #1 is ..decorative.
same script in #2 works, in #1 it doesn’t..

when i use requestbin as data processor, i get data…

In your “decorative” image, note that the Content-type: header is present in #1 but absent in #2. Your web or app server may be reacting to the differing content-type, disallowing application/json but allowing unspecified (which may be assumed to be something like application/www-form-urlencoded). Check your logs and see if your web/app server is returning an error code to the hits with the content-type specified.

If your sensor is accessible from your server, you may find it easier to poll the sensor directly for readings. It has a /json endpoint you can hit and get data from.

ok, the “decorative” issue fixed.
both urls are “visited” from purple air, the result is 200

[15/Jun/2025:04:44:38 +0300] "POST /purple/log_data.php HTTP/1.1" 200 264 "-" "PurpleAir/7.02"

the script i run is this:

<?php
date_default_timezone_set("Europe/Athens");
$logFile = 'all_data.log'; // File to store logged data
$data = file_get_contents('php://input'); // For raw POST data
$queryParams = $_GET; // For GET parameters
$postParams = $_POST; // For form-encoded POST data

$log = "Time: " . date('Y-m-d H:i:s') . "\n";
$log .= "Raw Data: " . $data . "\n";
$log .= "GET Params: " . json_encode($queryParams) . "\n";
$log .= "POST Params: " . json_encode($postParams) . "\n";
$log .= "--------------------------\n";

file_put_contents($logFile, $log, FILE_APPEND);
echo "Data received and logged.";
?>

but the result remains empty:

--------------------------
Time: 2025-06-15 04:46:38
Raw Data: 
GET Params: []
POST Params: []
--------------------------

lets describe the solution…

  • The request was reaching my server.
  • It’s a POST with Transfer-Encoding: chunked.
  • PHP handles it without errors — but no body content is exposed to PHP, not even when reading with fopen('php://input')

My server (Apache with PHP-FPM) does not buffer or pass chunked request bodies to PHP correctly. This is a known problem in some configurations, especially:

  • Apache + PHP-FPM (via proxy_fcgi)
  • Certain versions of Apache 2.4.x
  • PHP < 8.1 or misconfigured FPM

When Transfer-Encoding: chunked is used, Apache must buffer and reassemble the body before passing it to PHP. If it doesn’t, PHP sees an empty input stream.

so, I tried using mod_php Instead of php-fpm

and the problem solved !!!

Time: 2025-06-15 05:20:39
Raw Data: {"SensorId":"c8:c9:a3:f:5c:6c","DateTime":"2025/06/15T02:20:38z","Geo":"PurpleAir-5c6c","Mem":15808,"memfrag":28,"memfb":11288,"memcs":1096,"Id":10900,"lat":40.637901,"lon":22.948400,"Adc":0.01,"loggingrate":15,"place":"outside","version":"7.02","uptime":87377,"rssi":-72,"period":120,"httpsuccess":1505,"httpsends":2207,"hardwareversion":"2.0","hardwarediscovered":"2.0+BME280+PMSX003-B+PMSX003-A","current_temp_f":80,"current_humidity":49,"current_dewpoint_f":59,"pressure":1014.80,"p25aqic_b":"rgb(255,207,0)","pm2.5_aqi_b":86,"pm1_0_cf_1_b":17.79,"p_0_3_um_b":3052.34,"pm2_5_cf_1_b":28.59,"p_0_5_um_b":914.24,"pm10_0_cf_1_b":29.67,"p_1_0_um_b":184.55,"pm1_0_atm_b":17.79,"p_2_5_um_b":10.12,"pm2_5_atm_b":28.31,"p_5_0_um_b":1.90,"pm10_0_atm_b":29.67,"p_10_0_um_b":0.09,"p25aqic":"rgb(255,207,0)","pm2.5_aqi":86,"pm1_0_cf_1":18.56,"p_0_3_um":3223.58,"pm2_5_cf_1":28.28,"p_0_5_um":967.60,"pm10_0_cf_1":29.75,"p_1_0_um":194.23,"pm1_0_atm":18.47,"p_2_5_um":10.61,"pm2_5_atm":28.23,"p_5_0_um":2.00,"pm10_0_atm":29.75,"p_10_0_um":0.96,"pa_latency":312,"response":200,"response_date":1749953925,"latency":46,"response_b":200,"response_date_b":1749953930,"latency_b":104,"wlstate":"Connected","status_0":2,"status_1":2,"status_2":2,"status_3":2,"status_4":0,"status_6":1,"status_10":2}
GET Params: []
POST Params: []
--------------------------

THANK YOU FOR YOUR PATIENCE !!!