传感器 - Sensor

# Sensors > Stability: 2 - Stable sensors模块提供了获取手机上的传感器的信息的支持,这些传感器包括距离传感器、光线光感器、重力传感器、方向传感器等。 需要指出的是,**脚本只能获取传感器的数据,不能模拟或伪造传感器的数据和事件**,因此诸如模拟摇一摇的功能是无法实现的。 要监听一个传感器时,需要使用sensors.register()注册监听器,之后才能开始监听;不需要监听时则调用sensors.unregister()注销监听器。在脚本结束时会自动注销所有的监听器。同时,这种监听会使脚本保持运行状态,如果不注销监听器,脚本会一直保持运行状态。 例如,监听光线传感器的代码为: ```js //光线传感器监听 sensors.register("light").on("change", (event, light)=>{ log("当前光强度为", light); }); ``` 要注意的是,每个传感器的数据并不相同,所以对他们调用on()监听事件时的回调函数参数也不是相同,例如光线传感器参数为(event, light),加速度传感器参数为(event, ax, ay, az)。甚至在某些设备上的传感器参数有所增加,例如华为手机的距离传感器为三个参数,一般手机只有一个参数。 ### 常用的传感器及其事件参数: - accelerometer **加速度传感器**,参数(event, ax, ay, az): 1. event SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息 2. ax {number} x轴上的加速度,单位m/s^2 3. ay {number} y轴上的加速度,单位m/s^2 4. az {number} z轴上的加速度,单位m/s^2 这里的x轴,y轴,z轴所属的坐标系统如下图(其中z轴垂直于设备屏幕表面): - orientation **方向传感器**,参数(event, azimuth, pitch, roll): 1. event SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息 2. azimuth {number} 方位角,从地磁指北方向线起,依顺时针方向到y轴之间的水平夹角,单位角度,范围0~359 3. pitch {number} 绕x轴旋转的角度,当设备水平放置时该值为0,当设备顶部翘起时该值为正数,当设备尾部翘起时该值为负数,单位角度,范围-180~180 4. roll {number} 绕y轴顺时针旋转的角度,单位角度,范围-90~90 - gyroscope **陀螺仪传感器**,参数(event, wx, wy, wz): 1. event SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息 2. wx {number} 绕x轴的角速度,单位弧度/s 3. wy {number} 绕y轴的角速度,单位弧度/s 4. wz {number} 绕z轴的角速度,单位弧度/s - magnetic_field **磁场传感器**,参数(event, bx, by, bz): 1. event SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息 2. bx {number} x轴上的磁场强度,单位uT 3. by {number} y轴上的磁场强度,单位uT 4. bz {number} z轴上的磁场强度,单位uT - gravity **重力传感器**,参数(event, gx, gy, gz): 1. event SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息 2. gx {number} x轴上的重力加速度,单位m/s^2 3. gy {number} y轴上的重力加速度,单位m/s^2 4. gz {number} z轴上的重力加速度,单位m/s^2 - linear_acceleration **线性加速度传感器**,参数(event, ax, ay, az): 1. event SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息 2. ax {number} x轴上的线性加速度,单位m/s^2 3. ay {number} y轴上的线性加速度,单位m/s^2 4. az {number} z轴上的线性加速度,单位m/s^2 - ambient_temperature **环境温度传感器**,大部分设备并不支持,参数(event, t): 1. event SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息 2. t {number} 环境温度,单位摄氏度。 - light **光线传感器**,参数(event, light): 1. event SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息 2. light {number} 环境光强度,单位lux - pressure **压力传感器**,参数(event, p): 1. event SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息 2. p {number} 大气压,单位hPa - proximity **距离传感器**,参数(event, distance): 1. event SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息 2. distance {number} 一般指设备前置摄像头旁边的距离传感器到前方障碍物的距离,并且很多设备上这个值只有两种情况:当障碍物较近时该值为0,当障碍物较远或在范围内没有障碍物时该值为5 - relative_humidity **湿度传感器**,大部分设备并不支持,参数(event, rh): 1. event SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息 2. rh {number} 相对湿度,范围为0~100(百分比) ## sensors.register(sensorName[, delay]) - sensorName {string} 传感器名称,常用的传感器名称如上面所述 - delay {number} 传感器数据更新频率,可选,默认为sensors.delay.normal。可用的值如下: 1. sensors.delay.normal 正常频率 2. sensors.delay.ui 适合于用户界面的更新频率 3. sensors.delay.game 适合于游戏的更新频率 4. sensors.delay.fastest 最快的更新频率】 返回 SensorEventEmiiter 注册一个传感器监听并返回SensorEventEmitter。 例如: ```js console.show(); //注册传感器监听 var sensor = sensors.register("gravity"); if(sensor == null){ toast("不支持重力传感器"); exit(); } //监听数据 sensor.on("change", (gx, gy, gz)=>{ log("重力加速度: %d, %d, %d", gx, gy, gz); }); ``` 可以通过delay参数来指定传感器数据的更新频率,例如: ``` var sensor = sensors.register("gravity", sensors.delay.game); ``` 另外,如果不支持sensorName所指定的传感器,那么该函数将返回null;但如果sensors.ignoresUnsupportedSensor的值被设置为true, 则该函数会返回一个不会分发任何传感器事件的SensorEventEmitter。 例如: ``` sensors.ignoresUnsupportedSensor = true; //无需null判断 sensors.register("gravity").on("change", (gx, gy, gz)=>{ log("重力加速度: %d, %d, %d", gx, gy, gz); }); ``` 更多信息,参见SensorEventEmitter和sensors.ignoresUnsupportedSensor。 ## sensors.unregister(emitter) - emiiter SensorEventEmitter 注销该传感器监听器。被注销的监听器将不再能监听传感器数据。 ``` //注册一个传感器监听器 var sensor = sensors.register("gravity"); if(sensor == null){ exit(); } //2秒后注销该监听器 setTimeout(()=> { sensors.unregister(sensor); }, 2000); ``` ## sensors.unregisterAll() 注销所有传感器监听器。 ## sensors.ignoresUnsupportedSensor - {boolean} 表示是否忽略不支持的传感器。如果该值被设置为true,则函数sensors.register()即使对不支持的传感器也会返回一个无任何数据的虚拟传感器监听,也就是sensors.register()不会返回null从而避免非空判断,并且此时会触发sensors的"unsupported_sensor"事件。 ``` //忽略不支持的传感器 sensors.ignoresUnsupportedSensor = true; //监听有不支持的传感器时的事件 sensors.on("unsupported_sensor", function(sensorName){ toastLog("不支持的传感器: " + sensorName); }); //随便注册一个不存在的传感器。 log(sensors.register("aaabbb")); ``` ## 事件: 'unsupported_sensor' - sensorName {string} 不支持的传感器名称 当sensors.ignoresUnsupportedSensor被设置为true并且有不支持的传感器被注册时触发该事件。事件参数的传感器名称。 ## SensorEventEmitter 注册传感器返回的对象,其本身是一个EventEmmiter,用于监听传感器事件。 ## 事件: 'change' - ..args {Any} 传感器参数 当传感器数据改变时触发该事件;该事件触发的最高频繁由sensors.register()指定的delay参数决定。 事件参数根据传感器类型不同而不同,具体参见本章最前面的列表。 一个监听光线传感器和加速度传感器并且每0.5秒获取一个数据并最终写入一个csv表格文件的例子如下: ``` //csv文件路径 cosnt csvPath = "/sdcard/sensors_data.csv"; //记录光线传感器的数据 var light = 0; //记录加速度传感器的数据 var ax = 0; var ay = 0; var az = 0; //监听光线传感器 sensors.register("light", sensors.delay.fastest) .on("change", l => { light = l; }); //监听加速度传感器 sensors.register("accelerometer", sensors.delay.fastest) .on("change", (ax0, ay0, az0) => { ax = ax0; ay = ay0; az = az0; }); var file = open(csvPath, "w"); //写csv表格头 file.writeline("light,ax,ay,az") //每0.5秒获取一次数据并写入文件 setInterval(()=>{ file.writeline(util.format("%d,%d,%d,%d", light, ax, ay, az)); }, 500); //10秒后退出并打开文件 setTimeout(()=>{ file.close(); sensors.unregsiterAll(); app.viewFile(csvPath); }, 10 * 1000); ``` ## 事件: 'accuracy_change' - accuracy {number} 表示传感器精度。为以下值之一: 1. -1 传感器未连接 2. 0 传感器不可读 3. 1 低精度 4. 2 中精度 5. 3 高精度 当传感器精度改变时会触发的事件。比较少用。 # 示例 ## 打印常用传感器信息 ```js //忽略不支持的传感器,即使有传感器不支持也不抛出异常 sensors.ignoresUnsupportedSensor = true; sensors.on("unsupported_sensor", function(sensorName, sensorType){ log("不支持的传感器: %s 类型: %d", sensorName, sensorType); }); //加速度传感器 sensors.register("accelerometer").on("change", (event, ax, ay, az)=>{ log("x方向加速度: %d\ny方向加速度: %d\nz方向加速度: %d", ax, ay, az); }); //方向传感器 sensors.register("orientation").on("change", (event, dx, dy, dz)=>{ log("绕x轴转过角度: %d\n绕y轴转过角度: %d\n绕z轴转过角度: %d", dx, dy, dz); }); //陀螺仪传感器 sensors.register("gyroscope").on("change", (event, wx, wy, wz)=>{ log("绕x轴角速度: %d\n绕y轴角速度: %d\n绕z轴角速度: %d", wx, wy, wz); }); //磁场传感器 sensors.register("magnetic_field").on("change", (event, bx, by, bz)=>{ log("x方向磁场强度: %d\ny方向磁场强度: %d\nz方向磁场强度: %d", bx, by, bz); }); //重力传感器 sensors.register("magnetic_field").on("change", (event, gx, gy, gz)=>{ log("x方向重力: %d\ny方向重力: %d\nz方向重力: %d", gx, gy, gz); }); //线性加速度传感器 sensors.register("linear_acceleration").on("change", (event, ax, ay, az)=>{ log("x方向线性加速度: %d\ny方向线性加速度: %d\nz方向线性加速度: %d", ax, ay, az); }); //温度传感器 sensors.register("ambient_temperature").on("change", (event, t)=>{ log("当前温度: %d", t); }); //光线传感器 sensors.register("light").on("change", (event, l)=>{ log("当前光的强度: %d", l); }); //压力传感器 sensors.register("pressure").on("change", (event, p)=>{ log("当前压力: %d", p); }); //距离传感器 sensors.register("proximity").on("change", (event, d)=>{ log("当前距离: %d", d); }); //湿度传感器 sensors.register("relative_humidity").on("change", (event, rh)=>{ log("当前相对湿度: %d", rh); }); //30秒后退出程序 setTimeout(exit, 30 * 1000); ``` ## 显示常用传感器信息 ```js "ui"; ui.layout( <scroll> <vertical> <text id="accelerometer" margin="12dp" textSize="16sp" textColor="#000000"/> <text id="orientation" margin="12dp" textSize="16sp" textColor="#000000"/> <text id="gyroscope" margin="12dp" textSize="16sp" textColor="#000000"/> <text id="magnetic_field" margin="12dp" textSize="16sp" textColor="#000000"/> <text id="gravity" margin="12dp" textSize="16sp" textColor="#000000"/> <text id="linear_acceleration" margin="12dp" textSize="16sp" textColor="#000000"/> <text id="ambient_temperature" margin="12dp" textSize="16sp" textColor="#000000"/> <text id="light" margin="12dp" textSize="16sp" textColor="#000000"/> <text id="pressure" margin="12dp" textSize="16sp" textColor="#000000"/> <text id="proximity" margin="12dp" textSize="16sp" textColor="#000000"/> <text id="relative_humidity" margin="12dp" textSize="16sp" textColor="#000000"/> </vertical> </scroll> ); //忽略不支持的传感器,即使有传感器不支持也不抛出异常 sensors.ignoresUnsupportedSensor = true; sensors.on("unsupported_sensor", function(sensorName, sensorType){ log(util.format("不支持的传感器: %s 类型: %d", sensorName, sensorType)); }); //加速度传感器 sensors.register("accelerometer", sensors.delay.ui).on("change", (event, ax, ay, az)=>{ ui.accelerometer.setText(util.format("x方向加速度: %d\ny方向加速度: %d\nz方向加速度: %d", ax, ay, az)); }); //方向传感器 sensors.register("orientation", sensors.delay.ui).on("change", (event, dx, dy, dz)=>{ ui.orientation.setText(util.format("绕x轴转过角度: %d\n绕y轴转过角度: %d\n绕z轴转过角度: %d", dx, dy, dz)); }); //陀螺仪传感器 sensors.register("gyroscope", sensors.delay.ui).on("change", (event, wx, wy, wz)=>{ ui.gyroscope.setText(util.format("绕x轴角速度: %d\n绕y轴角速度: %d\n绕z轴角速度: %d", wx, wy, wz)); }); //磁场传感器 sensors.register("magnetic_field", sensors.delay.ui).on("change", (event, bx, by, bz)=>{ ui.magnetic_field.setText(util.format("x方向磁场强度: %d\ny方向磁场强度: %d\nz方向磁场强度: %d", bx, by, bz)); }); //重力传感器 sensors.register("gravity", sensors.delay.ui).on("change", (event, gx, gy, gz)=>{ ui.gravity.setText(util.format("x方向重力: %d\ny方向重力: %d\nz方向重力: %d", gx, gy, gz)); }); //线性加速度传感器 sensors.register("linear_acceleration", sensors.delay.ui).on("change", (event, ax, ay, az)=>{ ui.linear_acceleration.setText(util.format("x方向线性加速度: %d\ny方向线性加速度: %d\nz方向线性加速度: %d", ax, ay, az)); }); //温度传感器 sensors.register("ambient_temperature", sensors.delay.ui).on("change", (event, t)=>{ ui.ambient_temperature.setText(util.format("当前温度: %d", t)); }); //光线传感器 sensors.register("light", sensors.delay.ui).on("change", (event, l)=>{ ui.light.setText(util.format("当前光的强度: %d", l)); }); //压力传感器 sensors.register("pressure", sensors.delay.ui).on("change", (event, p)=>{ ui.pressure.setText(util.format("当前压力: %d", p)); }); //距离传感器 sensors.register("proximity", sensors.delay.ui).on("change", (event, d)=>{ ui.proximity.setText(util.format("当前距离: %d", d)); }); //湿度传感器 sensors.register("relative_humidity", sensors.delay.ui).on("change", (event, rh)=>{ ui.relative_humidity.setText(util.format("当前相对湿度: %d", rh)); }); //30秒后退出程序 setTimeout(exit, 30 * 1000); ```