Box instabil wenn Messwert < 1, dann HTTP/1.1 422 Unprocessable Entity

sensebox-mcu

#1

ich kämpfe schon eine ganze Zeit damit, dass meine Box gelegentlich keine Daten sendet, bzw. diese Daten nicht von opensensemap angenommen werden.
Meine Box ist ausgerüstet mit Temp und Feuchtigkeit, Beleuchtungs- und UV Intensitäts-, sowie Feinstaubsensor. Nur in dieser Kombi ist sie instabil, stecke ich den Feinstaubsensor oder den Beleuchtungssensor ab ist alles gut.
Meine Beobachtung ist nun diese, sobalb einer der Messwerte für Beleuchtung oder UV oder Feinstaub kleiner 1 wird, treten die Probleme auf. Bei Beleuchtung habe ich bereits 1 hinzuaddiert, bei UV Intersität 0.01, das hat die Stuation verbessert aber nicht geheilt.

Jetzt habe ich den ähnlichen Effekt beim PM2.5 beobachtet. Anbei das interessante Log für 2 aufeinderfolgende Messungen, einmal nicht erfolgeich, danach doch. Beachtet Sensor 5e1e144261fbc3001bb5e120, das ist PM2.5. Der Wert nach dem Komma der Messwert, einmal unter 1, danach darüber.

Loop
submit values
connecting...
Connection successful, transferring...
POST /boxes/5e1e144261fbc3001bb5e11f/data HTTP/1.1
Host: ingress.opensensemap.org
Content-Type: text/csv
Connection: close
Content-Length: 177

5e1e144261fbc3001bb5e125,16.18
5e1e144261fbc3001bb5e124,29.32
5e1e144261fbc3001bb5e123,5.00
5e1e144261fbc3001bb5e122,0.10
5e1e144261fbc3001bb5e121,1.50
5e1e144261fbc3001bb5e120,0.40

HTTP/1.1 422 Unprocessable Entity
Content-Length: 131
Content-Type: application/json; charset=utf-8
Date: Wed, 22 Apr 2020 19:12:58 GMT
Deprecation-Warning: If your client supports TLS, please use https://ingress.opensensemap.org
Connection: close

{"code":"UnprocessableEntity","message":"Missing value in measurement {\"sensor_id\":\"5e1e144261fbc3001bb5e120\",\"value\":\"\"}"}
disconnecting from server.
done!

Loop
submit values
connecting...
Connection successful, transferring...
POST /boxes/5e1e144261fbc3001bb5e11f/data HTTP/1.1
Host: ingress.opensensemap.org
Content-Type: text/csv
Connection: close
Content-Length: 179

5e1e144261fbc3001bb5e125,16.17
5e1e144261fbc3001bb5e124,30.43
5e1e144261fbc3001bb5e123,1.00
5e1e144261fbc3001bb5e122,0.10
5e1e144261fbc3001bb5e121,3.59
5e1e144261fbc3001bb5e120,1.10

HTTP/1.1 201 Created
Content-Length: 27
Content-Type: application/json; charset=utf-8
Date: Wed, 22 Apr 2020 19:13:56 GMT
Deprecation-Warning: If your client supports TLS, please use https://ingress.opensensemap.org
Connection: close

"Measurements saved in box"
disconnecting from server.
done!

Liegt der Fehler in den Libraries?


Bodenfeuchtesensor liefert unplausible Werte
#2

Markus, danke dass du uns die Logs mit geschickt hast!

Die API können wir glaube ich ausschliessen, habe gerade deine Messungen als Test definiert und als Unit-Test funktionieren sie.

Dann hab ich nochmal in deine Logs geschaut und mir ist folgendes aufgefallen: Die Content-Length wird im ersten Fall falsch berechnet: 177 und 179 im zweiten Fall.

Deine Vermutung sollte also richtig sein: Der Fehler liegt im Sketch. Das müssen wir jetzt aber erstmal herausfinden wo genau.

Viele Grüße,
Gerald


#3

Hallo Markus,

hat sich da etwas ergeben? Ich denke ich habe das gleiche Problem, mein Sketch ist unverändert von der Webseite, allerdings vermute ich den exotischen Bodenfeuchtesensor als Auslöser…

Viele Grüße

TK


#4

Hallo,
nein, kein Fortschritt seit dem letzten Post.
Hast du mal versucht 1 an der Stelle im Code hinzu zu addieren, an der der Messwert gelesen wird, analog meinem anderen Post in

Gruß
Markus


#5

Hi all,

ich glaub’ ich hab’s! Die Sensebox rechnet vor der Übertragung zum Server aus, wie viele Bytes die zu übertragenden Sensorwerte als Textstring lang sind. Im Originalsketch von der Webseite macht sie das wie folgt:

dataLength += String((int)value * 100).length() + 1; //length of measurement value + decimal digit

Das passt aber nicht immer. Liefert beispielsweise der Feinstaubsensor einen Wert zwischen 0 und 1 (was er hoffentlich oft tut), also sagen 0.8, dann passiert folgendes:

a) 0.8 wird als Integer interpretiert und das Ergebnis ist 0 (der cast zu int wird vor der Multiplikation ausgeführt)

b) 0 wird mit 100 multipliziert, es kommt wieder 0 raus

c) als String umgewandelt hat 0 die Länge eins

d) es wird noch eine Stelle für das Komma draufaddiert und die resultierende Länge ist 2

Der richtige Wert wäre aber sogar 4 für “0,80”. Somit sind durch diesen einen Sensorwert schon zwei Stellen verloren, die dann beim letzten übertragenen Sensorwert abgeschnitten werden.

Eine schöne Lösung wäre vermutlich über sprintf() oder ein Umstellen im Code, so dass zuerst die zu übertragenen Strings erzeugt werden, dann deren Länge bestimmt wird und die Strings im Anschluss übertragen werden.

Für mich zum Blumen gießen tut’s jetzt hoffentlich erstmal mit zwei fixen Nachkommastellen:

dataLength += String((int)value).length() + 1 + 2; //length of measurement value int part + decimal digit + 2x frac part

tk


#6

Nach einer Woche: Kein Problem mehr, Box läuft wie ein Uhrwerk. Endlich!

TK