riquezjp / kitchenTV

Kitchen TV; weather, clock, live news feeds & video for Raspberry pi using PHP/javascript
GNU General Public License v3.0
26 stars 12 forks source link

Adding alert windows for weather alerts #5

Closed JoshuaKimsey closed 7 years ago

JoshuaKimsey commented 7 years ago

So a thought occurred to me a few days ago and I decided to try an implement it today. That's the ability to receive weather alerts for your location you have set. Using Materialize's card system, I created a window that will appear under the clock and news feed on the right side at the bottom. You can see in the pictures I attached what it looks like. Using Wunderground, it wouldn't be hard to search the iFrame for the div tags associated with the weather alert badges they use on the site for your location. It could even be made to change the color of the box based on the severity of the alert.

What I will need is your help in making the PHP to do such a search of the iFrame, as I am completely unfamiliar with how PHP works in that regard. It might also be possible to do it with JS, but again I'd need your help to achieve that. I do think this would be a great feature, especially for those of us that live in rather active weather zones! (Like me! ⛈ 🌪 )

I'll update my fork with the added code for the alert box here shortly, after I fix a few other issues. Here are the pictures of what the alert box looks like:

screen shot 2017-06-18 at 10 54 56 pm screen shot 2017-06-18 at 11 02 10 pm

JoshuaKimsey commented 7 years ago

Just for a bit of clarification about what I mean by grabbing the warning data using PHP/JS. You can see in the picture in the last post the alert banner on the Wunderground site that says "Heat Advisory, Beach Hazard Statement". Here's the HTML code for that banner starting at where the iFrame is loaded, down to the text for the banner. This is what would need to be grabbed by either the PHP or the JS code. (Be sure and click on the image itself to see it clearly. The preview is loading really blurry for me for some reason)

screen shot 2017-06-18 at 11 09 08 pm

riquezjp commented 7 years ago

Hi J95, That will work but only if you have the page refreshing every so often as the code will need to run the check for a warning, say every 20 mins. Ill have a look now how best to extract that warning div

riquezjp commented 7 years ago

ok, added this. config - enter your wu local weather page URL index - uncomment the wu_advisory function call or move it to where you prefer. inc_library - new function created to extract the html css - create some to style it as prefered 😃

JoshuaKimsey commented 7 years ago

Cool! Wunderground naturally updates on its own every couple of minutes, so that by itself won't be an issue. Having the code update might be slightly trickier. A loop could be used, but I wonder if that'd effect performance in any way. You can see on there that the color preference for the alert box on Wunderground is determined by the "defcon" setting, 3 being yellow, 2 being orange, and 1 being red. That could be read by the code to determine the color of the alert box.

JoshuaKimsey commented 7 years ago

Lol! We posted at the same time! That's awesome! I'll check out the code! Did you use the Materialize boxes or did you make your own?

riquezjp commented 7 years ago

you will still need a refresh of some kind. Although WU updates its page, once our page extracts the alert it is now just some plain html inserted on our page.

I did not apply any styling, it's just plain html but it uses the same

direct from wu, so just create some css for it.

JoshuaKimsey commented 7 years ago

Oh hey! You added the materialize code to your main branch! That's awesome! :tada: Does this mean my fork and your fork are mostly equivalent now?

You want the code for the materialize card boxes so you can see how they work? The code for the card box starts with the div with the "row" class.


<div class="col2 <?php echo bg('col2'); ?>">
        <a href="javascript:;" onclick="document.forms['poster'].submit();">
            <div class="clocks">
                <canvas id="canvas" width="500" height="500"></canvas>
            </div>
        </a>

        <div id="news"></div>

        <div class="row" style="display: none;">
            <div class="col s12">
                <div class="card yellow darken-3">
                    <div class="card-content white-text">
                        <span class="card-title">Weather Alert!<i class="material-icons right small pulse">warning</i> </span>
                        <p>Heat Advisory</p>
                    </div>
                </div>
            </div>
        </div>
    </div>
