-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathreply.go
121 lines (111 loc) · 2.97 KB
/
reply.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Copyright 2014 Krishna Raman
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package firmata
import (
"bufio"
"fmt"
)
type FirmataValue struct {
valueType FirmataCommand
value int
analogChannelPinsMap map[byte]int
}
func (v FirmataValue) IsAnalog() bool {
return (v.valueType & 0xF0) == AnalogMessage
}
func (v FirmataValue) GetAnalogValue() (pin int, val int, err error) {
if !v.IsAnalog() {
err = fmt.Errorf("Cannot get analog value for digital pin")
return
}
pin = v.analogChannelPinsMap[byte(v.valueType & ^AnalogMessage)]
val = v.value
return
}
func (v FirmataValue) GetDigitalValue() (port byte, val map[byte]interface{}, err error) {
if v.IsAnalog() {
err = fmt.Errorf("Cannot get digital value for analog pin")
return
}
port = byte(v.valueType & ^DigitalMessage)
val = make(map[byte]interface{})
mask := 0x01
for i := byte(0); i < 8; i++ {
val[port*8+i] = ((v.value & mask) > 0)
mask = mask * 2
}
return
}
func (v FirmataValue) String() string {
if v.IsAnalog() {
p, v, _ := v.GetAnalogValue()
return fmt.Sprintf("Analog value %v = %v", p, v)
} else {
p, v, _ := v.GetAnalogValue()
return fmt.Sprintf("Digital port %v = %b", p, v)
}
}
func (c *FirmataClient) replyReader() {
r := bufio.NewReader(*c.conn)
c.valueChan = make(chan FirmataValue)
var init bool
for {
b, err := (r.ReadByte())
if err != nil {
c.Log.Print(err)
return
}
cmd := FirmataCommand(b)
if c.Verbose {
c.Log.Printf("Incoming cmd %v", cmd)
}
if !init {
if cmd != ReportVersion {
if c.Verbose {
c.Log.Printf("Discarding unexpected command byte %0d (not initialized)\n", b)
}
continue
} else {
init = true
}
}
switch {
case cmd == ReportVersion:
c.protocolVersion = make([]byte, 2)
c.protocolVersion[0], err = r.ReadByte()
c.protocolVersion[1], err = r.ReadByte()
c.Log.Printf("Protocol version: %d.%d", c.protocolVersion[0], c.protocolVersion[1])
case cmd == StartSysEx:
var sysExData []byte
sysExData, err = r.ReadSlice(byte(EndSysEx))
if err == nil {
c.parseSysEx(sysExData[0 : len(sysExData)-1])
}
case (cmd&DigitalMessage) > 0 || byte(cmd&AnalogMessage) > 0:
b1, _ := r.ReadByte()
b2, _ := r.ReadByte()
select {
case c.valueChan <- FirmataValue{cmd, int(from7Bit(b1, b2)), c.analogChannelPinsMap}:
}
default:
if c.Verbose {
c.Log.Printf("Discarding unexpected command byte %0d\n", b)
}
}
if err != nil {
c.Log.Print(err)
return
}
}
}