Documentation
¶
Overview ¶
Package radpro implements a simple library for RadPro devices. Specifically, it implements the RadPro communication protocol
Index ¶
- Variables
- func RecordValues(i iter.Seq[Record]) iter.Seq[Record]
- type Device
- func (d *Device) BatteryVoltage() (float64, error)
- func (d *Device) Close() error
- func (d *Device) DataLog(options *LogOptions) (iter.Seq[Record], error)
- func (d *Device) Info() (Info, error)
- func (d *Device) PowerState() (bool, error)
- func (d *Device) RandomData() ([]byte, error)
- func (d *Device) SetPowerState(v bool) error
- func (d *Device) SetTime(t time.Time) error
- func (d *Device) SetTimeZone(loc *time.Location) error
- func (d *Device) SetTubeLifetime(lifetime time.Duration) error
- func (d *Device) SetTubePWMDutyCycle(v float64) error
- func (d *Device) SetTubePWMFrequency(frequency float64) error
- func (d *Device) SetTubePulseCount(v uint32) error
- func (d *Device) StartBootloader() error
- func (d *Device) Time() (time.Time, error)
- func (d *Device) TimeZone() (*time.Location, error)
- func (d *Device) TubeDeadTime() (time.Duration, error)
- func (d *Device) TubeDeadTimeCompensation() (time.Duration, error)
- func (d *Device) TubeLifetime() (time.Duration, error)
- func (d *Device) TubePWMDutyCycle() (float64, error)
- func (d *Device) TubePWMFrequency() (float64, error)
- func (d *Device) TubePulseCount() (uint32, error)
- func (d *Device) TubeRate() (float64, error)
- func (d *Device) TubeSensitivity() (float64, error)
- func (d *Device) WipeDataLog() error
- type Info
- type LogOptions
- type Record
Examples ¶
- Device.BatteryVoltage
- Device.DataLog
- Device.DataLog (Limits)
- Device.Info
- Device.PowerState
- Device.RandomData
- Device.SetPowerState
- Device.SetTime
- Device.SetTimeZone
- Device.SetTubeLifetime
- Device.SetTubePWMDutyCycle
- Device.SetTubePWMFrequency
- Device.SetTubePulseCount
- Device.StartBootloader
- Device.Time
- Device.TimeZone
- Device.TubeDeadTime
- Device.TubeDeadTimeCompensation
- Device.TubeLifetime
- Device.TubePWMDutyCycle
- Device.TubePWMFrequency
- Device.TubePulseCount
- Device.TubeRate
- Device.TubeSensitivity
- Device.WipeDataLog
- Record.IsZero
- Record.IsZero (DeleteFunc)
- RecordValues
Constants ¶
This section is empty.
Variables ¶
var ( // ErrResponse indicates an error response from the device. // This means that the executed command was not valid according to the device. ErrResponse = errors.New("error response") // ErrInvalidResponse indicates that the command executed successfully, // but the response from the device could not be parsed. ErrInvalidResponse = errors.New("invalid response") )
Functions ¶
func RecordValues ¶
RecordValues returns an iterator that only returns the non-zero values from the given record iterator.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/radpro"
"go.hofstra.dev/radpro/radprotest"
)
func main() {
device := radprotest.NewDevice()
defer device.Close()
// This requests all log entries from the device:
log, _ := device.DataLog(nil)
for record := range radpro.RecordValues(log) {
fmt.Printf("%s: %d\n", record.Time.UTC(), record.PulseCount)
}
}
Output: 2023-07-22 04:26:40 +0000 UTC: 1542 2023-07-22 04:27:40 +0000 UTC: 1618 2023-07-22 04:28:40 +0000 UTC: 1693
Types ¶
type Device ¶
type Device struct {
// contains filtered or unexported fields
}
Device represents a RadPro device.
func New ¶
func New(rwc io.ReadWriteCloser) *Device
New returns a device that communicates over the given io.ReadWriteCloser.
func OpenSerial ¶
OpenSerial opens the serial device on the given path, and uses it to initialize a new device.
func (*Device) BatteryVoltage ¶
BatteryVoltage returns the current battery voltage of the device. The precision is limited to three decimal places.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/radpro/radprotest"
)
func main() {
device := radprotest.NewDevice()
defer device.Close()
voltage, _ := device.BatteryVoltage()
fmt.Printf("Battery voltage: %.3f V\n", voltage)
}
Output: Battery voltage: 1.421 V
func (*Device) Close ¶
Close closes the connection of the device and releases all associated resources. The behaviour of calling close twice is dependent on the type of io.ReadWriteCloser that the Device was initialized with.
func (*Device) DataLog ¶
DataLog returns an iterator for the data log of the device. It only returns records depending on the limits set in the options. All records are returned when the options are nil.
The iterator yields empty Record values to indicate the start of logging sessions unless NoSessions is set in LogOptions. Use Record.IsZero to identify and/or RecordValues to discard them afterward.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/radpro/radprotest"
)
func main() {
device := radprotest.NewDevice()
defer device.Close()
// This requests all log entries from the device:
logEntries, _ := device.DataLog(nil)
for entry := range logEntries {
fmt.Printf("%s: %d\n", entry.Time.UTC(), entry.PulseCount)
}
}
Output: 0001-01-01 00:00:00 +0000 UTC: 0 2023-07-22 04:26:40 +0000 UTC: 1542 2023-07-22 04:27:40 +0000 UTC: 1618 2023-07-22 04:28:40 +0000 UTC: 1693
Example (Limits) ¶
package main
import (
"fmt"
"time"
"go.hofstra.dev/radpro"
"go.hofstra.dev/radpro/radprotest"
)
func main() {
device := radprotest.NewDevice()
defer device.Close()
// This requests all log entries between the given limits,
// and omits the zero value records that would normally be present.
logEntries, _ := device.DataLog(&radpro.LogOptions{
Start: time.Date(2023, 7, 22, 4, 26, 0, 0, time.UTC),
End: time.Date(2023, 7, 22, 4, 29, 0, 0, time.UTC),
Max: 4,
NoSessions: true,
})
for entry := range logEntries {
fmt.Printf("%s: %d\n", entry.Time.UTC(), entry.PulseCount)
}
}
Output: 2023-07-22 04:26:40 +0000 UTC: 1542 2023-07-22 04:27:40 +0000 UTC: 1618 2023-07-22 04:28:40 +0000 UTC: 1693
func (*Device) Info ¶
Info returns the Info for the device.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/radpro/radprotest"
)
func main() {
device := radprotest.NewDevice()
defer device.Close()
info, _ := device.Info()
fmt.Printf("Hardware type: %s\n", info.HardwareType)
fmt.Printf("Software version: %s\n", info.SoftwareVersion)
fmt.Printf("Device ID: %s\n", info.DeviceID)
}
Output: Hardware type: FS2011 (STM32F051C8) Software version: Rad Pro 2.0/en Device ID: radprotest
func (*Device) PowerState ¶
PowerState returns the current power state of the device, with 'true' indicating 'on' and 'false' indicating 'off'.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/radpro/radprotest"
)
func main() {
device := radprotest.NewDevice()
defer device.Close()
powerState, _ := device.PowerState()
fmt.Printf("Power state: %t\n", powerState)
}
Output: Power state: false
func (*Device) RandomData ¶
RandomData retrieves up to 16 bytes of random data from the device. It may return zero bytes of data if no data is available.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/radpro/radprotest"
)
func main() {
device := radprotest.NewDevice()
defer device.Close()
data, _ := device.RandomData()
fmt.Printf("%x\n", data)
}
Output: 9155facb75c00e331cf7fd625102f37a
func (*Device) SetPowerState ¶
SetPowerState sets the power state of the device, with 'true' indicating 'on' and 'false' indicating 'off'.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/radpro/radprotest"
)
func main() {
device := radprotest.NewDevice()
defer device.Close()
_ = device.SetPowerState(true)
powerState, _ := device.PowerState()
fmt.Printf("On: %t\n", powerState)
_ = device.SetPowerState(false)
powerState, _ = device.PowerState()
fmt.Printf("On: %t\n", powerState)
}
Output: On: true On: false
func (*Device) SetTime ¶
SetTime sets the time of the device to the given value.
Example ¶
package main
import (
"fmt"
"time"
"go.hofstra.dev/radpro/radprotest"
)
func main() {
device := radprotest.NewDevice()
defer device.Close()
_ = device.SetTime(time.Date(2025, 9, 24, 17, 0, 38, 0, time.UTC))
ts, _ := device.Time()
fmt.Println(ts.UTC())
}
Output: 2025-09-24 17:00:38 +0000 UTC
func (*Device) SetTimeZone ¶
SetTimeZone sets the timezone of the device to the given location.
Example ¶
package main
import (
"fmt"
"time"
"go.hofstra.dev/radpro/radprotest"
)
func main() {
device := radprotest.NewDevice()
defer device.Close()
device.SetTimeZone(time.FixedZone("PT", -8*60*60))
loc, _ := device.TimeZone()
fmt.Printf("Time zone: %s\n", loc)
}
Output: Time zone: UTC-8
func (*Device) SetTubeLifetime ¶
SetTubeLifetime sets the tube's operational life in seconds.
Example ¶
package main
import (
"fmt"
"time"
"go.hofstra.dev/radpro/radprotest"
)
func main() {
device := radprotest.NewDevice()
defer device.Close()
_ = device.SetTubeLifetime(24 * time.Hour)
lifetime, _ := device.TubeLifetime()
fmt.Println(lifetime)
}
Output: 24h0m0s
func (*Device) SetTubePWMDutyCycle ¶
SetTubePWMDutyCycle set the PWM duty cycle of the high-voltage generator of the tube. The value is between 0 and 1 with precision limited to five decimal places.
This functionality is not supported on all devices.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/radpro/radprotest"
)
func main() {
device := radprotest.NewDevice()
defer device.Close()
_ = device.SetTubePWMDutyCycle(0.5)
pwmDutyCycle, _ := device.TubePWMDutyCycle()
fmt.Printf("%.3f%%\n", 100*pwmDutyCycle)
}
Output: 50.000%
func (*Device) SetTubePWMFrequency ¶
SetTubePWMFrequency sets the PWM frequency of the high-voltage generator of the tube in Hz. Precision is limited to two decimal places.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/radpro/radprotest"
)
func main() {
device := radprotest.NewDevice()
defer device.Close()
_ = device.SetTubePWMFrequency(1234.56)
pwmFrequency, _ := device.TubePWMFrequency()
fmt.Printf("%.2f Hz\n", pwmFrequency)
}
Output: 1234.56 Hz
func (*Device) SetTubePulseCount ¶
SetTubePulseCount sets the tube's lifetime pulse count.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/radpro/radprotest"
)
func main() {
device := radprotest.NewDevice()
defer device.Close()
_ = device.SetTubePulseCount(4321)
pulseCount, _ := device.TubePulseCount()
fmt.Println(pulseCount)
}
Output: 4321
func (*Device) StartBootloader ¶
StartBootloader starts the system bootloader so the device can be updated.
This functionality is not supported on all devices.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/radpro/radprotest"
)
func main() {
device := radprotest.NewDevice()
defer device.Close()
err := device.StartBootloader()
fmt.Printf("Error: %v\n", err)
}
Output: Error: <nil>
func (*Device) Time ¶
Time returns the current time according to the device.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/radpro/radprotest"
)
func main() {
device := radprotest.NewDevice()
defer device.Close()
ts, _ := device.Time()
fmt.Println(ts.UTC().String())
}
Output: 2023-07-22 04:26:40 +0000 UTC
func (*Device) TimeZone ¶
TimeZone returns a time.Location matching the device.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/radpro/radprotest"
)
func main() {
device := radprotest.NewDevice()
defer device.Close()
loc, _ := device.TimeZone()
fmt.Printf("Time zone: %s\n", loc)
}
Output: Time zone: UTC+0
func (*Device) TubeDeadTime ¶
TubeDeadTime returns an upper bound of the tube's dead time, with precision limited to 0.1 µs.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/radpro/radprotest"
)
func main() {
device := radprotest.NewDevice()
defer device.Close()
deadTime, _ := device.TubeDeadTime()
fmt.Println(deadTime)
}
Output: 242µs
func (*Device) TubeDeadTimeCompensation ¶
TubeDeadTimeCompensation returns the tube's dead-time compensation, with precision limited to 0.1 µs.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/radpro/radprotest"
)
func main() {
device := radprotest.NewDevice()
defer device.Close()
deadTimeCompensation, _ := device.TubeDeadTimeCompensation()
fmt.Println(deadTimeCompensation)
}
Output: 250µs
func (*Device) TubeLifetime ¶
TubeLifetime returns the tube's operational life in seconds.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/radpro/radprotest"
)
func main() {
device := radprotest.NewDevice()
defer device.Close()
lifetime, _ := device.TubeLifetime()
fmt.Println(lifetime)
}
Output: 4h26m40s
func (*Device) TubePWMDutyCycle ¶
TubePWMDutyCycle returns the PWM duty cycle of the high-voltage generator of the tube. The value is between 0 and 1 with precision limited to five decimal places.
This functionality is not supported on all devices.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/radpro/radprotest"
)
func main() {
device := radprotest.NewDevice()
defer device.Close()
pwmDutyCycle, _ := device.TubePWMDutyCycle()
fmt.Printf("%.3f%%\n", 100*pwmDutyCycle)
}
Output: 9.750%
func (*Device) TubePWMFrequency ¶
TubePWMFrequency returns the PWM frequency of the high-voltage generator of the tube in Hz. Precision is limited to two decimal places.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/radpro/radprotest"
)
func main() {
device := radprotest.NewDevice()
defer device.Close()
pwmFrequency, _ := device.TubePWMFrequency()
fmt.Printf("%.2f Hz\n", pwmFrequency)
}
Output: 1250.00 Hz
func (*Device) TubePulseCount ¶
TubePulseCount returns the tube's lifetime pulse count. This value is updated continuously, but overflows after math.MaxUint32 counts.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/radpro/radprotest"
)
func main() {
device := radprotest.NewDevice()
defer device.Close()
pulseCount, _ := device.TubePulseCount()
fmt.Println(pulseCount)
}
Output: 1500
func (*Device) TubeRate ¶
TubeRate returns the tube's instantaneous rate in counts per minute (cpm). The precision is limited to three decimal places, and the value is updated every second. For better precision use the difference between two Device.TubePulseCount measurements. Divide by Device.TubeSensitivity to convert the value in cpm to µSv/h.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/radpro/radprotest"
)
func main() {
device := radprotest.NewDevice()
defer device.Close()
rate, _ := device.TubeRate()
fmt.Printf("%.3f\n", rate)
}
Output: 142.857
func (*Device) TubeSensitivity ¶
TubeSensitivity returns the tube's sensitivity in cpm/(µSv/h). This value can be used to divide a value in cpm (eg Device.TubeRate) to calculate the radiation dose rate in µSv/h. The precision of the returned value is limited to three decimal places.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/radpro/radprotest"
)
func main() {
device := radprotest.NewDevice()
defer device.Close()
sensitivity, _ := device.TubeSensitivity()
fmt.Printf("%.3f cpm/(µSv/h)\n", sensitivity)
}
Output: 153.800 cpm/(µSv/h)
func (*Device) WipeDataLog ¶
WipeDataLog clears the data log from the device's memory.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/radpro/radprotest"
)
func main() {
device := radprotest.NewDevice()
defer device.Close()
_ = device.WipeDataLog()
logEntries, _ := device.DataLog(nil)
for entry := range logEntries {
fmt.Printf("%s: %d\n", entry.Time.UTC(), entry.PulseCount)
}
}
type Info ¶
type Info struct {
// Hardware type.
HardwareType string
// Software version and language.
SoftwareVersion string
// Unique device identifier.
DeviceID string
}
Info contains the information about the device.
type LogOptions ¶
type LogOptions struct {
// End limits the records to ones after the given time.
// No such limit is set when left at the zero value.
Start time.Time
// End limits the records to ones before the given time.
// No such limit is set when left at the zero value.
End time.Time
// Max limits the number of records returned to the given amount.
// No such limit is set when left at the zero value.
Max int
// NoSessions omits the zero value log records that mark the start
// of log session markers in the result.
NoSessions bool
}
LogOptions contains the options for the Device.DataLog method.
type Record ¶
A Record represents an entry from the device's data log. See Device.DataLog for details.
func (Record) IsZero ¶
IsZero returns true if the Record is the zero value. This indicates the start of a new logging session.
Example ¶
package main
import (
"fmt"
"time"
"go.hofstra.dev/radpro"
)
func main() {
records := []radpro.Record{
{},
{Time: time.Unix(1690000000, 0), PulseCount: 1542},
{Time: time.Unix(1690000060, 0), PulseCount: 1618},
{Time: time.Unix(1690000120, 0), PulseCount: 1693},
}
for _, record := range records {
fmt.Printf("%s: %d => is zero: %t\n",
record.Time.UTC(), record.PulseCount, record.IsZero())
}
}
Output: 0001-01-01 00:00:00 +0000 UTC: 0 => is zero: true 2023-07-22 04:26:40 +0000 UTC: 1542 => is zero: false 2023-07-22 04:27:40 +0000 UTC: 1618 => is zero: false 2023-07-22 04:28:40 +0000 UTC: 1693 => is zero: false
Example (DeleteFunc) ¶
package main
import (
"fmt"
"slices"
"time"
"go.hofstra.dev/radpro"
)
func main() {
records := []radpro.Record{
{},
{Time: time.Unix(1690000000, 0), PulseCount: 1542},
{Time: time.Unix(1690000060, 0), PulseCount: 1618},
{Time: time.Unix(1690000120, 0), PulseCount: 1693},
}
// Remove all zero values from the slice.
records = slices.DeleteFunc(records, radpro.Record.IsZero)
for _, record := range records {
fmt.Printf("%s: %d\n", record.Time.UTC(), record.PulseCount)
}
}
Output: 2023-07-22 04:26:40 +0000 UTC: 1542 2023-07-22 04:27:40 +0000 UTC: 1618 2023-07-22 04:28:40 +0000 UTC: 1693
Directories
¶
| Path | Synopsis |
|---|---|
|
Package radprotest provides utilities for testing the radpro package.
|
Package radprotest provides utilities for testing the radpro package. |