TI-Nspire & SensorTag / ボタンの状態を受信する / compasstech.com.au 版

The following script, from http://compasstech.com.au/TNS_Authoring/Scripting/script_tut31.html, will try to read the state of SensorTag's buttons. Do not press and hold any button for too long, or powering off or mode changing will occur.

-- The following script is from http://compasstech.com.au/TNS_Authoring/Scripting/script_tut31.html.
platform.apilevel = '2.5'

screen = platform.window
w = screen:width()
h = screen:height()

pcall(function () require 'bleCentral' end)

require "color"
local bleState = ''
local bleStatus = 'Stand by'
local peripheralName = ''
local myPeripheral = nil

-- SensorTag keyPress Variables
local keysRead = 'FFE1'
local keyPress = nil
local nameList = {'SensorTag', 'LaunchPad', 'HMSoft', 'BT05', 'CC41'}

-- Layout Functions (resize and paint)
function on.resize()
   w = screen:width() or 841
   h = screen:height() or 567
   pcall(function() ble.addStateListener(listenerCallback) end)
   refreshMenu()
   screen:invalidate()
end

function on.paint(gc)
   w = screen:width() or 841
   h = screen:height() or 567

   local fontSize = math.floor(h/28 + 0.5)
   fontSize = fontSize < 25 and fontSize or 24
   fontSize = fontSize > 6 and fontSize or 7
   if bleState:find("ON") then
      gc:setColorRGB(color.blue)
   else
      gc:setColorRGB(color.red)
   end
   gc:setFont("sansserif", "b", fontSize)
   gc:drawString(bleState, 0.1*w, 0.1*h)
   if peripheralName then
      gc:drawString(peripheralName.." "..bleStatus, 0.1*w, 0.2*h)
      for n = 1, #nameList do
         local sw = gc:getStringWidth(nameList[n])
         if peripheralName:find(nameList[n]) then
            gc:setColorRGB(color.green)
         else
            gc:setColorRGB(color.gray)
         end
         gc:drawString(nameList[n], 0.95*w - sw, 0.95*h - 0.01125*h*(n-1)*9-0.1*h, 'middle')
      end
   end

   gc:setColorRGB(color.green)
   gc:fillRect(0.9*w, 0.9*h, 0.1*w, 0.1*h)
   gc:setColorRGB(color.black)
   gc:drawRect(0.9*w, 0.9*h, 0.1*w, 0.1*h)
   local sw = gc:getStringWidth('Scan') 
   gc:drawString('Scan', 0.95*w - sw/2, 0.95*h, 'middle')

   gc:setColorRGB(color.red)
   gc:fillRect(0, 0.9*h, 0.1*w, 0.1*h)
   gc:setColorRGB(color.black)
   gc:drawRect(0, 0.9*h, 0.1*w, 0.1*h)
   local sw = gc:getStringWidth('Stop') 
   gc:drawString('Stop', 0.05*w - sw/2, 0.95*h, 'middle')

   local fontSize = math.floor(h/20 + 0.5)
   fontSize = fontSize < 25 and fontSize or 24
   fontSize = fontSize > 6 and fontSize or 7
   gc:setFont("sansserif", "b", 60)
   --   gc:setFont("sansserif", "b", fontSize)
   if bleStatus:find('Connect') then
      if keyPress and keyPress ~= 0 then
         local str = 'Keypress '..keyPress
         local sw = gc:getStringWidth(str)
         gc:drawString(str, 0.5*w - sw/2, 0.5*h, "middle")
      else
         local str = 'Press the left or right key...'
         local sw = gc:getStringWidth(str)
         gc:drawString(str, 0.5*w - sw/2, 0.5*h, "middle") 
      end
   end
end

--Menu, Keyboard and Mouse Functions--------------
function refreshMenu()
   Menu = {
      {"Controls",
         {"Scan and Connect", function() peripheralOn() end},
         {"Disconnect", function() peripheralOff() end},
         {"Reset", function() bleState = '' bleStatus = 'Stand by' on.resize() end},
      },
   }
   toolpalette.register(Menu)
end
function on.enterKey()
   peripheralOn()
end

function on.escapeKey()
   resetall()
end

function resetall()
   bleState = ''
   keyPress = nil
   peripheralOff() 
   on.resize()
end

function on.mouseUp(x, y)
   w = screen:width() or 841
   h = screen:height() or 567
   if x > 0.9*w and y > 0.9*h then on.enterKey() end
   if x < 0.1*w and y > 0.9*h then on.escapeKey() end
   screen:invalidate()
end

-- BLE General Functions -----------
function listenerCallback(state, scriptError)
   if     state == ble.ON          then bleState = 'BLE ON'
   elseif state == ble.OFF         then bleState = 'BLE OFF'
   elseif state == ble.RESETTING   then bleState = 'BLE RESET'
   elseif state == ble.UNSUPPORTED then bleState = 'UNSUPPORTED'
      if scriptError then
         print('Error message: BLE not supported')
      end
   end
   screen:invalidate()
end

function peripheralOn()
   bleCentral.startScanning(callbackScan)
   bleStatus = 'Scanning' 
   screen:invalidate()
end
function peripheralOff()
   bleCentral.stopScanning()
   if myPeripheral then
      myPeripheral:disconnect()
   end
   bleStatus = 'Stand by' 
   peripheralName = '' 
   screen:invalidate()
end

function callbackScan(peripheral)
   if peripheral ~= nil then
      peripheralName = peripheral:getName()
      for n =1, #nameList do
         if peripheral:getName() and (peripheral:getName()):find(nameList[n]) then
            peripheral:connect(callbackConnect) 
            break
         end
      end
   end
   screen:invalidate()
end

function callbackConnect(peripheral, event)
   if event == bleCentral.CONNECTED then 
      bleCentral.stopScanning()
      bleStatus = 'Connected'
      myPeripheral = peripheral
      peripheralName = peripheral:getName()
      peripheral:discoverServices(callbackServices)
   elseif event == bleCentral.DISCONNECTED then 
      bleStatus = 'Disconnected'
      peripheralName = ''
   end
   screen:invalidate()
end

function callbackServices(peripheral)
   if peripheral ~= nil and peripheral:getState() and peripheral:getState() == bleCentral.CONNECTED then
      local services = peripheral:getServices()
      for _,service in ipairs(services) do
         service:discoverCharacteristics(callbackCharacteristics)
      end
   end
   screen:invalidate()
end

-- BLE Specific Functions ---------
function callbackCharacteristics(service)
   local characteristicsList = service:getCharacteristics()
   for _,characteristic in ipairs(characteristicsList) do
      if characteristic:getUUID() == keysRead then
         characteristic:setValueUpdateListener(callbackCharacteristic)
         characteristic:setNotify(true)
      end
   end
end

function callbackCharacteristic(characteristic)
   if characteristic:getUUID() == keysRead then
   --Simple Keys
      local value = characteristic:getValue()
      if value and peripheralName then
         if peripheralName:find("Tag") or peripheralName:find("LaunchPad") then
            keyPress = ble.unpack('u8', value) 
         else
            keyPress = value:gsub("P", "")
            keyPress = keyPress:gsub(" ","")
            keyPress = tonumber(keyPress)
         end
      end
   end
   screen:invalidate()
end