Presentation is loading. Please wait.

Presentation is loading. Please wait.

Camtool - monitoring realtime information

Similar presentations


Presentation on theme: "Camtool - monitoring realtime information"— Presentation transcript:

1 Camtool - monitoring realtime information
webcam images for currently observing stations taken from remote URL, cached in Erlang DB webcam definitions stored in MySQL database URL, associated databasekey, refreshrate TSYS plots taken from logfile monitoring utility’s gnuplot frontend also cached locally in Erlang DB generate webpage(s) with dynamic content serve the images from Erlang i.s.o. disk fault tolerant: if process dies, restart it design, gen_server, supervisor (dynamic), mnesia, webtool

2 Startup of the utility start() ->
% gen_servers make interfacing to a % piece of code very simple! % They are trivial to create and GREAT % our mnesia database interface, a gen_server dumpstore:start(), % virtual time server, also a gen_server nowserver:start_link(), % these are supervisors webcammonitor:start_link(), tsysmonitor:start_link(), % webserver, mapping URLs to Erlang calls webtool:start( standard_path, [{port, 8000}, {bind_address, {0,0,0,0}}] ). design, gen_server, supervisor (dynamic), mnesia, webtool

3 a supervisor: webcammonitor
init(_) -> {one_for_one, 10, 1}, [ % This is the list of (static) ChildSpecifications % {Module, Function, [Arguments]} % the database connection first {dbconn, {mysql, start_link,[pool,”Host”, “User”, “Pass”, “DB”]}, permanent, 1000, worker, []}, % Poll(*) JSON from “.py” URL for current status % implemented as a gen_server {jsonneer, {jsonserver, start_link, []}, % Poll(*) the current status from the jsonserver % also implemented as a gen_server {monitorloop, {webcamloop, start_link, []}, permanent, 1000, worker, []} ] }. (*) In future version maybe publish-subscribe architecture design, gen_server, supervisor (dynamic), mnesia, webtool

4 a gen_server: jsonserver
% Handle a clock-tick, fetch new “current” data. handle_cast(tick, State) -> % Get the current time {{Y,M,D}, {HH,MM,SS}} = nowserver:datetime(), % Call a pythonscript over HTTP (queries SQLite DB and returns result as JSON) B = “ %d:%d:%d”, Url = io_lib:format(B, [Y,M,D,HH,MM,SS]), % Actually GET the json JSON = case of % only accept http-status “200” (succesfully retrieved url) {ok, {{_200,_}, _, Body}} -> Body; _ > [] end, % And parse it Obj = case rfc4627:decode(JSON) of {ok, {obj, KVList}, _} -> KVList; % Parsed into a [{Key, Value}[,{Key,Value}]] {ok, List, _} > [{stations, List}]; _ > [{stations, []}] {noreply, dict:store(currentjson, Obj, State)}. design, gen_server, supervisor (dynamic), mnesia, webtool

5 Dynamic supervision: add/remove childs otf
% Experiment stayed the same, now add/remove watchers update(NewExp, NewExp, CurrentStations, State) -> OldSet = sets:from_list(dict:fetch(stations, State)), NewSet = sets:from_list(CurrentStations), Removed = sets:subtract(OldSet, NewSet), Added = sets:subtract(NewSet, sets:intersection(OldSet,NewSet)), S = unwatch_tsys(sets:to_list(Removed), State), S = watch_tsys(sets:to_list(Added), S0) % dynamically add a child to the supervisor watch_tsys([Atom|Rest], State) -> % call helper function which creates a “ChildSpecification” Child = tsysgetter:mk(Atom, Expt, Station, DBKey), supervisor:start_child(?TSYSMONITOR, Child) % And remove it from supervision unwatch_tsys([Atom|Rest], State) -> supervisor:terminate_child(?TSYSMONITOR, Atom), supervisor:delete_child(?TSYSMONITOR, Atom), design, gen_server, supervisor (dynamic), mnesia, webtool

6 mnesia - the database It is transactional - enforced and working.
get_data(Id) -> % query the datenbank for a record where the lumpdata is still alive % (i.e. its “age” is <= Now + records’ “time-to-live” (ttl) Fun = fun() -> Now = nowfunc(), qlc:eval( qlc:q( [X || X <- mnesia:table(Table), X#lump.id =:= Id, Now<X#lump.last_refresh+X#lump.ttl] ) ) end, case mnesia:transaction( Fun ) of % data in record “too old” {atomic, []} > {reply, stale_data, Table}; % Still up-to-date {atomic, [R]} > {reply, R#lump.data, Table}; % something went wrong {aborted, Reason} -> {reply, {error, Reason}, Table} end; design, gen_server, supervisor (dynamic), mnesia, webtool

7 mnesia - the database It stores binary data, actually any data.
% From the webcam-image-getter-process Url = “ case of % Only accept statuscode 200 {ok, {{_,200,_}, _Headers, Jpeg}} -> dumpstore:update(DBKey, Jpeg, Now); _ > error end, % From the tsys-image-getter-process case gnuplot, make_plot, [....]) of {ok, Png} > dumpstore:update(DBKey, Png, Now); {error, Why} -> Why; _ > fail_but_buggered_if_we_know_why design, gen_server, supervisor (dynamic), mnesia, webtool

8 webtool - mapping URLs to Erlang fn calls
-compile(export_all). % return configdata for the “webtool” application webtool(_Args) -> {camtool, [{web_data,{"CamTool","/webcams/camtool/camtool"}}, {alias, {erl_alias, "/webcams", [camtool]}}]}. % The {alias, {erl_alias ...}} statement maps URLs of the form % “/webcams/camtool/function?arguments” % into the Erlang function call [Module:Function(Arguments)] % camtool:function(WebserverEnvironment, Arguments) % camtool:image(Env, Args) -> case get_input_data(Args, "id") of undefined -> [head(),”Please give an Id”,closing()]; ImgId > case dumpstore:get_lump(list_to_atom(ImgId)) of undefined -> [head(), “Invalid ImageId given”, closing()]; R > MimeType=R#lump.mimetype, Data=R#lump.data, "Content-Type: "++MimeType++"\r\n\r\n"++Data end end. design, gen_server, supervisor (dynamic), mnesia, webtool


Download ppt "Camtool - monitoring realtime information"

Similar presentations


Ads by Google