or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

atr-card-types.mdcard-connections.mdgui-components.mdindex.mdmonitoring.mdpcsc-interface.mdreader-management.mdsession-api.mdstatus-word-handling.mdutilities.md

monitoring.mddocs/

0

# Monitoring

1

2

Event-driven monitoring system for detecting card insertion/removal and reader connection/disconnection using the observer pattern. This enables applications to respond automatically to smart card and reader events.

3

4

## Capabilities

5

6

### Card Monitoring

7

8

CardMonitoring provides automatic detection of card insertion and removal events across all available readers.

9

10

```python { .api }

11

class CardObserver:

12

def update(self, observable, handlers):

13

"""

14

Called when card insertion or removal events occur.

15

16

Args:

17

observable (CardMonitor): The card monitor that detected the event

18

handlers (tuple): (added_cards, removed_cards) where:

19

- added_cards (list[Card]): Cards that were inserted

20

- removed_cards (list[Card]): Cards that were removed

21

"""

22

23

class CardMonitor:

24

"""

25

Singleton monitor for card insertion and removal events.

26

Automatically monitors all available readers.

27

"""

28

29

def addObserver(self, observer):

30

"""

31

Add an observer to receive card events.

32

33

Args:

34

observer (CardObserver): Observer to add

35

"""

36

37

def deleteObserver(self, observer):

38

"""

39

Remove an observer from receiving card events.

40

41

Args:

42

observer (CardObserver): Observer to remove

43

"""

44

```

45

46

### Reader Monitoring

47

48

ReaderMonitoring provides detection of reader connection and disconnection events, useful for applications that need to track available readers dynamically.

49

50

```python { .api }

51

class ReaderObserver:

52

def update(self, observable, handlers):

53

"""

54

Called when reader connection or disconnection events occur.

55

56

Args:

57

observable (ReaderMonitor): The reader monitor that detected the event

58

handlers (tuple): (added_readers, removed_readers) where:

59

- added_readers (list[Reader]): Readers that were connected

60

- removed_readers (list[Reader]): Readers that were disconnected

61

"""

62

63

class ReaderMonitor:

64

def __init__(self, startOnDemand=True, readerProc=None, period=1):

65

"""

66

Initialize reader monitoring.

67

68

Args:

69

startOnDemand (bool): If True, monitoring starts when first observer is added

70

readerProc (callable, optional): Function to get reader list. Defaults to readers()

71

period (int): Polling period in seconds for reader detection

72

"""

73

74

def addObserver(self, observer):

75

"""

76

Add an observer to receive reader events.

77

78

Args:

79

observer (ReaderObserver): Observer to add

80

"""

81

82

def deleteObserver(self, observer):

83

"""

84

Remove an observer from receiving reader events.

85

86

Args:

87

observer (ReaderObserver): Observer to remove

88

"""

89

```

90

91

### Observer Pattern Support

92

93

Base classes for implementing the observer pattern used throughout the monitoring system.

94

95

```python { .api }

96

class Observer:

97

def update(self, observable, handlers):

98

"""

99

Called when the observed object changes.

100

101

Args:

102

observable: The object being observed

103

handlers: Event-specific data

104

"""

105

106

class Observable:

107

def addObserver(self, observer):

108

"""Add an observer to this observable."""

109

110

def deleteObserver(self, observer):

111

"""Remove an observer from this observable."""

112

113

def deleteObservers(self):

114

"""Remove all observers."""

115

116

def notifyObservers(self, handlers=None):

117

"""

118

Notify all observers of a change.

119

120

Args:

121

handlers: Event data to pass to observers

122

"""

123

124

def setChanged(self):

125

"""Mark this observable as changed."""

126

127

def clearChanged(self):

128

"""Clear the changed flag."""

129

130

def hasChanged(self):

131

"""

132

Check if this observable has changed.

133

134

Returns:

135

bool: True if changed flag is set

136

"""

137

138

def countObservers(self):

139

"""

140

Get the number of observers.

141

142

Returns:

143

int: Observer count

144

"""

145

```

