sf1 / go-card

PC/SC client written in Go. Currently not maintained
MIT License
41 stars 23 forks source link

i need insert card event #2

Closed mrfelfel closed 5 years ago

mrfelfel commented 5 years ago

for check insert new card i wrote this code but cpu usage is 33% in windows `

func main() { ctx, _ := smartcard.EstablishContext()

defer ctx.Release()
messages := make(chan *smartcard.Card)
// var mutex = &sync.Mutex{}

go func() {
    // handle error, if any
    for {
        reader, _ := ctx.WaitForCardPresent()

        // handle error, if any

        // card, err := reader.Connect()
        // handle error, if any
        card, _ := reader.Connect()
        fmt.Printf("Card ATR: %s\n", card.ATR())

        messages <- card

        // handle error, if any
    }

}()

for i := range messages {
    v := string(i.ATR())
    log.Println(v)

}
fmt.Scanln()

} `

sf1 commented 5 years ago

The WaitForCardPresent function returns immediately if a card is present inside the reader and the loop in your goroutine keeps checking again and again. That means as long as a card is inserted, the loop does not enter any wait state and this results in the high CPU usage.

Can you let me know what you are trying to achieve exactly? Using the reader.IsCardPresent function together with time.Sleep in a goroutine could be used to detect when cards are inserted and removed.

If you are dealing with a single card reader, a non-concurrent approach might be an option:

  1. Wait for card present
  2. Open card and communicate
  3. Disconnect card
  4. Optionally use reader.IsCardPresent + time.Sleep to wait until card removed
  5. Go back to 1
mrfelfel commented 5 years ago

i wanna read atr of inserted card and send with websocket

but now i can't

do you mean this ? this is correct ? `package main

import ( "fmt" "log" "time"

"github.com/sf1/go-card/smartcard"

)

func main() { ctx, _ := smartcard.EstablishContext()

defer ctx.Release()
messages := make(chan string)
// var mutex = &sync.Mutex{}

go func() {
    // handle error, if any
    for {
        reader, _ := ctx.WaitForCardPresent()

        // handle error, if any

        card, _ := reader.Connect()
        // handle error, if any
        messages <- string(card.ATR())

        card.Disconnect()
        if reader.IsCardPresent() {
            time.Sleep(2 * time.Second)
        }
        // handle error, if any
    }

}()

for i := range messages {

    log.Println(i)
}
fmt.Scanln()

} `

sf1 commented 5 years ago

If you use for reader.IsCardPresent() instead of if reader.IsCardPresent() it might work. And to convert the ATR to a string, use card.ATR().String() - otherwise you'll get garbage values.

mrfelfel commented 5 years ago

i rewrite this code and change to card.ATR().String() . but cpu usage is 12%

sf1 commented 5 years ago

Did you change if reader.IsCardPresent() to a for reader.IsCardPresent() loop? On my Windows system the CPU usage is close to 0%. I'm closing this issue, please feel free to open another if you encounter any issues with the library or have feature requests.