···332332 (** Decode string list, trying results wrapper first then plain array. *)
333333 let decode_string_list body =
334334 match
335335- Jsont_bytesrw.decode_string Owntracks.Recorder.string_list_results_jsont
335335+ Json.of_string Owntracks.Recorder.string_list_results_jsont
336336 body
337337 with
338338 | Ok items -> items
339339 | Error _ -> (
340340 match
341341- Jsont_bytesrw.decode_string Owntracks.Recorder.string_list_jsont body
341341+ Json.of_string Owntracks.Recorder.string_list_jsont body
342342 with
343343 | Ok items -> items
344344 | Error _ -> [])
···346346 (** Decode locations, trying array first then data wrapper. *)
347347 let decode_locations body =
348348 match
349349- Jsont_bytesrw.decode_string Owntracks.Recorder.locations_jsont body
349349+ Json.of_string Owntracks.Recorder.locations_jsont body
350350 with
351351 | Ok locs -> locs
352352 | Error _ -> (
353353 match
354354- Jsont_bytesrw.decode_string Owntracks.Recorder.locations_data_jsont
354354+ Json.of_string Owntracks.Recorder.locations_data_jsont
355355 body
356356 with
357357 | Ok locs -> locs
+2-2
dune-project
···1212 (name owntracks)
1313 (synopsis "OwnTracks message types and JSON codecs")
1414 (description
1515- "Types and jsont codecs for parsing OwnTracks MQTT location messages.
1515+ "Types and JSON codecs for parsing OwnTracks MQTT location messages.
1616OwnTracks is an open-source location tracking application that publishes
1717GPS coordinates, accuracy, speed, battery, and other device state over MQTT.
1818This library provides type-safe parsing and serialization of all OwnTracks
1919message types including locations, transitions, waypoints, and cards.")
2020 (depends
2121 (ocaml (>= 5.1))
2222- (jsont (>= 0.1.0))
2222+ nox-json
2323 (bytesrw (>= 0.1))
2424 geojson
2525 (odoc :with-doc)))
···11111212type float_array = float array
13131414-let float_array_jsont ~kind = Jsont.array ~kind Jsont.number
1414+let float_array_jsont ~kind = Json.Codec.array ~kind Json.Codec.number
15151616type 'a garray = 'a array
17171818-let garray = Jsont.array
1818+let garray = Json.Codec.array
19192020(** Bounding box. *)
2121module Bbox = struct
···43434444(** Internal wrapper for GeoJSON objects with bbox and unknown fields. *)
4545module Geojson_object = struct
4646- type 'a t = { type' : 'a; bbox : Bbox.t option; unknown : Jsont.json }
4646+ type 'a t = { type' : 'a; bbox : Bbox.t option; unknown : Json.t }
47474848 let make type' bbox unknown = { type'; bbox; unknown }
4949 let type' o = o.type'
···52525353 let finish_jsont map =
5454 map
5555- |> Jsont.Object.opt_mem "bbox" Bbox.jsont ~enc:bbox
5656- |> Jsont.Object.keep_unknown Jsont.json_mems ~enc:unknown
5757- |> Jsont.Object.finish
5555+ |> Json.Codec.Object.opt_member "bbox" Bbox.jsont ~enc:bbox
5656+ |> Json.Codec.Object.keep_unknown Json.Codec.Value.members ~enc:unknown
5757+ |> Json.Codec.Object.seal
58585959 let geometry ~kind coordinates =
6060- Jsont.Object.map ~kind make
6161- |> Jsont.Object.mem "coordinates" coordinates ~enc:type'
6060+ Json.Codec.Object.map ~kind make
6161+ |> Json.Codec.Object.member "coordinates" coordinates ~enc:type'
6262 |> finish_jsont
6363end
6464···6767 type t = Position.t
68686969 let jsont = Geojson_object.geometry ~kind:"Point" Position.jsont
7070- let v pos = Geojson_object.make pos None (Jsont.Json.object' [])
7070+ let v pos = Geojson_object.make pos None (Json.Value.object' [])
7171end
72727373(** MultiPoint geometry. *)
···8282 type t = Position.t garray
83838484 let jsont = Geojson_object.geometry ~kind:"LineString" (garray Position.jsont)
8585- let v positions = Geojson_object.make positions None (Jsont.Json.object' [])
8585+ let v positions = Geojson_object.make positions None (Json.Value.object' [])
8686end
87878888(** MultiLineString geometry. *)
···132132 type t = {
133133 id : id option;
134134 geometry : geometry option;
135135- properties : Jsont.json option;
135135+ properties : Json.t option;
136136 }
137137138138 let make id geometry properties = { id; geometry; properties }
···148148149149 let v ?properties geometry =
150150 let obj = { id = None; geometry = Some geometry; properties } in
151151- Geojson_object.make obj None (Jsont.Json.object' [])
151151+ Geojson_object.make obj None (Json.Value.object' [])
152152 end
153153154154 type t =
···168168169169 let feature_id_jsont =
170170 let number =
171171- let dec = Jsont.Base.dec (fun n -> `Number n) in
172172- let enc =
173173- Jsont.Base.enc (function `Number n -> n | _ -> assert false)
174174- in
175175- Jsont.Base.number (Jsont.Base.map ~enc ~dec ())
171171+ Json.Codec.map
172172+ ~dec:(fun n -> `Number n)
173173+ ~enc:(function `Number n -> n | _ -> assert false)
174174+ Json.Codec.number
176175 in
177176 let string =
178178- let dec = Jsont.Base.dec (fun n -> `String n) in
179179- let enc =
180180- Jsont.Base.enc (function `String n -> n | _ -> assert false)
181181- in
182182- Jsont.Base.string (Jsont.Base.map ~enc ~dec ())
177177+ Json.Codec.map
178178+ ~dec:(fun n -> `String n)
179179+ ~enc:(function `String n -> n | _ -> assert false)
180180+ Json.Codec.string
183181 in
184182 let enc = function `Number _ -> number | `String _ -> string in
185185- Jsont.any ~kind:"id" ~dec_number:number ~dec_string:string ~enc ()
183183+ Json.Codec.any ~kind:"id" ~dec_number:number ~dec_string:string ~enc ()
186184187187- let case_map obj dec = Jsont.Object.Case.map (Jsont.kind obj) obj ~dec
185185+ let case_map obj dec = Json.Codec.Object.Case.map (Json.Codec.kind obj) obj ~dec
188186189187 let rec geometry_jsont =
190188 lazy begin
···200198 case_map (Lazy.force geometry_collection_jsont) geometry_collection
201199 in
202200 let enc_case = function
203203- | `Point v -> Jsont.Object.Case.value case_point v
204204- | `Multi_point v -> Jsont.Object.Case.value case_multi_point v
205205- | `Line_string v -> Jsont.Object.Case.value case_line_string v
201201+ | `Point v -> Json.Codec.Object.Case.value case_point v
202202+ | `Multi_point v -> Json.Codec.Object.Case.value case_multi_point v
203203+ | `Line_string v -> Json.Codec.Object.Case.value case_line_string v
206204 | `Multi_line_string v ->
207207- Jsont.Object.Case.value case_multi_line_string v
208208- | `Polygon v -> Jsont.Object.Case.value case_polygon v
209209- | `Multi_polygon v -> Jsont.Object.Case.value case_multi_polygon v
205205+ Json.Codec.Object.Case.value case_multi_line_string v
206206+ | `Polygon v -> Json.Codec.Object.Case.value case_polygon v
207207+ | `Multi_polygon v -> Json.Codec.Object.Case.value case_multi_polygon v
210208 | `Geometry_collection v ->
211211- Jsont.Object.Case.value case_geometry_collection v
209209+ Json.Codec.Object.Case.value case_geometry_collection v
212210 in
213211 let cases =
214214- Jsont.Object.Case.
212212+ Json.Codec.Object.Case.
215213 [
216214 make case_point;
217215 make case_multi_point;
···222220 make case_geometry_collection;
223221 ]
224222 in
225225- Jsont.Object.map ~kind:"Geometry object" Fun.id
226226- |> Jsont.Object.case_mem "type" Jsont.string ~enc:Fun.id ~enc_case cases
223223+ Json.Codec.Object.map ~kind:"Geometry object" Fun.id
224224+ |> Json.Codec.Object.case_member "type" Json.Codec.string ~enc:Fun.id ~enc_case cases
227225 ~tag_to_string:Fun.id ~tag_compare:String.compare
228228- |> Jsont.Object.finish
226226+ |> Json.Codec.Object.seal
229227 end
230228231231- and feature_jsont : Feature.t object' Jsont.t Lazy.t =
229229+ and feature_jsont : Feature.t object' Json.Codec.t Lazy.t =
232230 lazy begin
233231 let case_feature = case_map (Lazy.force case_feature_jsont) Fun.id in
234234- let enc_case v = Jsont.Object.Case.value case_feature v in
235235- let cases = Jsont.Object.Case.[ make case_feature ] in
236236- Jsont.Object.map ~kind:"Feature" Fun.id
237237- |> Jsont.Object.case_mem "type" Jsont.string ~enc:Fun.id ~enc_case cases
232232+ let enc_case v = Json.Codec.Object.Case.value case_feature v in
233233+ let cases = Json.Codec.Object.Case.[ make case_feature ] in
234234+ Json.Codec.Object.map ~kind:"Feature" Fun.id
235235+ |> Json.Codec.Object.case_member "type" Json.Codec.string ~enc:Fun.id ~enc_case cases
238236 ~tag_to_string:Fun.id ~tag_compare:String.compare
239239- |> Jsont.Object.finish
237237+ |> Json.Codec.Object.seal
240238 end
241239242242- and case_feature_jsont : Feature.t object' Jsont.t Lazy.t =
240240+ and case_feature_jsont : Feature.t object' Json.Codec.t Lazy.t =
243241 lazy begin
244244- Jsont.Object.map ~kind:"Feature" Feature.make_geojson_object
245245- |> Jsont.Object.opt_mem "id" feature_id_jsont ~enc:(fun o ->
242242+ Json.Codec.Object.map ~kind:"Feature" Feature.make_geojson_object
243243+ |> Json.Codec.Object.opt_member "id" feature_id_jsont ~enc:(fun o ->
246244 Feature.id (Geojson_object.type' o))
247247- |> Jsont.Object.mem "geometry"
248248- (Jsont.option (Jsont.rec' geometry_jsont))
245245+ |> Json.Codec.Object.member "geometry"
246246+ (Json.Codec.option (Json.Codec.fix geometry_jsont))
249247 ~enc:(fun o -> Feature.geometry (Geojson_object.type' o))
250250- |> Jsont.Object.mem "properties" (Jsont.option Jsont.json_object)
248248+ |> Json.Codec.Object.member "properties" (Json.Codec.option Json.Codec.Value.object')
251249 ~enc:(fun o -> Feature.properties (Geojson_object.type' o))
252250 |> Geojson_object.finish_jsont
253251 end
254252255253 and geometry_collection_jsont =
256254 lazy begin
257257- Jsont.Object.map ~kind:"GeometryCollection" Geojson_object.make
258258- |> Jsont.Object.mem "geometries"
259259- (Jsont.list (Jsont.rec' geometry_jsont))
255255+ Json.Codec.Object.map ~kind:"GeometryCollection" Geojson_object.make
256256+ |> Json.Codec.Object.member "geometries"
257257+ (Json.Codec.list (Json.Codec.fix geometry_jsont))
260258 ~enc:Geojson_object.type'
261259 |> Geojson_object.finish_jsont
262260 end
263261264262 and feature_collection_json =
265263 lazy begin
266266- Jsont.Object.map ~kind:"FeatureCollection" Geojson_object.make
267267- |> Jsont.Object.mem "features"
268268- Jsont.(list (Jsont.rec' feature_jsont))
264264+ Json.Codec.Object.map ~kind:"FeatureCollection" Geojson_object.make
265265+ |> Json.Codec.Object.member "features"
266266+ Json.Codec.(list (fix feature_jsont))
269267 ~enc:Geojson_object.type'
270268 |> Geojson_object.finish_jsont
271269 end
272270273273- and jsont : t Jsont.t Lazy.t =
271271+ and jsont : t Json.Codec.t Lazy.t =
274272 lazy begin
275273 let case_point = case_map Point.jsont point in
276274 let case_multi_point = case_map Multi_point.jsont multi_point in
···288286 case_map (Lazy.force feature_collection_json) feature_collection
289287 in
290288 let enc_case = function
291291- | `Point v -> Jsont.Object.Case.value case_point v
292292- | `Multi_point v -> Jsont.Object.Case.value case_multi_point v
293293- | `Line_string v -> Jsont.Object.Case.value case_line_string v
289289+ | `Point v -> Json.Codec.Object.Case.value case_point v
290290+ | `Multi_point v -> Json.Codec.Object.Case.value case_multi_point v
291291+ | `Line_string v -> Json.Codec.Object.Case.value case_line_string v
294292 | `Multi_line_string v ->
295295- Jsont.Object.Case.value case_multi_line_string v
296296- | `Polygon v -> Jsont.Object.Case.value case_polygon v
297297- | `Multi_polygon v -> Jsont.Object.Case.value case_multi_polygon v
293293+ Json.Codec.Object.Case.value case_multi_line_string v
294294+ | `Polygon v -> Json.Codec.Object.Case.value case_polygon v
295295+ | `Multi_polygon v -> Json.Codec.Object.Case.value case_multi_polygon v
298296 | `Geometry_collection v ->
299299- Jsont.Object.Case.value case_geometry_collection v
300300- | `Feature v -> Jsont.Object.Case.value case_feature v
297297+ Json.Codec.Object.Case.value case_geometry_collection v
298298+ | `Feature v -> Json.Codec.Object.Case.value case_feature v
301299 | `Feature_collection v ->
302302- Jsont.Object.Case.value case_feature_collection v
300300+ Json.Codec.Object.Case.value case_feature_collection v
303301 in
304302 let cases =
305305- Jsont.Object.Case.
303303+ Json.Codec.Object.Case.
306304 [
307305 make case_point;
308306 make case_multi_point;
···315313 make case_feature_collection;
316314 ]
317315 in
318318- Jsont.Object.map ~kind:"GeoJSON" Fun.id
319319- |> Jsont.Object.case_mem "type" Jsont.string ~enc:Fun.id ~enc_case cases
316316+ Json.Codec.Object.map ~kind:"GeoJSON" Fun.id
317317+ |> Json.Codec.Object.case_member "type" Json.Codec.string ~enc:Fun.id ~enc_case cases
320318 ~tag_to_string:Fun.id ~tag_compare:String.compare
321321- |> Jsont.Object.finish
319319+ |> Json.Codec.Object.seal
322320 end
323321324322 let jsont = Lazy.force jsont
325323326326- let to_string t =
327327- match Jsont_bytesrw.encode_string jsont t with
328328- | Ok s -> s
329329- | Error e -> failwith e
324324+ let to_string t = Json.to_string jsont t
330325end
331326332327(** Convenience module for working with GeoJSON geometry types. *)
+11-11
lib/geojson.mli
···4444 type t = float array
4545 (** The type for bounding boxes. *)
46464747- val jsont : t Jsont.t
4747+ val jsont : t Json.Codec.t
4848 (** [jsont] is a JSON codec for bounding boxes. *)
4949end
5050···6060 type t = float array
6161 (** The type for positions. *)
62626363- val jsont : t Jsont.t
6363+ val jsont : t Json.Codec.t
6464 (** [jsont] is a JSON codec for positions. *)
65656666 val v : ?altitude:float -> lng:float -> lat:float -> unit -> t
···104104 type t = Position.t
105105 (** The type for point coordinates. *)
106106107107- val jsont : t Geojson_object.t Jsont.t
107107+ val jsont : t Geojson_object.t Json.Codec.t
108108 (** [jsont] is a JSON codec for Point geometry objects. *)
109109110110 val v : Position.t -> t Geojson_object.t
···118118 type t = Position.t array
119119 (** The type for multipoint coordinates. *)
120120121121- val jsont : t Geojson_object.t Jsont.t
121121+ val jsont : t Geojson_object.t Json.Codec.t
122122 (** [jsont] is a JSON codec for MultiPoint geometry objects. *)
123123end
124124···130130 type t = Position.t array
131131 (** The type for linestring coordinates. *)
132132133133- val jsont : t Geojson_object.t Jsont.t
133133+ val jsont : t Geojson_object.t Json.Codec.t
134134 (** [jsont] is a JSON codec for LineString geometry objects. *)
135135136136 val v : Position.t array -> t Geojson_object.t
···144144 type t = Line_string.t array
145145 (** The type for multilinestring coordinates. *)
146146147147- val jsont : t Geojson_object.t Jsont.t
147147+ val jsont : t Geojson_object.t Json.Codec.t
148148 (** [jsont] is a JSON codec for MultiLineString geometry objects. *)
149149end
150150···157157 type t = Line_string.t array
158158 (** The type for polygon coordinates (array of linear rings). *)
159159160160- val jsont : t Geojson_object.t Jsont.t
160160+ val jsont : t Geojson_object.t Json.Codec.t
161161 (** [jsont] is a JSON codec for Polygon geometry objects. *)
162162end
163163···168168 type t = Polygon.t array
169169 (** The type for multipolygon coordinates. *)
170170171171- val jsont : t Geojson_object.t Jsont.t
171171+ val jsont : t Geojson_object.t Json.Codec.t
172172 (** [jsont] is a JSON codec for MultiPolygon geometry objects. *)
173173end
174174···215215 (** [geometry f] returns the optional geometry. A feature may have null
216216 geometry. *)
217217218218- val properties : t -> Jsont.json option
218218+ val properties : t -> Json.t option
219219 (** [properties f] returns the optional properties JSON object. Properties
220220 can be any JSON object. *)
221221222222 type collection = t object' list
223223 (** A FeatureCollection is a list of features. *)
224224225225- val v : ?properties:Jsont.json -> geometry -> t object'
225225+ val v : ?properties:Json.t -> geometry -> t object'
226226 (** [v ?properties geometry] creates a Feature with the given geometry and
227227 optional properties JSON object. *)
228228 end
···271271272272 (** {1:codec Encoding and Decoding} *)
273273274274- val jsont : t Jsont.t
274274+ val jsont : t Json.Codec.t
275275 (** [jsont] is a JSON codec for GeoJSON objects. Handles all GeoJSON types
276276 including features, feature collections, and all geometry types. *)
277277
+4-4
lib/owntracks.mli
···5566(** OwnTracks message types and JSON codecs.
7788- This module provides types and {{:https://erratique.ch/software/jsont}jsont}
88+ This module provides types and {{:https://tangled.org/@anil.recoil.org/nox-json}nox-json}
99 codecs for parsing {{:https://owntracks.org/}OwnTracks} MQTT messages.
1010 OwnTracks is an open-source location tracking application that publishes
1111 location data over MQTT.
···23232424 {1:example Example}
25252626- Decoding a location message using jsont_bytesrw:
2626+ Decoding a location message:
2727 {[
2828 let json =
2929 {|{"_type":"location","lat":51.5,"lon":-0.1,"tst":1234567890}|}
3030 in
3131- match Jsont_bytesrw.decode_string Owntracks.Message.jsont json with
3131+ match Json.of_string Owntracks.Message.jsont json with
3232 | Ok (Location loc) ->
3333 Printf.printf "Location: %.4f, %.4f\n"
3434 (Owntracks.Location.lat loc)
3535 (Owntracks.Location.lon loc)
3636 | Ok _ -> print_endline "Other message type"
3737- | Error e -> Printf.printf "Error: %s\n" e
3737+ | Error e -> Printf.printf "Error: %s\n" (Json.Error.to_string e)
3838 ]}
39394040 See {{:https://owntracks.org/booklet/tech/json/}OwnTracks JSON format} for
+13-13
lib/owntracks_card.ml
···1010let face t = t.face
1111let tid t = t.tid
12121313-let jsont_bare : t Jsont.t =
1313+let jsont_bare : t Json.Codec.t =
1414 let make name face tid = { name; face; tid } in
1515- Jsont.Object.map ~kind:"card" make
1616- |> Jsont.Object.opt_mem "name" Jsont.string ~enc:(fun c -> c.name)
1717- |> Jsont.Object.opt_mem "face" Jsont.string ~enc:(fun c -> c.face)
1818- |> Jsont.Object.opt_mem "tid" Jsont.string ~enc:(fun c -> c.tid)
1919- |> Jsont.Object.skip_unknown |> Jsont.Object.finish
1515+ Json.Codec.Object.map ~kind:"card" make
1616+ |> Json.Codec.Object.opt_member "name" Json.Codec.string ~enc:(fun c -> c.name)
1717+ |> Json.Codec.Object.opt_member "face" Json.Codec.string ~enc:(fun c -> c.face)
1818+ |> Json.Codec.Object.opt_member "tid" Json.Codec.string ~enc:(fun c -> c.tid)
1919+ |> Json.Codec.Object.skip_unknown |> Json.Codec.Object.seal
20202121-let jsont : t Jsont.t =
2121+let jsont : t Json.Codec.t =
2222 let make _type name face tid =
2323 ignore _type;
2424 { name; face; tid }
2525 in
2626- Jsont.Object.map ~kind:"card" make
2727- |> Jsont.Object.mem "_type" Jsont.string ~enc:(fun _ -> "card")
2828- |> Jsont.Object.opt_mem "name" Jsont.string ~enc:(fun c -> c.name)
2929- |> Jsont.Object.opt_mem "face" Jsont.string ~enc:(fun c -> c.face)
3030- |> Jsont.Object.opt_mem "tid" Jsont.string ~enc:(fun c -> c.tid)
3131- |> Jsont.Object.skip_unknown |> Jsont.Object.finish
2626+ Json.Codec.Object.map ~kind:"card" make
2727+ |> Json.Codec.Object.member "_type" Json.Codec.string ~enc:(fun _ -> "card")
2828+ |> Json.Codec.Object.opt_member "name" Json.Codec.string ~enc:(fun c -> c.name)
2929+ |> Json.Codec.Object.opt_member "face" Json.Codec.string ~enc:(fun c -> c.face)
3030+ |> Json.Codec.Object.opt_member "tid" Json.Codec.string ~enc:(fun c -> c.tid)
3131+ |> Json.Codec.Object.skip_unknown |> Json.Codec.Object.seal
32323333let pp ppf card =
3434 Format.fprintf ppf "Card: %s" (Option.value ~default:"(no name)" card.name)
+2-2
lib/owntracks_card.mli
···34343535(** {1 JSON Codec} *)
36363737-val jsont : t Jsont.t
3737+val jsont : t Json.Codec.t
3838(** [jsont] is a JSON codec for card messages. Expects the ["_type"] field to be
3939 ["card"]. *)
40404141-val jsont_bare : t Jsont.t
4141+val jsont_bare : t Json.Codec.t
4242(** [jsont_bare] is a JSON codec that doesn't require the ["_type"] field. *)
43434444(** {1 Pretty Printing} *)
+14-14
lib/owntracks_geojson_output.ml
···14141515let props ~device_name ~timestamp ~time ?accuracy ?speed ?battery ?tracker_id ()
1616 =
1717- let open Jsont.Json in
1717+ let open Json.Value in
1818 let add n f opt acc =
1919 match opt with Some v -> (n, f v) :: acc | None -> acc
2020 in
···2727 |> add "speed" number speed |> add "battery" int battery
2828 |> add "tracker_id" string tracker_id
2929 |> fun mems ->
3030- Jsont.Json.object'
3131- (List.map (fun (n, v) -> Jsont.Json.mem (Jsont.Json.name n) v) mems)
3030+ Json.Value.object'
3131+ (List.map (fun (n, v) -> Json.Value.member (Json.Value.name n) v) mems)
32323333let point_feature ~device_name loc : Geojson.t =
3434 let point = Geometry.Point.v (pos_of_loc loc) in
···6565 in
6666 let properties =
6767 Some
6868- (Jsont.Json.object'
6868+ (Json.Value.object'
6969 [
7070- Jsont.Json.mem (Jsont.Json.name "name")
7171- (Jsont.Json.string device_name);
7272- Jsont.Json.mem (Jsont.Json.name "points")
7373- (Jsont.Json.int (List.length sorted));
7474- Jsont.Json.mem
7575- (Jsont.Json.name "start_time")
7676- (Jsont.Json.string
7070+ Json.Value.member (Json.Value.name "name")
7171+ (Json.Value.string device_name);
7272+ Json.Value.member (Json.Value.name "points")
7373+ (Json.Value.int (List.length sorted));
7474+ Json.Value.member
7575+ (Json.Value.name "start_time")
7676+ (Json.Value.string
7777 (Owntracks_location.format_timestamp start_time));
7878- Jsont.Json.mem
7979- (Jsont.Json.name "end_time")
8080- (Jsont.Json.string (Owntracks_location.format_timestamp end_time));
7878+ Json.Value.member
7979+ (Json.Value.name "end_time")
8080+ (Json.Value.string (Owntracks_location.format_timestamp end_time));
8181 ])
8282 in
8383 let feature = Geojson.Feature.v ?properties geom in
+41-41
lib/owntracks_location.ml
···6464let topic t = t.topic
6565let with_topic topic t = { t with topic = Some topic }
66666767-let jsont : t Jsont.t =
6767+let jsont : t Json.Codec.t =
6868 let make _type tid tst lat lon alt acc vel cog batt bs conn t m poi inregions
6969 addr topic =
7070 ignore _type;
···8888 topic;
8989 }
9090 in
9191- Jsont.Object.map ~kind:"location" make
9292- |> Jsont.Object.mem "_type" Jsont.string ~enc:(fun _ -> "location")
9393- |> Jsont.Object.opt_mem "tid" Jsont.string ~enc:(fun l -> l.tid)
9494- |> Jsont.Object.mem "tst" Jsont.int ~enc:(fun l -> l.tst)
9595- |> Jsont.Object.mem "lat" Jsont.number ~enc:(fun l -> l.lat)
9696- |> Jsont.Object.mem "lon" Jsont.number ~enc:(fun l -> l.lon)
9797- |> Jsont.Object.opt_mem "alt" Jsont.number ~enc:(fun l -> l.alt)
9898- |> Jsont.Object.opt_mem "acc" Jsont.number ~enc:(fun l -> l.acc)
9999- |> Jsont.Object.opt_mem "vel" Jsont.number ~enc:(fun l -> l.vel)
100100- |> Jsont.Object.opt_mem "cog" Jsont.number ~enc:(fun l -> l.cog)
101101- |> Jsont.Object.opt_mem "batt" Jsont.int ~enc:(fun l -> l.batt)
102102- |> Jsont.Object.opt_mem "bs" Jsont.int ~enc:(fun l -> l.bs)
103103- |> Jsont.Object.opt_mem "conn" Jsont.string ~enc:(fun l -> l.conn)
104104- |> Jsont.Object.opt_mem "t" Jsont.string ~enc:(fun l -> l.t)
105105- |> Jsont.Object.opt_mem "m" Jsont.int ~enc:(fun l -> l.m)
106106- |> Jsont.Object.opt_mem "poi" Jsont.string ~enc:(fun l -> l.poi)
107107- |> Jsont.Object.opt_mem "inregions" (Jsont.list Jsont.string) ~enc:(fun l ->
9191+ Json.Codec.Object.map ~kind:"location" make
9292+ |> Json.Codec.Object.member "_type" Json.Codec.string ~enc:(fun _ -> "location")
9393+ |> Json.Codec.Object.opt_member "tid" Json.Codec.string ~enc:(fun l -> l.tid)
9494+ |> Json.Codec.Object.member "tst" Json.Codec.int ~enc:(fun l -> l.tst)
9595+ |> Json.Codec.Object.member "lat" Json.Codec.number ~enc:(fun l -> l.lat)
9696+ |> Json.Codec.Object.member "lon" Json.Codec.number ~enc:(fun l -> l.lon)
9797+ |> Json.Codec.Object.opt_member "alt" Json.Codec.number ~enc:(fun l -> l.alt)
9898+ |> Json.Codec.Object.opt_member "acc" Json.Codec.number ~enc:(fun l -> l.acc)
9999+ |> Json.Codec.Object.opt_member "vel" Json.Codec.number ~enc:(fun l -> l.vel)
100100+ |> Json.Codec.Object.opt_member "cog" Json.Codec.number ~enc:(fun l -> l.cog)
101101+ |> Json.Codec.Object.opt_member "batt" Json.Codec.int ~enc:(fun l -> l.batt)
102102+ |> Json.Codec.Object.opt_member "bs" Json.Codec.int ~enc:(fun l -> l.bs)
103103+ |> Json.Codec.Object.opt_member "conn" Json.Codec.string ~enc:(fun l -> l.conn)
104104+ |> Json.Codec.Object.opt_member "t" Json.Codec.string ~enc:(fun l -> l.t)
105105+ |> Json.Codec.Object.opt_member "m" Json.Codec.int ~enc:(fun l -> l.m)
106106+ |> Json.Codec.Object.opt_member "poi" Json.Codec.string ~enc:(fun l -> l.poi)
107107+ |> Json.Codec.Object.opt_member "inregions" (Json.Codec.list Json.Codec.string) ~enc:(fun l ->
108108 match l.inregions with [] -> None | xs -> Some xs)
109109- |> Jsont.Object.opt_mem "addr" Jsont.string ~enc:(fun l -> l.addr)
110110- |> Jsont.Object.opt_mem "topic" Jsont.string ~enc:(fun l -> l.topic)
111111- |> Jsont.Object.skip_unknown |> Jsont.Object.finish
109109+ |> Json.Codec.Object.opt_member "addr" Json.Codec.string ~enc:(fun l -> l.addr)
110110+ |> Json.Codec.Object.opt_member "topic" Json.Codec.string ~enc:(fun l -> l.topic)
111111+ |> Json.Codec.Object.skip_unknown |> Json.Codec.Object.seal
112112113113-let jsont_bare : t Jsont.t =
113113+let jsont_bare : t Json.Codec.t =
114114 let make tid tst lat lon alt acc vel cog batt bs conn t m poi inregions addr
115115 topic =
116116 {
···133133 topic;
134134 }
135135 in
136136- Jsont.Object.map ~kind:"location" make
137137- |> Jsont.Object.opt_mem "tid" Jsont.string ~enc:(fun l -> l.tid)
138138- |> Jsont.Object.mem "tst" Jsont.int ~enc:(fun l -> l.tst)
139139- |> Jsont.Object.mem "lat" Jsont.number ~enc:(fun l -> l.lat)
140140- |> Jsont.Object.mem "lon" Jsont.number ~enc:(fun l -> l.lon)
141141- |> Jsont.Object.opt_mem "alt" Jsont.number ~enc:(fun l -> l.alt)
142142- |> Jsont.Object.opt_mem "acc" Jsont.number ~enc:(fun l -> l.acc)
143143- |> Jsont.Object.opt_mem "vel" Jsont.number ~enc:(fun l -> l.vel)
144144- |> Jsont.Object.opt_mem "cog" Jsont.number ~enc:(fun l -> l.cog)
145145- |> Jsont.Object.opt_mem "batt" Jsont.int ~enc:(fun l -> l.batt)
146146- |> Jsont.Object.opt_mem "bs" Jsont.int ~enc:(fun l -> l.bs)
147147- |> Jsont.Object.opt_mem "conn" Jsont.string ~enc:(fun l -> l.conn)
148148- |> Jsont.Object.opt_mem "t" Jsont.string ~enc:(fun l -> l.t)
149149- |> Jsont.Object.opt_mem "m" Jsont.int ~enc:(fun l -> l.m)
150150- |> Jsont.Object.opt_mem "poi" Jsont.string ~enc:(fun l -> l.poi)
151151- |> Jsont.Object.opt_mem "inregions" (Jsont.list Jsont.string) ~enc:(fun l ->
136136+ Json.Codec.Object.map ~kind:"location" make
137137+ |> Json.Codec.Object.opt_member "tid" Json.Codec.string ~enc:(fun l -> l.tid)
138138+ |> Json.Codec.Object.member "tst" Json.Codec.int ~enc:(fun l -> l.tst)
139139+ |> Json.Codec.Object.member "lat" Json.Codec.number ~enc:(fun l -> l.lat)
140140+ |> Json.Codec.Object.member "lon" Json.Codec.number ~enc:(fun l -> l.lon)
141141+ |> Json.Codec.Object.opt_member "alt" Json.Codec.number ~enc:(fun l -> l.alt)
142142+ |> Json.Codec.Object.opt_member "acc" Json.Codec.number ~enc:(fun l -> l.acc)
143143+ |> Json.Codec.Object.opt_member "vel" Json.Codec.number ~enc:(fun l -> l.vel)
144144+ |> Json.Codec.Object.opt_member "cog" Json.Codec.number ~enc:(fun l -> l.cog)
145145+ |> Json.Codec.Object.opt_member "batt" Json.Codec.int ~enc:(fun l -> l.batt)
146146+ |> Json.Codec.Object.opt_member "bs" Json.Codec.int ~enc:(fun l -> l.bs)
147147+ |> Json.Codec.Object.opt_member "conn" Json.Codec.string ~enc:(fun l -> l.conn)
148148+ |> Json.Codec.Object.opt_member "t" Json.Codec.string ~enc:(fun l -> l.t)
149149+ |> Json.Codec.Object.opt_member "m" Json.Codec.int ~enc:(fun l -> l.m)
150150+ |> Json.Codec.Object.opt_member "poi" Json.Codec.string ~enc:(fun l -> l.poi)
151151+ |> Json.Codec.Object.opt_member "inregions" (Json.Codec.list Json.Codec.string) ~enc:(fun l ->
152152 match l.inregions with [] -> None | xs -> Some xs)
153153- |> Jsont.Object.opt_mem "addr" Jsont.string ~enc:(fun l -> l.addr)
154154- |> Jsont.Object.opt_mem "topic" Jsont.string ~enc:(fun l -> l.topic)
155155- |> Jsont.Object.skip_unknown |> Jsont.Object.finish
153153+ |> Json.Codec.Object.opt_member "addr" Json.Codec.string ~enc:(fun l -> l.addr)
154154+ |> Json.Codec.Object.opt_member "topic" Json.Codec.string ~enc:(fun l -> l.topic)
155155+ |> Json.Codec.Object.skip_unknown |> Json.Codec.Object.seal
156156157157let format_timestamp tst =
158158 let t = Unix.gmtime (float_of_int tst) in
+2-2
lib/owntracks_location.mli
···128128129129(** {1 JSON Codec} *)
130130131131-val jsont : t Jsont.t
131131+val jsont : t Json.Codec.t
132132(** [jsont] is a JSON codec for location messages. Expects the ["_type"] field
133133 to be ["location"]. *)
134134135135-val jsont_bare : t Jsont.t
135135+val jsont_bare : t Json.Codec.t
136136(** [jsont_bare] is a JSON codec that doesn't require the ["_type"] field. Use
137137 this for parsing recorder API responses which omit the type field. *)
138138
+9-9
lib/owntracks_lwt.ml
···88let v ~tst = { tst }
99let tst t = t.tst
10101111-let jsont_bare : t Jsont.t =
1111+let jsont_bare : t Json.Codec.t =
1212 let make tst = { tst } in
1313- Jsont.Object.map ~kind:"lwt" make
1414- |> Jsont.Object.mem "tst" Jsont.int ~enc:(fun l -> l.tst)
1515- |> Jsont.Object.skip_unknown |> Jsont.Object.finish
1313+ Json.Codec.Object.map ~kind:"lwt" make
1414+ |> Json.Codec.Object.member "tst" Json.Codec.int ~enc:(fun l -> l.tst)
1515+ |> Json.Codec.Object.skip_unknown |> Json.Codec.Object.seal
16161717-let jsont : t Jsont.t =
1717+let jsont : t Json.Codec.t =
1818 let make _type tst =
1919 ignore _type;
2020 { tst }
2121 in
2222- Jsont.Object.map ~kind:"lwt" make
2323- |> Jsont.Object.mem "_type" Jsont.string ~enc:(fun _ -> "lwt")
2424- |> Jsont.Object.mem "tst" Jsont.int ~enc:(fun l -> l.tst)
2525- |> Jsont.Object.skip_unknown |> Jsont.Object.finish
2222+ Json.Codec.Object.map ~kind:"lwt" make
2323+ |> Json.Codec.Object.member "_type" Json.Codec.string ~enc:(fun _ -> "lwt")
2424+ |> Json.Codec.Object.member "tst" Json.Codec.int ~enc:(fun l -> l.tst)
2525+ |> Json.Codec.Object.skip_unknown |> Json.Codec.Object.seal
26262727let pp ppf lwt =
2828 Format.fprintf ppf "LWT: client disconnected at %s"
+2-2
lib/owntracks_lwt.mli
···26262727(** {1 JSON Codec} *)
28282929-val jsont : t Jsont.t
2929+val jsont : t Json.Codec.t
3030(** [jsont] is a JSON codec for LWT messages. Expects the ["_type"] field to be
3131 ["lwt"]. *)
32323333-val jsont_bare : t Jsont.t
3333+val jsont_bare : t Json.Codec.t
3434(** [jsont_bare] is a JSON codec that doesn't require the ["_type"] field. *)
35353636(** {1 Pretty Printing} *)
+16-16
lib/owntracks_message.ml
···1717let card c = Card c
1818let lwt l = Lwt l
19192020-let jsont : t Jsont.t =
2020+let jsont : t Json.Codec.t =
2121 let case_location =
2222- Jsont.Object.Case.map "location" Owntracks_location.jsont_bare ~dec:location
2222+ Json.Codec.Object.Case.map "location" Owntracks_location.jsont_bare ~dec:location
2323 in
2424 let case_transition =
2525- Jsont.Object.Case.map "transition" Owntracks_transition.jsont_bare
2525+ Json.Codec.Object.Case.map "transition" Owntracks_transition.jsont_bare
2626 ~dec:transition
2727 in
2828 let case_waypoint =
2929- Jsont.Object.Case.map "waypoint" Owntracks_waypoint.jsont_bare ~dec:waypoint
2929+ Json.Codec.Object.Case.map "waypoint" Owntracks_waypoint.jsont_bare ~dec:waypoint
3030 in
3131 let case_waypoints =
3232- Jsont.Object.Case.map "waypoints" Owntracks_waypoint.jsont_bare
3232+ Json.Codec.Object.Case.map "waypoints" Owntracks_waypoint.jsont_bare
3333 ~dec:waypoint
3434 in
3535 let case_card =
3636- Jsont.Object.Case.map "card" Owntracks_card.jsont_bare ~dec:card
3636+ Json.Codec.Object.Case.map "card" Owntracks_card.jsont_bare ~dec:card
3737 in
3838 let case_lwt =
3939- Jsont.Object.Case.map "lwt" Owntracks_lwt.jsont_bare ~dec:lwt
3939+ Json.Codec.Object.Case.map "lwt" Owntracks_lwt.jsont_bare ~dec:lwt
4040 in
4141 let enc_case = function
4242- | Location l -> Jsont.Object.Case.value case_location l
4343- | Transition t -> Jsont.Object.Case.value case_transition t
4444- | Waypoint w -> Jsont.Object.Case.value case_waypoint w
4545- | Card c -> Jsont.Object.Case.value case_card c
4646- | Lwt l -> Jsont.Object.Case.value case_lwt l
4242+ | Location l -> Json.Codec.Object.Case.value case_location l
4343+ | Transition t -> Json.Codec.Object.Case.value case_transition t
4444+ | Waypoint w -> Json.Codec.Object.Case.value case_waypoint w
4545+ | Card c -> Json.Codec.Object.Case.value case_card c
4646+ | Lwt l -> Json.Codec.Object.Case.value case_lwt l
4747 | Unknown _ -> assert false (* Cannot encode Unknown *)
4848 in
4949 let cases =
5050- Jsont.Object.Case.
5050+ Json.Codec.Object.Case.
5151 [
5252 make case_location;
5353 make case_transition;
···5757 make case_lwt;
5858 ]
5959 in
6060- Jsont.Object.map ~kind:"message" Fun.id
6161- |> Jsont.Object.case_mem "_type" Jsont.string ~enc:Fun.id ~enc_case cases
6262- |> Jsont.Object.skip_unknown |> Jsont.Object.finish
6060+ Json.Codec.Object.map ~kind:"message" Fun.id
6161+ |> Json.Codec.Object.case_member "_type" Json.Codec.string ~enc:Fun.id ~enc_case cases
6262+ |> Json.Codec.Object.skip_unknown |> Json.Codec.Object.seal
63636464let pp ppf = function
6565 | Location loc -> Owntracks_location.pp ppf loc
+1-1
lib/owntracks_message.mli
···23232424(** {1 JSON Codec} *)
25252626-val jsont : t Jsont.t
2626+val jsont : t Json.Codec.t
2727(** [jsont] is a JSON codec for OwnTracks messages.
28282929 The message type is determined by the ["_type"] field in the JSON:
+2-2
lib/owntracks_mqtt.ml
···4343 else payload
4444 in
4545 match
4646- Jsont_bytesrw.decode_string Owntracks_message.jsont payload_with_topic
4646+ Json.of_string Owntracks_message.jsont payload_with_topic
4747 with
4848 | Ok message -> Ok { topic = msg.topic; user; device; message }
4949- | Error e -> Error e
4949+ | Error e -> Error (Json.Error.to_string e)
50505151let of_mqtt ~topic ~payload : (t, string) result =
5252 of_mqtt_message
+11-11
lib/owntracks_recorder.ml
···1111 let password t = t.password
1212end
13131414-let locations_jsont : Owntracks_location.t list Jsont.t =
1515- Jsont.list Owntracks_location.jsont_bare
1414+let locations_jsont : Owntracks_location.t list Json.Codec.t =
1515+ Json.Codec.list Owntracks_location.jsont_bare
16161717-let locations_data_jsont : Owntracks_location.t list Jsont.t =
1717+let locations_data_jsont : Owntracks_location.t list Json.Codec.t =
1818 let make data = data in
1919- Jsont.Object.map ~kind:"data_response" make
2020- |> Jsont.Object.mem "data" locations_jsont ~enc:Fun.id
2121- |> Jsont.Object.skip_unknown |> Jsont.Object.finish
1919+ Json.Codec.Object.map ~kind:"data_response" make
2020+ |> Json.Codec.Object.member "data" locations_jsont ~enc:Fun.id
2121+ |> Json.Codec.Object.skip_unknown |> Json.Codec.Object.seal
22222323-let string_list_jsont : string list Jsont.t = Jsont.list Jsont.string
2323+let string_list_jsont : string list Json.Codec.t = Json.Codec.list Json.Codec.string
24242525-let string_list_results_jsont : string list Jsont.t =
2525+let string_list_results_jsont : string list Json.Codec.t =
2626 let make results = results in
2727- Jsont.Object.map ~kind:"results_response" make
2828- |> Jsont.Object.mem "results" string_list_jsont ~enc:Fun.id
2929- |> Jsont.Object.skip_unknown |> Jsont.Object.finish
2727+ Json.Codec.Object.map ~kind:"results_response" make
2828+ |> Json.Codec.Object.member "results" string_list_jsont ~enc:Fun.id
2929+ |> Json.Codec.Object.skip_unknown |> Json.Codec.Object.seal
+4-4
lib/owntracks_recorder.mli
···40404141(** {1 JSON Codecs} *)
42424343-val locations_jsont : Owntracks_location.t list Jsont.t
4343+val locations_jsont : Owntracks_location.t list Json.Codec.t
4444(** Codec for a JSON array of location objects (without ["_type"] field). Use
4545 with the [/api/0/locations] endpoint when it returns an array. *)
46464747-val locations_data_jsont : Owntracks_location.t list Jsont.t
4747+val locations_data_jsont : Owntracks_location.t list Json.Codec.t
4848(** Codec for [{data: [...]}] response format from some recorder endpoints. *)
49495050-val string_list_jsont : string list Jsont.t
5050+val string_list_jsont : string list Json.Codec.t
5151(** Codec for a JSON array of strings (e.g., usernames or device names). *)
52525353-val string_list_results_jsont : string list Jsont.t
5353+val string_list_results_jsont : string list Json.Codec.t
5454(** Codec for [{results: [...]}] response format from [/api/0/list]. *)
+23-23
lib/owntracks_transition.ml
···2626let desc t = t.desc
2727let wtst t = t.wtst
28282929-let jsont_bare : t Jsont.t =
2929+let jsont_bare : t Json.Codec.t =
3030 let make tid tst lat lon acc event desc wtst =
3131 { tid; tst; lat; lon; acc; event; desc; wtst }
3232 in
3333- Jsont.Object.map ~kind:"transition" make
3434- |> Jsont.Object.opt_mem "tid" Jsont.string ~enc:(fun t -> t.tid)
3535- |> Jsont.Object.mem "tst" Jsont.int ~enc:(fun t -> t.tst)
3636- |> Jsont.Object.mem "lat" Jsont.number ~enc:(fun t -> t.lat)
3737- |> Jsont.Object.mem "lon" Jsont.number ~enc:(fun t -> t.lon)
3838- |> Jsont.Object.opt_mem "acc" Jsont.number ~enc:(fun t -> t.acc)
3939- |> Jsont.Object.mem "event" Jsont.string ~enc:(fun t -> t.event)
4040- |> Jsont.Object.opt_mem "desc" Jsont.string ~enc:(fun t -> t.desc)
4141- |> Jsont.Object.opt_mem "wtst" Jsont.int ~enc:(fun t -> t.wtst)
4242- |> Jsont.Object.skip_unknown |> Jsont.Object.finish
3333+ Json.Codec.Object.map ~kind:"transition" make
3434+ |> Json.Codec.Object.opt_member "tid" Json.Codec.string ~enc:(fun t -> t.tid)
3535+ |> Json.Codec.Object.member "tst" Json.Codec.int ~enc:(fun t -> t.tst)
3636+ |> Json.Codec.Object.member "lat" Json.Codec.number ~enc:(fun t -> t.lat)
3737+ |> Json.Codec.Object.member "lon" Json.Codec.number ~enc:(fun t -> t.lon)
3838+ |> Json.Codec.Object.opt_member "acc" Json.Codec.number ~enc:(fun t -> t.acc)
3939+ |> Json.Codec.Object.member "event" Json.Codec.string ~enc:(fun t -> t.event)
4040+ |> Json.Codec.Object.opt_member "desc" Json.Codec.string ~enc:(fun t -> t.desc)
4141+ |> Json.Codec.Object.opt_member "wtst" Json.Codec.int ~enc:(fun t -> t.wtst)
4242+ |> Json.Codec.Object.skip_unknown |> Json.Codec.Object.seal
43434444-let jsont : t Jsont.t =
4444+let jsont : t Json.Codec.t =
4545 let make _type tid tst lat lon acc event desc wtst =
4646 ignore _type;
4747 { tid; tst; lat; lon; acc; event; desc; wtst }
4848 in
4949- Jsont.Object.map ~kind:"transition" make
5050- |> Jsont.Object.mem "_type" Jsont.string ~enc:(fun _ -> "transition")
5151- |> Jsont.Object.opt_mem "tid" Jsont.string ~enc:(fun t -> t.tid)
5252- |> Jsont.Object.mem "tst" Jsont.int ~enc:(fun t -> t.tst)
5353- |> Jsont.Object.mem "lat" Jsont.number ~enc:(fun t -> t.lat)
5454- |> Jsont.Object.mem "lon" Jsont.number ~enc:(fun t -> t.lon)
5555- |> Jsont.Object.opt_mem "acc" Jsont.number ~enc:(fun t -> t.acc)
5656- |> Jsont.Object.mem "event" Jsont.string ~enc:(fun t -> t.event)
5757- |> Jsont.Object.opt_mem "desc" Jsont.string ~enc:(fun t -> t.desc)
5858- |> Jsont.Object.opt_mem "wtst" Jsont.int ~enc:(fun t -> t.wtst)
5959- |> Jsont.Object.skip_unknown |> Jsont.Object.finish
4949+ Json.Codec.Object.map ~kind:"transition" make
5050+ |> Json.Codec.Object.member "_type" Json.Codec.string ~enc:(fun _ -> "transition")
5151+ |> Json.Codec.Object.opt_member "tid" Json.Codec.string ~enc:(fun t -> t.tid)
5252+ |> Json.Codec.Object.member "tst" Json.Codec.int ~enc:(fun t -> t.tst)
5353+ |> Json.Codec.Object.member "lat" Json.Codec.number ~enc:(fun t -> t.lat)
5454+ |> Json.Codec.Object.member "lon" Json.Codec.number ~enc:(fun t -> t.lon)
5555+ |> Json.Codec.Object.opt_member "acc" Json.Codec.number ~enc:(fun t -> t.acc)
5656+ |> Json.Codec.Object.member "event" Json.Codec.string ~enc:(fun t -> t.event)
5757+ |> Json.Codec.Object.opt_member "desc" Json.Codec.string ~enc:(fun t -> t.desc)
5858+ |> Json.Codec.Object.opt_member "wtst" Json.Codec.int ~enc:(fun t -> t.wtst)
5959+ |> Json.Codec.Object.skip_unknown |> Json.Codec.Object.seal
60606161let pp ppf tr =
6262 Format.fprintf ppf "@[<v 0>";
+2-2
lib/owntracks_transition.mli
···59596060(** {1 JSON Codec} *)
61616262-val jsont : t Jsont.t
6262+val jsont : t Json.Codec.t
6363(** [jsont] is a JSON codec for transition messages. Expects the ["_type"] field
6464 to be ["transition"]. *)
65656666-val jsont_bare : t Jsont.t
6666+val jsont_bare : t Json.Codec.t
6767(** [jsont_bare] is a JSON codec that doesn't require the ["_type"] field. *)
68686969(** {1 Pretty Printing} *)
+17-17
lib/owntracks_waypoint.ml
···1212let rad t = t.rad
1313let desc t = t.desc
14141515-let jsont_bare : t Jsont.t =
1515+let jsont_bare : t Json.Codec.t =
1616 let make tst lat lon rad desc = { tst; lat; lon; rad; desc } in
1717- Jsont.Object.map ~kind:"waypoint" make
1818- |> Jsont.Object.mem "tst" Jsont.int ~enc:(fun w -> w.tst)
1919- |> Jsont.Object.mem "lat" Jsont.number ~enc:(fun w -> w.lat)
2020- |> Jsont.Object.mem "lon" Jsont.number ~enc:(fun w -> w.lon)
2121- |> Jsont.Object.mem "rad" Jsont.int ~enc:(fun w -> w.rad)
2222- |> Jsont.Object.mem "desc" Jsont.string ~enc:(fun w -> w.desc)
2323- |> Jsont.Object.skip_unknown |> Jsont.Object.finish
1717+ Json.Codec.Object.map ~kind:"waypoint" make
1818+ |> Json.Codec.Object.member "tst" Json.Codec.int ~enc:(fun w -> w.tst)
1919+ |> Json.Codec.Object.member "lat" Json.Codec.number ~enc:(fun w -> w.lat)
2020+ |> Json.Codec.Object.member "lon" Json.Codec.number ~enc:(fun w -> w.lon)
2121+ |> Json.Codec.Object.member "rad" Json.Codec.int ~enc:(fun w -> w.rad)
2222+ |> Json.Codec.Object.member "desc" Json.Codec.string ~enc:(fun w -> w.desc)
2323+ |> Json.Codec.Object.skip_unknown |> Json.Codec.Object.seal
24242525-let jsont : t Jsont.t =
2525+let jsont : t Json.Codec.t =
2626 let make _type tst lat lon rad desc =
2727 ignore _type;
2828 { tst; lat; lon; rad; desc }
2929 in
3030- Jsont.Object.map ~kind:"waypoint" make
3131- |> Jsont.Object.mem "_type" Jsont.string ~enc:(fun _ -> "waypoint")
3232- |> Jsont.Object.mem "tst" Jsont.int ~enc:(fun w -> w.tst)
3333- |> Jsont.Object.mem "lat" Jsont.number ~enc:(fun w -> w.lat)
3434- |> Jsont.Object.mem "lon" Jsont.number ~enc:(fun w -> w.lon)
3535- |> Jsont.Object.mem "rad" Jsont.int ~enc:(fun w -> w.rad)
3636- |> Jsont.Object.mem "desc" Jsont.string ~enc:(fun w -> w.desc)
3737- |> Jsont.Object.skip_unknown |> Jsont.Object.finish
3030+ Json.Codec.Object.map ~kind:"waypoint" make
3131+ |> Json.Codec.Object.member "_type" Json.Codec.string ~enc:(fun _ -> "waypoint")
3232+ |> Json.Codec.Object.member "tst" Json.Codec.int ~enc:(fun w -> w.tst)
3333+ |> Json.Codec.Object.member "lat" Json.Codec.number ~enc:(fun w -> w.lat)
3434+ |> Json.Codec.Object.member "lon" Json.Codec.number ~enc:(fun w -> w.lon)
3535+ |> Json.Codec.Object.member "rad" Json.Codec.int ~enc:(fun w -> w.rad)
3636+ |> Json.Codec.Object.member "desc" Json.Codec.string ~enc:(fun w -> w.desc)
3737+ |> Json.Codec.Object.skip_unknown |> Json.Codec.Object.seal
38383939let pp ppf wp =
4040 Format.fprintf ppf "Waypoint: %s at (%.6f, %.6f) radius %dm" wp.desc wp.lat
+2-2
lib/owntracks_waypoint.mli
···38383939(** {1 JSON Codec} *)
40404141-val jsont : t Jsont.t
4141+val jsont : t Json.Codec.t
4242(** [jsont] is a JSON codec for waypoint messages. Expects the ["_type"] field
4343 to be ["waypoint"]. *)
44444545-val jsont_bare : t Jsont.t
4545+val jsont_bare : t Json.Codec.t
4646(** [jsont_bare] is a JSON codec that doesn't require the ["_type"] field. *)
47474848(** {1 Pretty Printing} *)
+2-2
owntracks.opam
···22opam-version: "2.0"
33synopsis: "OwnTracks message types and JSON codecs"
44description: """
55-Types and jsont codecs for parsing OwnTracks MQTT location messages.
55+Types and JSON codecs for parsing OwnTracks MQTT location messages.
66OwnTracks is an open-source location tracking application that publishes
77GPS coordinates, accuracy, speed, battery, and other device state over MQTT.
88This library provides type-safe parsing and serialization of all OwnTracks
···1515depends: [
1616 "dune" {>= "3.21"}
1717 "ocaml" {>= "5.1"}
1818- "jsont" {>= "0.1.0"}
1818+ "nox-json"
1919 "bytesrw" {>= "0.1"}
2020 "geojson"
2121 "odoc" {with-doc}