]> git.giacomolli.uk - onehouse/blob - driver/m31/output_request.go
Exchange bounded Alamo gateway requests
[onehouse] / driver / m31 / output_request.go
1 package m31
2
3 import (
4 "bytes"
5 "encoding/json"
6 "math"
7 "math/big"
8 "time"
9
10 "onehouse/driver"
11 )
12
13 type outputRequest struct {
14 command driver.Command
15 point point
16 analog bool
17 value uint16
18 }
19
20 func newOutputRequest(command driver.Command, topology topology, deviceID string, batch bool) (outputRequest, string) {
21 request := outputRequest{command: command}
22
23 if command.DeviceID != deviceID {
24 return request, "Command belongs to another device"
25 }
26
27 if command.Expired(time.Now()) {
28 return request, "Command expired"
29 }
30
31 value := bytes.TrimSpace(command.Payload.Value)
32
33 for _, output := range topology.outputs {
34 if output.id != command.Capability {
35 continue
36 }
37
38 request.point = output
39 if !bytes.Equal(value, []byte("true")) && !bytes.Equal(value, []byte("false")) {
40 return request, "Digital output requires a Boolean value"
41 }
42
43 if bytes.Equal(value, []byte("true")) {
44 request.value = 1
45 }
46
47 if output.pulse != 0 && request.value != 1 {
48 return request, "Pulse output requires true"
49 }
50
51 if batch && output.pulse != 0 {
52 return request, "Batches require steady digital outputs"
53 }
54
55 return request, ""
56 }
57
58 for _, output := range topology.analog {
59 if output.id != command.Capability {
60 continue
61 }
62
63 request.point, request.analog = output, true
64 if batch {
65 return request, "Batches require steady digital outputs"
66 }
67
68 if len(value) == 0 || !json.Valid(value) || value[0] != '-' && (value[0] < '0' || value[0] > '9') {
69 return request, "Analog output requires zero through ten volts"
70 }
71
72 number, valid := new(big.Rat).SetString(string(value))
73 if !valid || number.Sign() < 0 || number.Cmp(big.NewRat(10, 1)) > 0 {
74 return request, "Analog output requires zero through ten volts"
75 }
76
77 voltage, _ := number.Float64()
78 request.value = uint16(math.Round(voltage * 1000))
79
80 return request, ""
81 }
82
83 return request, "Capability is not a configured output"
84 }