GitHub Sale: sign up for any paid plan this week and pay nothing until January 1, 2009!  [ hide ]

public
Description: My environmental monitoring stuff for the house.
Clone URL: git://github.com/dustin/environ.git
dustin (author)
Mon Jun 25 11:34:03 -0700 2007
commit  e3bd5483125548fef0f56a767736db0197f2bb81
tree    49659a5d177dffb700f1c407f7b29c4c4136a46c
parent  af820333e34cc3b6a7fb3f94d43e8e93a1f67935
environ / src / lemp_serv.erl
100644 131 lines (115 sloc) 3.496 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
%%
%%
%%
 
-module(lemp_serv).
 
-export([start/0, start/1, start_link/0, start_link/1, init/1, lemp/3]).
 
% Starting the server
start() ->
  start(8181).
 
start(PortNum) when integer(PortNum) ->
  {ok, spawn(?MODULE, init, [PortNum])}.
 
start_link() ->
  start_link(8181).
 
start_link(PortNum) when integer(PortNum) ->
  {ok, spawn_link(?MODULE, init, [PortNum])}.
 
%
% The server itself
%
 
% server self-init
init(PortNum) ->
  {ok, LS} = gen_tcp:listen(PortNum, [{reuseaddr, true}, {packet, 0},
                  {active, false}]),
  accept_loop(LS, environ_utilities:get_therm_map(), 1).
 
% Accept incoming connections
accept_loop(LS, Map, Count) ->
  case gen_tcp:accept(LS, 5000) of
    {ok, NS} ->
      Pid = spawn(?MODULE, lemp, [NS, Map, Count]),
      gen_tcp:controlling_process(NS, Pid),
      Pid ! go_ahead;
    {error, timeout} ->
      ok
  end,
  % Check to see if there's a stop message.
  receive
    stop ->
      error_logger:info_msg("lemp_serv received stop message.~n", []),
      gen_tcp:shutdown(LS, read_write);
    M ->
      error_logger:error_msg("Received unexpected data: ~p~n", [M]),
      accept_loop(LS, Map, Count + 1)
    after 1 ->
      accept_loop(LS, Map, Count + 1)
  end.
 
%
% The individual connections
%
 
lemp_temp_data(Key, Name, Val) ->
  io_lib:format("~s\t~s\t~f", [Key, Name, Val]).
 
% Set up and loop
lemp(Socket, Map, Id) ->
  process_flag(trap_exit, true),
  % Wait for sync
  receive
    go_ahead ->
      inet:setopts(Socket, [{active, true}])
  end,
  lemp_send(Socket, 220, "LEMP 1.0"),
  dict:fold(fun(K, V, Acc) ->
      lemp_send(Socket, 221, [K, [9], V]),
      Acc
    end, ok, Map),
  lemp_send(Socket, 222, "End of mappings"),
  dict:fold(fun(K, V, Acc) ->
      lemp_send(Socket, 223,
        lemp_temp_data(K, environ_utilities:get_therm_name(K), V)),
      Acc
    end, ok, temp_listener:getdict()),
  lemp_send(Socket, 224, "End of old data"),
  ok = temp_listener:add_handler({lemp_handler, Id}, [self(), Id]),
  lemp_loop(Socket, Id).
 
% remove the handler and exit
lemp_exit(_Reason, Id) ->
  error_logger:info_msg("lemp: deleting handler~n", []),
  ok = temp_listener:delete_handler({lemp_handler, Id}, []),
  exit(closed).
 
% Send a message with its status and all
lemp_send(Socket, Status, Message) when list(Status) ->
  gen_tcp:send(Socket, [Status, " ", Message, <<13,10>>]);
lemp_send(Socket, Status, Message) when integer(Status) ->
  lemp_send(Socket, integer_to_list(Status), Message).
 
% Message dispatch for the server processes
lemp_loop(Socket, Id) ->
  receive
    % Outbound messages
    {reading, Key, Name, Val, _Vals} ->
      ok = lemp_send(Socket, 200, lemp_temp_data(Key, Name, Val)),
      lemp_loop(Socket, Id);
    % Inbound messages
    {tcp, Socket, Bytes} ->
      error_logger:error_msg("lemp: Received unwanted data: ~p~n",
        [Bytes]),
      lemp_loop(Socket, Id);
    % Control messages
    {tcp_closed, Socket} ->
      error_logger:info_msg("lemp: socket closed~n", []),
      lemp_exit(closed, Id);
    {tcp_error, Socket, Reason} ->
      error_logger:error_msg("lemp: socket error: ~p~n", [Reason]),
      gen_tcp:close(Socket),
      lemp_exit(Reason, Id);
    % Deaths
    {'EXIT', _U, Why} ->
      error_logger:info_msg("lemp: exiting: ~p~n", [Why]),
      gen_tcp:close(Socket),
      lemp_exit(Why, Id);
    % Unknown
    Unknown ->
      error_logger:error_msg("lemp: Unhandled message: ~p~n", [Unknown]),
      lemp_loop(Socket, Id)
    after 120000 ->
      ok = lemp_send(Socket, 500, "timeout waiting for data"),
      error_logger:error_msg("lemp: timeout waiting for data~n", []),
      gen_tcp:close(Socket),
      lemp_exit(timeout, Id)
  end.