Auto-Heartbeat: กันแชร์ที่นั่ง License แบบอัตโนมัติ
ใช้ startAutoHeartbeat ใน SDK (JS/Python/C#) ให้แอปส่งสัญญาณ "ยังออนไลน์" เป็นรอบ ๆ เซิร์ฟเวอร์ยึดที่นั่งคืนอัตโนมัติเมื่อเงียบเกิน 3 เท่าของ interval — กันการแชร์ที่นั่งโดยไม่ต้องล็อกเครื่องตายตัว
สำหรับ floating license ปัญหาคือ ถ้าแอปปิดดื้อ ๆ (เครื่องดับ, แอป crash) ที่นั่งจะค้างไม่มีใครคืน คนอื่นเลยใช้ไม่ได้ ทางแก้คือ heartbeat — ให้แอปส่ง สัญญาณ “ยังออนไลน์” เป็นรอบ ๆ ถ้าเงียบเกินกำหนด เซิร์ฟเวอร์ยึดที่นั่งคืนเอง SDK มี startAutoHeartbeat ทำส่วนนี้ให้อัตโนมัติทั้ง 3 ภาษา
มันทำงานอย่างไร
startAutoHeartbeat จะส่ง beat แรกทันที แล้ววนส่งซ้ำตาม intervalSeconds แต่ละ beat อัปเดต last_heartbeat_at ของที่นั่งนั้น ฝั่งเซิร์ฟเวอร์มี cron ที่ ยึดที่นั่งคืนเมื่อเครื่องเงียบเกิน ประมาณ 3 เท่า ของ heartbeatIntervalSeconds ใน policy (เฉพาะ policy ที่ heartbeatRequired) — เผื่อ beat หล่นไป 1–2 ครั้งจากเน็ตสะดุดโดยไม่เด้ง ผู้ใช้ออก
ใช้งานใน JS / Python / C#
ทุก SDK ออกแบบให้ทนทาน: error ชั่วคราว (เน็ตหลุด, RATE_LIMITED) จะส่งเข้า onError แล้ว loop ทำงานต่อ ส่วนสถานะสุดท้าย (LICENSE_REVOKED, LICENSE_SUSPENDED, LICENSE_EXPIRED, MACHINE_NOT_FOUND) จะ หยุด loop เอง ไม่ยิงต่อให้เปลือง
import { KeyThaiClient } from "keythai-sdk";
const client = new KeyThaiClient({ apiKey: "kt_live_xxxxxxxxxxxx" });
const key = "KEYT-AB12-3C4D-5E6F-7G8H-9J0K";
// 1) activate ครั้งแรกเพื่อยึดที่นั่ง
await client.activate(key, { fingerprint, platform: "windows" });
// 2) ส่ง heartbeat อัตโนมัติ — beat แรกทันที จากนั้นทุก ๆ interval
const stopper = client.startAutoHeartbeat(key, fingerprint, {
intervalSeconds: 60, // ตั้งให้ <= heartbeat_interval_seconds ของ policy
onBeat: (res) => console.log("ยังออนไลน์:", res.status),
onError: (err) => console.warn("heartbeat ล้มเหลว (ชั่วคราว):", err),
});
// ตอนปิดแอป — คืน loop (idempotent)
stopper.stop();from keythai import KeyThaiClient, get_device_fingerprint
client = KeyThaiClient("kt_live_xxxxxxxxxxxx")
fp = get_device_fingerprint()
client.activate(key, fp) # ต้อง activate ให้มีที่นั่งก่อน
handle = client.start_auto_heartbeat(
key, fp,
interval_seconds=60, # None = ใช้ค่า policy heartbeat_interval_seconds ไม่งั้น 300s
on_beat=lambda res: print("beat ok"),
on_error=lambda exc: print("heartbeat ล้มเหลว:", exc),
)
# ... แอปทำงาน ...
handle.stop() # เรียกซ้ำได้ ไม่มีปัญหาusing KeyThai;
var client = new KeyThaiClient("kt_live_xxxxxxxxxxxx");
var fp = KeyThaiClient.GetDeviceFingerprint();
// คืนค่า IDisposable — เรียก Dispose() เพื่อหยุด
IDisposable beat = client.StartAutoHeartbeat(
"KEYT-AB12-3C4D-5E6F-7G8H-9J0K", fp,
interval: TimeSpan.FromSeconds(60), // null = policy หรือ 300s
onBeat: r => Console.WriteLine($"beat #{r.BeatNumber}"),
onError: ex => Console.WriteLine($"heartbeat error: {ex.Message}"));
// ตอนปิดแอป (เช่นใน OnFormClosed):
beat.Dispose();ตั้ง interval ให้ถูก
ค่าเริ่มต้นของ SDK คือ 300 วินาที เพราะ response ไม่ได้ส่งค่า heartbeat_interval_seconds ของ policy กลับมา SDK จึงเดาเองไม่ได้ ให้ดึงค่าจริง จาก listPolicies() (ฟิลด์ heartbeat_interval_seconds) แล้วส่งผ่าน intervalSeconds หลักการง่าย ๆ: beat ที่หรือถี่กว่าค่า policy เพราะเซิร์ฟเวอร์ยึดคืนที่ราว 3 เท่า ถ้า beat ห่างเกินไปที่นั่งจะถูกยึดทั้งที่ยังใช้อยู่
เกร็ด: บน Node ตัวจับเวลาถูก unref() จึงไม่กันไม่ให้ process ปิด, ใน C# ผูกกับ cancellationToken ได้, และเรียก startAutoHeartbeat ซ้ำด้วย key + fingerprint เดิมจะแทนที่ loop เก่า อย่าลืม activate ให้มีที่นั่งก่อนเริ่ม beat
heartbeat คือหัวใจของ floating license — ถ้ายังไม่แน่ใจว่า floating เหมาะกับคุณไหม อ่าน Floating License คืออะไร หรือดูภาพรวมการกัน crack หลายชั้นที่ ป้องกันโปรแกรมโดน Crack