%%%------------------------------------------------------------------- %%% @author Joe Zhao %%% @copyright (C) 2014, %%% @doc %%% This modules monitors different devices which includes registering devices when linked and monitoring their states. %%% Registering devices and deregister them are done automatically when device are on/off line. %%% Other than that the changing states of different devices is recorded, and boardcast / return when queried. %%% @end %%% Created : 29. 四月 2014 15:35 %%%------------------------------------------------------------------- -module(devicemon). -author("Joe Zhao"). -compile([debug_info,export_all]). -include("devicemon.hrl"). %% API %% -export([]). -define(QTOUT,100). cleanloop() -> %% Cleanup the message queue -> Don't call it receive _ -> cleanloop() after 0 -> ok end. deviceloop(Devices) -> receive %% Basic Ops within server {Pid,shutdown} -> ok; {Pid,reg,Addr,Type} -> %% Register -> auto replace deviceloop(orddict:store(Addr,#device{type=Type},Devices)); {Pid,reg,Addr,Type,State} -> deviceloop(orddict:store(Addr,#device{type=Type,state = State},Devices)); {Pid,dereg,Addr} -> %% Register -> auto remove case orddict:find(Addr,Devices) of error -> deviceloop(Devices); _Else -> deviceloop(orddict:erase(Addr,Devices)) end; {Pid,stat,Addr} -> case orddict:find(Addr,Devices) of error -> Pid ! {self(),Addr,error}; {ok,Value} -> Pid ! {self(),Addr,Value} end, deviceloop(Devices); %% Query about device list & status %% Next step: remembering states {Pid,comm,[0]} -> % General query Pid ! {self(),comm,orddict:fold(fun(Key,Val,Acc) -> [Key,Val#device.type]++Val#device.state++Acc end, [],Devices)}, deviceloop(Devices); {Pid,comm,[0,Addr]} -> % Specific query, this also shouldn't happen. Dev=orddict:fetch(Addr,Devices), Pid ! {self(),comm,[Dev#device.type]++Dev#device.state}, deviceloop(Devices); %% Messages received from rsbus {Pid,device,Addr,{error,Cause}} -> io:format("[Device Err]Device address: ~p Error: ~p \n",[Addr,Cause]), self() ! {self(),dereg,Addr}, deviceloop(Devices); {Pid,device,Addr,{stat,Type,Msg}} -> tcpserv ! {self(),comm,[Addr,Type|Msg]}, deviceloop(orddict:store(Addr,#device{type=Type,state = Msg},Devices)); %% Messages received from some other server -> redirect to rsbus {Pid,comm,[Addr|Msg]} -> rsbusserv ! {self(),comm,Addr,Msg}, deviceloop(Devices); %% General ops {Pid,clean} -> % Clean message queue -> use it when garbage might be cloting the server cleanloop(), deviceloop(Devices); {Pid,heartbeat,Addr} -> % Specific heartbeat !!! Good stuff self() ! {self(),comm,[Addr]}, deviceloop(Devices); {Pid,heartbeat} -> % This type of heartbeat will cause congestion, use with caution [self() ! {self(),comm,[Addr]}|| Addr <- lists:seq(1,?ADDRANGE)], deviceloop(Devices) end. devmon() -> register(?MODULE,self()), deviceloop(orddict:new()). getStat(Addr) -> devicemon ! {self(),stat,Addr}, receive {_Pid,Addr,error} -> error; {_Pid,Addr,Val} -> Val after ?QTOUT -> error end. getStatus(Addr) -> case getStat(Addr) of error -> error; Val -> ready %% device status multiplexer %% ready | busy end. start() -> spawn(?MODULE,devmon,[]).