Automatic Weather Forecast Tweet (PHP version)

From Domoticz
Jump to: navigation, search

Weather Forecast on Twitter with PHP

This wiki is applied to [1] http://www.domoticz.com/wiki/Automatic_Weather_Tweets . It is recommended to read that wiki first because there are some more detailled information for beginners.

The differences are:

* the code is written in PHP
* the PHP code is divided in two separate PHP scripts
* "tweet.php" is the generic PHP code for twittering any text stored in the variable $twitterwetter
* "tweet-forecast.php" is a PHP code which extracts a weather forecast for x hours in the future
* The "tweet-forecast.php" script starts the "tweet.php" script and that handover the data to Twitter.

The weather forecast is retrieved from weather underground: [2] http://www.wunderground.com/ .
A developers guide can be found here: [3] http://www.wunderground.com/weather/api/d/docs

We will come back to this documentation later on in this wiki.

The generic "tweet.php" script

    #!/usr/bin/php
    <?php
    #Twitter status update bot by http://360percents.com
    #Author: Luka Pusic <pusic93@gmail.com>
    #Translated to PHP by Dawt Maytrikx
     
    #REQUIRED PARAMS
    $username = urlencode("pinky.sugar@mail.com");
    $password = urlencode("1234567890");
 
    $tw = "/home/pi/domoticz/scripts/twitterwetter.txt";
    $wd = fopen ($tw, "r");
    $twitterwetter = fread ($wd, filesize($tw));
    fclose ($wd);
 
    $tweet = "$twitterwetter";
 
    $laenge = strlen($tweet);
    echo $laenge;
 
    #EXTRA OPTIONS
    $uagent = "Mozilla/5.0"; #user agent (fake a browser)
    $sleeptime = 0; #add pause between requests
     
    $host = fopen("cookie.txt", "w"); #create a temp. cookie file
    $ch = curl_init();
    curl_setopt_array($ch, array(//CURLOPT_MUTE => TRUE, //-s
    CURLOPT_COOKIE => "cookie.txt", //-b
    CURLOPT_COOKIEJAR => "cookie.txt", //-c
    CURLOPT_FOLLOWLOCATION => TRUE, //-L
    CURLOPT_SSLVERSION => 3, //--sslv3
    CURLOPT_USERAGENT => $uagent, //-A
    CURLOPT_RETURNTRANSFER => TRUE
    ));
 
    #GRAB LOGIN TOKENS
    echo "[+] Fetching twitter.com...\n";
    sleep($sleeptime);
 
    curl_setopt_array($ch, array(CURLOPT_URL => "https://mobile.twitter.com/session/new",
    ));
    $initpage = curl_exec($ch);
 
    preg_match("/<input.*authenticity_token.*value=\"(.*?)\".* \/>/i", $initpage, $matches);
    $token = $matches[1];
 
 
    #LOGIN
    echo "[+] Submitting the login form...\n";
    sleep($sleeptime);
 
    curl_setopt_array($ch, array(CURLOPT_URL => "https://mobile.twitter.com/session",
    CURLOPT_POSTFIELDS => "authenticity_token=$token&username=$username&password=$password",
    CURLOPT_POST => TRUE
    ));
    $loginpage = curl_exec($ch);
 
 
    #GRAB COMPOSE TWEET TOKENS
    echo "[+] Getting compose tweet page...\n";
    sleep($sleeptime);
 
    curl_setopt_array($ch, array(CURLOPT_URL => "https://mobile.twitter.com/compose/tweet",
    CURLOPT_POSTFIELDS => "",
    CURLOPT_POST => FALSE
    ));
    $composepage = curl_exec($ch);
 
    preg_match("/<input.*authenticity_token.*value=\"(.*?)\".*\/>/i", $composepage, $matches);
    $tweettoken = $matches[1];
 
 
    #TWEET
    echo "[+] Posting a new tweet: $tweet...\n";
    sleep($sleeptime);
 
    curl_setopt_array($ch, array(CURLOPT_URL => "https://mobile.twitter.com/",
    CURLOPT_POSTFIELDS => "authenticity_token=$tweettoken&tweet[text]=$tweet&tweet[display_coordinates]=false",
    CURLOPT_POST => TRUE
    ));
    $update = curl_exec($ch);
 
 
    #GRAB LOGOUT TOKENS
    curl_setopt_array($ch, array(CURLOPT_URL => "https://mobile.twitter.com/account",
    CURLOPT_POSTFIELDS => "",
    CURLOPT_POST => FALSE
    ));
    $logoutpage = curl_exec($ch);
 
    preg_match("/<input.*authenticity_token.*value=\"(.*?)\".* \/>/i", $logoutpage, $matches);
    $logouttoken = $matches[1];
 
    #LOGOUT
    echo "[+] Logging out...\n";
    sleep($sleeptime);
 
    curl_setopt_array($ch, array(CURLOPT_URL => "https://mobile.twitter.com/session/destroy",
    CURLOPT_POSTFIELDS => "authenticity_token=$logouttoken",
    CURLOPT_POST => TRUE
    ));
    $logout = curl_exec($ch);
 
 
    unlink("cookie.txt");
    curl_close($ch);
    exit(0);
    ?>


