You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
devices/am2320/am2320_test.go

191 lines
4.2 KiB
Go

// Copyright 2024 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package am2320
import (
"fmt"
"os"
"testing"
"time"
"periph.io/x/conn/v3/i2c"
"periph.io/x/conn/v3/i2c/i2creg"
"periph.io/x/conn/v3/i2c/i2ctest"
"periph.io/x/conn/v3/physic"
"periph.io/x/host/v3"
)
var bus i2c.Bus
var liveDevice bool
// Playback values for a single sense operation.
var pbSense = []i2ctest.IO{
{Addr: SensorAddress, W: []uint8{0x0}},
{Addr: SensorAddress, W: []uint8{0x3, 0x0, 0x4}, R: []uint8{0x3, 0x4, 0x1, 0x5c, 0x0, 0xef, 0x71, 0x8a}}}
func init() {
var err error
liveDevice = os.Getenv("AM2320") != ""
// Make sure periph is initialized.
if _, err = host.Init(); err != nil {
fmt.Println(err)
}
if liveDevice {
bus, err = i2creg.Open("")
if err != nil {
fmt.Println(err)
}
// Add the recorder to dump the data stream when we're using a live device.
bus = &i2ctest.Record{Bus: bus}
} else {
bus = &i2ctest.Playback{DontPanic: true}
}
}
// getDev returns a configured device using either an i2c bus, or a playback bus.
func getDev(t *testing.T, playbackOps ...[]i2ctest.IO) (*Dev, error) {
if liveDevice {
if recorder, ok := bus.(*i2ctest.Record); ok {
// Clear the operations buffer.
recorder.Ops = make([]i2ctest.IO, 0, 32)
}
} else {
if len(playbackOps) == 1 {
pb := bus.(*i2ctest.Playback)
pb.Ops = playbackOps[0]
pb.Count = 0
}
}
dev, err := NewI2C(bus, SensorAddress)
if err != nil {
t.Fatal(err)
}
return dev, err
}
// shutdown dumps the recorder values if we we're running a live device.
func shutdown(t *testing.T) {
if recorder, ok := bus.(*i2ctest.Record); ok {
t.Logf("%#v", recorder.Ops)
}
}
func TestBasic(t *testing.T) {
dev := Dev{}
env := &physic.Env{}
dev.Precision(env)
if env.Pressure != 0 {
t.Error("this device doesn't measure pressure")
}
if 10*env.Temperature != physic.Celsius {
t.Error("incorrect temperature precision value")
}
if env.Humidity != physic.MilliRH {
t.Error("incorrect humidity precision")
}
s := dev.String()
if len(s) == 0 {
t.Error("invalid value for String()")
}
// Check the CRC Calculation algorithm using the data supplied by the vendor.
crcTest := []byte{0x03, 0x04, 0x01, 0xf4, 0x00, 0xfa, 0x31, 0xa5}
if !checkCRC(crcTest) {
t.Error("crc error")
}
// ensure a corruption is detected.
crcTest[0] = crcTest[0] ^ 0xff
if checkCRC(crcTest) {
t.Error("crc error")
}
}
func TestSense(t *testing.T) {
d, err := getDev(t, pbSense)
if err != nil {
t.Fatalf("failed to initialize am2320: %v", err)
}
defer shutdown(t)
// Read temperature and humidity from the sensor
e := physic.Env{}
if err := d.Sense(&e); err != nil {
t.Fatal(err)
}
t.Logf("%8s %9s", e.Temperature, e.Humidity)
if !liveDevice {
// The playback temp is 23.9C Ensure that's what we got.
expected := physic.ZeroCelsius + 23_900*physic.MilliKelvin
if e.Temperature != expected {
t.Errorf("incorrect temperature value read. Expected: %s (%d) Found: %s (%d)",
e.Temperature.String(),
e.Temperature,
expected.String(),
expected)
}
// 34.8% expected.
expectedRH := 34*physic.PercentRH + 8*physic.MilliRH
if e.Humidity != expectedRH {
t.Errorf("incorrect humidity value read. Expected: %s (%d) Found: %s (%d)",
e.Humidity.String(),
e.Humidity,
expectedRH.String(),
expectedRH)
}
}
}
func TestSenseContinuous(t *testing.T) {
readCount := 10
// make 10 copies of the single reading playback data.
pb := make([]i2ctest.IO, 0, len(pbSense)*10)
for range readCount {
pb = append(pb, pbSense...)
}
d, err := getDev(t, pb)
if err != nil {
t.Fatalf("failed to initialize am2320: %v", err)
}
defer shutdown(t)
_, err = d.SenseContinuous(time.Second)
if err == nil {
t.Error("SenseContinuous() accepted invalid reading interval")
}
ch, err := d.SenseContinuous(3 * time.Second)
if err != nil {
t.Fatal(err)
}
go func() {
time.Sleep(3 * time.Duration(readCount) * time.Second)
err := d.Halt()
if err != nil {
t.Error(err)
}
}()
count := 0
for e := range ch {
count += 1
t.Log(time.Now(), e)
}
if count < (readCount-1) || count > (readCount+1) {
t.Errorf("expected %d readings. received %d", readCount, count)
}
}