4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AndroidAdvent Calendar 2023

Day 16

PythonでAndroidスマホの各種センサー情報を取得する。

Last updated at Posted at 2023-11-04

はじめに

PythonでAndroidアプリが作れるなら <記事:PythonでAndroidアプリを作る。> 、スマホの各種センサー情報を使ってアプリが作れないか?調べてみた。Plyerというkivy用のAPIで各種センサー情報を取得できることがわかったので記事にする。

Plyerはこちら

目次

Plyerとは

Kivyのフレームワーク上で動作するAPI。OSごとにできることに違いがあり、Androidのサポートは多い印象。この記事では動作確認の取れた〇を中心にまとめる。GPSも試してみたが、Pydroid3ではうまくいくけど、buildozerでアプリ化すると動作不安定になるため△とした。原因がわかり次第、別途記事にする。
センサー以外にも、ライトを光らせる、カメラを動作させる、画面の明るさを変更する、バイブレーションを動かす。など色々できるようだが、また別の機会で記事にしたいと思う。

API 内容 Android iOS Win OS X Linux
Accelerometer 加速度センサー
Gravity 重力センサー
Gyroscope ジャイロセンサー
Compass 電子コンパス
Battery バッテリー情報
Temperature 温度センサー
Light 照度センサー
Barometer 気圧センサー
GPS 位置情報

戻る

Plyerで各種センサー情報を取得する

各々のAPIの使い方をまとめる。enable()して値を読むだけなので、比較的簡単にAPIを使うことができる。注意点としてはkivyフレームワーク上でしか動作しないので、plyerを単独で使うことはできない。値が取れない場合はNoneが返答される。

Accelerometer(加速度センサー)

加速度をx,y,z軸で取得する。accelerometer.accelerationでタプル型で取得。

Accelerometer
from plyer import accelerometer
#有効
accelerometer.enable()
#取得
x,y,z = accelerometer.acceleration

if x!=None or y!=None or z!=None:
	output=f'Accelemeter\nx:{x:0.3f} m/s2\ny:{y:0.3f} m/s2\nz:{z:0.3f} m/s2\n\n'
else:
	output=f'Accelemeter\nx: m/s2\ny: m/s2\nz: m/s2\n\n'

Gravity(重力センサー)

重力加速度をx,y,z軸で取得する。gravity.gravityでタプル型で取得。

Gravity
from plyer import gravity
#有効
gravity.enable()
#取得
x,y,z = gravity.gravity

if x!=None or y!=None or z!=None:
	output+=f'Gravity\nx:{x:0.3f} m/s2\ny:{y:0.3f} m/s2\nz:{z:0.3f} m/s2\n\n'
else:
	output=f'Gravity\nx: m/s2\ny: m/s2\nz: m/s2\n\n'

Gyroscope(ジャイロセンサー)

角速度をx,y,z軸で取得する。gyroscope.rotationでタプル型で取得。

Gyroscope
from plyer import gyroscope
#有効
gyroscope.enable()
#取得
x,y,z = gyroscope.rotation

if x!=None or y!=None or z!=None:
	output+=f'Gyroscope\nx:{x:0.3f} rad/s\ny:{y:0.3f} rad/s\nz:{z:0.3f} rad/s\n\n'
else:
	output=f'Gyroscope\nx: rad/s\ny: rad/s\nz: rad/s\n'

Compass(電子コンパス)

磁力をx,y,z軸で取得する。compass.fieldでタプル型で取得。

Compass
from plyer import compass
#有効
compass.enable()
#取得
x,y,z = compass.field

if x!=None or y!=None or z!=None:
	output+=f'Compass\nx:{x:0.3f} uT\ny:{y:0.3f} uT\nz:{z:0.3f} uT\n\n'
else:
	output=f'Compass\nx: uT\ny: uT\nz: uT\n\n'

Battery(バッテリー情報)

バッテリーの残量と、現在充電中かどうかを取得する。battery.statusで辞書型で取得。isChargingが充電中かどうか。percentageがバッテリー残量。

Battery
from plyer import battery
#batteryはenable()不要。
#取得
output+=f'Battery\nCharging:{battery.status["isCharging"]}\n{battery.status["percentage"]}%\n\n'

Temperature(温度センサー)

温度を取得する。temperature.temperatureで取得。私のスマホは、常にNoneが返答されたので、スマホ自体が対応していないのだと思う。

Temperature
from plyer import temperature
#有効
temperature.enable()
#取得
output+=f'Temperature\n{temperature.temperature}\n\n'

Light(照度センサー)

明るさを取得する。light.illuminationで取得。

Light
from plyer import light
#有効
light.enable()
#取得
output+=f'illumination:\n{light.illumination:0.3f} lux\n\n'

Barometer(気圧センサー)

気圧を取得する。barometer.pressureで取得。