* Insert the eMail adress or username and the password of your Twitter account in the code.
* Save the tweet.php script in /home/domoticz/scripts and make it executable.
* This generic script will be called from the following PHP script.
* The variable $twitterwetter will contain the weather data to be twittered.

The specific PHP script for a "hourly" forecast (tween-forecast.php)

This one is specific for a weather forecast showing the predicted weather for the next hours in 1h steps.

The request can be send from a browser: [4]

http://api.wunderground.com/api/xxxxxxxxxxxxxxxx/hourly/lang:DL/q/germany/Solingen.json

Following parameters in this request have to be adapted:

The following PHP script is specific for a "hourly" forecast. If the "hourly" parameter is changed to any other, it will not work.
If any other weather information should be requested it has to be modified because the delivered array will have a different structure.

Here are all other possible request parameters: [6] http://www.wunderground.com/weather/api/d/docs?d=data/index

For more information have a look at this wiki: [7] http://www.domoticz.com/wiki/Extracting_status_and_measuring_values_with_PHP


tweet-forecast.php

 
    #!/usr/bin/php
    <?php
 
    //---get forecast for the next hours-------------------------
    //---see the wunderground webpage for other weather information download
    //---uselang:xx for language of your country
    //---change hourly to other values for other weather information
    //---change country and city
    $json_string = file_get_contents("http://api.wunderground.com/api/xxxxxxxxxxxxxxx/hourly/lang:DL/q/germany/Solingen.json");
    $parsed_json = json_decode($json_string, true);
 
 
    //---for debugging and development of own forecast combination
    //---this file will show the complete array of a weather forecast
    /**
    $wetterdatei = "/home/pi/domoticz/scripts/wetter_json.txt";
    $wd = fopen ($wetterdatei, "w+");
    fwrite ($wd, print_R($parsed_json, TRUE));
    fclose ($wd);
    */
 
    //--------- Weather in xh ------------------------------------
    //---look at the wetter_json.txt file about the structure
    $parsed_json = $parsed_json['hourly_forecast'][0]['FCTTIME'];
    //print_r($parsed_json);
 
    $stunde = $parsed_json['hour_padded'];
    $min = $parsed_json['min'];
    $tag = $parsed_json['mday_padded'];
    $monat = $parsed_json['mon_abbrev'];
    $jahr = $parsed_json['year'];
    echo $stunde.":".$min." ".$tag.".".$monat.".".$jahr."\n";
 
    $parsed_json = json_decode($json_string, true);
    $parsed_json = $parsed_json['hourly_forecast'][0]['temp'];
    $temp = $parsed_json['metric'];
    echo "Temp ".$temp."C"."\n";
 
    $parsed_json = json_decode($json_string, true);
    $parsed_json = $parsed_json['hourly_forecast'][0]['wspd'];
    $windspeed = $parsed_json['metric'];
    echo "Wind ".$windspeed."km/h"."\n";
 
    $parsed_json = json_decode($json_string, true);
    $parsed_json = $parsed_json['hourly_forecast'][0]['wdir'];
    $winddir = $parsed_json['dir'];
    echo "Windricht. ".$winddir."\n";
 
    $parsed_json = json_decode($json_string, true);
    $parsed_json = $parsed_json['hourly_forecast'][0];
    $humy = $parsed_json['humidity'];
    echo "Luftf. ".$humy."%"."\n";
 
    $parsed_json = json_decode($json_string, true);
    $parsed_json = $parsed_json['hourly_forecast'][0]['qpf'];
    $regen = $parsed_json['metric'];
    echo "Regen ".$regen."mm"."\n";
 
    $parsed_json = json_decode($json_string, true);
    $parsed_json = $parsed_json['hourly_forecast'][0]['snow'];
    $snow = $parsed_json['metric'];
    echo "Schnee ".$snow."mm"."\n";
 
    $parsed_json = json_decode($json_string, true);
    $parsed_json = $parsed_json['hourly_forecast'][0];
    $zustand = $parsed_json['condition'];
    echo $zustand."\n";
 
    $parsed_json = json_decode($json_string, true);
    $parsed_json = $parsed_json['hourly_forecast'][0];
    $regenwar = $parsed_json['pop'];
    echo "Regenrisiko ".$regenwar."%"."\n";
 
    $parsed_json = json_decode($json_string, true);
    $parsed_json = $parsed_json['hourly_forecast'][0]['mslp'];
    $druck = $parsed_json['metric'];
    echo "Luftdruck ".$druck."hPa"."\n";
 
    #$twitterwetter = "fuer ".$stunde.":".$min." ".$tag.".".$monat.".".$jahr."\n".$zustand."\n"."Temp ".$temp."C"."\n"."Luftf. ".$humy."%"."\n"."Regenrisiko ".$regenwar."% "."\n"."Regen ".$regen."mm"."\n"."Schnee ".$snow."mm"."\n"."Wind ".$windspeed."km/h"." aus ".$winddir." "."\n"."Luftdruck ".$druck."hPa";
    include('tweet.php');
 
    $twitterwetter = "fuer ".$stunde.":".$min." ".$tag.".".$monat.".".$jahr." ".$zustand." "."Temp ".$temp."C"." Luftf. ".$humy."%"." "."Regenrisiko ".$regenwar."% "."       "."     Regen ".$regen."mm"." "."Schnee ".$snow."mm"." "."Wind ".$windspeed."km/h"." aus ".$winddir." "."Luftdruck ".$druck."hPa";include('tweet.php'); 
    ?>

