diff --git a/README.md b/README.md index e69de29..24cd66b 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,120 @@ +# Froggit Weather Station Protocols for Custom Server + +This documentation explains how to receive data from a Froggit weather station using your own server. It covers two protocols: **Ecowitt** (POST requests) and **Wunderground** (GET requests). + +### Hardware: +- DP2000 7-In-1 Y-Edition Wifi/Lan Wireless Weather Station: [Product Link](https://www.froggit.de/dp2000-7-in-1-y-edition-wifi-lan-wireless-weather-station.html) + +## Setup +1. **Power the Gateway**: Connect the Gateway to a power source, and after a short period, a new Wi-Fi network (GW2000X-WIFIXXXX) should appear. +2. **Connect to the Gateway’s Wi-Fi**: Use the Gateway’s Wi-Fi to connect and open `192.168.4.1` in your browser. +3. **Select Connection Type**: In the “Local Network” tab, select your preferred connection type: **WiFi** or **Ethernet** (via cable). +4. **Configure Protocol**: Under the "Weather Services" tab, choose the desired protocol type: **Ecowitt** or **Wunderground**. + +**Ecowitt Example**: + +![Ecowitt Protocol Setup](./images/customized_ecowitt.png) + +**Wunderground Example**: + +![Wunderground Protocol Setup](./images/customized_wunderground.png) + +## PHP Code +The `both.php` file supports both **Ecowitt** and **Wunderground** protocols. + +## Example Protocol Data + +### Ecowitt (POST) + +* **HTTP Method**: POST +* **Data Format**: URL-encoded body + +#### Example POST Data: + +```php +[PASSKEY] => 123***************************** +[stationtype] => GW2000A_V3.2.4 +[runtime] => 296 +[heap] => 110140 +[dateutc] => 2025-05-08 16:00:56 +[tempinf] => 69.26 +[humidityin] => 61 +[baromrelin] => 28.804 +[baromabsin] => 28.804 +[tempf] => 69.44 +[humidity] => 60 +[vpd] => 0.290 +[winddir] => 69 +[windspeedmph] => 0.00 +[windgustmph] => 3.36 +[maxdailygust] => 11.41 +[solarradiation] => 0.15 +[uv] => 0 +[rainratein] => 0.000 +[eventrainin] => 0.000 +[hourlyrainin] => 0.000 +[dailyrainin] => 0.000 +[weeklyrainin] => 0.000 +[monthlyrainin] => 0.000 +[yearlyrainin] => 0.000 +[totalrainin] => 0.000 +[wh65batt] => 0 +[freq] => 868M +[model] => GW2000A +[interval] => 8 +``` + +### Wunderground (GET) + +* **HTTP Method**: GET +* **Data Format**: URL parameters (Query Parameters) + +#### Example GET Data: + +```php +[ID] => 1 +[PASSWORD] => 1 +[tempf] => 69.44 +[humidity] => 60 +[dewptf] => 55.04 +[windchillf] => 69.44 +[winddir] => 69 +[windspeedmph] => 0.00 +[windgustmph] => 0.00 +[rainin] => 0.000 +[dailyrainin] => 0.000 +[weeklyrainin] => 0.000 +[monthlyrainin] => 0.000 +[yearlyrainin] => 0.000 +[solarradiation] => 0.15 +[UV] => 0 +[indoortempf] => 69.26 +[indoorhumidity] => 61 +[baromin] => 28.804 +[lowbatt] => 0 +[dateutc] => now +[softwaretype] => GW2000A_V3.2.4 +[action] => updateraw +[realtime] => 1 +[rtfreq] => 5 +``` + +--- + +## PHP Code Overview + +The provided PHP code extracts data from incoming **POST** (Ecowitt) and **GET** (Wunderground) requests and normalizes the values before storing them into an SQLite database. + +### Key Mapping from Wunderground to Ecowitt: + +```php +$WUNDERGROUND_TO_ECOWITT = array( + 'tempf' => 'tempf', + ... +); +``` + +--- +## Conclusion + +This setup allows you to receive weather station data from either **Ecowitt** or **Wunderground** protocols, process it on your custom server, and store the data in an SQLite database for further analysis. The PHP code provided normalizes the data and ensures compatibility with both protocols. diff --git a/both.php b/both.php new file mode 100644 index 0000000..ca4a7bf --- /dev/null +++ b/both.php @@ -0,0 +1,165 @@ + 'tempf', + 'humidity' => 'humidity', + 'indoortempf' => 'tempinf', + 'indoorhumidity' => 'humidityin', + 'UV' => 'uv', + 'winddir' => 'winddir', + 'windspeedmph' => 'windspeedmph', + 'windgustmph' => 'windgustmph', + 'dailyrainin' => 'dailyrainin', + 'weeklyrainin' => 'weeklyrainin', + 'monthlyrainin' => 'monthlyrainin', + 'yearlyrainin' => 'yearlyrainin', + 'dateutc' => 'dateutc', + 'solarradiation' => 'solarradiation', + 'softwaretype' => 'model', +); +//POST (ecowitt): +// [PASSKEY] => 123***************************** +// [stationtype] => GW2000A_V3.2.4 +// [runtime] => 296 +// [heap] => 110140 +// [dateutc] => 2025-05-08 16:00:56 +// [tempinf] => 69.26 +// [humidityin] => 61 +// [baromrelin] => 28.804 +// [baromabsin] => 28.804 +// [tempf] => 69.44 +// [humidity] => 60 +// [vpd] => 0.290 +// [winddir] => 69 +// [windspeedmph] => 0.00 +// [windgustmph] => 3.36 +// [maxdailygust] => 11.41 +// [solarradiation] => 0.15 +// [uv] => 0 +// [rainratein] => 0.000 +// [eventrainin] => 0.000 +// [hourlyrainin] => 0.000 +// [dailyrainin] => 0.000 +// [weeklyrainin] => 0.000 +// [monthlyrainin] => 0.000 +// [yearlyrainin] => 0.000 +// [totalrainin] => 0.000 +// [wh65batt] => 0 +// [freq] => 868M +// [model] => GW2000A +// [interval] => 8 + +//GET (wunderground): +// [ID] => 1 +// [PASSWORD] => 1 +// [tempf] => 69.44 +// [humidity] => 60 +// [dewptf] => 55.04 +// [windchillf] => 69.44 +// [winddir] => 69 +// [windspeedmph] => 0.00 +// [windgustmph] => 0.00 +// [rainin] => 0.000 +// [dailyrainin] => 0.000 +// [weeklyrainin] => 0.000 +// [monthlyrainin] => 0.000 +// [yearlyrainin] => 0.000 +// [solarradiation] => 0.15 +// [UV] => 0 +// [indoortempf] => 69.26 +// [indoorhumidity] => 61 +// [baromin] => 28.804 +// [lowbatt] => 0 +// [dateutc] => now +// [softwaretype] => GW2000A_V3.2.4 +// [action] => updateraw +// [realtime] => 1 +// [rtfreq] => 5 + +$NORMALIZATION = array( + 'dateutc' => fn ($dt) => new DateTimeImmutable($dt), + 'tempf' => fn ($temp) => normalizeTemperature($temp), + 'indoortempf' => fn ($temp) => normalizeTemperature($temp), + 'windspeedmph' => fn ($mph) => normalizeSpeed($mph), + 'windgustmph' => fn ($mph) => normalizeSpeed($mph), +); + +function ecowittKey($key) +{ + global $WUNDERGROUND_TO_ECOWITT; + + return empty($WUNDERGROUND_TO_ECOWITT[$key]) ? $key : $WUNDERGROUND_TO_ECOWITT[$key]; +} + +function normalizeSpeed($mph) +{ + // string to float + $mph = (float) $mph; + return mphToKmh($mph); +} + +function normalizeTemperature($fahrenheit) +{ + // string to float + $fahrenheit = (float) $fahrenheit; + // missing readings are represented as -9999 + return $fahrenheit == -9999 + ? null + : fToC($fahrenheit); +} + +function fToC($fahrenheit) +{ + return ($fahrenheit - 32) * 5 / 9; +} + +function mphToKmh($mph) +{ + // TODO: check + return $mph * 1.609344; +} + +function extractParameter($key) +{ + global $NORMALIZATION; + + $value = empty($_GET[$key]) ? $_POST[ecowittKey($key)] : $_GET[$key]; + + return isset($NORMALIZATION[$key]) + ? ($NORMALIZATION[$key])($value) + : $value; +} + +function dbConn($path) +{ + + try { + return new \PDO($path); + } catch (\PDOException $e) { + die($e->getMessage()); + } +} + +function createTable($conn) +{ + // TODO: + $conn->exec("CREATE TABLE IF NOT EXISTS weatherdata ( + id INTEGER PRIMARY KEY, + reading_date TIMESTAMP, + temperature INTEGER, + humidity INTEGER, + barometer_rel INTEGER, + barometer_abs INTEGER + )"); +} + +$conn = dbConn($dbPath); +createTable($conn); + +$res = extractParameter('dateutc'); +var_dump($res); + +$res = extractParameter('tempf'); +var_dump($res); diff --git a/images/customized_ecowitt.png b/images/customized_ecowitt.png new file mode 100644 index 0000000..865a28f Binary files /dev/null and b/images/customized_ecowitt.png differ diff --git a/images/customized_wunderground.png b/images/customized_wunderground.png new file mode 100644 index 0000000..d115038 Binary files /dev/null and b/images/customized_wunderground.png differ