Skip to content

ibtikar-org-tr/qr-code-reader

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ibtikar Logo

Ibtikar Auto Detect

نظام تسجيل حضور الفعاليات التلقائي — Event Attendance Auto-Detection System

Deploy


Overview

Ibtikar Auto Detect is a dual-platform attendance system for Ibtikar Innovation Hub events:

Platform Description
Web (Cloudflare Worker) Volunteer portal — webcam QR scanning or manual lookup, marks attendance & confirms payment
Raspberry Pi 4 / Laptop Automatic QR detection via camera, marks attendance without volunteer interaction

QR code format: membershipNumber:email:eventId
Example: 2302002:member@example.com:b1ed6cdc-d9a9-4f08-ac48-54fe3eb52207

Check-in flow

Camera reads QR code
       │
       ▼
Search Google Sheet (Form Responses 1)
       │
    Found? ─── YES ──► Update column M (attendance) or O (payment)
       │
       NO
       │
       ▼
Search VMS (vms.ibtikar.tr)
       │
    Found? ─── YES ──► POST /event-registrations/{id}/approve?type=attendance
       │
       NO ──► Log "not found"

Live URLs

URL Purpose
https://auto-detect.ibtikar.tr Primary (custom domain)
https://ibtikar-auto-detect.ibtikar-org.workers.dev Backup (workers.dev)

Diagnostic endpoints (no login required)

Endpoint What it shows
/api/health Confirms all secrets are loaded
/api/debug Live test: Google Sheets + VMS connectivity

Project Structure

qr-code-reader/
├── web/                          # Hono + Cloudflare Workers (TypeScript)
│   ├── src/
│   │   ├── index.ts              # Main app — all routes & API
│   │   ├── types.ts              # Shared TypeScript interfaces
│   │   ├── services/
│   │   │   ├── auth.ts           # Session cookie (HMAC-SHA256)
│   │   │   ├── sheets.ts         # Google Sheets API (JWT auth, no SDK)
│   │   │   └── vms.ts            # VMS API client
│   │   └── views/
│   │       ├── login.ts          # Login page HTML
│   │       └── app.ts            # Scanner app HTML
│   ├── wrangler.jsonc            # Cloudflare Workers config
│   ├── package.json
│   └── tsconfig.json
│
├── pi/                           # Python — Raspberry Pi 4 / Laptop
│   ├── scanner.py                # Main camera loop
│   ├── services/
│   │   ├── sheets.py             # Google Sheets (gspread)
│   │   └── vms.py                # VMS API client
│   ├── requirements.txt
│   └── README.md                 # Pi-specific setup instructions
│
├── .github/
│   └── workflows/
│       └── deploy-web.yml        # Auto-deploy on push to main
│
├── example-qr-code/
│   └── image.png                 # Sample QR: 2302002:eng.abduallah1@gmail.com:eventId
│
└── .env.example                  # Template for required environment variables

Environment Variables

Copy .env.example to .env. Never commit .env to git.

Variable Description Example
GOOGLE_API_KEY Full service account JSON (single line) {"type":"service_account",...}
ETC_GOOGLE_SHEET_ID Google Spreadsheet ID (from URL) 1V9U_0eeMlba559n...
GOOGLE_SHEET_NAME Sheet tab name Form Responses 1
ETC_2026_EVENT_ID VMS Event UUID b1ed6cdc-d9a9-4f08-...
VMS_LOGIN VMS login (membership number) 2302002
VMS_PASSWORD VMS password ••••••••
VOLUNTEER_USERNAME Web portal login volunteer
VOLUNTEER_PASSWORD Web portal password ••••••••
SESSION_SECRET 64-char hex secret for cookies 9609d564...
CLOUDFLARE_API_TOKEN Wrangler deploy token ALru7Y...
CLOUDFLARE_ACCOUNT_ID Cloudflare account ID e0518b2d...

Google Sheet columns