Barometer
from plyer import barometer
#有効
barometer.enable()
#取得
output+=f'Barometer\n{barometer.pressure:0.2f} hPa\n\n'

戻る

PlyerのAndroidアプリ例

KivyのTextInputに1/30秒(スマホが30fpsなので)ごとに値を更新する例を作ってみた。buildozerでアプリ化するためのbuildozer.specも併せて記載する。buildozer.specは、初期値から変更した行だけ抜き出した。アプリの作り方は <記事:PythonでAndroidアプリを作る。> を参照。

main.py/buildozer.specファイルはこちら。
main.py
from kivy.app import App
from kivy.uix.textinput import TextInput
from kivy.clock import Clock

#Sensor
from plyer import accelerometer
from plyer import gravity
from plyer import gyroscope
from plyer import compass
from plyer import battery
from plyer import temperature
from plyer import light
from plyer import barometer
#for compass
import math
import numpy as np

class SensorApp(App):	
	#---------------------------
	# グローバル変数
	#---------------------------
	cnt=0
	toggle='off'

	#---------------------------
	# 初期化
	#---------------------------
	def build(self):
		#TextInput
		self.text = TextInput(text='')
		
		#enable each plyer lib
		accelerometer.enable()
		gravity.enable()
		gyroscope.enable()
		compass.enable()
		temperature.enable()
		light.enable()
		barometer.enable()
		
		# Update every 1/30sec
		Clock.schedule_interval(self.update_plyer, 1/30)
		return self.text
		
	#---------------------------
	# 1/30 sec 毎に更新 InputTextへ出力
	#---------------------------
	def update_plyer(self, dt):
		self.cnt+=1
		
		#accelerometer
		x,y,z = accelerometer.acceleration
		if x!=None or y!=None or z!=None:
			output=f'Accelemeter\nx:{x:0.3f} m/s2\ny:{y:0.3f} m/s2\nz:{z:0.3f} m/s2\n\n'
		else:
			output=f'Accelemeter\nx: m/s2\ny: m/s2\nz: m/s2\n\n'
		
		#gravity
		x,y,z = gravity.gravity
		if x!=None or y!=None or z!=None:
			output+=f'Gravity\nx:{x:0.3f} m/s2\ny:{y:0.3f} m/s2\nz:{z:0.3f} m/s2\n\n'
		else:
			output=f'Gravity\nx: m/s2\ny: m/s2\nz: m/s2\n\n'
		
		#gyroscope
		x,y,z = gyroscope.rotation
		if x!=None or y!=None or z!=None:
			output+=f'Gyroscope\nx:{x:0.3f} rad/s\ny:{y:0.3f} rad/s\nz:{z:0.3f} rad/s\n\n'
		else:
			output=f'Gyroscope\nx: rad/s\ny: rad/s\nz: rad/s\n'
		#compass
		x,y,z = compass.field
		if x!=None or y!=None or z!=None:
			output+=f'Compass\nx:{x:0.3f} uT\ny:{y:0.3f} uT\nz:{z:0.3f} uT\ndegree:{self.orientation(x,y,z):0.3f}\n\n'
		else:
			output=f'Compass\nx: uT\ny: uT\nz: uT\n\n'

		#battery
		output+=f'Battery\nCharging:{battery.status["isCharging"]}\n{battery.status["percentage"]}%\n\n'
		
		#temperature
		output+=f'Temperature\n{temperature.temperature}\n\n'
		
		#light
		if light.illumination!=None:
			output+=f'illumination:\n{light.illumination:0.3f} lux\n\n'
		
		#barometer
		if barometer.pressure!=None:
			output+=f'Barometer\n{barometer.pressure:0.2f} hPa\n\n'

        self.text.text = output

	#---------------------------
	# 方位計算
	#---------------------------
	def orientation(self,x,y,z):
		# ベクトル変換 (x,y逆転しないと90度ずれたため。)
		mag_vector = np.array([y, x, z])		
		# 地磁気ベクトルを計算
		mag_strength = np.linalg.norm(mag_vector)
		mag_unit_vector = mag_vector / mag_strength
		# ラジアン変換
		radian = math.atan2(mag_unit_vector[1], mag_unit_vector[0])
		# 度変換
		degree = math.degrees(radian)
		# 方位0から360度へ調整
		degree = (degree + 360) % 360
		
		return degree

if __name__ == '__main__':
    SensorApp().run()
buildozer.spec
[app]

# (str) Title of your application
title = Plyer_test

# (str) Package name
package.name = plyer_test

# (list) Application requirements
requirements = python3, kivy, plyer, android, numpy

# (list) Permissions
android.permissions = INTERNET,ACCESS_FINE_LOCATION,ACCESS_COARSE_LOCATION

アプリののスクリーンショット
Screenshot_20231104-184810.png

戻る

以上

4
5
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?