Skip to content

Commit ad67d07

Browse files
authored
1-wire(all): ensure halt is idempotent (#1174)
1 parent 7bfec7c commit ad67d07

File tree

4 files changed

+83
-14
lines changed

4 files changed

+83
-14
lines changed

drivers/onewire/ds18b20_driver.go

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ func (d *DS18B20Driver) Temperature() (float32, error) {
108108
d.mutex.Lock()
109109
defer d.mutex.Unlock()
110110

111-
val, err := d.connection.ReadInteger(temperatureCommand)
111+
val, err := d.readInteger(temperatureCommand)
112112
if err != nil {
113113
return 0, err
114114
}
@@ -121,7 +121,7 @@ func (d *DS18B20Driver) Resolution() (uint8, error) {
121121
d.mutex.Lock()
122122
defer d.mutex.Unlock()
123123

124-
val, err := d.connection.ReadInteger(resolutionCommand)
124+
val, err := d.readInteger(resolutionCommand)
125125
if err != nil {
126126
return 0, err
127127
}
@@ -138,7 +138,7 @@ func (d *DS18B20Driver) IsExternalPowered() (bool, error) {
138138
d.mutex.Lock()
139139
defer d.mutex.Unlock()
140140

141-
val, err := d.connection.ReadInteger(extPowerCommand)
141+
val, err := d.readInteger(extPowerCommand)
142142
if err != nil {
143143
return false, err
144144
}
@@ -151,7 +151,7 @@ func (d *DS18B20Driver) ConversionTime() (uint16, error) {
151151
d.mutex.Lock()
152152
defer d.mutex.Unlock()
153153

154-
val, err := d.connection.ReadInteger(convTimeCommand)
154+
val, err := d.readInteger(convTimeCommand)
155155
if err != nil {
156156
return 0, err
157157
}
@@ -166,13 +166,18 @@ func (d *DS18B20Driver) ConversionTime() (uint16, error) {
166166
// DebugConversionTime try to set the conversion time and compare with real time to read temperature.
167167
func (d *DS18B20Driver) DebugConversionTime(start, end uint16, stepwide uint16, skipInvalid bool) {
168168
r, _ := d.Resolution()
169+
id, err := d.id()
170+
if err != nil {
171+
fmt.Println(err.Error())
172+
return
173+
}
169174
fmt.Printf("\n---- Conversion time check for '%s'@%dbit %d..%d +%d ----\n",
170-
d.connection.ID(), r, start, end, stepwide)
175+
id, r, start, end, stepwide)
171176
fmt.Println("|r1(err)\t|w(err)\t\t|r2(err)\t|T(err)\t\t|real\t\t|diff\t\t|")
172177
fmt.Println("--------------------------------------------------------------------------------")
173178
for ct := start; ct < end; ct += stepwide {
174179
r1, e1 := d.ConversionTime()
175-
ew := d.connection.WriteInteger(convTimeCommand, int(ct))
180+
ew := d.writeInteger(convTimeCommand, int(ct))
176181
r2, e2 := d.ConversionTime()
177182
time.Sleep(100 * time.Millisecond) // relax the system
178183
start := time.Now()
@@ -189,27 +194,31 @@ func (d *DS18B20Driver) DebugConversionTime(start, end uint16, stepwide uint16,
189194

190195
func (d *DS18B20Driver) initialize() error {
191196
if d.ds18b20Cfg.resolution != ds18b20DefaultResolution {
192-
if err := d.connection.WriteInteger(resolutionCommand, int(d.ds18b20Cfg.resolution)); err != nil {
197+
if err := d.writeInteger(resolutionCommand, int(d.ds18b20Cfg.resolution)); err != nil {
193198
return err
194199
}
195200
}
196201

197202
if d.ds18b20Cfg.conversionTime != ds18b20DefaultConversionTime {
198-
return d.connection.WriteInteger(convTimeCommand, int(d.ds18b20Cfg.conversionTime))
203+
return d.writeInteger(convTimeCommand, int(d.ds18b20Cfg.conversionTime))
199204
}
200205

201206
return nil
202207
}
203208

204209
func (d *DS18B20Driver) shutdown() error {
210+
if d.connection == nil {
211+
return nil
212+
}
213+
205214
if d.ds18b20Cfg.resolution != ds18b20DefaultResolution {
206-
if err := d.connection.WriteInteger(resolutionCommand, ds18b20DefaultResolution); err != nil {
215+
if err := d.writeInteger(resolutionCommand, ds18b20DefaultResolution); err != nil {
207216
return err
208217
}
209218
}
210219

211220
if d.ds18b20Cfg.conversionTime != ds18b20DefaultConversionTime {
212-
return d.connection.WriteInteger(convTimeCommand, int(ds18b20DefaultConversionTime))
221+
return d.writeInteger(convTimeCommand, int(ds18b20DefaultConversionTime))
213222
}
214223

215224
return nil

drivers/onewire/ds18b20_driver_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,18 @@ func TestDS18B20Halt(t *testing.T) {
129129
}
130130
}
131131

132+
func TestDS18B20HaltIdempotent(t *testing.T) {
133+
// arrange
134+
d := NewDS18B20Driver(newOneWireTestAdaptor(), 2345)
135+
// to trigger write calls:
136+
d.ds18b20Cfg.resolution = ds18b20DefaultResolution + 1
137+
d.ds18b20Cfg.conversionTime = ds18b20DefaultConversionTime + 2
138+
// act, assert
139+
require.NoError(t, d.Halt()) // must be idempotent
140+
require.NoError(t, d.Start())
141+
require.NoError(t, d.Halt())
142+
}
143+
132144
func TestDS18B20Temperature(t *testing.T) {
133145
const readValue = 24500
134146
tests := map[string]struct {

drivers/onewire/onewire_driver.go

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,12 @@ func (d *driver) SetName(name string) {
8787
d.driverCfg.name = name
8888
}
8989

90-
// Connection returns the connection of the device.
90+
// Connection returns the gobot connection of the device.
9191
func (d *driver) Connection() gobot.Connection {
92+
if d.connection == nil {
93+
log.Printf("1-wire driver not started for %s\n", d.driverCfg.name)
94+
}
95+
9296
if conn, ok := d.connection.(gobot.Connection); ok {
9397
return conn
9498
}
@@ -116,10 +120,52 @@ func (d *driver) Halt() error {
116120
d.mutex.Lock()
117121
defer d.mutex.Unlock()
118122

119-
// currently there is nothing to do here for the driver, the connection is cached on adaptor side
120-
// and will be closed on adaptor Finalize()
123+
if err := d.beforeHalt(); err != nil {
124+
return err
125+
}
126+
127+
// the connection is also cached on adaptor side and will be closed on adaptor Finalize()
128+
d.connection = nil
129+
130+
return nil
131+
}
132+
133+
func (d *driver) id() (string, error) {
134+
if d.connection == nil {
135+
return "", fmt.Errorf("1-wire driver not started for %s", d.driverCfg.name)
136+
}
137+
138+
return d.connection.ID(), nil
139+
}
140+
141+
//nolint:unused // ok for now
142+
func (d *driver) readData(command string, data []byte) error {
143+
if d.connection == nil {
144+
return fmt.Errorf("1-wire driver not started for %s", d.driverCfg.name)
145+
}
146+
return d.connection.ReadData(command, data)
147+
}
121148

122-
return d.beforeHalt()
149+
//nolint:unused // ok for now
150+
func (d *driver) writeData(command string, data []byte) error {
151+
if d.connection == nil {
152+
return fmt.Errorf("1-wire driver not started for %s", d.driverCfg.name)
153+
}
154+
return d.connection.WriteData(command, data)
155+
}
156+
157+
func (d *driver) readInteger(command string) (int, error) {
158+
if d.connection == nil {
159+
return 0, fmt.Errorf("1-wire driver not started for %s", d.driverCfg.name)
160+
}
161+
return d.connection.ReadInteger(command)
162+
}
163+
164+
func (d *driver) writeInteger(command string, val int) error {
165+
if d.connection == nil {
166+
return fmt.Errorf("1-wire driver not started for %s", d.driverCfg.name)
167+
}
168+
return d.connection.WriteInteger(command, val)
123169
}
124170

125171
func (o nameOption) String() string {

drivers/onewire/onewire_driver_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ func TestHalt(t *testing.T) {
6262
// arrange
6363
d := initTestDriver()
6464
// act, assert
65+
require.NoError(t, d.Halt()) // must be idempotent
66+
require.NoError(t, d.Start())
6567
require.NoError(t, d.Halt())
6668
}
6769

0 commit comments

Comments
 (0)