fix/revision of example 'meshtastic'

This commit is contained in:
pls.153 2023-11-07 18:06:17 +01:00
parent a5af331a8d
commit 6da7bf8670
5 changed files with 126 additions and 110 deletions

View file

@ -25,5 +25,13 @@
</ul>
<p>All parts above combined cost me around 50€.</p>
<p>I used a soldering iron, a hot glue gun, a step drill bit, double sided tape.</p>
<br>
<h3>Antennas</h3>
<p>
A good antenna is crucial for the radio to function properly. A <a href="https://nanovna.com/" target="_blank">NanoVNA</a> is very helpful to test if an antenna is resonant at the specified frequency (otherwise it's useless). You can find good clones for about 50€/$ (beware of really cheap/bad clones).
</p>
<p>
Antennas listed in the <a href="https://store.rakwireless.com/products/" target="_blank">RAK store</a> are generally of good/industrial quality. Some other mass produced offerings are of such bad quality that I had to throw them away (after measuring them).
</p>
</body>
</html>

View file

@ -78,6 +78,7 @@
(/ (* deg pi) 180))
(defun distance (from to)
(qlog :distance from to)
;; Haversine formula
(destructuring-bind ((lat-1 lon-1) (lat-2 lon-2))
(list from to)

View file

@ -191,107 +191,110 @@
:alt (me:altitude pos)
:time (me:time pos))))))
(defun process-received ()
"Walks *RECEIVED* FROM-RADIOs and saves relevant data."
(setf *received* (nreverse *received*))
(unless *ble-names*
(setf *ble-names* (qt:short-names qt:*cpp*)))
(dolist (struct *received*)
(cond ((me:from-radio.has-packet struct)
(let* ((packet (me:from-radio.packet struct))
(decoded (me:decoded packet)))
(when decoded
(let ((payload (me:payload decoded)))
(case (me:portnum decoded)
;; text-message
(:text-message-app
(let ((timestamp (get-universal-time))
(mid (me:id packet))
(text (qfrom-utf8 payload)))
(setf msg:*message-id* (max mid msg:*message-id*))
(if (x:starts-with ":e" text) ; 'echo'
(qsingle-shot 1000 (lambda () (send-message (x:cc "<b>echo:</b>" (subseq text #.(length ":e"))))))
(progn
(when (x:starts-with "<b>echo:</b>" text)
(setf text (msg:echo-message text (me:from packet) (me:rx-snr packet) (me:rx-rssi packet))))
(msg:add-message
(list :receiver (my-name)
:sender (node-to-name (me:from packet))
:timestamp timestamp
:hour (timestamp-to-hour timestamp)
:text (add-line-breaks text)
:mid mid))))))
;; for :ack-state (acknowledgement state)
(:routing-app
(let ((state (me:routing.error-reason
(pr:deserialize-from-bytes 'me:routing payload))))
(msg:change-state (case state
(:none
:received)
(t
(qlog "message state changed: ~A" state)
:not-received))
(me:request-id decoded))))
;; GPS location
(:position-app
(unless (zerop (length payload))
(set-gps-position (me:from packet)
(pr:deserialize-from-bytes 'me:position payload)))))))))
;; my-info
((me:from-radio.has-my-info struct)
(setf *my-node-info* (me:my-node-num (me:my-info struct))))
;; node-info
((me:from-radio.has-node-info struct)
(let ((info (me:node-info struct)))
(if (eql *my-node-info* (me:num info))
(setf *my-node-info* info)
(setf *node-infos*
(nconc *node-infos* (list info))))
(x:when-it (me:position info)
(set-gps-position (me:num info) x:it))
(when *schedule-clear*
(radios:clear)
(group:clear))
(let ((name (me:short-name (me:user info)))
(current (= (me:num info)
(me:num *my-node-info*)))
(metrics (me:device-metrics info)))
(unless current
(group:add-person
(list :radio-name name
:custom-name (or (app:setting name :custom-name) "")
:node-num (me:num info)
:current (equal name (app:setting :latest-receiver)))))
(when (find name *ble-names* :test 'string=)
(setf radios:*found* t)
(radios:add-radio
(list :name name
:hw-model (symbol-name (me:hw-model (me:user info)))
:battery-level (float (if metrics (me:battery-level metrics) 0))
:current current))
(when current
(app:change-setting :device name))))))
;; channel
((me:from-radio.has-channel struct)
(let ((channel (me:channel struct)))
(when (eql :primary (me:role channel))
(setf *my-channel* channel))
(push channel *channels*)))
;; config lora
((me:from-radio.has-config struct)
(let ((config (me:config struct)))
(when (me:config.has-lora config)
(setf *config-lora* (me:lora config)))))
;; config-complete-id
((me:from-radio.has-config-complete-id struct)
(when (= *config-id* (me:config-complete-id struct))
(setf *config-complete* t)
(q> |playing| ui:*busy* nil)
(qlog "config-complete id: ~A" *config-id*)
(unless (string= *my-channel-name*
(me:name (me:settings *my-channel*)))
(qlater 'config-device))))))
(setf *received* nil))
(let (echo-text)
(defun process-received ()
"Walks *RECEIVED* FROM-RADIOs and saves relevant data."
(setf *received* (nreverse *received*))
(unless *ble-names*
(setf *ble-names* (qt:short-names qt:*cpp*)))
(dolist (struct *received*)
(cond ((me:from-radio.has-packet struct)
(let* ((packet (me:from-radio.packet struct))
(decoded (me:decoded packet)))
(when decoded
(let ((payload (me:payload decoded)))
(case (me:portnum decoded)
;; text-message
(:text-message-app
(let ((timestamp (get-universal-time))
(mid (me:id packet))
(text (qfrom-utf8 payload)))
(setf msg:*message-id* (max mid msg:*message-id*))
(if (x:starts-with ":e" text) ; 'echo'
(progn
(setf echo-text (subseq text #.(length ":e")))
(qsingle-shot 1000 (lambda () (send-message (x:cc "<b>echo:</b>" echo-text)))))
(progn
(when (x:starts-with "<b>echo:</b>" text)
(setf text (msg:echo-message text (me:from packet) (me:rx-snr packet) (me:rx-rssi packet))))
(msg:add-message
(list :receiver (my-name)
:sender (node-to-name (me:from packet))
:timestamp timestamp
:hour (timestamp-to-hour timestamp)
:text (add-line-breaks text)
:mid mid))))))
;; for :ack-state (acknowledgement state)
(:routing-app
(let ((state (me:routing.error-reason
(pr:deserialize-from-bytes 'me:routing payload))))
(msg:change-state (case state
(:none
:received)
(t
(qlog "message state changed: ~A" state)
:not-received))
(me:request-id decoded))))
;; GPS location
(:position-app
(unless (zerop (length payload))
(set-gps-position (me:from packet)
(pr:deserialize-from-bytes 'me:position payload)))))))))
;; my-info
((me:from-radio.has-my-info struct)
(setf *my-node-info* (me:my-node-num (me:my-info struct))))
;; node-info
((me:from-radio.has-node-info struct)
(let ((info (me:node-info struct)))
(if (eql *my-node-info* (me:num info))
(setf *my-node-info* info)
(setf *node-infos*
(nconc *node-infos* (list info))))
(x:when-it (me:position info)
(set-gps-position (me:num info) x:it))
(when *schedule-clear*
(radios:clear)
(group:clear))
(let ((name (me:short-name (me:user info)))
(current (= (me:num info)
(me:num *my-node-info*)))
(metrics (me:device-metrics info)))
(unless current
(group:add-person
(list :radio-name name
:custom-name (or (app:setting name :custom-name) "")
:node-num (me:num info)
:current (equal name (app:setting :latest-receiver)))))
(when (find name *ble-names* :test 'string=)
(setf radios:*found* t)
(radios:add-radio
(list :name name
:hw-model (symbol-name (me:hw-model (me:user info)))
:battery-level (float (if metrics (me:battery-level metrics) 0))
:current current))
(when current
(app:change-setting :device name))))))
;; channel
((me:from-radio.has-channel struct)
(let ((channel (me:channel struct)))
(when (eql :primary (me:role channel))
(setf *my-channel* channel))
(push channel *channels*)))
;; config lora
((me:from-radio.has-config struct)
(let ((config (me:config struct)))
(when (me:config.has-lora config)
(setf *config-lora* (me:lora config)))))
;; config-complete-id
((me:from-radio.has-config-complete-id struct)
(when (= *config-id* (me:config-complete-id struct))
(setf *config-complete* t)
(q> |playing| ui:*busy* nil)
(qlog "config-complete id: ~A" *config-id*)
(unless (string= *my-channel-name*
(me:name (me:settings *my-channel*)))
(qlater 'config-device))))))
(setf *received* nil)))
(defun send-admin (admin-message)
(send-to-radio

View file

@ -124,15 +124,19 @@
sending an ':e ...' text message, which will be echoed with info about signal
strength, position and distance."
(let ((from-pos (loc:position* from))
(my-pos #+mobile (nbutlast (loc:last-gps-position) 1)
(my-pos #+mobile (nbutlast (loc:latest-gps-position) 1)
#-mobile nil))
(format nil "~A~%~%snr: <b>~F</b> rssi: <b>~D</b>~%lat: ~,5F lon: ~,5F~%distance: <b>~:D m</b>"
text snr rssi
(if my-pos (first my-pos) "-")
(if my-pos (second my-pos) "-")
(if (and from-pos my-pos)
(loc:distance my-pos from-pos)
"-"))))
(x:cc (format nil "~A~%~%snr: <b>~F</b> rssi: <b>~D</b>"
text snr rssi)
(if my-pos
(format nil "~%lat: ~,5F lon: ~,5F"
(first my-pos)
(second my-pos))
"")
(if (and my-pos from-pos)
(format nil "~%distance: <b>~:D m</b>"
(loc:distance my-pos from-pos))
""))))
(defun swipe-to-left () ; see QML
(q> |currentIndex| ui:*main-view* 0)

View file

@ -128,7 +128,7 @@
#:distance
#:extract-map-bin
#:ini
#:last-gps-position
#:latest-gps-position
#:make-map-bin
#:position*
#:position-count