#lang scribble/doc @(require scribble/manual) @title{Live} @author{@(author+email "jeeve" "jvjulien@free.fr")} @defmodule[(planet jeeve/live)]{ This basic library provided client web service and graphics to follow specifical values in web pages.} @section{Values} @defproc[(live-web-number [url string?] [key-line string?] [regexp-pattern string?] [error-value number? 0] [delta-nb-lines number? 0]) number?] Extracts a value in a web page. Returns error-value if value not found or internet connection failed. Example to get wind velocity on a spot location (via @link["http://www.winds-up.com"]{winds-up} web page) @itemlist[ @item{Open the web site} @item{Inspect HTML code @image[#:scale 0.5 "./images/html.png"]} ] To find appropriate parameters, visualize position of searched value. Search a word to locate a reference line (key-line parameter). In the example, we choose "Aujourd" for the key-line word with delta-nb-lines = 3 to jump to velocity wind value. The value is an integer, therefore regexp-pattern parameter is "[0-9]+". Which gives @racketinput[(live-web-number "http://www.winds-up.com/index.php?p=spots&id=21" "Aujourd" "[0-9]+" -1 3)] Returns wind velocity read as an integer on winds-up web site at 3 lines after that containing "Aujourd" word. Otherwise returns -1. Another examples: Wind velocity at Belle-Ile, France via meteociel web site @racketinput[(live-web-number "http://www.meteociel.fr/observations-meteo/vent.php" "Belle-Ile" "[0-9]+ km/h")] Water level web service @racketblock[ (define (water-level id-station) (lambda () (live-web-number (string-append "http://www.vigicrues.gouv.fr/niveau3.php?idstation=" (number->string id-station) "&idspc=21&typegraphe=h&AffProfondeur=24" "&AffRef=auto&AffPrevi=non&nbrstations=3&ong=2") "Date" "[0-9]+\\.[0-9]+")))] @section{Graphics} @defproc[(live-graph [label string?] [function (-> number?)] [rate number?] [title string?]) any/c] Graphic evolution of value in web page. An example to display water level at Cavaillon in France (id-station = 142) @racketinput[(live-graph "Water level (m)" (water-level 142) (* 5 60) (code:comment "refresh each 5 minutes") "Cavaillon")] An other example to obtain pressure level in Paris @racketblock[ (define (pressure-paris) (live-web-number "http://www.station-meteo.com/historique-fr75020-paris/" "Pression atmosphérique" "[0-9]+\\.[0-9]+" -1 7))] With axis scale parameterize @racketblock[ (parameterize ([delta-x (* 12 3600)] (code:comment "12 hours") [delta-y 0.01]) (code:comment "1 %") (live-graph "Level pressure (hPa)" pressure-paris (* 5 60) "Paris"))] Use live-dashboard function to plot multiple web services @defproc[(live-dashboard [labels (listof (listof string?))] [functions (listof (listof (-> number?)))] [rate number?] [title string?]) any/c] This function displays graphics in rows and columns disposition. Each sublist is a row. @racketinput[(live-dashboard '(("Ners" "Besseges")) (list (list (water-level 38) (water-level 31))) (* 5 60) "Water level (m)")] The same but with one function of label parameter @defproc[(live-dashboard-one-ft [labels (listof (listof string?))] [function (-> string? number?)] [rate number?] [title string?]) any/c] Example: @racketinput[ (live-dashboard-one-ft '(("Paris" "Marseille")) pressure (* 15 60) "Pressure level (hPa)")] @racket[(pressure "Paris")] and @racket[(pressure "Marseille")] will be called every 15 minutes. @section{Database} Data displayed in graphs can be saved in real time in a database. For this you can use @racket[new-value-event] parameter with @racket[insert-into-db] procedure. First, describe your dabatase schema in a db-struct structure @defstruct*[db-struct ([connection connection?] [table-name string?] [field-label string?] [field-date-time string?] [field-value string?])] Then, use this function in @racket[new-value-event] handler @defproc[(insert-into-db [db db-struct?] [label string?] [seconds exact-integer?] [value string?]) void?] Example with a table named T_Data containing 3 fields F_Label, F_DateTime and F_Value: @racketblock[ (define my-db (db-struct (odbc-connect #:dsn "BdLive" #:user "" #:password "") "T_Data" "F_Label" "F_DateTime" "F_Value")) (parameterize ([new-value-event (lambda (label seconds value) (insert-into-db my-db label seconds value))]) (live-graph "test" (lambda () 10) 2 "demo"))]