146

147

## Usage Examples

148

149

### Basic Card Monitoring

150

151

```python

152

from smartcard.CardMonitoring import CardMonitor, CardObserver

153

from smartcard.util import toHexString

154

155

class SimpleCardObserver(CardObserver):

156

def update(self, observable, actions):

157

(addedcards, removedcards) = actions

158

159

for card in addedcards:

160

print(f"Card inserted in {card.reader}")

161

print(f"ATR: {toHexString(card.atr)}")

162

163

for card in removedcards:

164

print(f"Card removed from {card.reader}")

165

print(f"ATR: {toHexString(card.atr)}")

166

167

# Create and start monitoring

168

monitor = CardMonitor()

169

observer = SimpleCardObserver()

170

monitor.addObserver(observer)

171

172

print("Monitoring for card events... (Press Ctrl+C to stop)")

173

try:

174

# Keep the program running to receive events

175

import time

176

while True:

177

time.sleep(1)

178

except KeyboardInterrupt:

179

print("Stopping card monitoring")

180

monitor.deleteObserver(observer)

181

```

182

183

### Card Monitoring with Automatic Connection

184

185

```python

186

import threading

187

from smartcard.CardMonitoring import CardMonitor, CardObserver

188

from smartcard.util import toHexString

189

190

class AutoConnectObserver(CardObserver):

191

def update(self, observable, actions):

192

(addedcards, removedcards) = actions

193

194

for card in addedcards:

195

# Automatically connect to inserted cards

196

threading.Thread(target=self.handle_card, args=(card,)).start()

197

198

def handle_card(self, card):

199

try:

200

connection = card.createConnection()

201

connection.connect()

202

203

print(f"Connected to card in {card.reader}")

204

205

# Send a simple command

206

GET_DATA = [0x00, 0xCA, 0x9F, 0x7F, 0x00]

207

response, sw1, sw2 = connection.transmit(GET_DATA)

208

209

print(f"GET DATA response: {toHexString(response)}")

210

print(f"Status: {sw1:02X} {sw2:02X}")

211

212

except Exception as e:

213

print(f"Error handling card: {e}")

214

finally:

215

if 'connection' in locals():

216

connection.disconnect()

217

218

# Set up monitoring

219

monitor = CardMonitor()

220

observer = AutoConnectObserver()

221

monitor.addObserver(observer)

222

223

print("Auto-connecting to inserted cards...")

224

```

225

226

### Reader Monitoring

227

228

```python

229

from smartcard.ReaderMonitoring import ReaderMonitor, ReaderObserver

230

231

class SimpleReaderObserver(ReaderObserver):

232

def update(self, observable, actions):

233

(addedreaders, removedreaders) = actions

234

235

for reader in addedreaders:

236

print(f"Reader connected: {reader}")

237

238

for reader in removedreaders:

239

print(f"Reader disconnected: {reader}")

240

241

# Create and start reader monitoring

242

monitor = ReaderMonitor()

243

observer = SimpleReaderObserver()

244

monitor.addObserver(observer)

245

246

print("Monitoring for reader events...")

247

try:

248

import time

249

while True:

250

time.sleep(1)

251

except KeyboardInterrupt:

252

print("Stopping reader monitoring")

253

monitor.deleteObserver(observer)

254

```

255

256

### Combined Card and Reader Monitoring

257

258

