Skip to content

Commit

Permalink
emulator::get-controller - returning SSMP GET value
Browse files Browse the repository at this point in the history
  • Loading branch information
twystd committed Aug 7, 2024
1 parent d35543c commit fdf29e5
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 28 deletions.
67 changes: 67 additions & 0 deletions Rev.0/emulator/ssmp/bisync.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package ssmp
import (
"bytes"
"encoding/binary"
"fmt"
)

const SOH byte = 1
Expand Down Expand Up @@ -93,3 +94,69 @@ func encode(msgid uint32, packet []byte) ([]byte, error) {

return b.Bytes(), nil
}

func decode(msg []uint8) (uint32, []byte, error) {
packet := bytes.Buffer{}
msgid := uint32(0)
ix := 0

// .. get message header
for ix < len(msg) {
if b := msg[ix]; b == SOH {
break
} else {
ix++
}
}

if msg[ix] != SOH {
return 0, nil, fmt.Errorf("missing SOH")
} else {
ix++
}

for i := 0; i < 4; i++ {
if ix < len(msg) {
b := msg[ix]
ix++

msgid <<= 8
msgid += uint32(b)
} else {
return 0, nil, fmt.Errorf("missing message ID")
}
}

// ... get message content
for ix < len(msg) {
if b := msg[ix]; b == STX {
break
} else {
ix++
}
}

if msg[ix] != STX {
return 0, nil, fmt.Errorf("missing STX")
} else {
ix++
}

for ix < len(msg) {
if b := msg[ix]; b == ETX {
break
} else if err := packet.WriteByte(b); err != nil {
return 0, nil, err
} else {
ix++
}
}

if msg[ix] != ETX {
return 0, nil, fmt.Errorf("missing ETX")
} else {
ix++
}

return msgid, packet.Bytes(), nil
}
80 changes: 66 additions & 14 deletions Rev.0/emulator/ssmp/ssmp.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ type SSMP struct {
}

type request struct {
id uint32
packet []byte
pipe chan []byte
}