Now some explanatory notes about the code:

* for debugging activate the code part where the delivered data will be stored in a file named "wetter_json.txt"
* "wetter_json.txt" will show all the weather data for the next hours in a nice array structure.
* the row $twitterwetter = "fuer ..." will contain all the data to be delivered to Twitter. Be careful when you edit it.
* It is recommended for the first trials to insert only a valid weather underground API key and not change anything else.
* If this works start changing the language code, country, city and change the German language fragments.
* It is also possible to extract other data from the delivered array by changing the relevant "keys".
* Therefore read the wiki: [8]  http://www.domoticz.com/wiki/Extracting_status_and_measuring_values_with_PHP


parsed_json = $parsed_json['hourly_forecast'][0]; : The "key" [0] can be exchanged by [1],[2],[3],... since [0] shows the predicted weather in 1h, [1] in 2 hours and so on...


Some information for debugging if nothing is twittered:

* Only 140 characters will be twittered; if "$twitterwetter" will contain more nothing will happen.
* It is not possible to twitter the exactly same text more than once.
* Weather underground will accept only 500 API requests within 24h on a free account; 144 will be used by Domoticz (if you use weather underground info within Domoticz).
* "$twitterwetter" should not contain any "wrong" characters which could be misinterpreted as functional characters.
* include('tweet.php'); will start the "tweet.php" script automatically

An active Twitter account showing predicted weather can be found here: https://twitter.com/SGforecast https://twitter.com/SGforecast
(This Twitter also contains current weather from 2 Domoticz devices (Thermometer and hygrometer)).

WU forecast.jpg


The "predicted" weather forecast can be started by a cronjob.
This is explanied here: [9] http://www.domoticz.com/wiki/Automatic_Weather_Tweets

Summary

* create a Twitter account
* create the PHP script "tweet.php" in /home/pi/domoticz/scripts
* insert the Twitter account username or eMail account and password
* make "tweet.php" executable
* optional for first functional test: store something like "Hello" in the variable $twitterwetter" and start the "tweet.php" script from CLI (Putty) with ./tweet.php
* check if "Hello" is twittert
* create the PHP script "tweet-forecast.php" in /home/pi/domoticz/scripts
* make it executable
* you can create more than one "tweet-forecast.php" e.g. "tweet-forecast_1h.php", "tweet-forecast_2h.php" and so on and start them all with a cronjob to get a forecast for more than one  hour
* change the language, country and city in the PHP code
* optional: create a crontab which will start "tweet-forecast.php" every hour or so

Screenshot from CLI (Putty)

Here the script "tweet.php" is named "tweet-1.php"

Tweet.jpg

Example of an array (only shown the "keys" [0] to [1])

