TI-Nspire & SensorTag / 大気圧センサー BMP280 の値だけを取り出す


f:id:ti-nspire:20161114152501p:plain:h315
(photo: http://www.ti.com/ww/en/wireless_connectivity/sensortag2015/tearDown.html)

.lua

-- Refer to http://compasstech.com.au/TNS_Authoring/Scripting/script_tut35.html.
require "bleCentral"

local bleState        = ""
local peripheralState = ""
local myPeripheral    = nil
local peripheralName  = ""

-- Barometric Pressure 
local baDataUUID = "F000AA41-0451-4000-B000-000000000000"
local baConfUUID = "F000AA42-0451-4000-B000-000000000000"
local Pa     = nil
local baTemp = nil

function on.resize()
   W, H = platform.window:width(), platform.window:height()
   leftMargin = W/100
   fontSize   = W/14
   lineSpace  = H/6
   platform.window:invalidate()
end
function on.construction()
   refreshMenu()
   ble.addStateListener(stateListener)
end
function on.paint(gc)
   gc:setFont("sansserif", "r", fontSize)
   gc:drawString(bleState        or "none", leftMargin, lineSpace * 0)
   gc:drawString(peripheralName  or "none", leftMargin, lineSpace * 1)
   gc:drawString(peripheralState or "none", leftMargin, lineSpace * 2)
   if Pa then
      gc:drawString("Pa = "..string.format("%5.1f", Pa).." hPa", leftMargin, lineSpace * 3)
   else
      gc:drawString("Pa = none", leftMargin, lineSpace * 3 * H)
   end
   if baTemp then
      gc:drawString("baTemp = " ..string.format("%5.1f", baTemp).." ℃", leftMargin, lineSpace * 4)
   else
      gc:drawString("baTemp = none", leftMargin, lineSpace * 4 * H)
   end
end

------------------------------
-- Menu, Keyboard and Mouse --
------------------------------
function refreshMenu()
   Menu = {
      {"Controls",
         {"Scan and Connect", function() peripheralOn()  end},
         {"Disconnect"      , function() peripheralOff() end},
      }
   }
   toolpalette.register(Menu)
end

--------------------------
-- Define state listner --
--------------------------
function stateListener(state)
   if state == "on" then
      peripheralOn()
   end 
   bleState = "BLE: "..state
   platform.window:invalidate()
end

----------------------------
-- Start or stop scanning --
----------------------------
function peripheralOn()
   if peripheralState ~= "connected" then
      bleCentral.startScanning(scanner)
   end 
   platform.window:invalidate()
end
function peripheralOff()
   bleCentral.stopScanning()
   if myPeripheral then
      myPeripheral:disconnect()
   end
   peripheralName = "" 
   platform.window:invalidate()
end

--------------------
-- Define scanner --
--------------------
function scanner(peripheral)
   local name = peripheral:getName() or "none"
   if peripheral and name:find("SensorTag") then
      myPeripheral   = peripheral
      peripheralName = name
      peripheral:connect(connector) 
   end
   platform.window:invalidate()
end

----------------------
-- Define connector --
----------------------
function connector(peripheral, event)
   local name = peripheral:getName() or "none"
   if event == bleCentral.CONNECTED and name:find("SensorTag") then
      bleCentral.stopScanning()
      myPeripheral    = peripheral
      peripheralName  = name
      peripheral:discoverServices(servicesDiscoverer)
   elseif event == bleCentral.DISCONNECTED then 
      myPeripheral    = nil
      peripheralName  = ""
   end
   peripheralState = peripheral:getState()
   platform.window:invalidate()
end

--------------------------------
-- Define services discoverer --
--------------------------------
function servicesDiscoverer(peripheral)
   if peripheral:getState() == bleCentral.CONNECTED then
      local servicesList = peripheral:getServices()
      for _, v in ipairs(servicesList) do
         v:discoverCharacteristics(characteristicsDiscoverer)
      end
   end
   platform.window:invalidate()
end

---------------------------------------
-- Define characteristics discoverer --
---------------------------------------
function characteristicsDiscoverer(service)
   local characteristicsList = service:getCharacteristics()
   for _, v in ipairs(characteristicsList) do
      local UUID = v:getUUID() 

      -- Barometric Pressure
      if UUID == baDataUUID then
         v:setValueUpdateListener(valueUpdateListener)
         v:setNotify(true)
      end
      if UUID == baConfUUID then
         --v:setWriteCompleteListener(valueUpdateListener)
         v:write(string.uchar(0x01), true) 
      end
      
   end
end

----------------------------------
-- Define value-update listener --
----------------------------------
function valueUpdateListener(characteristic)
   local UUID = characteristic:getUUID()
   
   -- Barometric Pressure
   if UUID == baDataUUID then
      local value = characteristic:getValue() 
      if value then
         local temp, pressure = string.unpack("s24u24", value)
         if temp > 0 then baTemp = tonumber(temp) / 100
         else baTemp = -(tonumber(temp) + 2^24) / 100
         end
         Pa = tonumber(pressure) / 100
      end
   end
   
   platform.window:invalidate()
end