From 4d6b4b7fd69eeddb81e8102a1101cff028e69fe6 Mon Sep 17 00:00:00 2001 From: Magnus Persson Date: Sun, 30 Jan 2022 11:54:55 +0100 Subject: [PATCH 1/8] Fixing 3 bugs --- .github/workflows/pio-build.yaml | 1 + html/config.htm | 4 ++-- html/config.min.htm | 2 +- platformio.ini | 2 +- src/pushtarget.cpp | 5 ++--- src/templating.cpp | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/pio-build.yaml b/.github/workflows/pio-build.yaml index 3115156..012bc9e 100644 --- a/.github/workflows/pio-build.yaml +++ b/.github/workflows/pio-build.yaml @@ -4,6 +4,7 @@ on: push: branches: - dev + - patch jobs: build: diff --git a/html/config.htm b/html/config.htm index 8fe7df9..6928b5f 100644 --- a/html/config.htm +++ b/html/config.htm @@ -179,7 +179,7 @@
- +
@@ -188,7 +188,7 @@
- +
diff --git a/html/config.min.htm b/html/config.min.htm index e58779e..0d78174 100644 --- a/html/config.min.htm +++ b/html/config.min.htm @@ -1 +1 @@ -Beer Gravity Monitor

Temperature Format:




Gravity Format:


(C) Copyright 2021-22 Magnus Persson
\ No newline at end of file +Beer Gravity Monitor

Temperature Format:




Gravity Format:


(C) Copyright 2021-22 Magnus Persson
\ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 8a892dc..53220f2 100644 --- a/platformio.ini +++ b/platformio.ini @@ -34,7 +34,7 @@ build_flags = -D EMBED_HTML # If this is not used the html files needs to be on the file system (can be uploaded) -D USER_SSID=\""\"" # =\""myssid\"" -D USER_SSID_PWD=\""\"" # =\""mypwd\"" - -D CFG_APPVER="\"0.7.0\"" + -D CFG_APPVER="\"0.7.1\"" lib_deps = # Switched to forks for better version control. # Using local copy of these libraries #https://github.com/jrowberg/i2cdevlib.git# diff --git a/src/pushtarget.cpp b/src/pushtarget.cpp index 927b792..d13baa0 100644 --- a/src/pushtarget.cpp +++ b/src/pushtarget.cpp @@ -241,10 +241,9 @@ void PushTarget::sendMqtt(TemplatingEngine& engine) { // Allow secure channel, but without certificate validation myWifi.getWifiClientSecure().setInsecure(); Log.notice(F("PUSH: MQTT, SSL enabled without validation." CR)); - url.replace(":8883", ""); - mqtt.begin(url.c_str(), 8883, myWifi.getWifiClientSecure()); + mqtt.begin(url.c_str(), port, myWifi.getWifiClientSecure()); } else { - mqtt.begin(myConfig.getMqttUrl(), myWifi.getWifiClient()); + mqtt.begin(myConfig.getMqttUrl(), port, myWifi.getWifiClient()); } mqtt.connect(myConfig.getMDNS(), myConfig.getMqttUser(), diff --git a/src/templating.cpp b/src/templating.cpp index 7ee778a..9360cac 100644 --- a/src/templating.cpp +++ b/src/templating.cpp @@ -33,7 +33,7 @@ SOFTWARE. // Use iSpindle format for compatibility const char iSpindleFormat[] PROGMEM = "{" - "\"name\" : \"gravmon\", " + "\"name\" : \"${mdns}\", " "\"ID\": \"${id}\", " "\"token\" : \"gravmon\", " "\"interval\": ${sleep-interval}, " From b8959ae1654518b407d35e9b7e9d734f57a9887f Mon Sep 17 00:00:00 2001 From: Magnus Persson Date: Sun, 30 Jan 2022 12:09:47 +0100 Subject: [PATCH 2/8] Fixing workflow --- .github/workflows/pio-build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pio-build.yaml b/.github/workflows/pio-build.yaml index 012bc9e..33096a7 100644 --- a/.github/workflows/pio-build.yaml +++ b/.github/workflows/pio-build.yaml @@ -47,7 +47,7 @@ jobs: author_name: GitHub Action author_email: mp-se@noreply.github.com - branch: dev + branch: ${GITHUB_REF##*/} default_author: github_actor message: 'GitHub Action Build' From 4e0980e81409fb106d398cac96cfe8c6900b4ce2 Mon Sep 17 00:00:00 2001 From: Magnus Persson Date: Sun, 30 Jan 2022 12:13:59 +0100 Subject: [PATCH 3/8] New attempt to fix action --- .github/workflows/pio-build-patch.yaml | 53 ++++++++++++++++++++++++++ .github/workflows/pio-build.yaml | 3 +- 2 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/pio-build-patch.yaml diff --git a/.github/workflows/pio-build-patch.yaml b/.github/workflows/pio-build-patch.yaml new file mode 100644 index 0000000..7bb1915 --- /dev/null +++ b/.github/workflows/pio-build-patch.yaml @@ -0,0 +1,53 @@ +name: PlatformIO CI Patch + +on: + push: + branches: + - patch + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Cache pip + uses: actions/cache@v2 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip- + + - name: Cache PlatformIO + uses: actions/cache@v2 + with: + path: ~/.platformio + key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }} + + - name: Set up Python + uses: actions/setup-python@v2 + + - name: Install PlatformIO + run: | + python -m pip install --upgrade pip + pip install --upgrade platformio + git config --global advice.detachedHead false + + - name: Run PlatformIO + #run: pio run -e gravity-release -e gravity-perf -e gravity-debug + run: pio run -e gravity-release -e gravity-perf + #run: pio run -e gravity-release + + - uses: EndBug/add-and-commit@v7 # You can change this to use a specific version. https://github.com/marketplace/actions/add-commit + with: + add: 'bin' + author_name: GitHub Action + author_email: mp-se@noreply.github.com + + branch: patch + + default_author: github_actor + message: 'GitHub Action Build' + pathspec_error_handling: ignore diff --git a/.github/workflows/pio-build.yaml b/.github/workflows/pio-build.yaml index 33096a7..3115156 100644 --- a/.github/workflows/pio-build.yaml +++ b/.github/workflows/pio-build.yaml @@ -4,7 +4,6 @@ on: push: branches: - dev - - patch jobs: build: @@ -47,7 +46,7 @@ jobs: author_name: GitHub Action author_email: mp-se@noreply.github.com - branch: ${GITHUB_REF##*/} + branch: dev default_author: github_actor message: 'GitHub Action Build' From e076de022c69dc8a80db5946a0f826e45b22da79 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Sun, 30 Jan 2022 11:16:18 +0000 Subject: [PATCH 4/8] GitHub Action Build --- bin/config.min.htm | 2 +- bin/firmware-perf.bin | Bin 667184 -> 667120 bytes bin/firmware.bin | Bin 664256 -> 664176 bytes bin/version.json | 2 +- 4 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/config.min.htm b/bin/config.min.htm index e58779e..0d78174 100644 --- a/bin/config.min.htm +++ b/bin/config.min.htm @@ -1 +1 @@ -Beer Gravity Monitor

Temperature Format:




Gravity Format:


(C) Copyright 2021-22 Magnus Persson
\ No newline at end of file +Beer Gravity Monitor

Temperature Format:




Gravity Format:


