Skip to content

Instantly share code, notes, and snippets.

@currentoor
Created December 24, 2019 19:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save currentoor/23d248ac7dc10deeba9859131962629e to your computer and use it in GitHub Desktop.
Save currentoor/23d248ac7dc10deeba9859131962629e to your computer and use it in GitHub Desktop.
(ns ucv.models.vehicle-capture
(:require
[cljs.core.async :as async]
[cljs-http.client :as http]
[clojure.string :as str]
[com.wsscode.pathom.connect :as pc]
[com.wsscode.common.async-cljs :refer [go-catch]]
[com.fulcrologic.fulcro.ui-state-machines :as uism :refer [defstatemachine]]
[ucv.rest-networking :refer [defresolver]]
[ucv.util :as util]
[ucv.client.app-atom :refer [app-atom]]
[taoensso.timbre :as log]))
(def unknown-plate
"The text to use when a failure occurs. When this appears in the plate, the plate input will also auto-focus
and highlight the content for immediate editing."
"???")
(defn process-recognition [response]
(let [{:keys [plate region]} (-> response :body :results first)
plate* (str/upper-case (str region "-" plate))]
(if (or
(nil? response)
(false? (:success response))
(= 0 (:status response))
(not (seq plate)))
{:vehicle/recognition {:vehicle/plate unknown-plate}}
{:vehicle/recognition {:vehicle/plate plate*}})))
(defresolver `post-file-to-alpr-api
{::pc/output [{:vehicle/recognition [:vehicle/id :vehicle/plate]}]}
(fn [{:keys [ast]} _]
(go-catch
(let [base64-data (-> ast :params :base64 meta :value)
{:keys [secret-key server-url]} (util/client-config app-atom :open-alpr/config)
alpr-api (str server-url "/v2/recognize_bytes")
_ (log/info "image bytes" (count base64-data))
start (system-time)
response (async/<! (http/post alpr-api
{:body base64-data
:query-params {:recognize_vehicle 0
:country "us"
:topn 1
:secret_key secret-key}
:with-credentials? false
:timeout 5000}))
end (system-time)]
(log/info "image processing times" (-> response :body :processing_time))
(log/debug "round trip time" (- end start))
(process-recognition response)))))
(ns ucv.rest-networking
(:require
[com.wsscode.common.async-cljs :refer [go-catch]]
[clojure.core.async :refer [go <! >! put! promise-chan close!]]
[com.wsscode.common.async-cljs :refer [<? <?maybe go-catch <!p]]
[com.fulcrologic.fulcro.networking.http-remote]
[com.fulcrologic.fulcro.algorithms.tx-processing :as txn]
[com.wsscode.pathom.connect :as pc]
[com.wsscode.pathom.core :as p]
[edn-query-language.core :as eql]))
(defonce indexes (atom {}))
(defmulti resolver-fn pc/resolver-dispatch)
(defonce defresolver (pc/resolver-factory resolver-fn indexes))
(defmulti mutation-fn pc/mutation-dispatch)
(defonce defmutation (pc/mutation-factory mutation-fn indexes))
(defn rest-parser
"Create a REST parser. Make sure you've required all nses that define rest resolvers. The given app-atom will be available
to all resolvers in `env` as `:app-atom`."
[app-atom]
(p/parallel-parser
{::p/env {::p/reader [p/map-reader
pc/parallel-reader
pc/open-ident-reader]}
::p/mutate mutation-fn
::p/plugins [(p/env-plugin {:app-atom app-atom
::pc/resolver-dispatch resolver-fn
::pc/indexes @indexes})
p/error-handler-plugin
p/request-cache-plugin
(p/post-process-parser-plugin p/elide-not-found)]}))
(defn rest-remote
"Create a remote that can resolve REST requests via Pathom resolvers. The `app-atom` will be in
resolver `env` at `:app-atom`.
Use `rest-remote/defresolver` to define Pathom resolvers for satisfying REST API requests, like so:
```
(defresolver `ofac
{::pc/output [::check]}
(fn [env _]
(let [name (-> env :ast :params :name)
api-key (some-> env :app app/current-state ::api-key)
params {\"sources\" \"FSE,SSI,ISA,PLC,561,SDN\"
\"countries\" \"US\"
\"api_key\" api-key
\"name\" name}]
(go
(let [{:keys [body]} (<!
(http/get \"https://api.trade.gov/consolidated_screening_list/search\"
{:with-credentials? false
:query-params params}))]
{::check body})))))
```
which can then be used with:
```
(df/load this ::ofac/check nil {:params {:name \"Donald Trump\"}})
```
and can be targeted, use load markers, etc.
Of course, you can also define resolvers that \"compute\" derived data with normal resolver tricks. See Pathom
documentation.
"
[app-atom]
(let [parser (rest-parser app-atom)]
{:transmit! (fn transmit! [_ {::txn/keys [ast result-handler]}]
(let [edn (eql/ast->query ast)]
(go
(try
(let [result {:transaction edn
:body (<?maybe (parser {} edn))
:status-code 200}]
(result-handler result))
(catch :default e
(js/console.error "PathomRemote error:" e)
(result-handler {:transaction edn
:body {}
:status-code 500}))))))}))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment