diff --git a/simulator/UT0311L04/UTC0311L04.go b/simulator/UT0311L04/UTC0311L04.go index 72f5330..d86dfde 100644 --- a/simulator/UT0311L04/UTC0311L04.go +++ b/simulator/UT0311L04/UTC0311L04.go @@ -30,7 +30,7 @@ type UT0311L04 struct { Gateway net.IP `json:"gateway"` MacAddress types.MacAddress `json:"MAC"` Version types.Version `json:"version"` - Released *ReleaseDate `json:"released"` + Released types.Date `json:"released,omitempty"` TimeOffset entities.Offset `json:"offset"` Doors entities.Doors `json:"doors"` Keypads entities.Keypads `json:"keypads"` @@ -47,6 +47,8 @@ type UT0311L04 struct { Events entities.EventList `json:"events"` } +var RELEASE_DATE = types.MustParseDate("2020-01-01") + var onEvent = func(dest netip.AddrPort, event any) { } @@ -78,7 +80,7 @@ func NewUT0311L04(deviceID uint32, dir string, compressed bool) *UT0311L04 { Gateway: net.IPv4(0, 0, 0, 0), MacAddress: types.MacAddress(mac), Version: 0x0892, - Released: DefaultReleaseDate(), + Released: RELEASE_DATE, Doors: entities.MakeDoors(), Keypads: entities.MakeKeypads(), TimeProfiles: entities.TimeProfiles{}, @@ -277,98 +279,12 @@ func loadGZ(filepath string) (*UT0311L04, error) { return nil, err } - buffer, err := io.ReadAll(zr) + bytes, err := io.ReadAll(zr) if err != nil { return nil, err } - object := struct { - SerialNumber types.SerialNumber `json:"serial-number"` - IpAddress net.IP `json:"address"` - SubnetMask net.IP `json:"subnet"` - Gateway net.IP `json:"gateway"` - MacAddress types.MacAddress `json:"MAC"` - Version types.Version `json:"version"` - Released *ReleaseDate `json:"released"` - TimeOffset entities.Offset `json:"offset"` - Doors entities.Doors `json:"doors"` - Keypads entities.Keypads `json:"keypads"` - Listener json.RawMessage `json:"listener"` - RecordSpecialEvents bool `json:"record-special-events"` - PCControl bool `json:"pc-control"` - SystemError uint8 `json:"system-error"` - SequenceId uint32 `json:"sequence-id"` - SpecialInfo uint8 `json:"special-info"` - InputState uint8 `json:"input-state"` - TimeProfiles entities.TimeProfiles `json:"time-profiles,omitempty"` - TaskList json.RawMessage `json:"tasklist,omitempty"` - Cards entities.CardList `json:"cards"` - Events entities.EventList `json:"events"` - }{ - Released: DefaultReleaseDate(), - Doors: entities.MakeDoors(), - Keypads: entities.MakeKeypads(), - TimeProfiles: entities.TimeProfiles{}, - } - - if err = json.Unmarshal(buffer, &object); err != nil { - return nil, err - } - - // ... unmarshal event listener variants - var listener = netip.AddrPort{} - var addrPort netip.AddrPort - var udpAddr net.UDPAddr - - if err := json.Unmarshal(object.Listener, &addrPort); err == nil { - listener = addrPort - } else if err := json.Unmarshal(object.Listener, &udpAddr); err == nil { - listener = udpAddr.AddrPort() - } - - // ... unmarshal tasklist - tasklist := struct { - Tasks []types.Task `json:"tasks"` - }{ - Tasks: []types.Task{}, - } - - if err := json.Unmarshal(object.TaskList, &tasklist); err != nil { - warnf(object.SerialNumber, "error loading tasklist (%v)", err) - } - - // ... initialise simulator - simulator := UT0311L04{ - file: filepath, - compressed: true, - touched: time.Now(), - - SerialNumber: object.SerialNumber, - IpAddress: object.IpAddress, - SubnetMask: object.SubnetMask, - Gateway: object.Gateway, - MacAddress: object.MacAddress, - Version: object.Version, - Released: object.Released, - TimeOffset: object.TimeOffset, - Doors: object.Doors, - Keypads: object.Keypads, - Listener: listener, - RecordSpecialEvents: object.RecordSpecialEvents, - PCControl: object.PCControl, - SystemError: object.SystemError, - SequenceId: object.SequenceId, - SpecialInfo: object.SpecialInfo, - InputState: object.InputState, - TimeProfiles: object.TimeProfiles, - TaskList: entities.TaskList{ - Tasks: tasklist.Tasks, - }, - Cards: object.Cards, - Events: object.Events, - } - - return &simulator, nil + return unmarshal(bytes, filepath, true) } func load(filepath string) (*UT0311L04, error) { @@ -377,6 +293,10 @@ func load(filepath string) (*UT0311L04, error) { return nil, err } + return unmarshal(bytes, filepath, false) +} + +func unmarshal(bytes []byte, filepath string, compressed bool) (*UT0311L04, error) { object := struct { SerialNumber types.SerialNumber `json:"serial-number"` IpAddress net.IP `json:"address"` @@ -384,7 +304,7 @@ func load(filepath string) (*UT0311L04, error) { Gateway net.IP `json:"gateway"` MacAddress types.MacAddress `json:"MAC"` Version types.Version `json:"version"` - Released *ReleaseDate `json:"released"` + Released types.Date `json:"released,omitempty"` TimeOffset entities.Offset `json:"offset"` Doors entities.Doors `json:"doors"` Keypads entities.Keypads `json:"keypads"` @@ -400,13 +320,13 @@ func load(filepath string) (*UT0311L04, error) { Cards entities.CardList `json:"cards"` Events entities.EventList `json:"events"` }{ - Released: DefaultReleaseDate(), + Released: RELEASE_DATE, Doors: entities.MakeDoors(), Keypads: entities.MakeKeypads(), TimeProfiles: entities.TimeProfiles{}, } - if err = json.Unmarshal(bytes, &object); err != nil { + if err := json.Unmarshal(bytes, &object); err != nil { return nil, err } @@ -435,7 +355,7 @@ func load(filepath string) (*UT0311L04, error) { // ... initialise simulator simulator := UT0311L04{ file: filepath, - compressed: false, + compressed: compressed, touched: time.Now(), SerialNumber: object.SerialNumber, diff --git a/simulator/UT0311L04/UTC0311L04_test.go b/simulator/UT0311L04/UTC0311L04_test.go index 8246a25..3c64645 100644 --- a/simulator/UT0311L04/UTC0311L04_test.go +++ b/simulator/UT0311L04/UTC0311L04_test.go @@ -20,7 +20,7 @@ func TestNewUT0311L04(t *testing.T) { Gateway: net.IPv4(0, 0, 0, 0), // MacAddress: types.MacAddress(mac), Version: 0x0892, - Released: DefaultReleaseDate(), + Released: RELEASE_DATE, Doors: entities.MakeDoors(), TimeProfiles: entities.TimeProfiles{}, TaskList: entities.TaskList{}, @@ -66,302 +66,136 @@ func TestNewUT0311L04(t *testing.T) { } } -// TODO: ignore date/time fields -// func TestHandleGetStatus(t *testing.T) { -// swipeDateTime, _ := types.DateTimeFromString("2019-08-01 12:34:56") -// request := messages.GetStatusRequest{ -// SerialNumber: 12345, -// } -// -// response := messages.GetStatusResponse{ -// SerialNumber: 12345, -// EventIndex: 3, -// SwipeRecord: 0x00, -// Granted: false, -// Door: 3, -// DoorOpened: false, -// UserId: 1234567890, -// SwipeDateTime: *swipeDateTime, -// SwipeReason: 0x05, -// Door1State: false, -// Door2State: false, -// Door3State: false, -// Door4State: false, -// Door1Button: false, -// Door2Button: false, -// Door3Button: false, -// Door4Button: false, -// SystemState: 0x00, -// // SystemDate types.SystemDate `uhppote:"offset:51"` -// // SystemTime types.SystemTime `uhppote:"offset:37"` -// PacketNumber: 0, -// Backup: 0, -// SpecialMessage: 0, -// Battery: 0, -// FireAlarm: 0, -// } -// -// testHandle(&request, &response, t) -// } - -func TestHandleOpenDoor(t *testing.T) { - request := messages.OpenDoorRequest{ - SerialNumber: 12345, - Door: 3, - } - - response := messages.OpenDoorResponse{ - SerialNumber: 12345, - Succeeded: true, - } - - testHandle(&request, &response, t) -} - -func TestHandlePutCardRequest(t *testing.T) { - request := messages.PutCardRequest{ - SerialNumber: 12345, - CardNumber: 192837465, - From: types.MustParseDate("2019-01-01"), - To: types.MustParseDate("2019-12-31"), - Door1: 1, - Door2: 0, - Door3: 1, - Door4: 0, - } - - response := messages.PutCardResponse{ - SerialNumber: 12345, - Succeeded: true, - } - - testHandle(&request, &response, t) -} - -func TestHandleDeleteCardRequest(t *testing.T) { - request := messages.DeleteCardRequest{ - SerialNumber: 12345, - CardNumber: 192837465, - } - - response := messages.DeleteCardResponse{ - SerialNumber: 12345, - Succeeded: true, - } - - testHandle(&request, &response, t) -} - -func TestHandleDeleteCardsRequest(t *testing.T) { - request := messages.DeleteCardsRequest{ - SerialNumber: 12345, - MagicWord: 0x55aaaa55, - } - - response := messages.DeleteCardsResponse{ - SerialNumber: 12345, - Succeeded: true, - } - - testHandle(&request, &response, t) -} - -func TestHandleGetCardsRequest(t *testing.T) { - request := messages.GetCardsRequest{ - SerialNumber: 12345, - } - - response := messages.GetCardsResponse{ - SerialNumber: 12345, - Records: 3, - } - - testHandle(&request, &response, t) -} - -func TestHandleGetCardById(t *testing.T) { - request := messages.GetCardByIDRequest{ - SerialNumber: 12345, - CardNumber: 192837465, - } - - response := messages.GetCardByIDResponse{ - SerialNumber: 12345, - CardNumber: 192837465, - From: types.MustParseDate("2019-01-01"), - To: types.MustParseDate("2019-12-31"), - Door1: 1, - Door2: 0, - Door3: 0, - Door4: 1, - } - - testHandle(&request, &response, t) -} - -func TestHandleGetCardByIndex(t *testing.T) { - request := messages.GetCardByIndexRequest{ - SerialNumber: 12345, - Index: 2, - } - - response := messages.GetCardByIndexResponse{ - SerialNumber: 12345, - CardNumber: 192837465, - From: types.MustParseDate("2019-01-01"), - To: types.MustParseDate("2019-12-31"), - Door1: 1, - Door2: 0, - Door3: 0, - Door4: 1, - } - - testHandle(&request, &response, t) -} - -func TestHandleSetDoorControlState(t *testing.T) { - request := messages.SetDoorControlStateRequest{ - SerialNumber: 12345, - Door: 2, - ControlState: 3, - Delay: 7, - } - - response := messages.SetDoorControlStateResponse{ - SerialNumber: 12345, - Door: 2, - ControlState: 3, - Delay: 7, - } - - testHandle(&request, &response, t) -} - -func TestHandleGetDoorControlState(t *testing.T) { - request := messages.GetDoorControlStateRequest{ - SerialNumber: 12345, - Door: 2, - } - - response := messages.GetDoorControlStateResponse{ - SerialNumber: 12345, - Door: 2, - ControlState: 2, - Delay: 22, - } - - testHandle(&request, &response, t) -} - -func TestHandleSetListener(t *testing.T) { - request := messages.SetListenerRequest{ - SerialNumber: 12345, - AddrPort: netip.MustParseAddrPort("10.0.0.1:43210"), - } - - response := messages.SetListenerResponse{ - SerialNumber: 12345, - Succeeded: true, - } - - testHandle(&request, &response, t) -} +func TestUT0311L04Unmarshal(t *testing.T) { + MAC, _ := net.ParseMAC("00:12:23:34:45:56") + doors := entities.MakeDoors() -func TestHandleGetListener(t *testing.T) { - request := messages.GetListenerRequest{ - SerialNumber: 12345, - } + expected := UT0311L04{ + file: "test.json", + compressed: false, - response := messages.GetListenerResponse{ - SerialNumber: 12345, - AddrPort: netip.MustParseAddrPort("10.0.0.10:43210"), + SerialNumber: types.SerialNumber(405419896), + IpAddress: net.IPv4(0, 0, 0, 0), + SubnetMask: net.IPv4(255, 255, 255, 0), + Gateway: net.IPv4(0, 0, 0, 0), + MacAddress: types.MacAddress(MAC), + Version: 0x0892, + Released: types.MustParseDate("2018-11-05"), + Listener: netip.MustParseAddrPort("192.168.1.100:60001"), + Doors: doors, + Keypads: map[uint8]entities.Keypad{1: 3, 2: 3, 3: 0, 4: 3}, + TimeProfiles: entities.TimeProfiles{}, + TaskList: entities.TaskList{}, + Events: entities.NewEventList(), } - testHandle(&request, &response, t) -} - -// TODO: deferred pending some way to compare Date field -// func TestHandleFindDevices(t *testing.T) { -// MAC, _ := net.ParseMAC("00:66:19:39:55:2d") -// now := types.Date(time.Now().UTC()) -// -// request := messages.FindDevicesRequest{} -// -// response := messages.FindDevicesResponse{ -// SerialNumber: 12345, -// IpAddress: net.IPv4(10, 0, 0, 100), -// SubnetMask: net.IPv4(255, 255, 255, 0), -// Gateway: net.IPv4(10, 0, 0, 1), -// MacAddress: types.MacAddress(MAC), -// Version: 9876, -// Date: now, -// } -// -// testHandle(&request, &response, t) -// } - -func TestHandleSetAddress(t *testing.T) { - request := messages.SetAddressRequest{ - SerialNumber: 12345, - Address: net.IPv4(10, 0, 0, 100), - Mask: net.IPv4(255, 255, 255, 0), - Gateway: net.IPv4(10, 0, 0, 1), - MagicWord: 0x55aaaa55, - } + JSON := ` + { + "serial-number": 405419896, + "address": "0.0.0.0", + "subnet": "255.255.255.0", + "gateway": "0.0.0.0", + "MAC": "00:12:23:34:45:56", + "version": "0892", + "released": "2018-11-05", + "offset": "-7h0m0.666172s", + "doors": { + "1": { "control": 3, "delay": "5s", "passcodes": [ 0, 0, 0, 0 ] }, + "2": { "control": 3, "delay": "5s", "passcodes": [ 0, 0, 0, 0 ] }, + "3": { "control": 3, "delay": "5s", "passcodes": [ 0, 0, 0, 0 ] }, + "4": { "control": 3, "delay": "5s", "passcodes": [ 0, 0, 0, 0 ] }, + "interlock": 4 + }, + "keypads": { "1": 3, "2": 3, "3": 0, "4": 3 }, + "listener": "192.168.1.100:60001", + "record-special-events": true, + "pc-control": true, + "system-error": 0, + "sequence-id": 0, + "special-info": 0, + "input-state": 0, + "time-profiles": { + "100": { + "id": 100, + "start-date": "2023-04-01", + "end-date": "2023-12-31", + "weekdays": "Monday,Wednesday,Friday", + "segments": [ + { "start": "08:30", "end": "11:30" }, + { "start": "00:00", "end": "00:00" }, + { "start": "13:45", "end": "17:00" } + ] + } + }, + "tasklist": { + "tasks": [ + { "task": "LOCK DOOR", "door": 4, "start-date": "2024-01-01", "end-date": "2024-12-31", "weekdays": "Monday,Friday", "start": "08:30" } + ] + }, + "cards": [], + "events": { + "size": 256, + "chunk": 8, + "index": 0, + "events": [ + { "index": 1, "type": 1, "granted": false, "door": 3, "direction": 1, "card": 10058400, "timestamp": "2024-05-08 10:50:53", "reason": 18 } + ] + } + } + ` + + if controller, err := unmarshal([]byte(JSON), "test.json", false); err != nil { + t.Fatalf("error unmarshalling UT0311L04 (%v)", err) + } else if controller == nil { + t.Fatalf("error unmarshalling UT0311L04, expected UT0311L04{}, got %v", controller) + } else { + expected.touched = controller.touched + + if controller.SerialNumber != expected.SerialNumber { + t.Errorf("incorrect serial number - expected:%v, got:%v", expected.SerialNumber, controller.SerialNumber) + } - testHandle(&request, nil, t) -} + if !reflect.DeepEqual(controller.IpAddress, expected.IpAddress) { + t.Errorf("incorrect IP address - expected:%v, got:%v", expected.IpAddress, controller.IpAddress) + } -func TestHandleGetEvent(t *testing.T) { - datetime, _ := time.ParseInLocation("2006-01-02 15:04:05", "2019-08-01 12:34:56", time.Local) - timestamp := types.DateTime(datetime) + if !reflect.DeepEqual(controller.SubnetMask, expected.SubnetMask) { + t.Errorf("incorrect netmask - expected:%v, got:%v", expected.SubnetMask, controller.SubnetMask) + } - request := messages.GetEventRequest{ - SerialNumber: 12345, - Index: 2, - } + if controller.Version != expected.Version { + t.Errorf("incorrect version - expected:%v, got:%v", expected.Version, controller.Version) + } - response := messages.GetEventResponse{ - SerialNumber: 12345, - Index: 2, - Type: 0x06, - Granted: true, - Door: 4, - Direction: 0x01, - CardNumber: 555444321, - Timestamp: timestamp, - Reason: 9, + if !reflect.DeepEqual(controller.Released, expected.Released) { + t.Errorf("incorrect firmware date - expected:%v, got:%v", expected.Released, controller.Released) + } } - - testHandle(&request, &response, t) } -func TestHandleSetEventIndex(t *testing.T) { - request := messages.SetEventIndexRequest{ - SerialNumber: 12345, - Index: 7, - MagicWord: 0x55aaaa55, +func TestUT0311L04UnmarshalDefaultValues(t *testing.T) { + expected := UT0311L04{ + file: "test.json", + compressed: false, + Released: RELEASE_DATE, } - response := messages.SetEventIndexResponse{ - SerialNumber: 12345, - Changed: true, + JSON := ` + { } + ` - testHandle(&request, &response, t) -} - -func TestHandleGetEventIndex(t *testing.T) { - request := messages.GetEventIndexRequest{ - SerialNumber: 12345, - } + if controller, err := unmarshal([]byte(JSON), "test.json", false); err != nil { + t.Fatalf("error unmarshalling UT0311L04 (%v)", err) + } else if controller == nil { + t.Fatalf("error unmarshalling UT0311L04, expected UT0311L04{}, got %v", controller) + } else { + expected.touched = controller.touched - response := messages.GetEventIndexResponse{ - SerialNumber: 12345, - Index: 123, + if !reflect.DeepEqual(controller.Released, expected.Released) { + t.Errorf("incorrect firmware date - expected:%v, got:%v", expected.Released, controller.Released) + } } - - testHandle(&request, &response, t) } func testHandle(request messages.Request, expected messages.Response, t *testing.T) { diff --git a/simulator/UT0311L04/delete_card_test.go b/simulator/UT0311L04/delete_card_test.go new file mode 100644 index 0000000..09220b5 --- /dev/null +++ b/simulator/UT0311L04/delete_card_test.go @@ -0,0 +1,21 @@ +package UT0311L04 + +import ( + "testing" + + "github.com/uhppoted/uhppote-core/messages" +) + +func TestHandleDeleteCardRequest(t *testing.T) { + request := messages.DeleteCardRequest{ + SerialNumber: 12345, + CardNumber: 192837465, + } + + response := messages.DeleteCardResponse{ + SerialNumber: 12345, + Succeeded: true, + } + + testHandle(&request, &response, t) +} diff --git a/simulator/UT0311L04/delete_cards_test.go b/simulator/UT0311L04/delete_cards_test.go new file mode 100644 index 0000000..7c4834b --- /dev/null +++ b/simulator/UT0311L04/delete_cards_test.go @@ -0,0 +1,21 @@ +package UT0311L04 + +import ( + "testing" + + "github.com/uhppoted/uhppote-core/messages" +) + +func TestHandleDeleteCardsRequest(t *testing.T) { + request := messages.DeleteCardsRequest{ + SerialNumber: 12345, + MagicWord: 0x55aaaa55, + } + + response := messages.DeleteCardsResponse{ + SerialNumber: 12345, + Succeeded: true, + } + + testHandle(&request, &response, t) +} diff --git a/simulator/UT0311L04/get_card_test.go b/simulator/UT0311L04/get_card_test.go new file mode 100644 index 0000000..4c79593 --- /dev/null +++ b/simulator/UT0311L04/get_card_test.go @@ -0,0 +1,48 @@ +package UT0311L04 + +import ( + "testing" + + "github.com/uhppoted/uhppote-core/messages" + "github.com/uhppoted/uhppote-core/types" +) + +func TestHandleGetCardById(t *testing.T) { + request := messages.GetCardByIDRequest{ + SerialNumber: 12345, + CardNumber: 192837465, + } + + response := messages.GetCardByIDResponse{ + SerialNumber: 12345, + CardNumber: 192837465, + From: types.MustParseDate("2019-01-01"), + To: types.MustParseDate("2019-12-31"), + Door1: 1, + Door2: 0, + Door3: 0, + Door4: 1, + } + + testHandle(&request, &response, t) +} + +func TestHandleGetCardByIndex(t *testing.T) { + request := messages.GetCardByIndexRequest{ + SerialNumber: 12345, + Index: 2, + } + + response := messages.GetCardByIndexResponse{ + SerialNumber: 12345, + CardNumber: 192837465, + From: types.MustParseDate("2019-01-01"), + To: types.MustParseDate("2019-12-31"), + Door1: 1, + Door2: 0, + Door3: 0, + Door4: 1, + } + + testHandle(&request, &response, t) +} diff --git a/simulator/UT0311L04/get_cards_test.go b/simulator/UT0311L04/get_cards_test.go new file mode 100644 index 0000000..a1516e8 --- /dev/null +++ b/simulator/UT0311L04/get_cards_test.go @@ -0,0 +1,20 @@ +package UT0311L04 + +import ( + "testing" + + "github.com/uhppoted/uhppote-core/messages" +) + +func TestHandleGetCardsRequest(t *testing.T) { + request := messages.GetCardsRequest{ + SerialNumber: 12345, + } + + response := messages.GetCardsResponse{ + SerialNumber: 12345, + Records: 3, + } + + testHandle(&request, &response, t) +} diff --git a/simulator/UT0311L04/get_device.go b/simulator/UT0311L04/get_device.go index 9fd185a..cb0d538 100644 --- a/simulator/UT0311L04/get_device.go +++ b/simulator/UT0311L04/get_device.go @@ -17,7 +17,7 @@ func (s *UT0311L04) getDevice(request *messages.GetDeviceRequest) (*messages.Get Gateway: s.Gateway, MacAddress: s.MacAddress, Version: types.Version(s.Version), - Date: types.Date(*s.Released), + Date: s.Released, } return &response, nil diff --git a/simulator/UT0311L04/get_device_test.go b/simulator/UT0311L04/get_device_test.go index 9518d8d..907f1db 100644 --- a/simulator/UT0311L04/get_device_test.go +++ b/simulator/UT0311L04/get_device_test.go @@ -11,9 +11,28 @@ import ( "github.com/uhppoted/uhppote-simulator/entities" ) +// TODO: deferred pending some way to compare Date field +// func TestHandleFindDevices(t *testing.T) { +// MAC, _ := net.ParseMAC("00:66:19:39:55:2d") +// now := types.Date(time.Now().UTC()) +// +// request := messages.FindDevicesRequest{} +// +// response := messages.FindDevicesResponse{ +// SerialNumber: 12345, +// IpAddress: net.IPv4(10, 0, 0, 100), +// SubnetMask: net.IPv4(255, 255, 255, 0), +// Gateway: net.IPv4(10, 0, 0, 1), +// MacAddress: types.MacAddress(MAC), +// Version: 9876, +// Date: now, +// } +// +// testHandle(&request, &response, t) +// } + func TestGetDeviceWithMatchingAddress(t *testing.T) { MAC, _ := net.ParseMAC("00:66:19:39:55:2d") - released := types.MustParseDate("2020-12-05") listener := netip.MustParseAddrPort("10.0.0.10:43210") s := UT0311L04{ @@ -23,7 +42,7 @@ func TestGetDeviceWithMatchingAddress(t *testing.T) { Gateway: net.IPv4(10, 0, 0, 1), MacAddress: types.MacAddress(MAC), Version: 9876, - Released: (*ReleaseDate)(&released), + Released: types.MustParseDate("2020-12-05"), Listener: listener, Cards: entities.CardList{}, Events: entities.EventList{}, @@ -55,7 +74,6 @@ func TestGetDeviceWithMatchingAddress(t *testing.T) { func TestGetDeviceWithAddress0(t *testing.T) { MAC, _ := net.ParseMAC("00:66:19:39:55:2d") - released := types.MustParseDate("2020-12-05") listener := netip.MustParseAddrPort("10.0.0.10:43210") s := UT0311L04{ @@ -65,7 +83,7 @@ func TestGetDeviceWithAddress0(t *testing.T) { Gateway: net.IPv4(10, 0, 0, 1), MacAddress: types.MacAddress(MAC), Version: 9876, - Released: (*ReleaseDate)(&released), + Released: types.MustParseDate("2020-12-05"), Listener: listener, Cards: entities.CardList{}, Events: entities.EventList{}, @@ -97,7 +115,6 @@ func TestGetDeviceWithAddress0(t *testing.T) { func TestGetDeviceWithDifferentAddress(t *testing.T) { MAC, _ := net.ParseMAC("00:66:19:39:55:2d") - released := types.MustParseDate("2020-12-05") listener := netip.MustParseAddrPort("10.0.0.10:43210") s := UT0311L04{ @@ -107,7 +124,7 @@ func TestGetDeviceWithDifferentAddress(t *testing.T) { Gateway: net.IPv4(10, 0, 0, 1), MacAddress: types.MacAddress(MAC), Version: 9876, - Released: (*ReleaseDate)(&released), + Released: types.MustParseDate("2020-12-05"), Listener: listener, Cards: entities.CardList{}, Events: entities.EventList{}, diff --git a/simulator/UT0311L04/get_door_control_state_test.go b/simulator/UT0311L04/get_door_control_state_test.go new file mode 100644 index 0000000..163627a --- /dev/null +++ b/simulator/UT0311L04/get_door_control_state_test.go @@ -0,0 +1,23 @@ +package UT0311L04 + +import ( + "testing" + + "github.com/uhppoted/uhppote-core/messages" +) + +func TestHandleGetDoorControlState(t *testing.T) { + request := messages.GetDoorControlStateRequest{ + SerialNumber: 12345, + Door: 2, + } + + response := messages.GetDoorControlStateResponse{ + SerialNumber: 12345, + Door: 2, + ControlState: 2, + Delay: 22, + } + + testHandle(&request, &response, t) +} diff --git a/simulator/UT0311L04/get_event_test.go b/simulator/UT0311L04/get_event_test.go new file mode 100644 index 0000000..2f91aec --- /dev/null +++ b/simulator/UT0311L04/get_event_test.go @@ -0,0 +1,33 @@ +package UT0311L04 + +import ( + "testing" + "time" + + "github.com/uhppoted/uhppote-core/messages" + "github.com/uhppoted/uhppote-core/types" +) + +func TestHandleGetEvent(t *testing.T) { + datetime, _ := time.ParseInLocation("2006-01-02 15:04:05", "2019-08-01 12:34:56", time.Local) + timestamp := types.DateTime(datetime) + + request := messages.GetEventRequest{ + SerialNumber: 12345, + Index: 2, + } + + response := messages.GetEventResponse{ + SerialNumber: 12345, + Index: 2, + Type: 0x06, + Granted: true, + Door: 4, + Direction: 0x01, + CardNumber: 555444321, + Timestamp: timestamp, + Reason: 9, + } + + testHandle(&request, &response, t) +} diff --git a/simulator/UT0311L04/get_listener_test.go b/simulator/UT0311L04/get_listener_test.go new file mode 100644 index 0000000..55b12ca --- /dev/null +++ b/simulator/UT0311L04/get_listener_test.go @@ -0,0 +1,21 @@ +package UT0311L04 + +import ( + "net/netip" + "testing" + + "github.com/uhppoted/uhppote-core/messages" +) + +func TestHandleGetListener(t *testing.T) { + request := messages.GetListenerRequest{ + SerialNumber: 12345, + } + + response := messages.GetListenerResponse{ + SerialNumber: 12345, + AddrPort: netip.MustParseAddrPort("10.0.0.10:43210"), + } + + testHandle(&request, &response, t) +} diff --git a/simulator/UT0311L04/get_status_test.go b/simulator/UT0311L04/get_status_test.go new file mode 100644 index 0000000..3f24b4c --- /dev/null +++ b/simulator/UT0311L04/get_status_test.go @@ -0,0 +1,39 @@ +package UT0311L04 + +// TODO: ignore date/time fields +// func TestHandleGetStatus(t *testing.T) { +// swipeDateTime, _ := types.DateTimeFromString("2019-08-01 12:34:56") +// request := messages.GetStatusRequest{ +// SerialNumber: 12345, +// } +// +// response := messages.GetStatusResponse{ +// SerialNumber: 12345, +// EventIndex: 3, +// SwipeRecord: 0x00, +// Granted: false, +// Door: 3, +// DoorOpened: false, +// UserId: 1234567890, +// SwipeDateTime: *swipeDateTime, +// SwipeReason: 0x05, +// Door1State: false, +// Door2State: false, +// Door3State: false, +// Door4State: false, +// Door1Button: false, +// Door2Button: false, +// Door3Button: false, +// Door4Button: false, +// SystemState: 0x00, +// // SystemDate types.SystemDate `uhppote:"offset:51"` +// // SystemTime types.SystemTime `uhppote:"offset:37"` +// PacketNumber: 0, +// Backup: 0, +// SpecialMessage: 0, +// Battery: 0, +// FireAlarm: 0, +// } +// +// testHandle(&request, &response, t) +// } diff --git a/simulator/UT0311L04/open_door_test.go b/simulator/UT0311L04/open_door_test.go new file mode 100644 index 0000000..6f4c6ad --- /dev/null +++ b/simulator/UT0311L04/open_door_test.go @@ -0,0 +1,21 @@ +package UT0311L04 + +import ( + "testing" + + "github.com/uhppoted/uhppote-core/messages" +) + +func TestHandleOpenDoor(t *testing.T) { + request := messages.OpenDoorRequest{ + SerialNumber: 12345, + Door: 3, + } + + response := messages.OpenDoorResponse{ + SerialNumber: 12345, + Succeeded: true, + } + + testHandle(&request, &response, t) +} diff --git a/simulator/UT0311L04/put_card_test.go b/simulator/UT0311L04/put_card_test.go new file mode 100644 index 0000000..749ae6d --- /dev/null +++ b/simulator/UT0311L04/put_card_test.go @@ -0,0 +1,28 @@ +package UT0311L04 + +import ( + "testing" + + "github.com/uhppoted/uhppote-core/messages" + "github.com/uhppoted/uhppote-core/types" +) + +func TestHandlePutCardRequest(t *testing.T) { + request := messages.PutCardRequest{ + SerialNumber: 12345, + CardNumber: 192837465, + From: types.MustParseDate("2019-01-01"), + To: types.MustParseDate("2019-12-31"), + Door1: 1, + Door2: 0, + Door3: 1, + Door4: 0, + } + + response := messages.PutCardResponse{ + SerialNumber: 12345, + Succeeded: true, + } + + testHandle(&request, &response, t) +} diff --git a/simulator/UT0311L04/set_address_test.go b/simulator/UT0311L04/set_address_test.go new file mode 100644 index 0000000..4588bcc --- /dev/null +++ b/simulator/UT0311L04/set_address_test.go @@ -0,0 +1,20 @@ +package UT0311L04 + +import ( + "net" + "testing" + + "github.com/uhppoted/uhppote-core/messages" +) + +func TestHandleSetAddress(t *testing.T) { + request := messages.SetAddressRequest{ + SerialNumber: 12345, + Address: net.IPv4(10, 0, 0, 100), + Mask: net.IPv4(255, 255, 255, 0), + Gateway: net.IPv4(10, 0, 0, 1), + MagicWord: 0x55aaaa55, + } + + testHandle(&request, nil, t) +} diff --git a/simulator/UT0311L04/set_door_control_state_test.go b/simulator/UT0311L04/set_door_control_state_test.go new file mode 100644 index 0000000..3c729b1 --- /dev/null +++ b/simulator/UT0311L04/set_door_control_state_test.go @@ -0,0 +1,25 @@ +package UT0311L04 + +import ( + "testing" + + "github.com/uhppoted/uhppote-core/messages" +) + +func TestHandleSetDoorControlState(t *testing.T) { + request := messages.SetDoorControlStateRequest{ + SerialNumber: 12345, + Door: 2, + ControlState: 3, + Delay: 7, + } + + response := messages.SetDoorControlStateResponse{ + SerialNumber: 12345, + Door: 2, + ControlState: 3, + Delay: 7, + } + + testHandle(&request, &response, t) +} diff --git a/simulator/UT0311L04/set_event_index_test.go b/simulator/UT0311L04/set_event_index_test.go new file mode 100644 index 0000000..cc6ac8e --- /dev/null +++ b/simulator/UT0311L04/set_event_index_test.go @@ -0,0 +1,35 @@ +package UT0311L04 + +import ( + "testing" + + "github.com/uhppoted/uhppote-core/messages" +) + +func TestHandleSetEventIndex(t *testing.T) { + request := messages.SetEventIndexRequest{ + SerialNumber: 12345, + Index: 7, + MagicWord: 0x55aaaa55, + } + + response := messages.SetEventIndexResponse{ + SerialNumber: 12345, + Changed: true, + } + + testHandle(&request, &response, t) +} + +func TestHandleGetEventIndex(t *testing.T) { + request := messages.GetEventIndexRequest{ + SerialNumber: 12345, + } + + response := messages.GetEventIndexResponse{ + SerialNumber: 12345, + Index: 123, + } + + testHandle(&request, &response, t) +} diff --git a/simulator/UT0311L04/set_listener_test.go b/simulator/UT0311L04/set_listener_test.go new file mode 100644 index 0000000..8c693eb --- /dev/null +++ b/simulator/UT0311L04/set_listener_test.go @@ -0,0 +1,22 @@ +package UT0311L04 + +import ( + "net/netip" + "testing" + + "github.com/uhppoted/uhppote-core/messages" +) + +func TestHandleSetListener(t *testing.T) { + request := messages.SetListenerRequest{ + SerialNumber: 12345, + AddrPort: netip.MustParseAddrPort("10.0.0.1:43210"), + } + + response := messages.SetListenerResponse{ + SerialNumber: 12345, + Succeeded: true, + } + + testHandle(&request, &response, t) +} diff --git a/simulator/UT0311L04/types.go b/simulator/UT0311L04/types.go deleted file mode 100644 index 3e295e1..0000000 --- a/simulator/UT0311L04/types.go +++ /dev/null @@ -1,44 +0,0 @@ -package UT0311L04 - -import ( - "encoding/json" - "strings" - "time" -) - -// Firmware release date. -type ReleaseDate time.Time - -// Returns a fixed firmware release date to 2020-01-01 for default simulator initialisation. -func DefaultReleaseDate() *ReleaseDate { - date := ReleaseDate(time.Date(2020, time.January, 1, 0, 0, 0, 0, time.Local)) - - return &date -} - -// Custom JSON marshaller to format the release date as a string of the form 'YYYY-mm-dd'. -func (d ReleaseDate) MarshalJSON() ([]byte, error) { - return json.Marshal(time.Time(d).Format("2006-01-02")) -} - -// Custom JSON unmarshaller to parse a date string of the form 'YYYY-mm-dd'. -func (d *ReleaseDate) UnmarshalJSON(bytes []byte) error { - var s string - if err := json.Unmarshal(bytes, &s); err != nil { - return err - } - - if strings.TrimSpace(s) == "" { - *d = ReleaseDate(time.Date(2020, time.January, 1, 0, 0, 0, 0, time.Local)) - return nil - } - - date, err := time.ParseInLocation("2006-01-02", s, time.Local) - if err != nil { - return err - } - - *d = ReleaseDate(date) - - return nil -}