`
JoshuaKimsey commented 7 years ago

Hey, I found a few issues. Firstly, unless I've gone code-blind, I don't see the changes you made to extract the HTML code from WU. Also, seems like some of the formatting is messed up on the index, namely the nav bar is off the screen, but that's probably just a CSS issue.

riquezjp commented 7 years ago

The changes are in 3 files. • config.php - set your WU URL (at the bottom) • inc_library.php - the main extract function (also at the bottom) • index.php, below the news feed is where it will appear. The php is disabled & commented out with // so remove the 2 slashes to activate it

screen shot 2017-06-19 at 1 22 59 pm

riquezjp commented 7 years ago

The github code isnt updating - i am uploading & commiting the files, but they dont seem to be changing

riquezjp commented 7 years ago

worked now!

JoshuaKimsey commented 7 years ago

Awesome! I'll check it out now!

JoshuaKimsey commented 7 years ago

Ok, that looks like an awesome way to capture the warning alerts from WU! One question though, any chance you could explain how that short bit of code works in the inc_library file to capture the code? I'm trying to understand PHP better, and that would help me greatly if you explain how that reads the html code, and how to capture the code inside the html tags! 🙂

riquezjp commented 7 years ago

sure :-)

function wu_advisory($wupage){
    $file=file_get_contents("$wupage");
    preg_match_all("%<div class=\"alert-items\">(.*?)</div>%s", $file, $alert,PREG_PATTERN_ORDER);
    return $alert[0][0];
}

line 1 - create a function called wu_advisory that will accept the variable $wupage (your URL) line 2 - get the contents of the file "$wupage" (in this case the HTML of the page) & store it in a variable called $file line 3 - preg_match_all() performs a regular expression scan of the file to find patterns In this case the pattern is <div class=\"alert-items\">(.*?)</div> everything (.*?) between those two specific tags preg_match_all will continue though the file & find other matches too, but in this case there is only one. line 4 - preg_match_all will store the pattern matches in 2 arrays $alert[0] & $alert[1] the first is everything including the search tags, the 2nd is just the stuff inside the pattern match. So we are using the 1st version $alert[0]. $alert[0][0] is the first match found, if there were more they would $alert[0][1] $alert[0][2] $alert[0][3] etc

riquezjp commented 7 years ago

regular expression code is a kind of shorthand to match patterns - it's found in many programing languages & tbh i find it quite confusing, so i stick with simple patterns & that's OK!

JoshuaKimsey commented 7 years ago

Awesome! Thank you so much for the tutorial! That helps me to understand that function a lot better! Also, I totally know what you mean by regular expression code. I like pattern matching a lot better! It's so much easier to understand! 😄

One question, how would I limit the search to just the a tags? I wanna skip the span tag that says "Active Advisory", because that's a bit redundant to have in the card system I'm using. Also, is there any way to search, and pull, the name of an html class using PHP? I wanna use that to determine the color of the background of the card based on the alert type.

JoshuaKimsey commented 7 years ago

Along with my question above, here's a picture showing my progress so far!

  • I added the alert code to the Materialize card box.
  • I moved the digital clock to its own card box above the canvas clock.
  • I added a button to the alert card box, that flashes when an alert is active, and links to the WU page for the location set by the user
  • I started working on an "About" page that will include links to your original video, the GitHub repo, and any other sites you'd like to list on there! :)

Still working on the finer touches, and I will implement the color code system of the alert card box when I figure out how to grab a class name using PHP. Also, the page still needs to be set to refresh every 5 mins or so, at least on the WU index anyways. The stream doesn't need to refresh often to prevent interruptions!

Anyways, here's the picture: screen shot 2017-06-19 at 3 44 00 am

riquezjp commented 7 years ago

2 way - use CSS to hide the span inside alert-items or use functions like str_replace(), substr(), strpos(), preg_replace() to modify what you have.

JoshuaKimsey commented 7 years ago

Awesome! Any idea how to pull a single HTML class name using PHP?

riquezjp commented 7 years ago

Sorry I am not sure I get what you mean. Do you mean the class names heat, beach, etc? If you have your own css for .heat{background-color: red;} then you dont need to extract it - or have i misunderstood?

JoshuaKimsey commented 7 years ago

No that's my fault! I wasn't being clear! In the iframe, the alert banner we grab the alert text from has a class called "defcon-3", with the number indicating what color the banner should be based on the alert severity. My question is, can we use PHP to grab that class name, as to be able to determine the alert severity, and use that to change the background color of the alert box I made under the click and news feed? If that info can be gotten, I can make it change the alert card boxes background, but we need to get that class name first in order to determine the alert severity. Can PHP grab class names, specifically from an iFrame?

riquezjp commented 7 years ago

ok, so just change alert-items to alert-bar in the reg-ex part, it will get the html from an earlier point.

preg_match_all("%<div class=\"alert-bar(.*?)</div>%s", $file, $alert,PREG_PATTERN_ORDER);

because you will be going up 1 div, you need to add an extra close div

return $alert[0][0]."</div>";

not tested it!

JoshuaKimsey commented 7 years ago

Ok, I can confirm that your code for gathering the classes from the div worked! Now I can work with JS/jQuery to pull just the "defcon-#" part from the class. Just so I don't make a bad error, that output from the PHP code is a string, correct? I assume that's what the "%s" means when it's used?

JoshuaKimsey commented 7 years ago

Ok, I have fixed the PHP, after crash-coursing myself, to change the color of the alert-box based on the alert severity. I also made it so the button in the top-right corner will lead to a new tab that opens to the WU page where you can see the alerts themselves.

I have actually found PHP to be not that bad of a language, despite what many people claim! 😄

If you wanna see what the code looks like, here it is:

//Determines the color of the alert-card based on the alert type
function wu_advisory_color($wupage){
    $file=file_get_contents("$wupage");
    preg_match_all("%<div class=\"alert-bar(.*?)</div>%s", $file, $alert_color, PREG_PATTERN_ORDER);
    $defcon = $alert_color[1][0];
    $defcon = substr($defcon, 8, 1);

    if ($defcon == "3") {
        return "$(function() { $('#alert-card').removeClass('red').removeClass('orange').removeClass('grey').addClass('yellow') });";
    } elseif ($defcon == "2") {
        return "$(function() { $('#alert-card').removeClass('red').removeClass('yellow').removeClass('grey').addClass('orange') });";
    } elseif ($defcon == "1") {
        return "$(function() { $('#alert-card').removeClass('orange').removeClass('yellow').removeClass('grey').addClass('red') });";
    } else {
        return "$(function() { $('#alert-card').removeClass('red').removeClass('orange').removeClass('yellow').addClass('grey') });";
    }

}
JoshuaKimsey commented 7 years ago

I have now also properly implemented the weather alert text into the Materialize card boxes! Again, PHP made that job really easy!

Here's the code! It's an updated version of your original function. I created both a condensed version and a more easily readable version, for people to learn from, that's commented out:

//Pulls the weather alert text from Wunderground for the user specified location
function wu_advisory($wupage){
        $file=file_get_contents("$wupage");
        preg_match_all("%<div class=\"alert-items\">(.*?)</div>%s", $file, $alert, PREG_PATTERN_ORDER);
        /* Detailed code for simpler viewing and understanding */
        //$alert_text = $alert[0][0];
        //$alert_text = strip_tags($alert_text);
        //$alert_text = trim($alert_text);
        //$alert_text = substr($alert_text, 16);
        //$alert_text = trim($alert_text);

        //Condensed code version
        $alert_text = trim(substr(trim(strip_tags($alert[0][0])), 16));
        return $alert_text;
    }
JoshuaKimsey commented 7 years ago

I updated my fork with the new code improvements I added! Hopefully everything will work correctly!

Note: I haven't updated the stream.php file with the new additions yet. Will do that in the next update.

Here's the link to my fork: https://github.com/hsoj95/kitchenTV

JoshuaKimsey commented 7 years ago

I have now added the weather alert box and the digital clock box to the stream.php file! With that, my goal of adding alert boxes is effectively complete!

I will go ahead and close this thread! One feature down, many to go! :D