updated workflow for TLJ locks

This commit is contained in:
yurii 2025-08-08 11:31:48 +01:00
parent 8b0e7df582
commit 61b089fe55
4 changed files with 109 additions and 19 deletions

View File

@ -24,6 +24,12 @@ const (
AssaAbloy = "assaabloy"
Omnitec = "omnitec"
Salto = "salto"
TLJ = "tlj"
)
var (
Cert string
LockServerURL string
)
type (
@ -33,29 +39,36 @@ type (
}
AssaLockServer struct {
encoderAddr string
command string
encoderAddr string
command string
}
OmniLockServer struct {
encoderAddr string // Encoder unit address
command []byte // Command to be sent to the lock server
command []byte // Command to be sent to the lock server
}
SaltoLockServer struct {
encoderAddr string
command []byte
encoderAddr string
command []byte
}
TLJLockServer struct {
encoderAddr string
command string
}
)
func NewLockServer(lockType, encoderAddr string, fatalError func(error)) LockServer {
switch lockType {
switch strings.ToLower(lockType) {
case AssaAbloy:
return &AssaLockServer{encoderAddr: encoderAddr}
case Omnitec:
return &OmniLockServer{encoderAddr: encoderAddr}
case Salto:
return &SaltoLockServer{encoderAddr: encoderAddr}
case TLJ:
return &TLJLockServer{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
@ -100,8 +113,3 @@ func sendAndReceive(conn net.Conn, command []byte) (string, error) {
response := buf[:n]
return string(response), nil
}

View File

@ -0,0 +1,70 @@
package lockserver
import (
"encoding/json"
"fmt"
"io/ioutil"
"net"
"net/http"
"net/url"
"time"
log "github.com/sirupsen/logrus"
)
// GuestCardResponse represents the JSON response from the GuestCard API call.
type GuestCardResponse struct {
Code string `json:"code"`
CardID string `json:"CardID"`
CommandID int `json:"CommandID"` // optional
Msg string `json:"Msg"` // error message if Code != "0"
}
func (lock *TLJLockServer) BuildCommand(doorReq DoorCardRequest, checkIn, checkOut time.Time) error {
params := url.Values{}
params.Set("cer", Cert)
params.Set("room", doorReq.RoomField)
params.Set("BeginTime", checkIn.Format("2006-01-02 15:04:05"))
params.Set("EndTime", checkOut.Format("2006-01-02 15:04:05"))
switch doorReq.FollowStr {
case "0":
params.Set("CheckInMode", "new")
case "1":
params.Set("CheckInMode", "follow")
}
lock.command = fmt.Sprintf("%s/GuestCard?%s", LockServerURL, params.Encode())
return nil
}
func (lock *TLJLockServer) LockSequence(conn net.Conn) error {
client := &http.Client{Timeout: 10 * time.Second}
resp, err := client.Get(lock.command)
if err != nil {
return fmt.Errorf("HTTP request failed: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("unexpected HTTP status: %s", resp.Status)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("failed to read response: %v", err)
}
// Parse response JSON
var result GuestCardResponse
err = json.Unmarshal(body, &result)
if err != nil {
return fmt.Errorf("invalid JSON response: %v", err)
}
if result.Code != "0" {
log.Printf("API error %s: %s", result.Code, result.Msg)
return fmt.Errorf("API error %s: %s", result.Code, result.Msg)
}
log.Printf("Guest card created successfully: CardID=%s, CommandID=%d", result.CardID, result.CommandID)
return nil
}

23
main.go
View File

@ -30,7 +30,7 @@ import (
)
const (
buildVersion = "1.0.8"
buildVersion = "1.0.9"
serviceName = "hardlink"
customLayout = "2006-01-02 15:04:05 -0700"
transactionUrl = "http://127.0.0.1:18181/start-transaction/"
@ -42,6 +42,7 @@ type configRec struct {
LockserverUrl string `yaml:"lockservUrl"`
LockType string `yaml:"lockType"`
EncoderAddress string `yaml:"encoderAddr"`
Cert string `yaml:"cert"`
DispenserPort string `yaml:"dispensPort"`
DispenserAdrr string `yaml:"dispensAddr"`
PrinterName string `yaml:"printerName"`
@ -67,10 +68,13 @@ func newApp(dispPort *serial.Port, lockConn net.Conn, config configRec) *App {
func main() {
// Load config
config := readConfig()
printer.Layout = readTicketLayout()
printer.PrinterName = config.PrinterName
var lockConn net.Conn
lockserver.Cert = config.Cert
lockserver.LockServerURL = config.LockserverUrl
// Setup logging and get file handle
logFile, err := setupLogging(config.LogDir)
if err != nil {
@ -100,12 +104,17 @@ func main() {
log.Infof("Dispenser initialized on port %s, %s", config.DispenserPort, status)
// Initialize lock-server connection once
lockConn, err := lockserver.InitializeServerConnection(config.LockserverUrl)
if err != nil {
fatalError(err)
switch strings.ToLower(config.LockType) {
case lockserver.TLJ:
default:
lockConn, err = lockserver.InitializeServerConnection(config.LockserverUrl)
if err != nil {
fatalError(err)
}
defer lockConn.Close()
log.Infof("Connected to lock server at %s", config.LockserverUrl)
}
defer lockConn.Close()
log.Infof("Connected to lock server at %s", config.LockserverUrl)
// db, err := payment.InitMSSQL(config.dbport, config.dbname, config.dbuser, config.dbpassword)
// if err != nil {

View File

@ -2,7 +2,10 @@
builtVersion is a const in main.go
#### 1.0.8 - 1 August 2024
#### 1.0.9 - 08 August 2024
updated workflow for TLJ locks
#### 1.0.8 - 01 August 2024
improved error handling and logging in Salto
#### 1.0.7 - 25 July 2024