Decode radio transmissions from devices on the ISM bands in OCaml
1(* Hierarchical data structure *)
2
3type value =
4 | Int of int
5 | Float of float
6 | String of string
7 | Data of t
8 | Array of value array
9
10and field = {
11 key : string;
12 pretty_key : string option;
13 format : string option;
14 value : value;
15}
16
17and t = field list
18
19let make items =
20 List.map
21 (fun (key, pretty_key, value) -> { key; pretty_key; format = None; value })
22 items
23
24let int key ?pretty ?format value =
25 { key; pretty_key = pretty; format; value = Int value }
26
27let float key ?pretty ?format value =
28 { key; pretty_key = pretty; format; value = Float value }
29
30let string key ?pretty ?format value =
31 { key; pretty_key = pretty; format; value = String value }
32
33let data key ?pretty value =
34 { key; pretty_key = pretty; format = None; value = Data value }
35
36let array key ?pretty value =
37 { key; pretty_key = pretty; format = None; value = Array value }
38
39let hex key ?pretty bytes len =
40 let s = Rtl433_util.bytes_to_hex bytes len in
41 { key; pretty_key = pretty; format = None; value = String s }
42
43let find key data = List.find_opt (fun f -> f.key = key) data
44
45let get_int key data =
46 match find key data with Some { value = Int i; _ } -> Some i | _ -> None
47
48let get_float key data =
49 match find key data with Some { value = Float f; _ } -> Some f | _ -> None
50
51let get_string key data =
52 match find key data with Some { value = String s; _ } -> Some s | _ -> None
53
54let rec pp_value fmt = function
55 | Int i -> Format.fprintf fmt "%d" i
56 | Float f -> Format.fprintf fmt "%g" f
57 | String s -> Format.fprintf fmt "%S" s
58 | Data d -> pp fmt d
59 | Array a ->
60 Format.fprintf fmt "[%a]"
61 (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ", ") pp_value)
62 (Array.to_list a)
63
64and pp fmt data =
65 Format.fprintf fmt "{%a}"
66 (Format.pp_print_list
67 ~pp_sep:(fun fmt () -> Format.fprintf fmt ", ")
68 (fun fmt f -> Format.fprintf fmt "%s: %a" f.key pp_value f.value))
69 data
70
71let to_json data =
72 let buf = Buffer.create 256 in
73 let rec emit_value = function
74 | Int i -> Buffer.add_string buf (string_of_int i)
75 | Float f -> Buffer.add_string buf (string_of_float f)
76 | String s ->
77 Buffer.add_char buf '"';
78 Buffer.add_string buf (String.escaped s);
79 Buffer.add_char buf '"'
80 | Data d -> emit_data d
81 | Array a ->
82 Buffer.add_char buf '[';
83 Array.iteri
84 (fun i v ->
85 if i > 0 then Buffer.add_char buf ',';
86 emit_value v)
87 a;
88 Buffer.add_char buf ']'
89 and emit_data fields =
90 Buffer.add_char buf '{';
91 List.iteri
92 (fun i f ->
93 if i > 0 then Buffer.add_char buf ',';
94 Buffer.add_char buf '"';
95 Buffer.add_string buf f.key;
96 Buffer.add_string buf "\":";
97 emit_value f.value)
98 fields;
99 Buffer.add_char buf '}'
100 in
101 emit_data data;
102 Buffer.contents buf
103
104(* Mutable storage for last decoded output *)
105let last_output : t option ref = ref None
106
107let set_last_output data = last_output := Some data
108let get_last_output () = !last_output
109let clear_last_output () = last_output := None