Weather radar images on 6.4" C-Touch screen pages.

Discussion in 'C-Bus Wired Hardware' started by Brendan Rogers, Jun 16, 2013.

  1. Brendan Rogers

    ssaunders

    Joined:
    Dec 17, 2008
    Messages:
    231
    Likes Received:
    31
    Location:
    Melbourne
    Using WeatherZone data

    Nice work, Brad.

    I normally use WeatherZone data feeds, so your approach set me to work on an animation with radar and lightning strike data.

    First cut of the approach below in case others want to follow.

    I made some improvements to your approach regarding memory utilisation used in prefix/suffix processing, basically getting rid of the large arrays and directly reading/writing. The logic is a lot simpler, too, but relies on reading the current set of timestamps available from WeatherZone, and not assuming images from certain times will be available by calculation (I've found these are sometimes not exactly 6 minutes apart). I've set my code to pull around 1K of data from the WeatherZone web site every 2 minutes at the moment, which needs further work on the logic. My plan is to only have the CTC get the current list of timestamps (and keep updating the list over time) when the radar page is user selected.

    The radar animation is quite sluggish on a CTC2. Should be much better on the CTC3. I am using very large radar images, which would explain it (960x720), though not scaling them, just cropping with css clip (a wonderful feature, by the way). There are two animation layers as well, being the radar and lightning overlays, so dropping lightning would help make it snappier.

    Thanks for sharing your approach.

    (Note that copyright notices are not included in this proof of concept. Make sure you have authorisation to use. I also don't recommend hitting the WeatherZone site every 2 minutes 24x7 to get the radar timestamp list.)

    Here's the modified prefix and suffix, along with the radarimages() call generated by logic:

    Code:
    <!DOCTYPE HTML>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
    
    <script type="text/javascript">
    var radarview = new Array();
    var lightview = new Array();
    
    function radarimages() {
      for (i = 0; i < radarimages.arguments.length; i++) {
        radarview[i] = new Image();
        lightview[i] = new Image();
        radarprefix = "http://otf.weatherzone.com.au/otfimage/timestamped/radar/reflectivity/radar/002/";
        radarsuffix = "/twc15/0/radarz/002/radsat_640/960x720/image.png";
        lightprefix = "http://otf.weatherzone.com.au/otfimage/timestamped/lightning/radarz/002/radsat_640/gpats/";
        lightsuffix = "/60/4/960x720/image.png";
        radarview[i].src = radarprefix.concat(radarimages.arguments[i], radarsuffix);
        lightview[i].src = lightprefix.concat(radarimages.arguments[i], lightsuffix);
      }
    }
    &lt;/script>
    
    &lt;style type="text/css">
    #radargallery { position: absolute; top:0px; left:0px; width:480px; height:420px; }
    #radargallery img { position: absolute; margin-top:-150px; margin-left:-240px;
    clip: rect(150px, 720px, 570px, 240px);
    clip: rect(150px  720px  570px  240px); // pre-ie8 syntax
    }
    #layer1 { z-index: 10; }
    #layer2 { z-index: 20; }
    html, body { overflow: hidden; }
    &lt;/style>
    
    &lt;/head>
    
    &lt;body scroll="no">
    
    &lt;div id="radargallery">
    &lt;div id="radarbackground">&lt;img src="terrain_radarz_002_960x720.jpg">&lt;/div>
    &lt;img id="layer1" src="placeholder.png" alt="Currently Updating" name="radar_link">
    &lt;img id="layer2" src="placeholder.png" alt="Currently Updating" name="light_link">
    &lt;div id="radarforeground">&lt;img src="locations_radarz_002_960x720.gif">&lt;/div>
    &lt;/div>
    
    &lt;script>
    // ^^^^^ Prefix
    radarimages("201311171030","201311171036","201311171042","201311171048","201311171054","201311171100","201311171106","201311171112","201311171118","201311171124","201311171130");
    // vvvvv Suffix
    
    var radarindex=0;
    
    function ImageSwitch() {
      if (!document.images) return;
      document.images.radar_link.src=radarview[radarindex].src;
      document.images.light_link.src=lightview[radarindex].src;
      if (radarindex < radarview.length - 1) { radarindex++; setTimeout("ImageSwitch()",800); } else { radarindex=0; setTimeout("ImageSwitch()",2500); }
    }
    
    ImageSwitch()
    
    &lt;/script>
    
    &lt;/body>
    &lt;/html>
    
    And the gist of the module in logic:

    Code:
    Some variables (there are others, though, some integer counters and using_page http boolean semaphore)...
    
    weather_url : array [1..5] of midstring;
    radar_timestamp : array [1..25] of integer;
    radar_last_timestamp : array [0..12] of char;
    
    From initialisation...
    
    Format(weather_url[5],'http://data.weatherzone.com.au/json/animator/','?&lt=radarz&lc=002&type=radar&xli=1','&scope=60&xsync=1&rel=false&md=960x720');
    
    From module...
    
    if (not using_page) then
    begin
      using_page := true;
      GetHTTPData(weather_url[5]);
      TimerStart(WeatherGetTimer);
      repeat
        delay(1);
        ReadHTTPData(page);
      until (page<>'') or (TimerTime(WeatherGetTimer) >= 10);
      TimerStop(WeatherGetTimer);
      if (page<>'') then
      begin
        //locate timestamps
        position := 1;
        count := 0;
        repeat
          count := count + 1;
          position := pos2('/twc15/',page,position) - 12;
          radar_timestamp[count] := position;
          position := position + 13;
        until (position-13 < 0) or (position >= length(page));
        count := count - 1;
      end;
    
      if (count > 0) then
      begin
        // check whether last timestamp updated, and if not then don't update the html file
        copy(s,page,radar_timestamp[count],12);
        if (s <> radar_last_timestamp) then
        begin
          radar_last_timestamp := s;
          
          AssignFile(file2, 'weatherradar.html');
          ReWrite(file2);
    
          AssignFile(file1, 'weatherradar_prefix.html'); Reset(file1); while not eof(file1) do begin Readln(file1, s); Writeln(file2, s); end; CloseFile(file1);
        
          Write(file2, 'radarimages(');
          for i := count-10 to count do
          begin
            copy(s,page,radar_timestamp[i],12);
            Write(file2, '"',s,'"');
            if i=count then Writeln(file2,');') else Write(file2,',');
          end;
    
          AssignFile(file1, 'weatherradar_suffix.html'); Reset(file1); while not eof(file1) do begin Readln(file1, s); Writeln(file2, s); end; CloseFile(file1);
    
          CloseFile(file2);
        end;
        using_page := false;
      end;
      
      delay(120);
    end;
    
    Image of the touch screen (apologies - no serious weather activity :)):

    [​IMG]
     
    Last edited by a moderator: Nov 18, 2013
    ssaunders, Nov 17, 2013
    #41
  2. Brendan Rogers

    ssaunders

    Joined:
    Dec 17, 2008
    Messages:
    231
    Likes Received:
    31
    Location:
    Melbourne
    In case anyone is interested, updated logic below to ensure that WeatherZone site is only repeatedly polled for radar timestamps while the radar is displayed on screen, or when first selected by the user.

    A launch page is used that shows a 'Loading...' message. The logic detects this page is displayed and kicks off the update cycle. If the radar or the launch page is not displayed, then the update cycle ends.

    Cheers.

    Code:
    if ShowingPage("Weather Radar Launch") and (not show_radar_page) then
    begin
      radar_last_timestamp := '';
      show_radar_page := true;
    end;
    
    if (not (ShowingPage("Weather Radar Launch") or ShowingPage("Weather Radar"))) then
    begin
      show_radar_page := false;
      ExitModule;
    end;
    
    if (TimerTime(RadarGetTimer) > 59) or (show_radar_page) then
    begin
      if (not using_page) then
      begin
        using_page := true;
        GetHTTPData(weather_url[5]);
        TimerStart(WeatherGetTimer);
        repeat
          delay(1);
          ReadHTTPData(page);
        until (page<>'') or (TimerTime(WeatherGetTimer) >= 10);
        TimerStop(WeatherGetTimer);
        if (page<>'') then
        begin
          //locate timestamps
          position := 1;
          count := 0;
          repeat
            count := count + 1;
            position := pos2('/twc15/',page,position) - 12;
            radar_timestamp[count] := position;
            position := position + 13;
          until (position-13 < 0) or (position >= length(page));
          count := count - 1;
        end;
    
        if (count > 0) then
        begin
          // check whether last timestamp updated, and if not then don't update the html file
          copy(s,page,radar_timestamp[count],12);
          if (s <> radar_last_timestamp) then
          begin
            radar_last_timestamp := s;
          
            AssignFile(file2, 'weatherradar.html');
            ReWrite(file2);
    
            AssignFile(file1, 'weatherradar_prefix.html'); Reset(file1); while not eof(file1) do begin Readln(file1, s); Writeln(file2, s); end; CloseFile(file1);
        
            Write(file2, 'radarimages(');
            for i := count-10 to count do
            begin
              copy(s,page,radar_timestamp[i],12);
              Write(file2, '"',s,'"');
              if i=count then Writeln(file2,');') else Write(file2,',');
            end;
    
            AssignFile(file1, 'weatherradar_suffix.html'); Reset(file1); while not eof(file1) do begin Readln(file1, s); Writeln(file2, s); end; CloseFile(file1);
    
            CloseFile(file2);
          end;
          using_page := false;
        end;
      
        TimerStart(RadarGetTimer);
    
        if show_radar_page then begin ShowPage("Weather Radar"); show_radar_page := false; end;
      end;
    end;
    
     
    ssaunders, Nov 17, 2013
    #42
  3. Brendan Rogers

    bmerrick

    Joined:
    Jun 13, 2007
    Messages:
    434
    Likes Received:
    34
    Location:
    Sydney
    Hi Steve,

    That's really great work there. Love the use of CLIP rect!! Excellent idea.

    I think the HTML 'stuffing' method does work well for making custom content pages that can't always be accessed directly in the CTC browser for memory, flash or other reasons, as you can make your own pages by parsing others. Glad to see it was some help. You are a much neater programmer than me!!!

    In case you or others were wondering, the sad ironic fact is that prior to release of my final multi-sweep BOM version, my house copped a decent lightning strike which simultaneously came in the Foxtel/Cable extreme modem and a power phase and toasted many systems on my Ethernet but also a few old things on the power system. The CTC2 power supply, which was old and already cracked with the usual age based heating was one of only 2 substantial 'deaths' on the power side. The Ethernet attached and Foxtel attached systems had less luck as my switch & Foxtel STU generously dosed out the spike to many devices care of the Telstra cable.

    Anyway, had been waiting for spares from RS for over a month and only rebuilt the CTC2 PSU at the end of Oct. CTC2 came back up which is great but haven't been back to look at the code though as it's really busy now, so I'm actually glad someone has grabbed 'the torch'. I think your approach is a good one.

    Keep them coming (and anyone else who has another good bit of code to help everyone-give it back to the forum-we probably all appreciate it more than your client does :p ) .....cya

    Brad
     
    bmerrick, Nov 18, 2013
    #43
  4. Brendan Rogers

    ssaunders

    Joined:
    Dec 17, 2008
    Messages:
    231
    Likes Received:
    31
    Location:
    Melbourne
    Used to be an assembler coder, then Pascal, then c, then c++. Can't shake the habit... :)

    Sorry to hear about the fry up.

    Steve
     
    ssaunders, Nov 18, 2013
    #44
  5. Brendan Rogers

    ssaunders

    Joined:
    Dec 17, 2008
    Messages:
    231
    Likes Received:
    31
    Location:
    Melbourne
    FYI, I tried changing to cropped 640x480 Weatherzone radar/lightning images instead of 960x720 and the display is still equally sluggish on the CTC2, so the source images are not the performance problem. Guess it's a browser or graphics rendering thing on the platform with multiple image layers.

    In case anyone wants the topography and place labels that I didn't link to...
    http://data.weatherzone.com.au/maplayers/wz/terrain/terrain_radarz_002_960x720.jpg
    http://data.weatherzone.com.au/maplayers/wz/locations/locations_radarz_002_960x720.gif

    Substitute 640x480 in the URL if you want the smaller size ones (obviously you'll need to change the prefix file to suit, along with the crop area). You can link straight to these on the wz site instead of using downloaded images as in my proof of concept.

    I've also added JavaScript to display image timestamp text in local time zone as a z-index layer. If anyone's interested I can post the code.

    Cheers,
    S.
     
    ssaunders, Nov 19, 2013
    #45
  6. Brendan Rogers

    bmerrick

    Joined:
    Jun 13, 2007
    Messages:
    434
    Likes Received:
    34
    Location:
    Sydney
    Hi Steve,

    Can tell ;)

    It had its good and bad points. The insurance process is painful but in the end got newer versions of some of the gear in return for the dead stuff. The problem will be the half dead stuff that fails in the next 12 months.

    Yep, and take a look at the memory left in the log. This is why I combined the BOM overlays using paintshop into a single file rather than 5 or 6 transparencies.

    Sure, post it up. Did it work on CTC2? I found some z-index issues where it worked perfectly in PICED simulation but wouldn't work on the screen itself albeit using an image rather than text.

    Have a good one,

    Brad
     
    bmerrick, Nov 19, 2013
    #46
  7. Brendan Rogers

    ssaunders

    Joined:
    Dec 17, 2008
    Messages:
    231
    Likes Received:
    31
    Location:
    Melbourne
    Works equally fine on the CTC2 and simulation as a z-index layer on top of the radar. Adjusts for local time zone, as the timestamps from both BOM and WZ are zulu. The code below is also adjusted for 640x480 WZ images.

    Code:
    &lt;!DOCTYPE HTML>
    &lt;head>
    &lt;meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
    
    &lt;script type="text/javascript">
    var radarview = new Array();
    var lightview = new Array();
    var timestamp = new Array();
    
    function radarimages() {
      var d = new Date(), ts, tst, h, m, i, radarprefix, radarsuffix, lightprefix, lightsuffix;
      for (i = 0; i < radarimages.arguments.length; i++) {
        ts = radarimages.arguments[i];
        radarview[i] = new Image();
        radarprefix = "http://otf.weatherzone.com.au/otfimage/timestamped/radar/reflectivity/radar/002/";
        radarsuffix = "/twc15/0/radarz/002/radsat_640/640x480/image.png";
        radarview[i].src = radarprefix.concat(ts, radarsuffix);
        lightview[i] = new Image();
        lightprefix = "http://otf.weatherzone.com.au/otfimage/timestamped/lightning/radarz/002/radsat_640/gpats/";
        lightsuffix = "/60/4/640x480/image.png";
        lightview[i].src = lightprefix.concat(ts, lightsuffix);
        tst = Number(ts.substring(8,10))*60 + Number(ts.substring(10,12)) + (d.getTimezoneOffset() * -1);
        if (tst >= 1440) { tst = tst - 1440; }
        h = Math.floor(tst / 60);
        m = Math.round(tst % 60);
        timestamp[i] = ("00" + String(h)).slice (-2) + ":" + ("00" + String(m)).slice (-2);
      }
    }
    &lt;/script>
    
    &lt;style type="text/css">
    #radargallery { position: absolute; top:0px; left:0px; width:480px; height:420px; }
    #radargallery img { position: absolute; margin-top:-30px; margin-left:-50px;
    clip: rect(30px, 480px, 450px, 50px); //960x720 640-480=220
    clip: rect(30px  480px  450px  50px); // pre-ie8 syntax
    }
    #layer1 { z-index: 10; }
    #layer2 { z-index: 20; }
    #layer3 { z-index: 30; position: absolute; top:0px; left:7px; color: white; font-family: "Arial",sans-serif; font-size: 10pt; }
    html, body { overflow: hidden; }
    &lt;/style>
    
    &lt;/head>
    
    &lt;body scroll="no">
    
    &lt;div id="radargallery">
    &lt;div id="radarbackground">&lt;img src="terrain_radarz_002_640x480.jpg">&lt;/div>
    &lt;img id="layer1" src="placeholder.png" alt="Currently Updating" name="radar_link">
    &lt;img id="layer2" src="placeholder.png" alt="Currently Updating" name="light_link">
    &lt;div id="layer3"> &lt;/div>
    &lt;div id="radarforeground">&lt;img src="locations_radarz_002_640x480.gif">&lt;/div>
    &lt;/div>
    
    &lt;script>
    // ^^^^^ Prefix
    radarimages("201311192030","201311192036","201311192042","201311192048","201311192054","201311192100","201311192106","201311192112","201311192118","201311192124","201311192130");
    // vvvvv Suffix
    
    var radarindex=0;
    
    function ImageSwitch() {
      if (!document.images) return;
      document.images.radar_link.src=radarview[radarindex].src;
      document.images.light_link.src=lightview[radarindex].src;
      document.getElementById('layer3').innerHTML = timestamp[radarindex];
      if (radarindex < radarview.length - 1) { radarindex++; setTimeout("ImageSwitch()",800); } else { radarindex=0; setTimeout("ImageSwitch()",2500); }
    }
    
    ImageSwitch()
    
    &lt;/script>
    
    &lt;/body>
    &lt;/html>
    
     
    ssaunders, Nov 21, 2013
    #47
Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.