updated lock server
This commit is contained in:
parent
d9871e6a1c
commit
b002c80b01
@ -10,11 +10,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Build key encoding request command for the Assa Abloy lock server.
|
// Build key encoding request command for the Assa Abloy lock server.
|
||||||
func (lock *AssaLockServer) BuildCommand(encoderAddr, lockId string, checkIn, checkOut time.Time) error {
|
func (lock *AssaLockServer) BuildCommand(lockId string, checkIn, checkOut time.Time) error {
|
||||||
ci := checkIn.Format("200601021504")
|
ci := checkIn.Format("200601021504")
|
||||||
co := checkOut.Format("200601021504")
|
co := checkOut.Format("200601021504")
|
||||||
|
|
||||||
lock.command = fmt.Sprintf("CCA;EA%s;GR%s;CO%s;CI%s;AM1;\r\n", encoderAddr, lockId, co, ci)
|
lock.command = fmt.Sprintf("CCA;EA%s;GR%s;CO%s;CI%s;AM1;\r\n", lock.encoderAddr, lockId, co, ci)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,19 +19,33 @@ const (
|
|||||||
|
|
||||||
type (
|
type (
|
||||||
LockServer interface {
|
LockServer interface {
|
||||||
|
BuildCommand(lockId string, checkIn, checkOut time.Time) error
|
||||||
LockSequence(conn net.Conn) error
|
LockSequence(conn net.Conn) error
|
||||||
BuildCommand(encoderAddr, lockId string, checkIn, checkOut time.Time) error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AssaLockServer struct {
|
AssaLockServer struct {
|
||||||
|
encoderAddr string
|
||||||
command string
|
command string
|
||||||
}
|
}
|
||||||
|
|
||||||
OmniLockServer struct {
|
OmniLockServer struct {
|
||||||
|
encoderAddr string // Encoder address for the lock server
|
||||||
command []byte // Command to be sent to the lock server
|
command []byte // Command to be sent to the lock server
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func NewLockServer(lockType, encoderAddr string, fatalError func(error)) LockServer {
|
||||||
|
switch lockType {
|
||||||
|
case AssaAbloy:
|
||||||
|
return &AssaLockServer{encoderAddr: encoderAddr}
|
||||||
|
case Omnitec:
|
||||||
|
return &OmniLockServer{encoderAddr: encoderAddr}
|
||||||
|
default:
|
||||||
|
fatalError(fmt.Errorf("unsupported LockType: %s; must be 'assaabloy' or 'omnitec'", lockType))
|
||||||
|
return nil // This line will never be reached, but is needed to satisfy the compiler
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func InitializeServerConnection(LockserverUrl string) (net.Conn, error) {
|
func InitializeServerConnection(LockserverUrl string) (net.Conn, error) {
|
||||||
const funcName = "InitializeServerConnection"
|
const funcName = "InitializeServerConnection"
|
||||||
// Parse the URL to extract host and port
|
// Parse the URL to extract host and port
|
||||||
@ -46,7 +60,7 @@ func InitializeServerConnection(LockserverUrl string) (net.Conn, error) {
|
|||||||
// Establish a TCP connection to the Visionline server
|
// Establish a TCP connection to the Visionline server
|
||||||
conn, err := net.Dial("tcp", address)
|
conn, err := net.Dial("tcp", address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to connect to Visionline server: %v", err)
|
return nil, fmt.Errorf("failed to connect to lock server: %v", err)
|
||||||
}
|
}
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Build key encoding request command for the Omnitec lock server.
|
// Build key encoding request command for the Omnitec lock server.
|
||||||
func (lock *OmniLockServer) BuildCommand(encoderAddr, lockId string, checkIn, checkOut time.Time) error {
|
func (lock *OmniLockServer) BuildCommand(lockId string, checkIn, checkOut time.Time) error {
|
||||||
const funcName = "OmniLockServer.BuildCommand"
|
const funcName = "OmniLockServer.BuildCommand"
|
||||||
hostname, err := os.Hostname()
|
hostname, err := os.Hostname()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -36,7 +36,7 @@ func (lock *OmniLockServer) BuildCommand(encoderAddr, lockId string, checkIn, ch
|
|||||||
// Construct payload
|
// Construct payload
|
||||||
payload := fmt.Sprintf(
|
payload := fmt.Sprintf(
|
||||||
"KR|KC%s|KTD|RN%s|%s|DT%s|G#75|GA%s|GD%s|KO0000|DA%s|TI%s|",
|
"KR|KC%s|KTD|RN%s|%s|DT%s|G#75|GA%s|GD%s|KO0000|DA%s|TI%s|",
|
||||||
encoderAddr,
|
lock.encoderAddr,
|
||||||
formattedLockId,
|
formattedLockId,
|
||||||
hostname,
|
hostname,
|
||||||
dt,
|
dt,
|
||||||
|
27
main.go
27
main.go
@ -53,10 +53,17 @@ type DoorCardRequest struct {
|
|||||||
type App struct {
|
type App struct {
|
||||||
dispPort *serial.Port
|
dispPort *serial.Port
|
||||||
lockConn net.Conn
|
lockConn net.Conn
|
||||||
config configRec
|
|
||||||
lockserver lockserver.LockServer
|
lockserver lockserver.LockServer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newApp(dispPort *serial.Port, lockConn net.Conn, config configRec) *App {
|
||||||
|
return &App{
|
||||||
|
dispPort: dispPort,
|
||||||
|
lockConn: lockConn,
|
||||||
|
lockserver: lockserver.NewLockServer(config.LockType, config.EncoderAddress, fatalError),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// Load config
|
// Load config
|
||||||
config := readConfig()
|
config := readConfig()
|
||||||
@ -101,21 +108,7 @@ func main() {
|
|||||||
log.Infof("Connected to lock server at %s", config.LockserverUrl)
|
log.Infof("Connected to lock server at %s", config.LockserverUrl)
|
||||||
|
|
||||||
// Create App and wire routes
|
// Create App and wire routes
|
||||||
app := &App{
|
app := newApp(dispHandle, lockConn, config)
|
||||||
dispPort: dispHandle,
|
|
||||||
lockConn: lockConn,
|
|
||||||
config: config,
|
|
||||||
}
|
|
||||||
|
|
||||||
switch config.LockType {
|
|
||||||
case lockserver.AssaAbloy:
|
|
||||||
app.lockserver = &lockserver.AssaLockServer{}
|
|
||||||
case lockserver.Omnitec:
|
|
||||||
app.lockserver = &lockserver.OmniLockServer{}
|
|
||||||
default:
|
|
||||||
err = fmt.Errorf("unsupported LockType: %s; must be 'assaabloy' or 'omnitec'", config.LockType)
|
|
||||||
fatalError(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
setUpRoutes(app, mux)
|
setUpRoutes(app, mux)
|
||||||
@ -238,7 +231,7 @@ func (app *App) issueDoorCard(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// build lock server command
|
// build lock server command
|
||||||
app.lockserver.BuildCommand(app.config.EncoderAddress, doorReq.RoomField, checkIn, checkOut)
|
app.lockserver.BuildCommand(doorReq.RoomField, checkIn, checkOut)
|
||||||
|
|
||||||
// lock server sequence
|
// lock server sequence
|
||||||
err = app.lockserver.LockSequence(app.lockConn)
|
err = app.lockserver.LockSequence(app.lockConn)
|
||||||
|
42
payment/creditcall.go
Normal file
42
payment/creditcall.go
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package payment
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// StartTransaction sends a start transaction XML to ChipDNA Server
|
||||||
|
func (pc *PaymentClient) StartTransaction(amountMinorUnits int, reference string) (string, error) {
|
||||||
|
conn, err := net.Dial("tcp", pc.Addr)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to connect: %w", err)
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
// Set timeout
|
||||||
|
conn.SetDeadline(time.Now().Add(15 * time.Second))
|
||||||
|
|
||||||
|
// Format XML request
|
||||||
|
request := fmt.Sprintf(`
|
||||||
|
<StartTransaction>
|
||||||
|
<Amount>%d</Amount>
|
||||||
|
<AmountType>Actual</AmountType>
|
||||||
|
<Reference>%s</Reference>
|
||||||
|
<TransactionType>Sale</TransactionType>
|
||||||
|
</StartTransaction>`, amountMinorUnits, reference)
|
||||||
|
|
||||||
|
_, err = conn.Write([]byte(request))
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to write to server: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read response
|
||||||
|
buff := make([]byte, 4096)
|
||||||
|
n, err := conn.Read(buff)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to read from server: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(buff[:n]), nil
|
||||||
|
}
|
32
payment/paymentcommon.go
Normal file
32
payment/paymentcommon.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package payment
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"net/url"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PaymentClient holds connection data
|
||||||
|
type PaymentClient struct {
|
||||||
|
Addr string // e.g., "127.0.0.1:1869"
|
||||||
|
}
|
||||||
|
|
||||||
|
func InitializeConnection(paymentrUrl string) (net.Conn, error) {
|
||||||
|
const funcName = "InitializeServerConnection"
|
||||||
|
// Parse the URL to extract host and port
|
||||||
|
parsedUrl, err := url.Parse(paymentrUrl)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("[%s] failed to parse LockserverUrl: %v", funcName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove any leading/trailing slashes just in case
|
||||||
|
address := strings.Trim(parsedUrl.Host, "/")
|
||||||
|
|
||||||
|
// Establish a TCP connection to the Visionline server
|
||||||
|
conn, err := net.Dial("tcp", address)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to connect to payment server: %v", err)
|
||||||
|
}
|
||||||
|
return conn, nil
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user