Adding upstream version 0.0~git20250520.a1d9079+dfsg.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
590ac7ff5f
commit
20149b7f3a
456 changed files with 70406 additions and 0 deletions
85
exp/sensor/android.c
Normal file
85
exp/sensor/android.c
Normal file
|
@ -0,0 +1,85 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build android
|
||||
// +build android
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <jni.h>
|
||||
|
||||
#include <android/sensor.h>
|
||||
|
||||
#define GO_ANDROID_SENSOR_LOOPER_ID 100
|
||||
|
||||
#define GO_ANDROID_READ_TIMEOUT_MS 1000
|
||||
|
||||
ASensorEventQueue* queue = NULL;
|
||||
ALooper* looper = NULL;
|
||||
|
||||
static ASensorManager* getSensorManager() {
|
||||
#pragma clang diagnostic push
|
||||
// Builders convert C warnings to errors, so suppress the
|
||||
// error from ASensorManager_getInstance being deprecated
|
||||
// in Android 26.
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
return ASensorManager_getInstance();
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
|
||||
void GoAndroid_createManager() {
|
||||
ASensorManager* manager = getSensorManager();
|
||||
looper = ALooper_forThread();
|
||||
if (looper == NULL) {
|
||||
looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
|
||||
}
|
||||
queue = ASensorManager_createEventQueue(manager, looper, GO_ANDROID_SENSOR_LOOPER_ID, NULL, NULL);
|
||||
}
|
||||
|
||||
int GoAndroid_enableSensor(int s, int32_t usec) {
|
||||
ASensorManager* manager = getSensorManager();
|
||||
const ASensor* sensor = ASensorManager_getDefaultSensor(manager, s);
|
||||
if (sensor == NULL) {
|
||||
return 1;
|
||||
}
|
||||
ASensorEventQueue_enableSensor(queue, sensor);
|
||||
ASensorEventQueue_setEventRate(queue, sensor, usec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GoAndroid_disableSensor(int s) {
|
||||
ASensorManager* manager = getSensorManager();
|
||||
const ASensor* sensor = ASensorManager_getDefaultSensor(manager, s);
|
||||
ASensorEventQueue_disableSensor(queue, sensor);
|
||||
}
|
||||
|
||||
int GoAndroid_readQueue(int n, int32_t* types, int64_t* timestamps, float* vectors) {
|
||||
int id;
|
||||
int events;
|
||||
ASensorEvent event;
|
||||
int i = 0;
|
||||
// Try n times read from the event queue.
|
||||
// If anytime timeout occurs, don't retry to read and immediately return.
|
||||
// Consume the event queue entirely between polls.
|
||||
while (i < n && (id = ALooper_pollOnce(GO_ANDROID_READ_TIMEOUT_MS, NULL, &events, NULL)) >= 0) {
|
||||
if (id != GO_ANDROID_SENSOR_LOOPER_ID) {
|
||||
continue;
|
||||
}
|
||||
while (i < n && ASensorEventQueue_getEvents(queue, &event, 1)) {
|
||||
types[i] = event.type;
|
||||
timestamps[i] = event.timestamp;
|
||||
vectors[i*3] = event.vector.x;
|
||||
vectors[i*3+1] = event.vector.y;
|
||||
vectors[i*3+2] = event.vector.z;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
void GoAndroid_destroyManager() {
|
||||
ASensorManager* manager = getSensorManager();
|
||||
ASensorManager_destroyEventQueue(manager, queue);
|
||||
queue = NULL;
|
||||
looper = NULL;
|
||||
}
|
206
exp/sensor/android.go
Normal file
206
exp/sensor/android.go
Normal file
|
@ -0,0 +1,206 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build android
|
||||
|
||||
package sensor
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -landroid
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <android/sensor.h>
|
||||
|
||||
void GoAndroid_createManager();
|
||||
void GoAndroid_destroyManager();
|
||||
int GoAndroid_enableSensor(int, int32_t);
|
||||
void GoAndroid_disableSensor(int);
|
||||
int GoAndroid_readQueue(int n, int32_t* types, int64_t* timestamps, float* vectors);
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"sync"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
collectingMu sync.Mutex // guards collecting
|
||||
|
||||
// collecting is true if sensor event collecting background
|
||||
// job has already started.
|
||||
collecting bool
|
||||
)
|
||||
|
||||
// closeSignal destroys the underlying looper and event queue.
|
||||
type closeSignal struct{}
|
||||
|
||||
// readSignal reads up to len(dst) events and mutates n with
|
||||
// the number of returned events.
|
||||
type readSignal struct {
|
||||
dst []Event
|
||||
n *int
|
||||
}
|
||||
|
||||
// enableSignal enables the sensors events on the underlying
|
||||
// event queue for the specified sensor type with the specified
|
||||
// latency criterion.
|
||||
type enableSignal struct {
|
||||
t Type
|
||||
delay time.Duration
|
||||
err *error
|
||||
}
|
||||
|
||||
// disableSignal disables the events on the underlying event queue
|
||||
// from the sensor specified.
|
||||
type disableSignal struct {
|
||||
t Type
|
||||
}
|
||||
|
||||
type inOut struct {
|
||||
in interface{}
|
||||
out chan struct{}
|
||||
}
|
||||
|
||||
var inout = make(chan inOut)
|
||||
|
||||
// init inits the manager and creates a goroutine to proxy the CGO calls.
|
||||
// All actions related to an ALooper needs to be performed from the same
|
||||
// OS thread. The goroutine proxy locks itself to an OS thread and handles the
|
||||
// CGO traffic on the same thread.
|
||||
func init() {
|
||||
go func() {
|
||||
runtime.LockOSThread()
|
||||
C.GoAndroid_createManager()
|
||||
|
||||
for {
|
||||
v := <-inout
|
||||
switch s := v.in.(type) {
|
||||
|
||||
case enableSignal:
|
||||
usecsDelay := s.delay.Nanoseconds() / 1000
|
||||
code := int(C.GoAndroid_enableSensor(typeToInt(s.t), C.int32_t(usecsDelay)))
|
||||
if code != 0 {
|
||||
*s.err = fmt.Errorf("sensor: no default %v sensor on the device", s.t)
|
||||
}
|
||||
case disableSignal:
|
||||
C.GoAndroid_disableSensor(typeToInt(s.t))
|
||||
case readSignal:
|
||||
n := readEvents(s.dst)
|
||||
*s.n = n
|
||||
case closeSignal:
|
||||
C.GoAndroid_destroyManager()
|
||||
close(v.out)
|
||||
return // we don't need this goroutine anymore
|
||||
}
|
||||
close(v.out)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// enable enables the sensor t on sender. A non-nil sender is
|
||||
// required before calling enable.
|
||||
func enable(t Type, delay time.Duration) error {
|
||||
startCollecting()
|
||||
|
||||
var err error
|
||||
done := make(chan struct{})
|
||||
inout <- inOut{
|
||||
in: enableSignal{t: t, delay: delay, err: &err},
|
||||
out: done,
|
||||
}
|
||||
<-done
|
||||
return err
|
||||
}
|
||||
|
||||
func startCollecting() {
|
||||
collectingMu.Lock()
|
||||
defer collectingMu.Unlock()
|
||||
|
||||
if collecting {
|
||||
// already collecting.
|
||||
return
|
||||
}
|
||||
collecting = true
|
||||
|
||||
go func() {
|
||||
ev := make([]Event, 8)
|
||||
var n int
|
||||
for {
|
||||
done := make(chan struct{})
|
||||
inout <- inOut{
|
||||
in: readSignal{dst: ev, n: &n},
|
||||
out: done,
|
||||
}
|
||||
<-done
|
||||
for i := 0; i < n; i++ {
|
||||
sender.Send(ev[i])
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func disable(t Type) error {
|
||||
done := make(chan struct{})
|
||||
inout <- inOut{
|
||||
in: disableSignal{t: t},
|
||||
out: done,
|
||||
}
|
||||
<-done
|
||||
return nil
|
||||
}
|
||||
|
||||
func readEvents(e []Event) int {
|
||||
num := len(e)
|
||||
types := make([]C.int32_t, num)
|
||||
timestamps := make([]C.int64_t, num)
|
||||
vectors := make([]C.float, 3*num)
|
||||
|
||||
n := int(C.GoAndroid_readQueue(
|
||||
C.int(num),
|
||||
(*C.int32_t)(unsafe.Pointer(&types[0])),
|
||||
(*C.int64_t)(unsafe.Pointer(×tamps[0])),
|
||||
(*C.float)(unsafe.Pointer(&vectors[0]))),
|
||||
)
|
||||
for i := 0; i < n; i++ {
|
||||
e[i] = Event{
|
||||
Sensor: intToType[int(types[i])],
|
||||
Timestamp: int64(timestamps[i]),
|
||||
Data: []float64{
|
||||
float64(vectors[i*3]),
|
||||
float64(vectors[i*3+1]),
|
||||
float64(vectors[i*3+2]),
|
||||
},
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// TODO(jbd): Remove destroy?
|
||||
func destroy() error {
|
||||
done := make(chan struct{})
|
||||
inout <- inOut{
|
||||
in: closeSignal{},
|
||||
out: done,
|
||||
}
|
||||
<-done
|
||||
return nil
|
||||
}
|
||||
|
||||
var intToType = map[int]Type{
|
||||
C.ASENSOR_TYPE_ACCELEROMETER: Accelerometer,
|
||||
C.ASENSOR_TYPE_GYROSCOPE: Gyroscope,
|
||||
C.ASENSOR_TYPE_MAGNETIC_FIELD: Magnetometer,
|
||||
}
|
||||
|
||||
func typeToInt(t Type) C.int {
|
||||
for k, v := range intToType {
|
||||
if v == t {
|
||||
return C.int(k)
|
||||
}
|
||||
}
|
||||
return C.int(-1)
|
||||
}
|
153
exp/sensor/darwin_armx.go
Normal file
153
exp/sensor/darwin_armx.go
Normal file
|
@ -0,0 +1,153 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build darwin && (arm || arm64)
|
||||
|
||||
package sensor
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -x objective-c
|
||||
#cgo LDFLAGS: -framework CoreMotion
|
||||
|
||||
#import <stdlib.h>
|
||||
|
||||
void GoIOS_createManager();
|
||||
|
||||
void GoIOS_startAccelerometer(float interval);
|
||||
void GoIOS_stopAccelerometer();
|
||||
void GoIOS_readAccelerometer(int64_t* timestamp, float* vector);
|
||||
|
||||
void GoIOS_startGyro(float interval);
|
||||
void GoIOS_stopGyro();
|
||||
void GoIOS_readGyro(int64_t* timestamp, float* vector);
|
||||
|
||||
void GoIOS_startMagneto(float interval);
|
||||
void GoIOS_stopMagneto();
|
||||
void GoIOS_readMagneto(int64_t* timestamp, float* vector);
|
||||
|
||||
void GoIOS_destroyManager();
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var channels struct {
|
||||
sync.Mutex
|
||||
done [nTypes]chan struct{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
C.GoIOS_createManager()
|
||||
}
|
||||
|
||||
// minDelay is the minimum delay allowed.
|
||||
//
|
||||
// From Event Handling Guide for iOS:
|
||||
//
|
||||
// "You can set the reporting interval to be as small as 10
|
||||
// milliseconds (ms), which corresponds to a 100 Hz update rate,
|
||||
// but most app operate sufficiently with a larger interval."
|
||||
//
|
||||
// There is no need to poll more frequently than once every 10ms.
|
||||
//
|
||||
// https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/motion_event_basics/motion_event_basics.html
|
||||
|
||||
const minDelay = 10 * time.Millisecond
|
||||
|
||||
// enable enables the sensor t on sender. A non-nil sender is
|
||||
// required before calling enable.
|
||||
func enable(t Type, delay time.Duration) error {
|
||||
channels.Lock()
|
||||
defer channels.Unlock()
|
||||
|
||||
if channels.done[t] != nil {
|
||||
return fmt.Errorf("sensor: cannot enable; %v sensor is already enabled", t)
|
||||
}
|
||||
channels.done[t] = make(chan struct{})
|
||||
|
||||
if delay < minDelay {
|
||||
delay = minDelay
|
||||
}
|
||||
interval := C.float(float64(delay) / float64(time.Second))
|
||||
|
||||
switch t {
|
||||
case Accelerometer:
|
||||
C.GoIOS_startAccelerometer(interval)
|
||||
case Gyroscope:
|
||||
C.GoIOS_startGyro(interval)
|
||||
case Magnetometer:
|
||||
C.GoIOS_startMagneto(interval)
|
||||
}
|
||||
go pollSensor(t, delay, channels.done[t])
|
||||
return nil
|
||||
}
|
||||
|
||||
func disable(t Type) error {
|
||||
channels.Lock()
|
||||
defer channels.Unlock()
|
||||
|
||||
if channels.done[t] == nil {
|
||||
return fmt.Errorf("sensor: cannot disable; %v sensor is not enabled", t)
|
||||
}
|
||||
close(channels.done[t])
|
||||
channels.done[t] = nil
|
||||
|
||||
switch t {
|
||||
case Accelerometer:
|
||||
C.GoIOS_stopAccelerometer()
|
||||
case Gyroscope:
|
||||
C.GoIOS_stopGyro()
|
||||
case Magnetometer:
|
||||
C.GoIOS_stopMagneto()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func pollSensor(t Type, d time.Duration, done chan struct{}) {
|
||||
var lastTimestamp int64
|
||||
|
||||
var timestamp C.int64_t
|
||||
var ev [3]C.float
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-done:
|
||||
return
|
||||
default:
|
||||
tp := (*C.int64_t)(unsafe.Pointer(×tamp))
|
||||
vp := (*C.float)(unsafe.Pointer(&ev[0]))
|
||||
|
||||
switch t {
|
||||
case Accelerometer:
|
||||
C.GoIOS_readAccelerometer(tp, vp)
|
||||
case Gyroscope:
|
||||
C.GoIOS_readGyro(tp, vp)
|
||||
case Magnetometer:
|
||||
C.GoIOS_readMagneto(tp, vp)
|
||||
}
|
||||
ts := int64(timestamp)
|
||||
if ts > lastTimestamp {
|
||||
// TODO(jbd): Do we need to convert the values to another unit?
|
||||
// How does iOS units compare to the Android units.
|
||||
sender.Send(Event{
|
||||
Sensor: t,
|
||||
Timestamp: ts,
|
||||
Data: []float64{float64(ev[0]), float64(ev[1]), float64(ev[2])},
|
||||
})
|
||||
lastTimestamp = ts
|
||||
time.Sleep(d / 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(jbd): Remove destroy?
|
||||
func destroy() error {
|
||||
C.GoIOS_destroyManager()
|
||||
return nil
|
||||
}
|
71
exp/sensor/darwin_armx.m
Normal file
71
exp/sensor/darwin_armx.m
Normal file
|
@ -0,0 +1,71 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build darwin && (arm || arm64)
|
||||
// +build darwin
|
||||
// +build arm arm64
|
||||
|
||||
#import <CoreMotion/CoreMotion.h>
|
||||
|
||||
CMMotionManager* manager = nil;
|
||||
|
||||
void GoIOS_createManager() {
|
||||
manager = [[CMMotionManager alloc] init];
|
||||
}
|
||||
|
||||
void GoIOS_startAccelerometer(float interval) {
|
||||
manager.accelerometerUpdateInterval = interval;
|
||||
[manager startAccelerometerUpdates];
|
||||
}
|
||||
|
||||
void GoIOS_stopAccelerometer() {
|
||||
[manager stopAccelerometerUpdates];
|
||||
}
|
||||
|
||||
void GoIOS_readAccelerometer(int64_t* timestamp, float* v) {
|
||||
CMAccelerometerData* data = manager.accelerometerData;
|
||||
*timestamp = (int64_t)(data.timestamp * 1000 * 1000);
|
||||
v[0] = data.acceleration.x;
|
||||
v[1] = data.acceleration.y;
|
||||
v[2] = data.acceleration.z;
|
||||
}
|
||||
|
||||
void GoIOS_startGyro(float interval) {
|
||||
manager.gyroUpdateInterval = interval;
|
||||
[manager startGyroUpdates];
|
||||
}
|
||||
|
||||
void GoIOS_stopGyro() {
|
||||
[manager stopGyroUpdates];
|
||||
}
|
||||
|
||||
void GoIOS_readGyro(int64_t* timestamp, float* v) {
|
||||
CMGyroData* data = manager.gyroData;
|
||||
*timestamp = (int64_t)(data.timestamp * 1000 * 1000);
|
||||
v[0] = data.rotationRate.x;
|
||||
v[1] = data.rotationRate.y;
|
||||
v[2] = data.rotationRate.z;
|
||||
}
|
||||
|
||||
void GoIOS_startMagneto(float interval) {
|
||||
manager.magnetometerUpdateInterval = interval;
|
||||
[manager startMagnetometerUpdates];
|
||||
}
|
||||
|
||||
void GoIOS_stopMagneto() {
|
||||
[manager stopMagnetometerUpdates];
|
||||
}
|
||||
|
||||
void GoIOS_readMagneto(int64_t* timestamp, float* v) {
|
||||
CMMagnetometerData* data = manager.magnetometerData;
|
||||
*timestamp = (int64_t)(data.timestamp * 1000 * 1000);
|
||||
v[0] = data.magneticField.x;
|
||||
v[1] = data.magneticField.y;
|
||||
v[2] = data.magneticField.z;
|
||||
}
|
||||
|
||||
void GoIOS_destroyManager() {
|
||||
[manager release];
|
||||
manager = nil;
|
||||
}
|
24
exp/sensor/notmobile.go
Normal file
24
exp/sensor/notmobile.go
Normal file
|
@ -0,0 +1,24 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build (linux && !android) || (darwin && !arm && !arm64) || windows
|
||||
|
||||
package sensor
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
func enable(t Type, delay time.Duration) error {
|
||||
return errors.New("sensor: no sensors available")
|
||||
}
|
||||
|
||||
func disable(t Type) error {
|
||||
return errors.New("sensor: no sensors available")
|
||||
}
|
||||
|
||||
func destroy() error {
|
||||
return nil
|
||||
}
|
130
exp/sensor/sensor.go
Normal file
130
exp/sensor/sensor.go
Normal file
|
@ -0,0 +1,130 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package sensor provides sensor events from various movement sensors.
|
||||
package sensor
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Type represents a sensor type.
|
||||
type Type int
|
||||
|
||||
var sensorNames = map[Type]string{
|
||||
Accelerometer: "Accelerometer",
|
||||
Gyroscope: "Gyroscope",
|
||||
Magnetometer: "Magnetometer",
|
||||
}
|
||||
|
||||
// String returns the string representation of the sensor type.
|
||||
func (t Type) String() string {
|
||||
if n, ok := sensorNames[t]; ok {
|
||||
return n
|
||||
}
|
||||
return "Unknown sensor"
|
||||
}
|
||||
|
||||
const (
|
||||
Accelerometer = Type(0)
|
||||
Gyroscope = Type(1)
|
||||
Magnetometer = Type(2)
|
||||
nTypes = Type(3)
|
||||
)
|
||||
|
||||
// Event represents a sensor event.
|
||||
type Event struct {
|
||||
// Sensor is the type of the sensor the event is coming from.
|
||||
Sensor Type
|
||||
|
||||
// Timestamp is a device specific event time in nanoseconds.
|
||||
// Timestamps are not Unix times, they represent a time that is
|
||||
// only valid for the device's default sensor.
|
||||
Timestamp int64
|
||||
|
||||
// Data is the event data.
|
||||
//
|
||||
// If the event source is Accelerometer,
|
||||
// - Data[0]: acceleration force in x axis in m/s^2
|
||||
// - Data[1]: acceleration force in y axis in m/s^2
|
||||
// - Data[2]: acceleration force in z axis in m/s^2
|
||||
//
|
||||
// If the event source is Gyroscope,
|
||||
// - Data[0]: rate of rotation around the x axis in rad/s
|
||||
// - Data[1]: rate of rotation around the y axis in rad/s
|
||||
// - Data[2]: rate of rotation around the z axis in rad/s
|
||||
//
|
||||
// If the event source is Magnetometer,
|
||||
// - Data[0]: force of gravity along the x axis in m/s^2
|
||||
// - Data[1]: force of gravity along the y axis in m/s^2
|
||||
// - Data[2]: force of gravity along the z axis in m/s^2
|
||||
//
|
||||
Data []float64
|
||||
}
|
||||
|
||||
// TODO(jbd): Move Sender interface definition to a top-level package.
|
||||
|
||||
var (
|
||||
// senderMu protects sender.
|
||||
senderMu sync.Mutex
|
||||
|
||||
// sender is notified with the sensor data each time a new event is available.
|
||||
sender Sender
|
||||
)
|
||||
|
||||
// Sender sends an event.
|
||||
type Sender interface {
|
||||
Send(event interface{})
|
||||
}
|
||||
|
||||
// Notify registers a Sender and sensor events will be sent to s.
|
||||
// A typical example of Sender implementations is app.App.
|
||||
// Once you call Notify, you are not allowed to call it again.
|
||||
// You cannot call Notify with a nil Sender.
|
||||
func Notify(s Sender) {
|
||||
senderMu.Lock()
|
||||
defer senderMu.Unlock()
|
||||
|
||||
if s == nil {
|
||||
panic("sensor: cannot set a nil sender")
|
||||
}
|
||||
if sender != nil {
|
||||
panic("sensor: another sender is being notified, cannot set s as the sender")
|
||||
}
|
||||
sender = s
|
||||
}
|
||||
|
||||
// Enable enables the specified sensor type with the given delay rate.
|
||||
// Users must set a non-nil Sender via Notify before enabling a sensor,
|
||||
// otherwise an error will be returned.
|
||||
func Enable(t Type, delay time.Duration) error {
|
||||
if t < 0 || int(t) >= len(sensorNames) {
|
||||
return errors.New("sensor: unknown sensor type")
|
||||
}
|
||||
if err := validSender(); err != nil {
|
||||
return err
|
||||
}
|
||||
return enable(t, delay)
|
||||
}
|
||||
|
||||
// Disable disables to feed the manager with the specified sensor.
|
||||
// Disable is not safe for concurrent use.
|
||||
func Disable(t Type) error {
|
||||
if t < 0 || int(t) >= len(sensorNames) {
|
||||
return errors.New("sensor: unknown sensor type")
|
||||
}
|
||||
return disable(t)
|
||||
}
|
||||
|
||||
func validSender() error {
|
||||
senderMu.Lock()
|
||||
defer senderMu.Unlock()
|
||||
|
||||
if sender == nil {
|
||||
return errors.New("sensor: no senders to be notified; cannot enable the sensor")
|
||||
}
|
||||
return nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue