aboutsummaryrefslogtreecommitdiff
path: root/hsm-web
diff options
context:
space:
mode:
Diffstat (limited to 'hsm-web')
-rw-r--r--hsm-web/Client/package-lock.json77
-rw-r--r--hsm-web/Client/package.json1
-rw-r--r--hsm-web/Client/src/App.vue11
-rw-r--r--hsm-web/Client/src/INA226.vue48
-rw-r--r--hsm-web/Client/src/config.js3
-rw-r--r--hsm-web/Hsm/Web.hs32
-rw-r--r--hsm-web/Main.hs6
-rw-r--r--hsm-web/hsm-web.cabal6
8 files changed, 171 insertions, 13 deletions
diff --git a/hsm-web/Client/package-lock.json b/hsm-web/Client/package-lock.json
index 5324573..14e6a57 100644
--- a/hsm-web/Client/package-lock.json
+++ b/hsm-web/Client/package-lock.json
@@ -6,6 +6,7 @@
"": {
"dependencies": {
"@vue/cli": "^5.0.9",
+ "axios": "^1.13.2",
"core-js": "^3.8.3",
"vue": "^3.2.13"
},
@@ -4614,6 +4615,12 @@
"retry": "0.13.1"
}
},
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "license": "MIT"
+ },
"node_modules/at-least-node": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
@@ -4687,6 +4694,17 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/axios": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz",
+ "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==",
+ "license": "MIT",
+ "dependencies": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.4",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
"node_modules/babel-core": {
"version": "7.0.0-bridge.0",
"resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz",
@@ -5679,6 +5697,18 @@
"node": ">=0.1.90"
}
},
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/commander": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
@@ -6677,6 +6707,15 @@
"node": ">=0.10.0"
}
},
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
@@ -7099,6 +7138,21 @@
"node": ">= 0.4"
}
},
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/escalade": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
@@ -8456,7 +8510,6 @@
"version": "1.15.11",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
"integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
- "dev": true,
"funding": [
{
"type": "individual",
@@ -8497,6 +8550,22 @@
"node": ">=0.10.0"
}
},
+ "node_modules/form-data": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
+ "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "es-set-tostringtag": "^2.1.0",
+ "hasown": "^2.0.2",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
@@ -12930,6 +12999,12 @@
"node": ">= 0.10"
}
},
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "license": "MIT"
+ },
"node_modules/ps-list": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/ps-list/-/ps-list-7.2.0.tgz",
diff --git a/hsm-web/Client/package.json b/hsm-web/Client/package.json
index 65a15d8..21f7248 100644
--- a/hsm-web/Client/package.json
+++ b/hsm-web/Client/package.json
@@ -9,6 +9,7 @@
},
"dependencies": {
"@vue/cli": "^5.0.9",
+ "axios": "^1.13.2",
"core-js": "^3.8.3",
"vue": "^3.2.13"
},
diff --git a/hsm-web/Client/src/App.vue b/hsm-web/Client/src/App.vue
index 202e4d2..84fefcf 100644
--- a/hsm-web/Client/src/App.vue
+++ b/hsm-web/Client/src/App.vue
@@ -1,3 +1,14 @@
<template>
<h1>HsMouse</h1>
+ <INA226 />
</template>
+
+<script>
+import INA226 from './INA226.vue'
+
+export default {
+ components: {
+ INA226
+ }
+}
+</script>
diff --git a/hsm-web/Client/src/INA226.vue b/hsm-web/Client/src/INA226.vue
new file mode 100644
index 0000000..bf0141f
--- /dev/null
+++ b/hsm-web/Client/src/INA226.vue
@@ -0,0 +1,48 @@
+<template>
+ <h3>Battery Status</h3>
+ <table>
+ <tbody>
+ <tr>
+ <td>{{ ina226Reading.voltage.toFixed(2) }}V</td>
+ <td>{{ ina226Reading.current.toFixed(2) }}A</td>
+ <td>{{ ina226Reading.power.toFixed(2) }}W</td>
+ </tr>
+ </tbody>
+ </table>
+</template>
+
+<script>
+import axios from 'axios'
+import config from './config'
+
+export default {
+ data() {
+ return {
+ ina226Reading: {
+ voltage: 0,
+ current: 0,
+ power: 0
+ }
+ }
+ },
+ mounted() {
+ this.getINA226Reading()
+ },
+ methods: {
+ getINA226Reading() {
+ axios
+ .get(`${config.api}/ina226`)
+ .then(res => {
+ this.ina226Reading = res.data
+ setTimeout(this.getINA226Reading, 1000)
+ })
+ }
+ }
+}
+</script>
+
+<style>
+table {
+ width: 100%;
+}
+</style>
diff --git a/hsm-web/Client/src/config.js b/hsm-web/Client/src/config.js
new file mode 100644
index 0000000..b8e9a98
--- /dev/null
+++ b/hsm-web/Client/src/config.js
@@ -0,0 +1,3 @@
+module.exports = {
+ api: 'http://192.168.8.170:3000'
+}
diff --git a/hsm-web/Hsm/Web.hs b/hsm-web/Hsm/Web.hs
index ae8b1f2..4f6fb6e 100644
--- a/hsm-web/Hsm/Web.hs
+++ b/hsm-web/Hsm/Web.hs
@@ -8,15 +8,24 @@ module Hsm.Web
)
where
-import Effectful (Dispatch (Static), DispatchOf, Eff, IOE, (:>))
-import Effectful.Dispatch.Static (SideEffects (WithSideEffects), StaticRep, evalStaticRep, getStaticRep, unsafeEff)
+import Data.Aeson (encode)
+import Effectful (Dispatch (Static), DispatchOf, Eff, IOE, liftIO, (:>))
+import Effectful.Dispatch.Static
+ ( SideEffects (WithSideEffects)
+ , StaticRep
+ , evalStaticRep
+ , getStaticRep
+ , unEff
+ , unsafeEff
+ )
import Effectful.Dispatch.Static.Primitive (Env)
import Effectful.Exception (finally)
-import Hsm.Log (Log, Logs, Severity (Info, Trace), logMsg, makeLoggerIO)
+import Hsm.INA226 (I2CINA226, INA226, readINA226State)
+import Hsm.Log (Logs, Severity (Info, Trace), logMsg, makeLoggerIO)
import Network.Wai.Handler.Warp (defaultSettings, setLogger)
import Network.Wai.Middleware.Static (addBase, noDots, staticPolicy, (>->))
import Paths_hsm_web (getDataFileName)
-import Web.Scotty (Options (settings, verbose), defaultOptions, file, get, middleware, scottyOpts)
+import Web.Scotty (Options (settings, verbose), defaultOptions, file, get, middleware, raw, scottyOpts, setHeader)
data Web (a :: * -> *) (b :: *)
@@ -25,21 +34,24 @@ type instance DispatchOf Web = Static WithSideEffects
newtype instance StaticRep Web
= Web Options
-server :: Options -> Env es -> IO ()
-server options _ = do
+server :: (I2CINA226 :> es, INA226 :> es, Logs '["i2c", "ina226"] es) => Options -> Env es -> IO ()
+server options env = do
dist <- getDataFileName "Client/dist/"
scottyOpts options $ do
- get "/" . file $ dist <> "index.html"
middleware . staticPolicy $ noDots >-> addBase dist
+ get "/" . file $ dist <> "index.html"
+ get "/ina226" $ do
+ setHeader "Content-Type" "application/json"
+ liftIO (unEff readINA226State env) >>= raw . encode
-runServer :: (Log "web" :> es, Web :> es) => Eff es ()
+runServer :: (I2CINA226 :> es, INA226 :> es, Logs '["i2c", "ina226", "web"] es, Web :> es) => Eff es ()
runServer = finally startServer stopServer
where
startServer = do
Web options <- getStaticRep
- logMsg Info "Starting scotty web server"
+ logMsg @"web" Info "Starting scotty web server"
unsafeEff $ server options
- stopServer = logMsg Info "Stopping scotty web server"
+ stopServer = logMsg @"web" Info "Stopping scotty web server"
runWeb :: (IOE :> es, Logs '["scotty", "web"] es) => Eff (Web : es) a -> Eff es a
runWeb action = do
diff --git a/hsm-web/Main.hs b/hsm-web/Main.hs
index 7555067..0ec780e 100644
--- a/hsm-web/Main.hs
+++ b/hsm-web/Main.hs
@@ -3,6 +3,8 @@
import Data.Function ((&))
import Effectful (runEff)
import Hsm.Core.App (bootstrapAppNoEcho)
+import Hsm.I2C (runI2C)
+import Hsm.INA226 (runINA226)
import Hsm.Log (Severity (Info), runLogsOpt)
import Hsm.Log.Options (makeLoggerOptionParser)
import Hsm.Web (runServer, runWeb)
@@ -10,9 +12,9 @@ import Hsm.Web (runServer, runWeb)
-- Avoids package/module qualifiers in generated code
import Options.Applicative
-type Logs = '["scotty", "web"]
+type Logs = '["i2c", "ina226", "scotty", "web"]
$(makeLoggerOptionParser @Logs "Options" "parser" 'Info)
main :: IO ()
-main = bootstrapAppNoEcho parser "Launch HsMouse Web Server" $ \opts -> runServer & runWeb & runLogsOpt @Options @Logs opts & runEff
+main = bootstrapAppNoEcho parser "Launch HsMouse Web Server" $ \opts -> runServer & runWeb & runINA226 & runI2C & runLogsOpt @Options @Logs opts & runEff
diff --git a/hsm-web/hsm-web.cabal b/hsm-web/hsm-web.cabal
index d3b9074..20b7db0 100644
--- a/hsm-web/hsm-web.cabal
+++ b/hsm-web/hsm-web.cabal
@@ -4,14 +4,17 @@ name: hsm-web
version: 0.1.0.0
data-files:
Client/dist/*.html
+ Client/dist/css/*.css
Client/dist/js/*.js
Client/dist/js/*.js.map
library
build-depends:
+ , aeson
, base
, effectful-core
, effectful-plugin
+ , hsm-ina226
, hsm-log
, scotty
, wai-middleware-static
@@ -27,10 +30,13 @@ library
executable hsm-web
build-depends:
+ , aeson
, base
, effectful-core
, effectful-plugin
, hsm-core
+ , hsm-i2c
+ , hsm-ina226
, hsm-log
, optparse-applicative
, scotty