Array
(
   [response] => Array
       (
           [version] => 0.1
           [termsofService] => http://www.wunderground.com/weather/api/d/terms.html
           [features] => Array
               (
                   [hourly] => 1
               )
       )
   [hourly_forecast] => Array
       (
           [0] => Array
               (
                   [FCTTIME] => Array
                       (
                           [hour] => 20
                           [hour_padded] => 20
                           [min] => 00
                           [sec] => 0
                           [year] => 2014
                           [mon] => 2
                           [mon_padded] => 02
                           [mon_abbrev] => Feb
                           [mday] => 18
                           [mday_padded] => 18
                           [yday] => 48
                           [isdst] => 0
                           [epoch] => 1392750000
                           [pretty] => 8:00 PM CET on February 18, 2014
                           [civil] => 8:00 PM
                           [month_name] => Februar
                           [month_name_abbrev] => Feb
                           [weekday_name] => Dienstag
                           [weekday_name_night] => Dienstag Nacht
                           [weekday_name_abbrev] => Di
                           [weekday_name_unlang] => Tuesday
                           [weekday_name_night_unlang] => Tuesday Night
                           [ampm] => PM
                           [tz] => 
                           [age] => 
                       )
                   [temp] => Array
                       (
                           [english] => 45
                           [metric] => 7
                       )
                   [dewpoint] => Array
                       (
                           [english] => 36
                           [metric] => 2
                       )
                   [condition] => Bedeckt
                   [icon] => cloudy
                   [icon_url] => http://icons-ak.wxug.com/i/c/k/nt_cloudy.gif
                   [fctcode] => 4
                   [sky] => 100
                   [wspd] => Array
                       (
                           [english] => 8
                           [metric] => 13
                       )
                   [wdir] => Array
                       (
                           [dir] => Süd
                           [degrees] => 186
                       )
                   [wx] => 
                   [uvi] => 0
                   [humidity] => 66
                   [windchill] => Array
                       (
                           [english] => -9998
                           [metric] => -9998
                       )
                   [heatindex] => Array
                       (
                           [english] => -9998
                           [metric] => -9998
                       )
                   [feelslike] => Array
                       (
                           [english] => 45
                           [metric] => 7
                       )
                   [qpf] => Array
                       (
                           [english] => 
                           [metric] => 
                       )
                   [snow] => Array
                       (
                           [english] => 
                           [metric] => 
                       )
                   [pop] => 0
                   [mslp] => Array
                       (
                           [english] => 29.91
                           [metric] => 1012
                       )
               )
           [1] => Array
               (
                   [FCTTIME] => Array
                       (
                           [hour] => 21
                           [hour_padded] => 21
                           [min] => 00
                           [sec] => 0
                           [year] => 2014
                           [mon] => 2
                           [mon_padded] => 02
                           [mon_abbrev] => Feb
                           [mday] => 18
                           [mday_padded] => 18
                           [yday] => 48
                           [isdst] => 0
                           [epoch] => 1392753600
                           [pretty] => 9:00 PM CET on February 18, 2014
                           [civil] => 9:00 PM
                           [month_name] => Februar
                           [month_name_abbrev] => Feb
                           [weekday_name] => Dienstag
                           [weekday_name_night] => Dienstag Nacht
                           [weekday_name_abbrev] => Di
                           [weekday_name_unlang] => Tuesday
                           [weekday_name_night_unlang] => Tuesday Night
                           [ampm] => PM
                           [tz] => 
                           [age] => 
                       )
                   [temp] => Array
                       (
                           [english] => 44
                           [metric] => 7
                       )
                   [dewpoint] => Array
                       (
                           [english] => 36
                           [metric] => 2
                       )
                   [condition] => Bedeckt
                   [icon] => cloudy
                   [icon_url] => http://icons-ak.wxug.com/i/c/k/nt_cloudy.gif
                   [fctcode] => 4
                   [sky] => 100
                   [wspd] => Array
                       (
                           [english] => 8
                           [metric] => 13
                       )
                   [wdir] => Array
                       (
                           [dir] => Süd
                           [degrees] => 186
                       )
                   [wx] => 
                   [uvi] => 0
                   [humidity] => 68
                   [windchill] => Array
                       (
                           [english] => -9998
                           [metric] => -9998
                       )
                   [heatindex] => Array
                       (
                           [english] => -9998
                           [metric] => -9998
                       )
                   [feelslike] => Array
                       (
                           [english] => 44
                           [metric] => 7
                       )
                   [qpf] => Array
                       (
                           [english] => 
                           [metric] => 
                       )
                   [snow] => Array
                       (
                           [english] => 
                           [metric] => 
                       )
                   [pop] => 0
                   [mslp] => Array
                       (
                           [english] => 29.91
                           [metric] => 1012
                       )
               )


Changes

September 26th around 08:00 PM TWITTER seems to change something. An "\n" ( = Line feed) in the row $twitterwetter = ... was non more accepted by their system-
In consequence TWITTER does not propagate a new message when using this "\n" in a TWITTER-text.
Therefore I removed the "\n" by " " and everything was fine.