From ff3ba72208a65788ba5d2f85a7bfd8de505943e2 Mon Sep 17 00:00:00 2001 From: twystd Date: Mon, 16 Dec 2024 16:01:21 -0800 Subject: [PATCH] emulator: genericized driver 'get' --- Rev.0/driver/rpc/ssmp/ssmp.go | 4 +- Rev.0/emulator/go/UT0311/UT0311.go | 12 ---- Rev.0/emulator/go/UT0311/get-controller.go | 16 ++--- Rev.0/emulator/go/UT0311/get-listener.go | 3 +- Rev.0/emulator/go/UT0311/get-status.go | 71 ++++++---------------- Rev.0/emulator/go/UT0311/get-time.go | 26 +++----- Rev.0/emulator/go/UT0311/set-listener.go | 3 +- Rev.0/emulator/go/UT0311/set-time.go | 3 +- Rev.0/emulator/go/driver/driver.go | 65 +++++++++++++++++++- Rev.0/emulator/go/driver/rpc/rpcd.go | 52 +++++++++++++++- Rev.0/emulator/go/driver/stub/stub.go | 52 +++++++++++++++- 11 files changed, 207 insertions(+), 100 deletions(-) diff --git a/Rev.0/driver/rpc/ssmp/ssmp.go b/Rev.0/driver/rpc/ssmp/ssmp.go index 47b77f2..f3ceb57 100644 --- a/Rev.0/driver/rpc/ssmp/ssmp.go +++ b/Rev.0/driver/rpc/ssmp/ssmp.go @@ -35,12 +35,12 @@ func (s SSMP) Get(oid string) (any, error) { // ... controller error if oid == ".1.3.6.1.4.1.65536.2.9" { - return 0x12, nil + return uint8(0x12), nil } // ... controller special info if oid == ".1.3.6.1.4.1.65536.2.10" { - return 0x23, nil + return uint8(0x23), nil } // ... door 1 unlocked diff --git a/Rev.0/emulator/go/UT0311/UT0311.go b/Rev.0/emulator/go/UT0311/UT0311.go index a8d0874..af9bc0c 100644 --- a/Rev.0/emulator/go/UT0311/UT0311.go +++ b/Rev.0/emulator/go/UT0311/UT0311.go @@ -1,14 +1,12 @@ package UT0311 import ( - "fmt" "reflect" "sync" "time" "github.com/uhppoted/uhppote-core/messages" - "emulator/MIB" "emulator/config" "emulator/driver" "emulator/log" @@ -139,16 +137,6 @@ func isnil(v any) bool { return false } -func (ut0311 *UT0311) getID() (uint32, error) { - if v, err := ut0311.driver.Get(MIB.OID_CONTROLLER_ID); err != nil { - return 0, err - } else if id, ok := v.(uint32); !ok { - return 0, fmt.Errorf("invalid controller ID (%v)", v) - } else { - return id, nil - } -} - func debugf(format string, args ...any) { log.Debugf("UT0311", format, args...) } diff --git a/Rev.0/emulator/go/UT0311/get-controller.go b/Rev.0/emulator/go/UT0311/get-controller.go index 50e2d45..b00cc37 100644 --- a/Rev.0/emulator/go/UT0311/get-controller.go +++ b/Rev.0/emulator/go/UT0311/get-controller.go @@ -1,7 +1,6 @@ package UT0311 import ( - "fmt" "net" "net/netip" @@ -10,10 +9,11 @@ import ( "emulator/MIB" "emulator/config" + "emulator/driver" ) func (ut0311 *UT0311) getController(rq *messages.GetDeviceRequest) (any, error) { - if id, err := ut0311.getID(); err != nil { + if id, err := driver.Get[uint32](ut0311.driver, MIB.OID_CONTROLLER_ID); err != nil { return nil, err } else if id == 0 || (rq.SerialNumber != 0 && uint32(rq.SerialNumber) != id) { return nil, nil @@ -46,22 +46,16 @@ func (ut0311 *UT0311) getController(rq *messages.GetDeviceRequest) (any, error) response.MacAddress = []byte(MAC) } - if v, err := ut0311.driver.Get(MIB.OID_CONTROLLER_VERSION); err != nil { + if version, err := driver.Get[uint16](ut0311.driver, MIB.OID_CONTROLLER_VERSION); err != nil { return nil, err - } else if version, ok := v.(uint16); !ok { - return nil, fmt.Errorf("invalid controller version (%v)", version) } else { response.Version = types.Version(version) } - if v, err := ut0311.driver.Get(MIB.OID_CONTROLLER_RELEASED); err != nil { + if released, err := driver.Get[types.Date](ut0311.driver, MIB.OID_CONTROLLER_RELEASED); err != nil { return nil, err - } else if released, ok := v.(string); !ok { - return nil, fmt.Errorf("invalid controller release date (%v)", released) - } else if date, err := types.ParseDate(released); err != nil { - return nil, fmt.Errorf("invalid controller release date (%v)", released) } else { - response.Date = date + response.Date = released } return response, nil diff --git a/Rev.0/emulator/go/UT0311/get-listener.go b/Rev.0/emulator/go/UT0311/get-listener.go index 1f88d56..626d1ab 100644 --- a/Rev.0/emulator/go/UT0311/get-listener.go +++ b/Rev.0/emulator/go/UT0311/get-listener.go @@ -8,10 +8,11 @@ import ( "emulator/MIB" "emulator/config" + "emulator/driver" ) func (ut0311 *UT0311) getListener(rq *messages.GetListenerRequest) (any, error) { - if id, err := ut0311.getID(); err != nil { + if id, err := driver.Get[uint32](ut0311.driver, MIB.OID_CONTROLLER_ID); err != nil { return nil, err } else if id == 0 || (rq.SerialNumber != 0 && uint32(rq.SerialNumber) != id) { return nil, nil diff --git a/Rev.0/emulator/go/UT0311/get-status.go b/Rev.0/emulator/go/UT0311/get-status.go index 03cc9f4..0364838 100644 --- a/Rev.0/emulator/go/UT0311/get-status.go +++ b/Rev.0/emulator/go/UT0311/get-status.go @@ -1,16 +1,15 @@ package UT0311 import ( - "fmt" - "github.com/uhppoted/uhppote-core/messages" "github.com/uhppoted/uhppote-core/types" "emulator/MIB" + "emulator/driver" ) func (ut0311 *UT0311) getStatus(rq *messages.GetStatusRequest) (any, error) { - if id, err := ut0311.getID(); err != nil { + if id, err := driver.Get[uint32](ut0311.driver, MIB.OID_CONTROLLER_ID); err != nil { return nil, err } else if id == 0 || (rq.SerialNumber != 0 && uint32(rq.SerialNumber) != id) { return nil, nil @@ -20,129 +19,97 @@ func (ut0311 *UT0311) getStatus(rq *messages.GetStatusRequest) (any, error) { RelayState: 0x00, } - if v, err := ut0311.driver.Get(MIB.OID_CONTROLLER_DATETIME); err != nil { - return nil, err - } else if s, ok := v.(string); !ok { - return nil, fmt.Errorf("invalid controller date/time (%v)", v) - } else if datetime, err := types.ParseDateTime(s); err != nil { + if datetime, err := driver.Get[types.DateTime](ut0311.driver, MIB.OID_CONTROLLER_DATETIME); err != nil { return nil, err } else { response.SystemDate = types.SystemDate(datetime) response.SystemTime = types.SystemTime(datetime) } - if v, err := ut0311.driver.Get(MIB.OID_CONTROLLER_ERROR); err != nil { + if v, err := driver.Get[uint8](ut0311.driver, MIB.OID_CONTROLLER_ERROR); err != nil { return nil, err - } else if e, ok := v.(int); !ok { - return nil, fmt.Errorf("invalid controller error (%T)", v) } else { - response.SystemError = uint8(e) + response.SystemError = v } - if v, err := ut0311.driver.Get(MIB.OID_CONTROLLER_SPECIAL_INFO); err != nil { + if v, err := driver.Get[uint8](ut0311.driver, MIB.OID_CONTROLLER_SPECIAL_INFO); err != nil { return nil, err - } else if e, ok := v.(int); !ok { - return nil, fmt.Errorf("invalid controller special info (%T)", v) } else { - response.SpecialInfo = uint8(e) + response.SpecialInfo = v } // ... door 1 - if v, err := ut0311.driver.Get(MIB.OID_DOORS_1_UNLOCKED); err != nil { + if unlocked, err := driver.Get[bool](ut0311.driver, MIB.OID_DOORS_1_UNLOCKED); err != nil { return nil, err - } else if unlocked, ok := v.(bool); !ok { - return nil, fmt.Errorf("invalid controller door 1 unlocked (%T)", v) } else if unlocked { response.RelayState |= 0x01 } - if v, err := ut0311.driver.Get(MIB.OID_DOORS_1_OPEN); err != nil { + if open, err := driver.Get[bool](ut0311.driver, MIB.OID_DOORS_1_OPEN); err != nil { return nil, err - } else if open, ok := v.(bool); !ok { - return nil, fmt.Errorf("invalid controller door 1 open (%T)", v) } else { response.Door1State = open } - if v, err := ut0311.driver.Get(MIB.OID_DOORS_1_BUTTON); err != nil { + if pressed, err := driver.Get[bool](ut0311.driver, MIB.OID_DOORS_1_BUTTON); err != nil { return nil, err - } else if pressed, ok := v.(bool); !ok { - return nil, fmt.Errorf("invalid controller door 1 button (%T)", v) } else { response.Door1Button = pressed } // ... door 2 - if v, err := ut0311.driver.Get(MIB.OID_DOORS_2_UNLOCKED); err != nil { + if unlocked, err := driver.Get[bool](ut0311.driver, MIB.OID_DOORS_2_UNLOCKED); err != nil { return nil, err - } else if unlocked, ok := v.(bool); !ok { - return nil, fmt.Errorf("invalid controller door 2 unlocked (%T)", v) } else if unlocked { response.RelayState |= 0x02 } - if v, err := ut0311.driver.Get(MIB.OID_DOORS_2_OPEN); err != nil { + if open, err := driver.Get[bool](ut0311.driver, MIB.OID_DOORS_2_OPEN); err != nil { return nil, err - } else if open, ok := v.(bool); !ok { - return nil, fmt.Errorf("invalid controller door 2 open (%T)", v) } else { response.Door2State = open } - if v, err := ut0311.driver.Get(MIB.OID_DOORS_2_BUTTON); err != nil { + if pressed, err := driver.Get[bool](ut0311.driver, MIB.OID_DOORS_2_BUTTON); err != nil { return nil, err - } else if pressed, ok := v.(bool); !ok { - return nil, fmt.Errorf("invalid controller door 2 button (%T)", v) } else { response.Door2Button = pressed } // ... door 3 - if v, err := ut0311.driver.Get(MIB.OID_DOORS_3_UNLOCKED); err != nil { + if unlocked, err := driver.Get[bool](ut0311.driver, MIB.OID_DOORS_3_UNLOCKED); err != nil { return nil, err - } else if unlocked, ok := v.(bool); !ok { - return nil, fmt.Errorf("invalid controller door 3 unlocked (%T)", v) } else if unlocked { response.RelayState |= 0x04 } - if v, err := ut0311.driver.Get(MIB.OID_DOORS_3_OPEN); err != nil { + if open, err := driver.Get[bool](ut0311.driver, MIB.OID_DOORS_3_OPEN); err != nil { return nil, err - } else if open, ok := v.(bool); !ok { - return nil, fmt.Errorf("invalid controller door 3 open (%T)", v) } else { response.Door3State = open } - if v, err := ut0311.driver.Get(MIB.OID_DOORS_3_BUTTON); err != nil { + if pressed, err := driver.Get[bool](ut0311.driver, MIB.OID_DOORS_3_BUTTON); err != nil { return nil, err - } else if pressed, ok := v.(bool); !ok { - return nil, fmt.Errorf("invalid controller door 3 button (%T)", v) } else { response.Door3Button = pressed } // ... door 4 - if v, err := ut0311.driver.Get(MIB.OID_DOORS_4_UNLOCKED); err != nil { + if unlocked, err := driver.Get[bool](ut0311.driver, MIB.OID_DOORS_4_UNLOCKED); err != nil { return nil, err - } else if unlocked, ok := v.(bool); !ok { - return nil, fmt.Errorf("invalid controller door 4 unlocked (%T)", v) } else if unlocked { response.RelayState |= 0x08 } - if v, err := ut0311.driver.Get(MIB.OID_DOORS_4_OPEN); err != nil { + if open, err := driver.Get[bool](ut0311.driver, MIB.OID_DOORS_4_OPEN); err != nil { return nil, err - } else if open, ok := v.(bool); !ok { - return nil, fmt.Errorf("invalid controller door 4 open (%T)", v) } else { response.Door4State = open } - if v, err := ut0311.driver.Get(MIB.OID_DOORS_4_BUTTON); err != nil { + if pressed, err := driver.Get[bool](ut0311.driver, MIB.OID_DOORS_4_BUTTON); err != nil { return nil, err - } else if pressed, ok := v.(bool); !ok { - return nil, fmt.Errorf("invalid controller door 4 button (%T)", v) } else { response.Door4Button = pressed } diff --git a/Rev.0/emulator/go/UT0311/get-time.go b/Rev.0/emulator/go/UT0311/get-time.go index 6157365..0ad1523 100644 --- a/Rev.0/emulator/go/UT0311/get-time.go +++ b/Rev.0/emulator/go/UT0311/get-time.go @@ -1,34 +1,26 @@ package UT0311 import ( - "fmt" - "github.com/uhppoted/uhppote-core/messages" "github.com/uhppoted/uhppote-core/types" "emulator/MIB" + "emulator/driver" ) func (ut0311 *UT0311) getTime(rq *messages.GetTimeRequest) (any, error) { - if id, err := ut0311.getID(); err != nil { + if id, err := driver.Get[uint32](ut0311.driver, MIB.OID_CONTROLLER_ID); err != nil { return nil, err } else if id == 0 || (rq.SerialNumber != 0 && uint32(rq.SerialNumber) != id) { return nil, nil + } else if datetime, err := driver.Get[types.DateTime](ut0311.driver, MIB.OID_CONTROLLER_DATETIME); err != nil { + return nil, err } else { - - if v, err := ut0311.driver.Get(MIB.OID_CONTROLLER_DATETIME); err != nil { - return nil, err - } else if s, ok := v.(string); !ok { - return nil, fmt.Errorf("invalid controller date/time (%v)", v) - } else if datetime, err := types.ParseDateTime(s); err != nil { - return nil, err - } else { - response := messages.GetTimeResponse{ - SerialNumber: types.SerialNumber(id), - DateTime: datetime, - } - - return response, nil + response := messages.GetTimeResponse{ + SerialNumber: types.SerialNumber(id), + DateTime: datetime, } + + return response, nil } } diff --git a/Rev.0/emulator/go/UT0311/set-listener.go b/Rev.0/emulator/go/UT0311/set-listener.go index 53ce864..248949b 100644 --- a/Rev.0/emulator/go/UT0311/set-listener.go +++ b/Rev.0/emulator/go/UT0311/set-listener.go @@ -6,10 +6,11 @@ import ( "emulator/MIB" "emulator/config" + "emulator/driver" ) func (ut0311 *UT0311) setListener(rq *messages.SetListenerRequest) (any, error) { - if id, err := ut0311.getID(); err != nil { + if id, err := driver.Get[uint32](ut0311.driver, MIB.OID_CONTROLLER_ID); err != nil { return nil, err } else if id == 0 || (rq.SerialNumber != 0 && uint32(rq.SerialNumber) != id) { return nil, nil diff --git a/Rev.0/emulator/go/UT0311/set-time.go b/Rev.0/emulator/go/UT0311/set-time.go index 80171ea..be5a44f 100644 --- a/Rev.0/emulator/go/UT0311/set-time.go +++ b/Rev.0/emulator/go/UT0311/set-time.go @@ -7,10 +7,11 @@ import ( "github.com/uhppoted/uhppote-core/types" "emulator/MIB" + "emulator/driver" ) func (ut0311 *UT0311) setTime(rq *messages.SetTimeRequest) (any, error) { - if id, err := ut0311.getID(); err != nil { + if id, err := driver.Get[uint32](ut0311.driver, MIB.OID_CONTROLLER_ID); err != nil { return nil, err } else if id == 0 || (rq.SerialNumber != 0 && uint32(rq.SerialNumber) != id) { return nil, nil diff --git a/Rev.0/emulator/go/driver/driver.go b/Rev.0/emulator/go/driver/driver.go index 5c6b44d..b846f17 100644 --- a/Rev.0/emulator/go/driver/driver.go +++ b/Rev.0/emulator/go/driver/driver.go @@ -1,10 +1,73 @@ package driver import ( + "fmt" + + "github.com/uhppoted/uhppote-core/types" + "emulator/MIB" ) type Driver interface { - Get(oid MIB.OID) (any, error) Set(oid MIB.OID, value any) (any, error) + + GetUint8(oid MIB.OID) (uint8, error) + GetUint16(oid MIB.OID) (uint16, error) + GetUint32(oid MIB.OID) (uint32, error) + GetBool(oid MIB.OID) (bool, error) + GetString(oid MIB.OID) (string, error) +} + +func Get[T any](driver Driver, oid MIB.OID) (T, error) { + var zero T + + switch any(zero).(type) { + case uint8: + if v, err := driver.GetUint8(oid); err != nil { + return zero, err + } else { + return any(v).(T), nil + } + + case uint16: + if v, err := driver.GetUint16(oid); err != nil { + return zero, err + } else { + return any(v).(T), nil + } + + case uint32: + if v, err := driver.GetUint32(oid); err != nil { + return zero, err + } else { + return any(v).(T), nil + } + + case bool: + if v, err := driver.GetBool(oid); err != nil { + return zero, err + } else { + return any(v).(T), nil + } + + case types.Date: + if v, err := driver.GetString(oid); err != nil { + return zero, err + } else if date, err := types.ParseDate(v); err != nil { + return zero, err + } else { + return any(date).(T), nil + } + + case types.DateTime: + if v, err := driver.GetString(oid); err != nil { + return zero, err + } else if datetime, err := types.ParseDateTime(v); err != nil { + return zero, err + } else { + return any(datetime).(T), nil + } + } + + return zero, fmt.Errorf("unknown type %T", zero) } diff --git a/Rev.0/emulator/go/driver/rpc/rpcd.go b/Rev.0/emulator/go/driver/rpc/rpcd.go index 785cb0c..5d22fc9 100644 --- a/Rev.0/emulator/go/driver/rpc/rpcd.go +++ b/Rev.0/emulator/go/driver/rpc/rpcd.go @@ -16,7 +16,7 @@ type KV struct { Value any } -func (r RPC) Get(oid MIB.OID) (any, error) { +func (r RPC) get(oid MIB.OID) (any, error) { debugf("get %v", oid) var key = fmt.Sprintf("%v", oid) @@ -31,6 +31,56 @@ func (r RPC) Get(oid MIB.OID) (any, error) { } } +func (r RPC) GetUint8(oid MIB.OID) (uint8, error) { + if v, err := r.get(oid); err != nil { + return 0, err + } else if u8, ok := v.(uint8); !ok { + return 0, fmt.Errorf("invalid uint8 value (%T)", v) + } else { + return u8, nil + } +} + +func (r RPC) GetUint16(oid MIB.OID) (uint16, error) { + if v, err := r.get(oid); err != nil { + return 0, err + } else if u16, ok := v.(uint16); !ok { + return 0, fmt.Errorf("invalid uint16 value (%T)", v) + } else { + return u16, nil + } +} + +func (r RPC) GetUint32(oid MIB.OID) (uint32, error) { + if v, err := r.get(oid); err != nil { + return 0, err + } else if u32, ok := v.(uint32); !ok { + return 0, fmt.Errorf("invalid uint32 value (%T)", v) + } else { + return u32, nil + } +} + +func (r RPC) GetBool(oid MIB.OID) (bool, error) { + if v, err := r.get(oid); err != nil { + return false, err + } else if b, ok := v.(bool); !ok { + return false, fmt.Errorf("invalid boolean value (%T)", v) + } else { + return b, nil + } +} + +func (r RPC) GetString(oid MIB.OID) (string, error) { + if v, err := r.get(oid); err != nil { + return "", err + } else if s, ok := v.(string); !ok { + return "", fmt.Errorf("invalid string value (%T)", v) + } else { + return s, nil + } +} + func (r RPC) Set(oid MIB.OID, value any) (any, error) { debugf("get %v %v", oid, value) diff --git a/Rev.0/emulator/go/driver/stub/stub.go b/Rev.0/emulator/go/driver/stub/stub.go index 680db0f..b99ecbf 100644 --- a/Rev.0/emulator/go/driver/stub/stub.go +++ b/Rev.0/emulator/go/driver/stub/stub.go @@ -16,7 +16,7 @@ type KV struct { Value any } -func (s Stub) Get(oid MIB.OID) (any, error) { +func (s Stub) get(oid MIB.OID) (any, error) { debugf("get %v", oid) key := fmt.Sprintf("%v", oid) @@ -44,6 +44,56 @@ func (s Stub) Get(oid MIB.OID) (any, error) { return nil, fmt.Errorf("unknown OID %v", oid) } +func (s Stub) GetUint8(oid MIB.OID) (uint8, error) { + if v, err := s.get(oid); err != nil { + return 0, err + } else if u8, ok := v.(uint8); !ok { + return 0, fmt.Errorf("invalid uint8 value (%T)", v) + } else { + return u8, nil + } +} + +func (s Stub) GetUint16(oid MIB.OID) (uint16, error) { + if v, err := s.get(oid); err != nil { + return 0, err + } else if u16, ok := v.(uint16); !ok { + return 0, fmt.Errorf("invalid uint16 value (%T)", v) + } else { + return u16, nil + } +} + +func (s Stub) GetUint32(oid MIB.OID) (uint32, error) { + if v, err := s.get(oid); err != nil { + return 0, err + } else if u32, ok := v.(uint32); !ok { + return 0, fmt.Errorf("invalid uint32 value (%T)", v) + } else { + return u32, nil + } +} + +func (s Stub) GetBool(oid MIB.OID) (bool, error) { + if v, err := s.get(oid); err != nil { + return false, err + } else if b, ok := v.(bool); !ok { + return false, fmt.Errorf("invalid value - expected 'bool', got %T", v) + } else { + return b, nil + } +} + +func (s Stub) GetString(oid MIB.OID) (string, error) { + if v, err := s.get(oid); err != nil { + return "", err + } else if s, ok := v.(string); !ok { + return "", fmt.Errorf("invalid string value (%T)", v) + } else { + return s, nil + } +} + func (s Stub) Set(oid MIB.OID, value any) (any, error) { debugf("set %v %v", oid, value)