```python

259

from smartcard.CardMonitoring import CardMonitor, CardObserver

260

from smartcard.ReaderMonitoring import ReaderMonitor, ReaderObserver

261

from smartcard.util import toHexString

262

263

class SmartCardSystemObserver(CardObserver, ReaderObserver):

264

def __init__(self):

265

self.active_cards = {}

266

267

def update(self, observable, actions):

268

# Handle both card and reader events

269

if isinstance(observable, CardMonitor):

270

self.handle_card_event(actions)

271

elif isinstance(observable, ReaderMonitor):

272

self.handle_reader_event(actions)

273

274

def handle_card_event(self, actions):

275

(addedcards, removedcards) = actions

276

277

for card in addedcards:

278

reader_name = str(card.reader)

279

self.active_cards[reader_name] = card

280

print(f"βœ“ Card inserted in {reader_name}")

281

print(f" ATR: {toHexString(card.atr)}")

282

283

for card in removedcards:

284

reader_name = str(card.reader)

285

if reader_name in self.active_cards:

286

del self.active_cards[reader_name]

287

print(f"βœ— Card removed from {reader_name}")

288

289

def handle_reader_event(self, actions):

290

(addedreaders, removedreaders) = actions

291

292

for reader in addedreaders:

293

print(f"πŸ”Œ Reader connected: {reader}")

294

295

for reader in removedreaders:

296

reader_name = str(reader)

297

if reader_name in self.active_cards:

298

del self.active_cards[reader_name]

299

print(f"πŸ”Œ Reader disconnected: {reader}")

300

301

# Set up comprehensive monitoring

302

observer = SmartCardSystemObserver()

303

304

card_monitor = CardMonitor()

305

card_monitor.addObserver(observer)

306

307

reader_monitor = ReaderMonitor()

308

reader_monitor.addObserver(observer)

309

310

print("Monitoring smart card system events...")

311

print("Insert/remove cards and connect/disconnect readers to see events")

312

313

try:

314

import time

315

while True:

316

time.sleep(1)

317

318

# Show current status every 10 seconds

319

if int(time.time()) % 10 == 0:

320

print(f"\nCurrent active cards: {len(observer.active_cards)}")

321

for reader, card in observer.active_cards.items():

322

print(f" {reader}: {toHexString(card.atr, toHexString.PACK)}")

323

print()

324

325

except KeyboardInterrupt:

326

print("\nCleaning up monitors...")

327

card_monitor.deleteObserver(observer)

328

reader_monitor.deleteObserver(observer)

329

```

330

331

### Context Manager for Monitoring

332

333

```python

334

from smartcard.CardMonitoring import CardMonitor, CardObserver

335

import contextlib

336

337

class ContextCardObserver(CardObserver):

338

def __init__(self):

339

self.events = []

340

341

def update(self, observable, actions):

342

(addedcards, removedcards) = actions

343

for card in addedcards:

344

self.events.append(('inserted', card))

345

for card in removedcards:

346

self.events.append(('removed', card))

347

348

@contextlib.contextmanager

349

def card_monitoring():

350

"""Context manager for card monitoring."""

351

monitor = CardMonitor()

352

observer = ContextCardObserver()

353

monitor.addObserver(observer)

354

355

try:

356

yield observer

357

finally:

358

monitor.deleteObserver(observer)

359

360

# Usage with context manager

361

with card_monitoring() as observer:

362

print("Monitoring cards for 10 seconds...")

363

import time

364

time.sleep(10)

365

366

print(f"Detected {len(observer.events)} events:")

367

for event_type, card in observer.events:

368

print(f" {event_type}: {card.reader}")

369

```

370

371

## Related Types

372

373

```python { .api }

374

# Card and Reader objects used in monitoring events

375

class Card:

376

def __init__(self, reader, atr):

377

"""

378

Card object containing reader and ATR information.

379

380

Args:

381

reader (Reader): Reader containing the card

382

atr (list[int]): Answer To Reset bytes

383

"""

384

385

@property

386

def reader(self):

387

"""Reader: The reader containing this card."""

388

389

@property

390

def atr(self):

391

"""list[int]: Answer To Reset bytes."""

392

393

class Reader:

394

def __init__(self, readername):

395

"""

396

Reader object.

397

398

Args:

399

readername (str): Name of the reader

400

"""

401

402

def __str__(self):

403

"""str: Reader name as string."""

404

405

# Monitoring event data types

406

EventHandlers = tuple[list[Card], list[Card]] # (added, removed)

407

ReaderEventHandlers = tuple[list[Reader], list[Reader]] # (added, removed)

408

```