(C) Copyright 2021-22 Magnus Persson
\ No newline at end of file diff --git a/bin/firmware-perf.bin b/bin/firmware-perf.bin index 914445c546fce727428e8c671d3ec17e3d4bedfc..1441db1d3978b25e18efc9b769c0f4924d98ff01 100644 GIT binary patch delta 32872 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 N^}eCv*zf(u{2v*FXjK3J delta 32711 zcmb@udwfjC`v<-=$%!O(a}&9c$exoRVMBHW2_l z%3s3wl!fondTEy}a??b0aM!$b+37Pmz-vf=`boEh$F`Je+uFS@3DqnRsg2V~AIKkg zt$kBn)GgtpE#;IgozF6^J*o>QG2Y28qnn5ybW1pDOZmyRcA>T}N%dw~xP{#k4%WJM_6A>2Fj!wB<&&%s1u+2ROuR(|uyU4%*-^9ws%aN|bF_3_E_`WVrJd&d;BpxsZ# zKhSD%hWsF=x0m{sDZSiy#nx_Oq|2moE<-lQW>IOJ{C(_fDqYX-+AX<>UH=>Z)-SI~ zFj8)+d@{k19gYH*BXNOFqhS@$vI>A!N)hG{8h8Z=f7lRSi7-na1-i6>=heWgUKC+o z)4;okaDGF0KEf=|1kl0;o*Cg2I*o_D&@e>KvIKcSqM3@L^M6WwNW3%9FG>HYcVX{$ zDAz@f5eEfEA#p@Qq84GMzk=0W-Ylk2v0Z+(80Dnv4Ne54-fqg28~eplwQ6fdKPO!# z61pQH!k+McQUn!`dh#sy2&rz4AjjB z<2({>G-LJS)7!M+xX|-)`T~Pq>|~?7(@DP6+o#Y=SE*s5Mcbg?n7SU%Zjl~3Y1IIo44U!2#%tpn0m@LIcX_P@hQ|d6tx}V z&Hff|GpRXMpU82O{Owg%kl4B*u>+MV<(x_W!K{K361uPigjwHDN8C-z3RNfdrfP-U zbng9aHlyyXBM#?KlS!how z&S*!~gK}L)HW?t#o!Xa5+vF2dH$lRAD_CiKEC<(`uIW1>*J@(cV~V> z_Q`AB{)!Be6EZ{G^yv|1XP``;l!*^1QQnZ*GFvo9kL&0?v!hS4cC_vbpLXE`V#aXs z(O>v<4WAY>k1@HPh(*L~3SYruVqCO#$UUEFi#bhN8+}}pac_Cge9K4e-k{|RA3f8+ zB&BZ1r;nKzK8?lH*l2C9dp=$IIB8fk(j~5m6chc0&c`ceO!$Cg?fKDqsjJ-UomZ$T z$jjd8LPf27?41ZIxygUMBXkg(M7TI>5-pm+7Lu^sX6oo3{yFCop$%HsYKcd}2lrAI z-ivdKbX{s&^_G_!Cda?qmvSBCrSGOvDLDW3yNe0s9>`O&a;W5)U!T>9Qt^Aa)9g-^ zv&!kS_fxf>95UzJP;q-u!cE&~YRYZp#p|VY;c-ML)QePaD%3~nBwsyZ-0cuS>v^ll z>%DQb#6S`**+%PvZbuSzjYC?pg)nIk)!Qz8Q%;=wIyok9oa^r@Z4DKQ0>rKIp}BMX z0wzb8?@Wp?`xI85;tOBc+>DW0X`eh`UI?qyTk{Sy7r*PYRv^Y-U^dk~o$mR-&T~2W zJ+fz^F_ZHT%+CfLF2^p!L>nTHS}0H{MV=2L4wScnaLMw?h3zOO$<+|SEb;#!l&YfK z;{%>bz2vcoi3#$e586<*rJ%y$F6Nyi5-Q(a%u~@OyM7o-xjH%WL*#rer+j$XPi)g^?Lva}3nQb) z$mlRKq>~)C1dHPfIb%r*m7dB+mcYh5l>b^XlZyA`@k`tIsP~13RIAfcVPN1{9r~(5 z{%mOoRqx4%mSUjp$Q4UJ)ruE|#Xs4!PLZC{1$o6sy`02Lf>JPugvDGC^i_K4GIVU% zQW>w0)RrU#N@oNts>MPb)Y@SMENu9^d_=2dY%t)75ev(n#BgF9O#to}dNlV+a=H96B zfWUDBLohJAqjGy?i=?kAJksjp78mLORVoSMV`1O8dgxp2OcQQ#HBL}qO(oGvoaoR{NdEEx3aTMdCPBi(^x;PKE zCo)~G(nRVE7q}sEt~`v2{pDx!6hZ1ORONX2o#RZoZ=8?RtD;bOv-?tVZDDjocRxf{3>>`xvHtden74*<^&uo!8uBC9DE?Z^z3DzZASX^V% zjJmMc13G4d(FwwNyJO-oeJ|R2Y(-T}LZmKED?LU|(Vyi!YRWaR+C~Y-t8E(On+xG6 z`TUw-f3>}^*i(bQl1Rn3N&>%an9p&}_tJoe)j`{MWwP8)f&s#d2-wo|t1 zEEpfw)r?9kjKYAcpVu?1Avy`h`*k%v984_7jLA{Kc(<-5$iWmhIwWnpvAnKE+mQV; zJ5vJlmpZUc8lY496ihbrU-Ha;8^lT*O7{=NKe;XCK1v6dm?;rv*D3NWrEL>#1*)dD zly@qfn{YZNvo`;ZvYK>Lo0yhuF;1^XM?AJ2AFk1q=Us==n?3cSOXFx>sB0Wej%yrE zEHHc5ml3wauly{AeQ>8g`+;&H@`oGN_!PnDZv)sjlMWg^S?;hAmiM$gd}FI1H41f+ ze#8fkPo;tlfm?l_&Qt^D5Aw>5?R}(}mSr7_D{9!6qLbFwi;8@9qj?Z#3l?&Tkfad` z2T3Kt#pfIXs$4JS@DGGI9ppI~ox;+~ZKlFOLXnsHB3SF=$RnN$E>;_quB;bV$fGv} zwv=lAPUnh(iw`=|#pU(f$8yf57BS+Jzth!|!H@Fn>7Lw2_0os@bvk^DQ=BI&c4E7RB-1ou7?>fY!+4bD}@}AFI z3>9zxovwZtTs*m<=&XA69sa>MY(ddH@x6LjS+q-4Z9?uM^lUqWdgJeWVt#P(XqFGs zQf56jQ*M5k= zfpV|Po3?bPVjuaJEnTRZC^y@RU1Pl5A4Kggf52if@()`(Q#D$y+S-$gIsL!j?Lx-+f{Gv`0J2xGjbncS<;SI+v~LB zVgEa^txOM{vD(I0+r%p^!79)Sqg}C_o&a@2{2Zt|;+H|2GBf)N0#G8|l%IduflQYp zb|rM@e$bjWxM9zH6x1E77k3(grU*#q5zw;0B?NR3xu#_eZagsFk+<)9jXMboy-g-x zZKmpv^0u!qA#TejztX!zW#FuzA^-VRU^8`q7UxG)KupmVo~%cW*2^vO!ehA{Ev9L* zM%xUmkI^<%ZLBs3F>$ok&YWZ?(wkcBvb54<#Gpl;BG1knK-FRLnY;)$Zhh-Gf*jbP z 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 diff --git a/bin/firmware.bin b/bin/firmware.bin index e1409dbac209271a2d99ff403e30bb098bb10eb6..d40a705015005f5c70abfacac32d61f4a99543a2 100644 GIT binary patch delta 31561 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
7fbE84a=0}V7v*muR;&BG04Y2 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 x@Kg9yU8@!aU-n9-xC`RR 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 z Date: Sun, 30 Jan 2022 14:25:29 +0100 Subject: [PATCH 5/8] Updated html --- html/config.htm | 4 +- html/config.min.htm | 2 +- src_docs/source/advanced.rst | 92 +++++ src_docs/source/api.rst | 322 ++++++++++++++++ src_docs/source/backlog.rst | 20 - src_docs/source/conf.py | 2 +- src_docs/source/configuration.rst | 602 +----------------------------- src_docs/source/data.rst | 156 ++++++++ src_docs/source/formula.rst | 16 + src_docs/source/index.rst | 8 +- src_docs/source/releases.rst | 11 + src_docs/source/services.rst | 136 +++++++ 12 files changed, 762 insertions(+), 609 deletions(-) create mode 100644 src_docs/source/advanced.rst create mode 100644 src_docs/source/api.rst delete mode 100644 src_docs/source/backlog.rst create mode 100644 src_docs/source/data.rst create mode 100644 src_docs/source/formula.rst create mode 100644 src_docs/source/services.rst diff --git a/html/config.htm b/html/config.htm index 6928b5f..4409fad 100644 --- a/html/config.htm +++ b/html/config.htm @@ -173,7 +173,7 @@
- +
@@ -188,7 +188,7 @@
- +
diff --git a/html/config.min.htm b/html/config.min.htm index 0d78174..44954f2 100644 --- a/html/config.min.htm +++ b/html/config.min.htm @@ -1 +1 @@ -Beer Gravity Monitor

Temperature Format:




Gravity Format:


(C) Copyright 2021-22 Magnus Persson
\ No newline at end of file +Beer Gravity Monitor

Temperature Format:




Gravity Format:


(C) Copyright 2021-22 Magnus Persson
\ No newline at end of file diff --git a/src_docs/source/advanced.rst b/src_docs/source/advanced.rst new file mode 100644 index 0000000..49028dc --- /dev/null +++ b/src_docs/source/advanced.rst @@ -0,0 +1,92 @@ +Advanced Configuration +###################### + +.. _format-editor: + +Format editor ++++++++++++++ + +To reduce the need for adding custom endpoints for various services there is an built in format editor that allows the user to customize the format being sent to the push target. + +.. warning:: + + Since the format templates can be big this function can be quite slow on a small device such as the esp8266. + +.. image:: images/format.png + :width: 800 + :alt: Format editor + +You enter the format data in the text field and the test button will show an example on what the output would look like. If the data cannot be formatted in json it will just be displayed as a long string. +The save button will save the current formla and reload the data from the device. + +.. tip:: + + If you save a blank string the default template will be loaded. + +These are the format keys available for use in the format. + +.. list-table:: Directory structure + :widths: 30 50 20 + :header-rows: 1 + + * - key + - description + - example + * - ${mdns} + - Name of the device + - gravmon2 + * - ${id} + - Unique id of the device + - e422a3 + * - ${sleep-interval} + - Seconds between data is pushed + - 900 + * - ${temp} + - Temperature in format configured on device, one decimal + - 21.2 + * - ${temp-c} + - Temperature in C, one decimal + - 21.2 + * - ${temp-f} + - Temperature in F, one decimal + - 58.0 + * - ${temp-unit} + - Temperature format `C` or `F` + - C + * - ${battery} + - Battery voltage, two decimals + - 3.89 + * - ${rssi} + - Wifi signal strength + - -75 + * - ${run-time} + - How long the last measurement took, two decimals + - 3.87 + * - ${angle} + - Angle of the gyro, two decimals + - 28.67 + * - ${tilt} + - Same as angle. + - 28.67 + * - ${gravity} + - Calculated gravity, 4 decimals for SG and 1 for Plato. + - 1.0456 + * - ${gravity-sg} + - Calculated gravity in SG, 4 decimals + - 1.0456 + * - ${gravity-plato} + - Calculated gravity in Plato, 1 decimal + - 8.5 + * - ${corr-gravity} + - Temperature corrected gravity, 4 decimals for SG and 1 for Plato. + - 1.0456 + * - ${corr-gravity-sg} + - Temperature corrected gravity in SG, 4 decimals + - 1.0456 + * - ${corr-gravity-plato} + - Temperature corrected gravity in Plato, 1 decimal + - 8.5 + * - ${gravity-unit} + - Gravity format, `G` or `P` + - G + diff --git a/src_docs/source/api.rst b/src_docs/source/api.rst new file mode 100644 index 0000000..e066dd2 --- /dev/null +++ b/src_docs/source/api.rst @@ -0,0 +1,322 @@ +.. _rest-api: + +REST API +######## + +All the API's use a key called ``ID`` which is the unique device id (chip id). This is used as an API key when sending requests to the device. + +GET: /api/config +================ + +Retrive the current configuation of the device via an HTTP GET command. Payload is in JSON format. + +* ``temp-format`` can be either ``C`` or ``F`` +* ``gravity-format`` is always ``G`` (plato is not yet supported) + +Other parameters are the same as in the configuration guide. + +.. code-block:: json + + { + "mdns": "gravmon", + "id": "ee1bfc", + "ota-url": "http://192.168.1.50:80/firmware/gravmon/", + "temp-format": "C", + "brewfather-push": "http://log.brewfather.net/stream?id=Qwerty", + "http-push": "http://192.168.1.50:9090/api/v1/Qwerty/telemetry", + "http-push-h1": "header: value", + "http-push-h2": "header: value", + "http-push2": "http://192.168.1.50/ispindel", + "http-push2-h1": "header: value", + "http-push2-h2": "header: value", + "influxdb2-push": "http://192.168.1.50:8086", + "influxdb2-org": "org", + "influxdb2-bucket": "bucket_id", + "influxdb2-auth": "token", + "mqtt-push": "192.168.1.50", + "mqtt-port": 1883, + "mqtt-user": "user", + "mqtt-pass": "pass", + "sleep-interval": 30, + "voltage-factor": 1.59, + "gravity-formula": "0.0*tilt^3+0.0*tilt^2+0.0017978*tilt+0.9436", + "gravity-format": "G", + "temp-adjustment-value": 0, + "gravity-temp-adjustment": false, + "gyro-temp": true, + "gyro-calibration-data": { + "ax": -330, + "ay": -2249, + "az": 1170, + "gx": 99, + "gy": -6, + "gz": 4 + }, + "angle": 90.93, + "gravity": 1.105, + "battery": 0.04 + } + + +GET: /api/device +================ + +Retrive the current device settings via an HTTP GET command. Payload is in JSON format. + +.. code-block:: json + + { + "app-name": "GravityMon", + "app-ver": "0.0.0", + "id": "ee1bfc", + "mdns": "gravmon" + } + + +GET: /api/status +================ + +Retrive the current device status via an HTTP GET command. Payload is in JSON format. + +* ``temp-format`` can be either ``C`` or ``F`` + +Other parameters are the same as in the configuration guide. + +.. code-block:: json + + { + "id": "ee1bfc", + "angle": 89.86, + "gravity": 1.1052, + "gravity-tempcorr": 1.1031, + "temp-c": 0, + "temp-f": 32, + "battery": 0, + "temp-format": "C", + "sleep-mode": false, + "rssi": -56 + } + + +GET: /api/config/formula +======================== + +Retrive the data used for formula calculation data via an HTTP GET command. Payload is in JSON format. + +* ``a1``-``a4`` are the angles/tilt readings (up to 5 are currently supported) +* ``g1``-``g4`` are the corresponding gravity reaadings in SG or Plato depending on the device-format. + +.. code-block:: json + + { + "id": "ee1bfc", + "a1": 22.4, + "a2": 54.4, + "a3": 58, + "a4": 0, + "a5": 0, + "g1": 1.000, + "g2": 1.053, + "g3": 1.062, + "g4": 1, + "g5": 1, + "gravity-format": "G", + "gravity-formula": "0.0*tilt^3+0.0*tilt^2+0.0017978*tilt+0.9436" + } + + +POST: /api/config/device +======================== + +Used to update device settings via an HTTP POST command. + +Payload should be in standard format used for posting a form. Such as as: `id=value&mdns=value` etc. Key value pairs are shown below. + +* ``temp-format`` can be either ``C`` (Celcius) or ``F`` (Farenheight) + +.. code-block:: + + id=ee1bfc + mdns=gravmon + temp-format=C + sleep-interval=30 + + +POST: /api/config/push +====================== + +Used to update push settings via an HTTP POST command. Payload is in JSON format. + +Payload should be in standard format used for posting a form. Such as as: `id=value&mdns=value` etc. Key value pairs are shown below. + +.. code-block:: + + id=ee1bfc + http-push=http://192.168.1.50/ispindel + http-push2= + http-push-h1= + http-push-h2= + http-push2-h1= + http-push2-h2= + brewfather-push= + influxdb2-push=http://192.168.1.50:8086 + influxdb2-org= + influxdb2-bucket= + influxdb2-auth= + mqtt-push=192.168.1.50 + mqtt-port=1883 + mqtt-user= + mqtt-pass= + + +POST: /api/config/gravity +========================= + +Used to update gravity settings via an HTTP POST command. Payload is in JSON format. + +* ``gravity-formula`` keywords ``temp`` and ``tilt`` are supported. +* ``gravity-format`` can be either ``G`` (SG) or ``P`` (PLATO) + +.. note:: + ``gravity-temp-adjustment`` is defined as "on" or "off" when posting since this is the output values + from a checkbox, when reading data it's sent as boolean (true,false). + +Payload should be in standard format used for posting a form. Such as as: `id=value&mdns=value` etc. Key value pairs are shown below. + +.. code-block:: + + id=ee1bfc + gravity-formula=0.0*tilt^3+0.0*tilt^2+0.0017978*tilt+0.9436, + gravity-format=P + gravity-temp-adjustment=off + + +POST: /api/config/hardware +========================== + +Used to update hardware settings via an HTTP POST command. Payload is in JSON format. + +.. note:: + ``gyro-temp`` is defined as "on" or "off" when posting since this is the output values from a checkbox, when + reading data it's sent as boolean (true,false). + +Payload should be in standard format used for posting a form. Such as as: `id=value&mdns=value` etc. Key value pairs are shown below. + +.. code-block:: + + id=ee1bfc + voltage-factor=1.59 + temp-adjustment=0 + gyro-temp=off + ota-url=http://192.168.1.50/firmware/gravmon/ + + +POST: /api/config/formula +========================= + +Used to update formula calculation data via an HTTP POST command. Payload is in JSON format. + +* ``a1``-``a4`` are the angles/tilt readings (up to 5 are currently supported) +* ``g1``-``g4`` are the corresponding gravity reaadings (in SG) + +Payload should be in standard format used for posting a form. Such as as: `id=value&mdns=value` etc. Key value pairs are shown below. + +.. code-block:: + + id=ee1bfc + a1=22.4 + a2=54.4 + a3=58 + a4=0 + a5=0 + g1=1.000 + g2=1.053 + g3=1.062 + g4=1 + g5=1 + + +Calling the API's from Python +============================= + +Here is some example code for how to access the API's from a python script. Keys should always be +present or the API call will fail. + +The requests package converts the json to standard form post format. + +.. code-block:: python + + import requests + import json + + host = "192.168.1.1" # IP adress (or name) of the device to send these settings to + id = "ee1bfc" # Device ID (shown in serial console during startup or in UI) + + def set_config( url, json ): + headers = { "ContentType": "application/json" } + print( url ) + resp = requests.post( url, headers=headers, data=json ) + if resp.status_code != 200 : + print ( "Failed " ) + else : + print ( "Success " ) + + url = "http://" + host + "/api/config/device" + json = { "id": id, + "mdns": "gravmon", # Name of the device + "temp-format": "C", # Temperature format C or F + "sleep-interval": 30 # Sleep interval in seconds + } + set_config( url, json ) + + url = "http://" + host + "/api/config/push" + json = { "id": id, + "http-push": "http://192.168.1.1/ispindel", + "http-push2": "", + "http-push-h1": "", + "http-push-h2": "", + "http-push2-h1": "", + "http-push2-h2": "", + "brewfather-push": "", + "influxdb2-push": "", + "influxdb2-org": "", + "influxdb2-bucket": "", + "influxdb2-auth": "", + "mqtt-push": "192.168.1.50", + "mqtt-port": 1883, + "mqtt-user": "Qwerty", + "mqtt-pass": "Qwerty" + } + set_config( url, json ) + + url = "http://" + host + "/api/config/gravity" + json = { "id": id, + "gravity-formula": "", + "gravity-format": "P", + "gravity-temp-adjustment": "off" # Adjust gravity (on/off) + } + set_config( url, json ) + + url = "http://" + host + "/api/config/hardware" + json = { "id": id, + "voltage-factor": 1.59, # Default value for voltage calculation + "temp-adjustment": 0, # If temp sensor needs to be corrected + "gyro-temp": "on", # Use the temp sensor in the gyro instead (on/off) + "ota-url": "" # if the device should seach for a new update when active + } + set_config( url, json ) + + url = "http://" + host + "/api/formula" + json = { "id": id, + "a1": 22.4, + "a2": 54.4, + "a3": 58, + "a4": 0, + "a5": 0, + "g1": 1.000, + "g2": 1.053, + "g3": 1.062, + "g4": 1, + "g5": 1 + } + set_config( url, json ) diff --git a/src_docs/source/backlog.rst b/src_docs/source/backlog.rst deleted file mode 100644 index 7f1a0a9..0000000 --- a/src_docs/source/backlog.rst +++ /dev/null @@ -1,20 +0,0 @@ -Backlog of changes -################## - -This is a list of potential ideas to implemnt in the software. - -Documentation -------------- - -- Write contribution instructions -- Example project for creating integrations and instructions -- Add instructions for other services - -Code ----- - -- Support for plato -- Use pre-commit for validating check-in -- Show indicated battery life based on interval (check if its feasable) -- Add possibility to add one certificate for proper SSL authentication. -- Add configurable Authentication/Token header to http/https requests diff --git a/src_docs/source/conf.py b/src_docs/source/conf.py index f40c9c7..5583b9d 100644 --- a/src_docs/source/conf.py +++ b/src_docs/source/conf.py @@ -22,7 +22,7 @@ copyright = '2021-2022, Magnus Persson' author = 'Magnus Persson' # The full version, including alpha/beta/rc tags -release = '0.7.0' +release = '0.7.1' # -- General configuration --------------------------------------------------- diff --git a/src_docs/source/configuration.rst b/src_docs/source/configuration.rst index 5738188..c14d794 100644 --- a/src_docs/source/configuration.rst +++ b/src_docs/source/configuration.rst @@ -1,7 +1,7 @@ .. _setting-up-device: -Setting up device -################# +Configuration +############# The device can operate in two modes and must be in ``configuration mode`` in order for the web server to be active. @@ -48,11 +48,12 @@ URL: (http://gravmon.local/device) * **Device name:** - This is unique name of the device. + This is unique name of the device which is set in the configuration, also known as MDNS name. * **Device ID:** - This is unique identifier for the device (ESP8266 id), this is required when using the API as an API Key to safeguard against faulty requests. + This is unique identifier for the device (ESP8266 id), this is required when using the API as an API Key to safeguard + against faulty requests. This is the ESP8266 chip ID, so it should be unique. Configuration @@ -73,15 +74,19 @@ Device Setting * **Temperature format:** - Choose between Celsius and Farenheight + Choose between Celsius and Farenheight when displaying temperature. * **Interval:** - This defines how long the device should be sleeping between the readings when in `gravity monitoring` mode. You will also see the values in minutes/seconds to easier set the interval. 900s is a recommended interval. + This defines how long the device should be sleeping between the readings when in `gravity monitoring` mode. You will also see + the values in minutes/seconds to easier set the interval. 900s is a recommended interval. The sleep interval can + be set between 10 - 3600 seconds (60 minutes). .. note:: - The sleep interval can be set between 10 - 3600 seconds (60 minutes). + A low value such as 30s will give a lifespan of 1-2 weeks and 300s (5 min) would last for 3+ weeks. This assumes that + there is good wifi connection that takes less than 1s to reconnect. Poor wifi connection is the main reason for battery drain. + * **Calibration values:** @@ -166,16 +171,20 @@ Gravity Settings * **Gravity format:** - Gravity format can be eihter `SG` or `Plato`. The device will use SG Internally and convert to Plato when displaying data. + Gravity format can be eihter `SG` or `Plato`. The device will use SG Internally and convert to Plato when displaying or sending data. * **Gravity formula:** Gravity formula is compatible with standard iSpindle formulas so any existing calculation option can be used. You can also use the feature to create the formula by supplying the raw data. See :ref:`create-formula` + The gravity formula accepts to paramaters, **tilt** for the angle or **temp** for temperature (temperature inserted into the formula + will be in celsius). I would recommend to use the formula calculation feature instead since this is much easier. + * **Temperature correct gravity:** - Will apply a temperature calibration formula to the gravity as a second step. + Will apply a temperature calibration formula to the gravity as a second step after gravity has been calculated. It's also possible to + build this into the gravity formula. .. warning:: This formula assumes that the calibration has been done at 20°C / 68°F. @@ -213,7 +222,7 @@ Hardware Settings * **OTA URL:** - Should point to a URL where the .bin file + version.json file is located. + Should point to a URL where the firmware.bin file + version.json file are located. For the OTA to work, place the following files (version.json + firmware.bin) at the location that you pointed out in OTA URL. If the version number in the json file is newer than in the code the update will be done during startup. @@ -225,578 +234,5 @@ Hardware Settings .. code-block:: http://192.168.1.1/firmware/gravmon/ - -.. _format-editor: -Format editor -############# - -To reduce the need for adding custom endpoints for various services there is an built in format editor that allows the user to customize the format being sent to the push target. - -.. warning:: - - Since the format templates can be big this function can be quite slow on a small device such as the esp8266. - -.. image:: images/format.png - :width: 800 - :alt: Format editor - -You enter the format data in the text field and the test button will show an example on what the output would look like. If the data cannot be formatted in json it will just be displayed as a long string. -The save button will save the current formla and reload the data from the device. - -.. tip:: - - If you save a blank string the default template will be loaded. - -These are the format keys available for use in the format. - -.. list-table:: Directory structure - :widths: 30 50 20 - :header-rows: 1 - - * - key - - description - - example - * - ${mdns} - - Name of the device - - gravmon2 - * - ${id} - - Unique id of the device - - e422a3 - * - ${sleep-interval} - - Seconds between data is pushed - - 900 - * - ${temp} - - Temperature in format configured on device, one decimal - - 21.2 - * - ${temp-c} - - Temperature in C, one decimal - - 21.2 - * - ${temp-f} - - Temperature in F, one decimal - - 58.0 - * - ${temp-unit} - - Temperature format `C` or `F` - - C - * - ${battery} - - Battery voltage, two decimals - - 3.89 - * - ${rssi} - - Wifi signal strength - - -75 - * - ${run-time} - - How long the last measurement took, two decimals - - 3.87 - * - ${angle} - - Angle of the gyro, two decimals - - 28.67 - * - ${tilt} - - Same as angle. - - 28.67 - * - ${gravity} - - Calculated gravity, 4 decimals for SG and 1 for Plato. - - 1.0456 - * - ${gravity-sg} - - Calculated gravity in SG, 4 decimals - - 1.0456 - * - ${gravity-plato} - - Calculated gravity in Plato, 1 decimal - - 8.5 - * - ${corr-gravity} - - Temperature corrected gravity, 4 decimals for SG and 1 for Plato. - - 1.0456 - * - ${corr-gravity-sg} - - Temperature corrected gravity in SG, 4 decimals - - 1.0456 - * - ${corr-gravity-plato} - - Temperature corrected gravity in Plato, 1 decimal - - 8.5 - * - ${gravity-unit} - - Gravity format, `G` or `P` - - G - - -.. _create-formula: - -Create formula -############## - -.. image:: images/formula1.png - :width: 800 - :alt: Formula data - -Here you can enter up to 5 values (angles + gravity) that is then used to create the formula. Angles equal to zero will be regarded as empty even if there is a gravity reading. - -.. image:: images/formula2.png - :width: 800 - :alt: Formula graph - -Once the formula is created a graph over the entered values and a simulation of the formula will give you a nice overview on how the formula will work. - -.. _rest-api: - -REST API -######## - -All the API's use a key called ``ID`` which is the unique device id (chip id). This is used as an API key when sending requests to the device. - -GET: /api/config -================ - -Retrive the current configuation of the device via an HTTP GET command. Payload is in JSON format. - -* ``temp-format`` can be either ``C`` or ``F`` -* ``gravity-format`` is always ``G`` (plato is not yet supported) - -Other parameters are the same as in the configuration guide. - -.. code-block:: json - - { - "mdns": "gravmon", - "id": "ee1bfc", - "ota-url": "http://192.168.1.50:80/firmware/gravmon/", - "temp-format": "C", - "brewfather-push": "http://log.brewfather.net/stream?id=Qwerty", - "http-push": "http://192.168.1.50:9090/api/v1/Qwerty/telemetry", - "http-push2": "http://192.168.1.50/ispindel", - "influxdb2-push": "http://192.168.1.50:8086", - "influxdb2-org": "Qwerty", - "influxdb2-bucket": "Qwerty", - "influxdb2-auth": "Qwerty", - "mqtt-push": "192.168.1.50", - "mqtt-port": 1883, - "mqtt-user": "Qwerty", - "mqtt-pass": "Qwerty", - "sleep-interval": 30, - "voltage-factor": 1.59, - "gravity-formula": "0.0*tilt^3+0.0*tilt^2+0.0017978*tilt+0.9436", - "gravity-format": "G", - "temp-adjustment-value": 0, - "gravity-temp-adjustment": false, - "gyro-temp": true, - "gyro-calibration-data": { - "ax": -330, - "ay": -2249, - "az": 1170, - "gx": 99, - "gy": -6, - "gz": 4 - }, - "angle": 90.93, - "gravity": 1.105, - "battery": 0.04 - } - - -GET: /api/device -================ - -Retrive the current device settings via an HTTP GET command. Payload is in JSON format. - -.. code-block:: json - - { - "app-name": "GravityMon ", - "app-ver": "0.0.0", - "id": "ee1bfc", - "mdns": "gravmon" - } - - -GET: /api/status -================ - -Retrive the current device status via an HTTP GET command. Payload is in JSON format. - -* ``temp-format`` can be either ``C`` or ``F`` - -Other parameters are the same as in the configuration guide. - -.. code-block:: json - - { - "id": "ee1bfc", - "angle": 89.86, - "gravity": 1.1052, - "gravity-tempcorr": 1.1031, - "temp-c": 0, - "temp-f": 32, - "battery": 0, - "temp-format": "C", - "sleep-mode": false, - "rssi": -56 - } - - -GET: /api/config/formula -======================== - -Retrive the data used for formula calculation data via an HTTP GET command. Payload is in JSON format. - -* ``a1``-``a4`` are the angles/tilt readings (up to 5 are currently supported) -* ``g1``-``g4`` are the corresponding gravity reaadings in SG or Plato depending on the device-format. - -.. code-block:: json - - { - "id": "ee1bfc", - "a1": 22.4, - "a2": 54.4, - "a3": 58, - "a4": 0, - "a5": 0, - "g1": 1.000, - "g2": 1.053, - "g3": 1.062, - "g4": 1, - "g5": 1, - "gravity-format": "G", - "gravity-formula": "0.0*tilt^3+0.0*tilt^2+0.0017978*tilt+0.9436" - } - - -POST: /api/config/device -======================== - -Used to update device settings via an HTTP POST command. Payload is in JSON format. - -* ``temp-format`` can be either ``C`` (Celcius) or ``F`` (Farenheight) - -.. code-block:: json - - { - "id": "ee1bfc", - "mdns": "gravmon", - "temp-format": "C", - "sleep-interval": 30 - } - - -POST: /api/config/push -====================== - -Used to update push settings via an HTTP POST command. Payload is in JSON format. - -.. code-block:: json - - { - "id": "ee1bfc", - "http-push": "http://192.168.1.50/ispindel", - "http-push2": "", - "brewfather-push": "", - "influxdb2-push": "http://192.168.1.50:8086", - "influxdb2-org": "Qwerty", - "influxdb2-bucket": "Qwerty", - "influxdb2-auth": "Qwerty" - "mqtt-push": "192.168.1.50", - "mqtt-port": 1883, - "mqtt-user": "Qwerty", - "mqtt-pass": "Qwerty", - } - - -POST: /api/config/gravity -========================= - -Used to update gravity settings via an HTTP POST command. Payload is in JSON format. - -* ``gravity-formula`` keywords ``temp`` and ``tilt`` are supported. -* ``gravity-format`` can be either ``G`` (SG) or ``P`` (PLATO) - -.. note:: - ``gravity-temp-adjustment`` is defined as "on" or "off" when posting since this is the output values - from a checkbox, when reading data it's sent as boolean (true,false). - -.. code-block:: json - - { - "id": "ee1bfc", - "gravity-formula": "0.0*tilt^3+0.0*tilt^2+0.0017978*tilt+0.9436", - "gravity-format": "P", - "gravity-temp-adjustment": "off" - } - - -POST: /api/config/hardware -========================== - -Used to update hardware settings via an HTTP POST command. Payload is in JSON format. - -.. note:: - ``gyro-temp`` is defined as "on" or "off" when posting since this is the output values from a checkbox, when - reading data it's sent as boolean (true,false). - -.. code-block:: json - - { - "id": "ee1bfc", - "voltage-factor": 1.59, - "temp-adjustment": 0, - "gyro-temp": "off", - "ota-url": "http://192.168.1.50/firmware/gravmon/" - } - - -POST: /api/config/formula -========================= - -Used to update formula calculation data via an HTTP POST command. Payload is in JSON format. - -* ``a1``-``a4`` are the angles/tilt readings (up to 5 are currently supported) -* ``g1``-``g4`` are the corresponding gravity reaadings (in SG) - -.. code-block:: json - - { - "id": "ee1bfc", - "a1": 22.4, - "a2": 54.4, - "a3": 58, - "a4": 0, - "a5": 0, - "g1": 1.000, - "g2": 1.053, - "g3": 1.062, - "g4": 1, - "g5": 1 - } - - -Calling the API's from Python -============================= - -Here is some example code for how to access the API's from a python script. Keys should always be -present or the API call will fail. - -.. code-block:: python - - import requests - import json - - host = "192.168.1.1" # IP adress (or name) of the device to send these settings to - id = "ee1bfc" # Device ID (shown in serial console during startup or in UI) - - def set_config( url, json ): - headers = { "ContentType": "application/json" } - print( url ) - resp = requests.post( url, headers=headers, data=json ) - if resp.status_code != 200 : - print ( "Failed " ) - else : - print ( "Success " ) - - url = "http://" + host + "/api/config/device" - json = { "id": id, - "mdns": "gravmon", # Name of the device - "temp-format": "C", # Temperature format C or F - "sleep-interval": 30 # Sleep interval in seconds - } - set_config( url, json ) - - url = "http://" + host + "/api/config/push" - json = { "id": id, - "http-push": "http://192.168.1.1/ispindel", - "http-push2": "", - "brewfather-push": "", - "influxdb2-push": "", - "influxdb2-org": "", - "influxdb2-bucket": "", - "influxdb2-auth": "", - "mqtt-push": "192.168.1.50", - "mqtt-port": 1883, - "mqtt-user": "Qwerty", - "mqtt-pass": "Qwerty" - } - set_config( url, json ) - - url = "http://" + host + "/api/config/gravity" - json = { "id": id, - "gravity-formula": "", - "gravity-format": "P", - "gravity-temp-adjustment": "off" # Adjust gravity (on/off) - } - set_config( url, json ) - - url = "http://" + host + "/api/config/hardware" - json = { "id": id, - "voltage-factor": 1.59, # Default value for voltage calculation - "temp-adjustment": 0, # If temp sensor needs to be corrected - "gyro-temp": "on", # Use the temp sensor in the gyro instead (on/off) - "ota-url": "" # if the device should seach for a new update when active - } - set_config( url, json ) - - url = "http://" + host + "/api/formula" - json = { "id": id, - "a1": 22.4, - "a2": 54.4, - "a3": 58, - "a4": 0, - "a5": 0, - "g1": 1.000, - "g2": 1.053, - "g3": 1.062, - "g4": 1, - "g5": 1 - } - set_config( url, json ) - - -.. _data-formats: - -Data Formats -############ - -.. _data-formats-ispindle: - -iSpindle format -=============== - -This is the format used for standard http posts. - -* ``corr-gravity`` is an extended parameter containing a temperature corrected gravity reading. -* ``gravity-format`` is an extended parameter containing the gravity format (G or P). -* ``run-time`` is an extended parameter containing the number of seconds the execution took. - -.. code-block:: json - - { - "name" : "gravmon", - "ID": "2E6753", - "token" : "gravmon", - "interval": 900, - "temperature": 20.5, - "temp-units": "C", - "gravity": 1.0050, - "angle": 45.34, - "battery": 3.67, - "rssi": -12, - - "corr-gravity": 1.0050, - "gravity-unit": "G", - "run-time": 6 - } - -This is the format template used to create the json above. - -.. code-block:: - - { - "name" : "gravmon", - "ID": "${id}", - "token" : "gravmon", - "interval": ${sleep-interval}, - "temperature": ${temp}, - "temp-units": "${temp-unit}", - "gravity": ${gravity}, - "angle": ${angle}, - "battery": ${battery}, - "rssi": ${rssi}, - "corr-gravity": ${corr-gravity}, - "gravity-unit": "${gravity-unit}", - "run-time": ${run-time} - } - - -.. _data-formats-brewfather: - -Brewfather format -================= - -This is the format for Brewfather. See: `Brewfather API docs `_ - -.. code-block:: json - - { - "name" : "gravmon", - "temp": 20.5, - "temp_unit": "C", - "battery": 3.67, - "gravity": 1.0050, - "gravity_unit": "G", - } - - -.. _data-formats-influxdb2: - -Influx DB v2 -============ - -This is the format for InfluxDB v2 - -.. code-block:: - - measurement,host=,device=,temp-format=,gravity-format=SG,gravity=1.0004,corr-gravity=1.0004,angle=45.45,temp=20.1,battery=3.96,rssi=-18 - - -This is the format template used to create the json above. - -.. code-block:: - - measurement,host=${mdns},device=${id},temp-format=${temp-unit},gravity-format=${gravity-unit} gravity=${gravity},corr-gravity=${corr-gravity},angle=${angle},temp=${temp},battery=${battery},rssi=${rssi} - - -.. _data-formats-mqtt: - -MQTT -==== - -This is the format used to send data to MQTT. Each of the lines are specific topics - -.. code-block:: - - ispindel/device_name/tilt 89.96796 - ispindel/device_name/temperature 21.375 - ispindel/device_name/temp_units C - ispindel/device_name/battery 0.04171 - ispindel/device_name/gravity 33.54894 - ispindel/device_name/interval 1 - ispindel/device_name/RSSI -58 - - -This is the format template used to create the json above. - -.. tip:: - - Each line in the format is treated as one topic. The `|` is used as separator between lines and the first `:` is used as separator between topic and value. Each line is formatted as `:` - -.. code-block:: - - ispindel/${mdns}/tilt:${angle}| - ispindel/${mdns}/temperature:${temp}| - ispindel/${mdns}/temp_units:${temp-unit}| - ispindel/${mdns}/battery:${battery}| - ispindel/${mdns}/gravity:${gravity}| - ispindel/${mdns}/interval:${sleep-interval}| - ispindel/${mdns}/RSSI:${rssi}| - -This is a format template that is compatible with v0.6. Just replace the `topic` with the topic you want to post data to. - -.. code-block:: - - topic:{"name":"gravmon","ID":"${id}","token":"gravmon","interval": ${sleep-interval},"temperature": ${temp},"temp-units": "${temp-unit}","gravity":${gravity},"angle": ${angle},"battery":${battery},"rssi": ${rssi},"corr-gravity":${corr-gravity},"gravity-unit": "${gravity-unit}","run-time": ${run-time}}| - - -version.json -============ - -Contents version.json. The version is used by the device to check if the this version is newer. The html files will also be downloaded if the are present on the server. This way it's easy to -upgrade to a version that serve the html files from the file system. If they dont exist nothing will happen, the OTA flashing will still work. If the html files are missing from the file system -they can be uploaded manually afterwards. - -.. code-block:: json - - { - "project":"gravmon", - "version":"0.7.0", - "html": [ - "index.min.htm", - "device.min.htm", - "config.min.htm", - "format.min.htm", - "calibration.min.htm", - "about.min.htm" - ] - } diff --git a/src_docs/source/data.rst b/src_docs/source/data.rst new file mode 100644 index 0000000..d16d875 --- /dev/null +++ b/src_docs/source/data.rst @@ -0,0 +1,156 @@ +.. _data-formats: + +Data Formats +############ + +.. _data-formats-ispindle: + +iSpindle format +=============== + +This is the format used for standard http posts. + +* ``corr-gravity`` is an extended parameter containing a temperature corrected gravity reading. +* ``gravity-format`` is an extended parameter containing the gravity format (G or P). +* ``run-time`` is an extended parameter containing the number of seconds the execution took. + +.. code-block:: json + + { + "name" : "gravmon", + "ID": "2E6753", + "token" : "gravmon", + "interval": 900, + "temperature": 20.5, + "temp-units": "C", + "gravity": 1.0050, + "angle": 45.34, + "battery": 3.67, + "rssi": -12, + + "corr-gravity": 1.0050, + "gravity-unit": "G", + "run-time": 6 + } + +This is the format template used to create the json above. + +.. code-block:: + + { + "name" : "${mdns}", + "ID": "${id}", + "token" : "gravmon", + "interval": ${sleep-interval}, + "temperature": ${temp}, + "temp-units": "${temp-unit}", + "gravity": ${gravity}, + "angle": ${angle}, + "battery": ${battery}, + "rssi": ${rssi}, + "corr-gravity": ${corr-gravity}, + "gravity-unit": "${gravity-unit}", + "run-time": ${run-time} + } + + +.. _data-formats-brewfather: + +Brewfather format +================= + +This is the format for Brewfather. See: `Brewfather API docs `_ + +.. code-block:: json + + { + "name" : "gravmon", + "temp": 20.5, + "temp_unit": "C", + "battery": 3.67, + "gravity": 1.0050, + "gravity_unit": "G", + } + + +.. _data-formats-influxdb2: + +Influx DB v2 +============ + +This is the format for InfluxDB v2 + +.. code-block:: + + measurement,host=,device=,temp-format=,gravity-format=SG,gravity=1.0004,corr-gravity=1.0004,angle=45.45,temp=20.1,battery=3.96,rssi=-18 + + +This is the format template used to create the json above. + +.. code-block:: + + measurement,host=${mdns},device=${id},temp-format=${temp-unit},gravity-format=${gravity-unit} gravity=${gravity},corr-gravity=${corr-gravity},angle=${angle},temp=${temp},battery=${battery},rssi=${rssi} + + +.. _data-formats-mqtt: + +MQTT +==== + +This is the format used to send data to MQTT. Each of the lines are specific topics + +.. code-block:: + + ispindel/device_name/tilt 89.96796 + ispindel/device_name/temperature 21.375 + ispindel/device_name/temp_units C + ispindel/device_name/battery 0.04171 + ispindel/device_name/gravity 33.54894 + ispindel/device_name/interval 1 + ispindel/device_name/RSSI -58 + + +This is the format template used to create the json above. + +.. tip:: + + Each line in the format is treated as one topic. The `|` is used as separator between lines and the first `:` is used as separator between topic and value. Each line is formatted as `:` + +.. code-block:: + + ispindel/${mdns}/tilt:${angle}| + ispindel/${mdns}/temperature:${temp}| + ispindel/${mdns}/temp_units:${temp-unit}| + ispindel/${mdns}/battery:${battery}| + ispindel/${mdns}/gravity:${gravity}| + ispindel/${mdns}/interval:${sleep-interval}| + ispindel/${mdns}/RSSI:${rssi}| + +This is a format template that is compatible with v0.6. Just replace the `topic` with the topic you want to post data to. + +.. code-block:: + + topic:{"name":"gravmon","ID":"${id}","token":"gravmon","interval": ${sleep-interval},"temperature": ${temp},"temp-units": "${temp-unit}","gravity":${gravity},"angle": ${angle},"battery":${battery},"rssi": ${rssi},"corr-gravity":${corr-gravity},"gravity-unit": "${gravity-unit}","run-time": ${run-time}}| + + +version.json +============ + +Contents version.json. The version is used by the device to check if the this version is newer. The html files will also be downloaded if the are present on the server. This way it's easy to +upgrade to a version that serve the html files from the file system. If they dont exist nothing will happen, the OTA flashing will still work. If the html files are missing from the file system +they can be uploaded manually afterwards. + +.. code-block:: json + + { + "project":"gravmon", + "version":"0.7.0", + "html": [ + "index.min.htm", + "device.min.htm", + "config.min.htm", + "format.min.htm", + "calibration.min.htm", + "about.min.htm" + ] + } diff --git a/src_docs/source/formula.rst b/src_docs/source/formula.rst new file mode 100644 index 0000000..3c51780 --- /dev/null +++ b/src_docs/source/formula.rst @@ -0,0 +1,16 @@ +.. _create-formula: + +Create formula +############## + +.. image:: images/formula1.png + :width: 800 + :alt: Formula data + +Here you can enter up to 5 values (angles + gravity) that is then used to create the formula. Angles equal to zero will be regarded as empty even if there is a gravity reading. + +.. image:: images/formula2.png + :width: 800 + :alt: Formula graph + +Once the formula is created a graph over the entered values and a simulation of the formula will give you a nice overview on how the formula will work. diff --git a/src_docs/source/index.rst b/src_docs/source/index.rst index ac00540..eff9733 100644 --- a/src_docs/source/index.rst +++ b/src_docs/source/index.rst @@ -7,7 +7,7 @@ Welcome to GravityMon's documentation! ###################################### .. note:: - This documentation reflects **v0.7**. Last updated 2022-01-23 + This documentation reflects **v0.7.1**. Last updated 2022-01-30 GravityMon is a replacement firmare for the iSpindle firmware, it uses the same hardware configuration so @@ -125,10 +125,14 @@ the following libraries and without these this would have been much more difficu functionallity installation configuration + formula + services + advanced + api + data compiling contributing q_and_a - backlog Indices and tables ================== diff --git a/src_docs/source/releases.rst b/src_docs/source/releases.rst index 09620fb..fc89ec3 100644 --- a/src_docs/source/releases.rst +++ b/src_docs/source/releases.rst @@ -3,6 +3,17 @@ Releases ######## +v0.7.1 +------ + +* Added instructions for how to configure integration with Fermentrack +* Added instructions for how to configure integration with Ubidots +* Added instructions for how to configure integration with HomeAssistant +* Added instructions for how to configure integration with Brewers Friend (not verified) +* BUG: Defined mqtt port was ignored, used default values. +* BUG: Extended length of HTTP url fields from 100 to 120 chars. +* BUG: Fixed issue with default template so it now includes the device name correctly. + v0.7.0 ------ diff --git a/src_docs/source/services.rst b/src_docs/source/services.rst new file mode 100644 index 0000000..2040980 --- /dev/null +++ b/src_docs/source/services.rst @@ -0,0 +1,136 @@ +.. _services: + +Service Integration +################### + +This chapter contains a list of targets and what configuration is needed to interact with them. + +Brewfather +++++++++++ + +Brewfather is an all in one service that allows you to manage you recepies and brews. + +Just enter the http adress found on brewfather, not other settings are needed. The endpoint has the following format: + +.. code-block:: + + http://log.brewfather.net/http://log.brewfather.net/stream?id= + + +The URL is found under settings. + +Fermentrack ++++++++++++ + +`Fermentrack `_ is a open source brewing software to monitor and control fermentation. + +GravityMon can be installed and used as an iSpindle. Just register the device as an iSpindle and use the defined endpoint which normally is: + +.. code-block:: + + http://myservername/ispindel + + +UBIdots ++++++++ + +`UBIdots `_ is a IoT service that display data collected various sources. + +For this service there are two options to configure the integration. First you will need your default token which is found under `API Credentials` ( in the example below). +Swap the text with the name you want to show in ubidots. + +**Option 1** - token as an URL parameter + +Enter the following as URL: + +.. code-block:: + + http://industrial.api.ubidots.com/api/v1.6/devices//?token= + + +Even though ubidots can handle the default ispindle format it probably better to just post the data you want. This is an example of a +format template that can be used. For information on customizing the format see :ref:`format-editor`. + +.. code-block:: + + { + "temperature": ${temp}, + "gravity": ${gravity}, + "angle": ${angle}, + "battery": ${battery}, + "rssi": ${rssi} + } + + +Home Assistant ++++++++++++++++ + +`HomeAssistant `_ is a platform for home automation and can collect sensor data +from multiple devices. + +This setup uses the MQTT integration with home assistant to collect values from the device. + +This part of the configuration goes into the home assistant configuration.yaml file. The example assumes that the +device is named `gravmon2` + +:: + + sensor: + - platform: mqtt + name: "gravmon2_gravity" + state_topic: "gravmon/gravmon2/gravity" + - platform: mqtt + name: "gravmon2_battery" + state_topic: "gravmon/gravmon2/battery" + - platform: mqtt + name: "gravmon2_rssi" + state_topic: "gravmon/gravmon2/rssi" + + +Enter the name of the MQTT server in Home Assistant in the URL. You might need to install that option +first. This is the format needed to submit the data to the correct topics as needed above. You can add as +many sensors / topics as you want. + +:: + + gravmon/${mdns}/tilt:${angle}| + gravmon/${mdns}/temperature:${temp}| + gravmon/${mdns}/temp_units:${temp-unit}| + + +Brewer's Friend ++++++++++++++++ + +Brewer's friend is an all in one service that allows you to manage you recepies and brews. + +.. warning:: + I dont have an account for brewers friend so I have not been able to verfy this completely. Its based on + the available documentation. + +You can find you API key when logged in to the service. Follow these `instructions `_ + +**Note there are different URLs if you are using plato or specific gravity!** + +.. code-block:: + + http://log.brewersfriend.com/ispindel/[API KEY] + http://log.brewersfriend.com/ispindel_sg/[API KEY] + + +From what I can read in the documentation you need to add the API key as a token as well. This can be done using a custom +format for the endpoint. Just add you API key after token. + +.. code-block:: + + { + "name" : "${mdns}", + "ID": "${id}", + "token" : "[API KEY]", + "interval": ${sleep-interval}, + "temperature": ${temp}, + "temp-units": "${temp-unit}", + "gravity": ${gravity}, + "angle": ${angle}, + "battery": ${battery}, + "rssi": ${rssi} + } From 9727e87e331c7981a9bb3be05fa04fbe1ec1986c Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Sun, 30 Jan 2022 13:27:18 +0000 Subject: [PATCH 6/8] GitHub Action Build --- bin/config.min.htm | 2 +- bin/firmware-perf.bin | Bin 667120 -> 667120 bytes bin/firmware.bin | Bin 664176 -> 664176 bytes 3 files changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/config.min.htm b/bin/config.min.htm index 0d78174..44954f2 100644 --- a/bin/config.min.htm +++ b/bin/config.min.htm @@ -1 +1 @@ -Beer Gravity Monitor

Temperature Format:




Gravity Format:


(C) Copyright 2021-22 Magnus Persson
\ No newline at end of file +Beer Gravity Monitor

Temperature Format:




Gravity Format:


(C) Copyright 2021-22 Magnus Persson
\ No newline at end of file diff --git a/bin/firmware-perf.bin b/bin/firmware-perf.bin index 1441db1d3978b25e18efc9b769c0f4924d98ff01..6066a406d23322081e4a5c53fe33340ea14f0ef1 100644 GIT binary patch delta 82 zcmexxTjRrRjSV6KEN8#ZU)(Gq&@Lgs2*gZ4%nZaVK+FonY(UJuT|$7vv~s$BH;4Rm e-!2Z$?WLU@yBMeYc5=wK`*m|{_v_|dvmk%^^SC ew~K>wdub=fF2?D4T^#c5e%&0~{kl09Edl@w&lv6i diff --git a/bin/firmware.bin b/bin/firmware.bin index d40a705015005f5c70abfacac32d61f4a99543a2..68b3356b2eca410817dfe8ef5bbfdcb22e00deeb 100644 GIT binary patch delta 77 zcmexxMB~E|jSV6KEQ_CBUezoi&@Lgs2*gZ4%nZaVK+FonY(UJuT|$6Ews5+5Gl%^4 ZkVcNfjML@YIpo{TnmM+cHFH|c2LQ{>7fApB delta 77 zcmexxMB~E|jSV6KEJ=4*I+`T}+9d=SftU%1nSq!Eh*^P{4T#ydO9*ht7EYIM=aAnX Y(#Ua`ak^L&hkUzPGskwbW=^a50DICF3;+NC From 1fd3b1911d447e6b65d8dfd837ec945aac89210e Mon Sep 17 00:00:00 2001 From: Magnus Persson Date: Sun, 30 Jan 2022 14:30:52 +0100 Subject: [PATCH 7/8] Bump version of html --- html/device.htm | 2 +- html/device.min.htm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/html/device.htm b/html/device.htm index c39de14..80fb0ab 100644 --- a/html/device.htm +++ b/html/device.htm @@ -100,7 +100,7 @@ $('#spinner').show(); $.getJSON(url, function (cfg) { console.log( cfg ); - $("#app-ver").text(cfg["app-ver"] + " (html 0.7.0)"); + $("#app-ver").text(cfg["app-ver"] + " (html 0.7.1)"); $("#mdns").text(cfg["mdns"]); $("#id").text(cfg["id"]); }) diff --git a/html/device.min.htm b/html/device.min.htm index 1ac0ad2..06f4d8f 100644 --- a/html/device.min.htm +++ b/html/device.min.htm @@ -1 +1 @@ -Beer Gravity Monitor

Current version:
Loading...
Host name:
Loading...
Device ID:
Loading...

(C) Copyright 2021-22 Magnus Persson
\ No newline at end of file +Beer Gravity Monitor

Current version:
Loading...
Host name:
Loading...
Device ID:
Loading...

(C) Copyright 2021-22 Magnus Persson
\ No newline at end of file From 044bfcddad17503b77517c0053a4e536186f6a56 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Sun, 30 Jan 2022 13:32:41 +0000 Subject: [PATCH 8/8] GitHub Action Build --- bin/device.min.htm | 2 +- bin/firmware-perf.bin | Bin 667120 -> 667120 bytes bin/firmware.bin | Bin 664176 -> 664176 bytes 3 files changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/device.min.htm b/bin/device.min.htm index 1ac0ad2..06f4d8f 100644 --- a/bin/device.min.htm +++ b/bin/device.min.htm @@ -1 +1 @@ -Beer Gravity Monitor

Current version:
Loading...
Host name:
Loading...
Device ID:
Loading...

(C) Copyright 2021-22 Magnus Persson
\ No newline at end of file +Beer Gravity Monitor

Current version:
Loading...
Host name:
Loading...
Device ID:
Loading...

(C) Copyright 2021-22 Magnus Persson
\ No newline at end of file diff --git a/bin/firmware-perf.bin b/bin/firmware-perf.bin index 6066a406d23322081e4a5c53fe33340ea14f0ef1..fde55cf6f3aea239fac2aaa15da9c47d178c8b80 100644 GIT binary patch delta 65 zcmexxTjRrRjSV6KEVnfFNH$9dv`Yvu0x=U1GXpUT5VHa?8xXT^mk{7cPhd1`Zz$l{ M-cZ1qzn3uu0Gn14#sB~S delta 65 zcmexxTjRrRjSV6KEN8#ZU)(Gq&@Lgs2*gZ4%nZaVK+FonY(UJuT|$5(J%Q1ny`g|( MdqV+d{$9pZ0NOAU^#A|> diff --git a/bin/firmware.bin b/bin/firmware.bin index 68b3356b2eca410817dfe8ef5bbfdcb22e00deeb..60207eb826dabd43bb5b921d1fcb1917bf5de116 100644 GIT binary patch delta 65 zcmexxMB~E|jSV6KEK%RhEt(|++9d=SftU%1nSq!Eh*^P{4T#ydO9*iIM=%<;XJl|} M&&c3p-^JJf0EJT#(f|Me delta 65 zcmexxMB~E|jSV6KEQ_CBUezoi&@Lgs2*gZ4%nZaVK+FonY(UJuT|$7vKZ4PqJtKo- MdqxH)`!2>t0LY#b7XSbN