Column Purpose
A–K Google Form responses (searched for email / membership number)
M Attendance mark — written when attendee is found & checked in
O Payment confirmation — written when payment is confirmed

Web App — Cloudflare Workers

Local development

cd web
npm install
npx wrangler dev
# Opens http://localhost:8787

The .dev.vars file (gitignored) provides secrets locally — see scripts/rebuild-devvars.ps1.

Deploy to Cloudflare

cd web
npx wrangler deploy

Or push to main — GitHub Actions (deploy-web.yml) deploys automatically.

First-time secret setup (run once):

# Set each secret in Cloudflare Workers:
echo "your-value" | npx wrangler secret put SECRET_NAME

See scripts/set-secrets.ps1 for the full automated setup script.

Custom domain setup

The worker is configured to run on auto-detect.ibtikar.tr. This requires:

  1. ibtikar.tr zone to be in the same Cloudflare account
  2. Wrangler config routes entry already set in wrangler.jsonc
  3. DNS record created automatically by Cloudflare on first deploy

Raspberry Pi / Laptop Scanner

The Python scanner works on:

  • Raspberry Pi 4 (Raspberry Pi OS)
  • Windows / macOS / Linux laptops (any machine with a webcam)

Quick start (laptop)

cd pi
python -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate
pip install -r requirements.txt
cp ../.env .env                    # Copy root .env
python scanner.py                  # Camera index 0
python scanner.py --camera 1       # External USB webcam
python scanner.py --no-window      # Headless (no GUI)
python scanner.py --test           # Decode example QR and exit (no camera needed)

Full Pi setup: see pi/README.md


API Reference

All endpoints except /api/health require a session cookie (set by /login).

Method Path Description
GET / Redirect to /login or /app
GET /login Login page
POST /login Authenticate — sets ibtikar_session cookie
GET /logout Clears session cookie
GET /app Scanner app (protected)
GET /api/health Config health check (public)
GET /api/debug Live Sheet + VMS connectivity test
POST /api/process Look up member (no writes)
POST /api/attendance Mark attendance in Sheet and/or VMS
POST /api/payment Confirm payment in Sheet and/or VMS

POST body (all mutation endpoints)

{ "qrData": "2302002:member@example.com:b1ed6cdc-d9a9-4f08-ac48-54fe3eb52207" }

Accepts three input formats:

  1. Full QRmembershipNo:email:eventId
  2. Email onlymember@example.com (uses ETC_2026_EVENT_ID from env)
  3. Membership # only2302002 (uses ETC_2026_EVENT_ID from env)

Response format

{
  "success": true,
  "results": {
    "sheet": { "success": true, "row": 42 },
    "vms":   { "success": false, "error": "Registration not found in VMS" }
  }
}

VMS API Reference

Base URL: https://vms.ibtikar.tr/ms/membership-app/api

Endpoint Method Description
/login POST Get access token
/event-registrations?eventId=X&membershipNumber=Y GET Find registration
/event-registrations/{id}/approve?type=attendance POST Mark attendance
/event-registrations/{id}/approve?type=payment POST Confirm payment

Architecture Notes

  • No secrets in code — all sensitive values via Cloudflare Worker secrets / .dev.vars
  • Google Sheets JWT auth — implemented with Web Crypto API (no Node.js SDK, works in Workers edge runtime)
  • Session auth — HMAC-SHA256 signed cookies, 8-hour TTL, constant-time comparison
  • Encoding — all Arabic text in HTML uses &#x...; entities to prevent encoding issues
  • Fallback logic — Sheet is primary; if member not found in Sheet, VMS is tried automatically

GitHub Actions

Workflow: .github/workflows/deploy-web.yml

Triggers on push to main when files in web/ change.

Required GitHub repository secrets:

Secret Value
CLOUDFLARE_API_TOKEN Cloudflare API token with Workers edit permission
CLOUDFLARE_ACCOUNT_ID Cloudflare account ID

Built for تجمّع إبتكار · Ibtikar Innovation Hubvms.ibtikar.tr

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors