Read and log sensor output from the Arduino sensor hub device.
authorPat Thoyts <Patrick.Thoyts@renishaw.com>
Thu, 14 Apr 2016 13:30:03 +0000 (14:30 +0100)
committerPat Thoyts <Patrick.Thoyts@renishaw.com>
Thu, 14 Apr 2016 13:30:03 +0000 (14:30 +0100)
INSTALL [new file with mode: 0644]
monitor.tcl [new file with mode: 0644]
sensor-hub.conf [new file with mode: 0644]

diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..9f85e6a
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,3 @@
+Install the sensor-hub.conf file into /etc/init to create the service.
+Then service sensor-hub start.
+
diff --git a/monitor.tcl b/monitor.tcl
new file mode 100644 (file)
index 0000000..b5fd092
--- /dev/null
@@ -0,0 +1,116 @@
+#/usr/bin/env tclsh
+#
+# URL=https://api.thingspeak.com/update
+# KEY=QXY49R9TYM0LYCB2
+# curl --data "key=$KEY&field1=$Temp0&field2=$Pressure0&field3=$Lux" $URL
+
+package require Tcl 8.6
+package require http
+package require tls
+package require autoproxy
+
+variable URL "http://api.thingspeak.com/update"
+variable KEY "1HWAT971G1N0RJ6U"
+
+proc OnHttpComplete {tok} {
+    puts "[http::status $tok] $tok"
+    http::cleanup $tok
+}
+
+proc avg {lst} {
+    set count [llength $lst]
+    foreach v $lst {
+        set sum [expr {$sum + $v}]
+    }
+    return [expr {$sum / double($count)}]
+}
+
+proc median {lst} {
+    set lst [lsort -real $lst]
+    set len [llength $lst]
+    if {$len & 1} {
+        # odd number of elements
+        return [lindex $lst [expr {($len-1)/2}]]
+    } else {
+        # for even number, interpolate center pair
+        set idx2 [expr {$len / 2}]
+        set idx1 [expr {$idx2-1}]
+        return [expr {([lindex $lst $idx1] + [lindex $lst $idx2]) / 2.0}]
+    }
+}
+
+proc upload {} {
+    variable URL
+    variable KEY
+    variable TEMPERATURES
+    variable HUMIDITIES
+    variable PRESSURES
+
+    set A [median $TEMPERATURES]
+    set B [set C 0]
+    if {[llength $HUMIDITIES] > 0} { set B [median $HUMIDITIES] }
+    if {[llength $PRESSURES] > 0} {set C [median $PRESSURES] }
+    set TEMPERATURES [set HUMIDITIES [set PRESSURES {}]]
+    set req [http::formatQuery api_key $KEY field1 $A field2 $B field3 $C]
+    set tok [http::geturl $URL -query $req -timeout 500 -command [list OnHttpComplete]]
+    http::wait $tok
+}
+
+proc main {port {baudrate 57600}} {
+    variable TEMPERATURES {}
+    variable HUMIDITIES {}
+    variable PRESSURES {}
+
+    http::register https 443 [list autoproxy::tls_socket -ssl2 0 -ssl3 0 -tls1 1]
+    autoproxy::init
+    puts "# proxy: [autoproxy::cget -proxy_host]"
+
+    set sio [open $port r]
+    fconfigure $sio -buffering line -encoding ascii -translation {auto crlf} -mode $baudrate,n,8,1
+    while {[gets $sio line] != -1} {
+        if {[string match "# *" $line]} { puts $line; continue }
+        set T {}
+        set H {}
+        set P {}
+        if {[catch {
+            foreach sensor [lrange [split $line "\["] 1 end] {
+                set sensor [string trim $sensor "\[\] "]
+                lassign $sensor id ts t h p
+                lappend T [expr {double($t)}]
+                if {$h != 0} {lappend H [expr {double($h)}]}
+                if {$p != 0} {lappend P [expr {double($p)}]}
+            }
+            set temperature [median $T]
+            lappend TEMPERATURES $temperature
+            if {[llength $H] > 0} {
+                set humidity [median $H]
+                lappend HUMIDITIES $humidity
+            } else {
+                set humidity -1
+            }
+            if {[llength $P]} {
+                set pressure [median $P]
+                lappend PRESSURES $pressure
+            } else {
+                set pressure -1
+            }
+            puts [format "%d %.2f %.2f %.2f : {$T} {$H} {$P}" \
+                      [clock seconds] $temperature $humidity $pressure]
+            # every 5 minutes
+            if {[llength $TEMPERATURES] > (60 * 5)} {
+                upload
+            }
+        } err]} {
+            puts "! $line\n! $::errorInfo"
+        }
+    }
+    return 0
+}
+
+if {!$tcl_interactive} {
+    set r [catch [linsert $argv 0 main] err]
+    if {$r} {
+        puts stderr $::errorInfo
+    }
+    exit $r
+}
diff --git a/sensor-hub.conf b/sensor-hub.conf
new file mode 100644 (file)
index 0000000..76f562c
--- /dev/null
@@ -0,0 +1,13 @@
+# sensor-hub - office temperature aggregation and IoT upload
+description    "sensor-hub monitor"
+
+start on runlevel [2345]
+stop on runlevel [!2345]
+
+respawn
+
+script
+  [ ! -f /etc/default/sensor-hub ] || . /etc/default/sensor-hub
+  exec su pat -c "/usr/bin/env http_proxy=http://localhost:3128 https_proxy=http://localhost:3128 /usr/bin/tclsh /home/pat/sensor-hub/monitor.tcl /dev/ttyUSB0 57600 > /tmp/sensor-hub.log"
+end script
+