TI-Nspire & SensorTag / 照度センサー OPT3001 の値だけを取り出す


f:id:ti-nspire:20161118153535p: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  = ""

-- Light
local optDataUUID = "F000AA71-0451-4000-B000-000000000000"
local optConfUUID = "F000AA72-0451-4000-B000-000000000000"
local Light = 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 Light then
      gc:drawString("Light = "..string.format("%5.1f", Light).." lux", leftMargin, lineSpace * 3)
   else
      gc:drawString("Light = none", leftMargin, lineSpace * 3 * 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() 

      -- Light
      if UUID == optDataUUID then
         v:setValueUpdateListener(valueUpdateListener)
         v:setNotify(true)
      end
      if UUID == optConfUUID then
         --v:setWriteCompleteListener(valueUpdateListener)
         v:write(string.uchar(0x01), true) 
      end
      
   end
end

----------------------------------
-- Define value-update listener --
----------------------------------
function valueUpdateListener(characteristic)
   local UUID = characteristic:getUUID()
   
   -- Light
   if UUID == optDataUUID then
      local value = characteristic:getValue() 
      if value then
         local rawLux = string.unpack("u16", value)
         local exponent = math.evalStr("shift(("..rawLux.." and 0hF000), -12)")
         local mantissa = math.evalStr("("..rawLux.." and 0h0FFF)")
         Light = mantissa * (0.01 * 2^exponent)
      end
   end
   
   platform.window:invalidate()
end