var write = make(chan request)
Expand All @@ -30,9 +30,9 @@ func Get(oid []uint32) (any, error) {
logger := gosnmp.NewLogger(syslog.New(os.Stdout, "", 0))

pdu := gosnmp.SnmpPDU{
Value: nil,
Value: uint32(405419896),
Name: ".1.3.6.655136.1.1",
Type: gosnmp.Null,
Type: gosnmp.Uinteger32,
}

packet := gosnmp.SnmpPacket{
Expand All @@ -55,18 +55,32 @@ func Get(oid []uint32) (any, error) {
if bytes, err := packet.MarshalMsg(); err != nil {
return nil, err
} else {
id := uint32(1) // rqid.Add(1)
if encoded, err := encode(id, bytes); err != nil {
return nil, err
} else {
write <- request{
id: id,
packet: encoded,
rq := request{
packet: bytes,
pipe: make(chan []byte),
}

timeout := time.After(500 * time.Millisecond)

write <- rq
select {
case reply := <-rq.pipe:
debugf("reply to SSMP GET request (%v)", reply)

if value, err := get(reply, ".1.3.6.655136.1.1"); err != nil {
return 0, fmt.Errorf("invalid reply to SSMP GET %v request", ".1.3.6.655136.1.1")
} else if v, ok := value.(uint32); !ok {
return 0, fmt.Errorf("invalid valid in reply to SSMP GET %v request", ".1.3.6.655136.1.1")
} else {
return v, nil
}

case <-timeout:
return 0, fmt.Errorf("no reply to SSMP GET %v request", ".1.3.6.655136.1.1")
}
}

return uint32(405419896), nil
return 0, fmt.Errorf("SSMP GET %v failed", ".1.3.6.655136.1.1")
}

func (ssmp SSMP) Run() {
Expand All @@ -80,6 +94,8 @@ func (ssmp SSMP) Run() {
}

func (ssmp SSMP) read() error {
handlers := map[uint32]request{}

if t, err := term.Open(ssmp.USB, term.Speed(9600), term.RawMode); err != nil {
return err
} else {
Expand Down Expand Up @@ -149,15 +165,35 @@ func (ssmp SSMP) read() error {

for {
select {
case reply := <-pipe:
debugf("read %v %v", len(reply), reply)
case msg := <-pipe:
debugf("read %v %v", len(msg), msg)
if id, reply, err := decode(msg); err != nil {
warnf("read error (%v)", err)
} else {
debugf("read %v %v", id, reply)

if h, ok := handlers[id]; ok {
h.pipe <- reply
} else {
warnf("read error (%v)", fmt.Errorf("missing handler for message %v", id))
}

delete(handlers, id)
}

case request := <-write:
debugf("write %v", request)
if N, err := t.Write(request.packet); err != nil {
id := uint32(1) // rqid.Add(1)
if encoded, err := encode(id, request.packet); err != nil {
warnf("write error (%v)", err)
} else if N, err := t.Write(encoded); err != nil {
warnf("write error (%v)", err)
} else if N != len(encoded) {
warnf("write error (%v)", fmt.Errorf("sent %v bytes of %v)", N, len(encoded)))
} else {
debugf("write (%v bytes)", N)

handlers[id] = request
}

case <-idle:
Expand All @@ -172,6 +208,22 @@ func (ssmp SSMP) read() error {
}
}

func get(msg []uint8, OID string) (any, error) {
snmp := gosnmp.GoSNMP{}

if packet, err := snmp.SnmpDecodePacket(msg); err != nil {
return nil, err
} else {
for _, pdu := range packet.Variables {
if pdu.Name == OID {
return pdu.Value, nil
}
}
}

return nil, fmt.Errorf("OID %v not found", OID)
}

func debugf(format string, args ...any) {
log.Debugf("SSMP", format, args...)
}
Expand Down
31 changes: 17 additions & 14 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,29 @@
- https://www.raspberrypi.com/documentation/pico-sdk/hardware.html#rpip2aed586200427c10f67f
- compile time constant

### emulator
- [ ] get-controller
- [x] from MIB
- [ ] populate MIB from SSMP
- [ ] errors pipe in request
- [ ] prune handlers
- [ ] move encoding to encoding/BER
- [ ] move encoding to encoding/bisync
- [ ] use SNMP request/message ID
- [ ] walk MIB to initialise/refresh cache
- [ ] // TODO: exponential backoff
- [ ] tinygo


### SSMP
- [x] disable print/println in SSMP mode
- [x] SYN-SYN-ENQ/SYN-SYN-ACK
- [ ] MIB
- [ ] GET
- [x] // FIXME doesn't work with binary protocol
- [x] DLE
```
write [22 22 1 0 0 0 1 2 48 37 2 1 0 4 6 112 117 98 108 105 99 160 24 2 1 1 2 1 0 2 1 0 48 13 48 11 6 7 43 6 167 254 32 1 1 5 0 3]
read [22 22 1 0 0 0 1 2 48 37 2 1 0 4 6 112 117 98 108 105 99 160 24 2 1 1 2 1 0 2 1 0 48 13 48 11 6 7 43 6 167 254 32 1 1 5 0 3]
```
- (?) hexadecimal text
- [ ] usb_init
- [x] decode::DLE
- [ ] return SnmpGetResponse
- [ ] encode::DLE
- [ ] Enable FIFO
- [ ] pico: txrx/uart conflict
- https://www.baeldung.com/cs/bisync
Expand All @@ -36,13 +46,6 @@ read [22 22 1 0 0 0 1 2 48 37 2 1 0 4 6 112 117 98 108 105 99 160 24 2 1 1 2 1
- [ ] dropping last typed character if echo uses sys::print
- printf works but sys::print doesn't

### emulator
- [ ] get-controller
- [x] from MIB
- [ ] populate MIB from SSMP
- [ ] // TODO: exponential backoff
- [ ] tinygo

## PiZeroW
- [ ] Reduce power consumption
- [ ] NB: 24/7 operation - Cam said to ask him
Expand Down

0 comments on commit fdf29e5

Please sign in to comment.