প্রকল্প সম্পর্কে

## সংক্ষিপ্ত বিবরণ plexus-python হলো Plexus প্ল্যাটফর্মের হালকা Python SDK। Plexus হার্ডওয়্যার টিমকে টাইম-সিরিজ ডেটা স্টোরেজ ও ড্যাশবোর্ড প্রদান করে: ড্রোন, রোবট, IoT ডিভাইসের ডেটা Plexus Time Series-এ স্ট্রিম করে লেখা যায়, বা বিদ্যমান ডেটাবেসে সংযুক্ত করা যায়, ফলে রিয়েল-টাইম ড্যাশবোর্ড ও অ্যালার্ট পাওয়া যায়। এই প্যাকেজ শুধু ডেটা Plexus গেটওয়েতে পাঠানোর কাজ করে; স্টোরেজ, ড্যাশবোর্ড, অ্যালার্ট ও ফ্লিট ম্যানেজমেন্ট প্ল্যাটফর্মের দিকে থাকে। ## দ্রুত শুরু ```bash pip install plexus-python ``` ```python from plexus import Plexus px = Plexus(api_key="plx_xxx", source_id="device-001") px.send("temperature", 72.5) ``` API key app.plexus.company/api থেকে পাওয়া যায়, অথবা `plexus init` চালিয়ে ব্রাউজারে এই মেশিন অনুমোদন করা যায়। ## ডিভাইস শনাক্তকরণ প্রতিটি ডিভাইসের জন্য অনন্য `source_id` প্রয়োজন। বুটস্ট্র্যাপ স্ক্রিপ্ট দিয়ে সেট করা সুপারিশ করা হয়, যা প্রথমে ডিভাইসের নাম চায়: ```bash curl -sL https://app.plexus.company/setup | bash -s -- \ --key plx_xxx --name drone-01 ``` নামটি ডিভাইসের `source_id`-তে রূপান্তরিত হয়, যা `^[a-z0-9][a-z0-9._-]*$` প্যাটার্ন মেলাতে হবে (সর্বোচ্চ ২৫৬ অক্ষর)। যদি `--name` বা কোডে `source_id=...` কোনোটিই না থাকে, SDK প্রথমবার চালানোর সময় একটি র‍্যান্ডম id (যেমন `source-1a2b3c4d`) তৈরি করে `~/.plexus/config.json`-এ সংরক্ষণ করে। হোস্টনেম ব্যবহার করবেন না: ক্লোন করা SD কার্ড ইমেজ সবই `raspberrypi` নামে বুট হয়, ফলে টেলিমেট্রি একই source-এ মিলে যায়। নাম স্বয়ংক্রিয়ভাবে ডিডুপ্লিকেট হয় না, গেটওয়ে ঘোষিত `source_id` হুবহু ফেরত দেয়, দুটি ডিভাইস একই নাম ঘোষণা করলে একই source-এ লেখা হবে। ## মূল মেথড ### send(metric, value) সবচেয়ে বেশি ব্যবহৃত মেথড, প্রতিবার নতুন রিডিং এলে কল করুন। `metric` হলো ডট-নোটেশন নেমস্পেস স্ট্রিং (যেমন `"motor.rpm"`), `value` যেকোনো JSON-সিরিয়ালাইজযোগ্য টাইপ গ্রহণ করে: float/int (সেন্সর রিডিং, কাউন্টার), str (স্টেট মেশিন, এরর কোড), bool (বাইনারি ফ্ল্যাগ), dict (ভেক্টর, স্ট্রাকচার্ড রিডিং), list (ওয়েভফর্ম, জয়েন্ট অ্যাঙ্গেল)। ঐচ্ছিক প্যারামিটার `tags={"motor_id": "A1"}` ড্যাশবোর্ড ফিল্টারিংয়ের জন্য, `timestamp=t` Unix সেকেন্ড-লেভেল টাইমস্ট্যাম্প নির্দিষ্ট করে। ### send_batch(points) একবারে একাধিক রিডিং পাঠায়, একই টাইমস্ট্যাম্প শেয়ার করে এবং একটি নেটওয়ার্ক কলে একত্রিত করে। `points` হলো `(metric, value)` টাপলের তালিকা, অথবা প্রতি-পয়েন্ট টাইমস্ট্যাম্প দরকার হলে `(metric, value, timestamp)` ট্রিপলের তালিকা। ### batch() সেকেন্ডে কয়েকটির বেশি রিডিং হলে ব্যবহার করুন। প্রতিটি `send()` একটি WebSocket মেসেজ, গেটওয়ে মেসেজ সংখ্যা সীমিত করে পয়েন্ট সংখ্যা নয় (প্রতি সংযোগে ২,০০০/s)। ২৫টি চ্যানেল ১০০ Hz-এ আলাদা আলাদা পাঠালে ২,৫০০ মেসেজ/s হয়, ওভারফ্লো স্টোরেজের আগেই বাদ পড়ে। ```python with px.batch(interval_ms=50) as b: while running: b.send("att.pos_x", att.x) ``` ব্যাকগ্রাউন্ড থ্রেড প্রতি `interval_ms`-এ কিউ ফ্লাশ করে, কোডব্লক ছাড়ার সময় বাকি ডেটা ফ্লাশ করে, রিডিং সংগ্রহকালীন টাইমস্ট্যাম্প সংরক্ষণ করে। গেটওয়ে ফ্রেম বাদ দিলে `RATE_LIMITED` রিপোর্ট করে, SDK `px.rate_limited_frames`-এ গণনা করে এবং পরের পাঠানোর সময় `RateLimitedError` ছোড়ে। ### run(name) run হলো source-এর উপর একটি নামযুক্ত সময় উইন্ডো, যা `/runs`-এ পরে দেখা যায়, T+0-তে সারিবদ্ধ করে তুলনা করা যায়, এবং বন্ধ করার সময় পাস মানদণ্ড অনুযায়ী যাচাই করা যায়। কোডব্লক ছাড়লে run `completed` হিসেবে চিহ্নিত হয়, ব্যতিক্রম হলে `aborted` হিসেবে চিহ্নিত হয় এবং পুনরায় ছোড়া হয়। `px.start_run()` / `px.end_run()` আলাদাভাবে কল করাও যায়, `end_run()` `test_result` সহ run ফেরত দেয়। ### event(name, data) "যা ঘটেছে" তা রেকর্ড করতে ব্যবহৃত হয়, "যা ধারাবাহিকভাবে মাপা হচ্ছে" তা নয়: ত্রুটি, স্টেট পরিবর্তন, অপারেটরের কাজ, লগ এন্ট্রি। প্ল্যাটফর্ম ইভেন্টগুলোকে টেলিমেট্রি গ্রাফে টাইম-সিরিজ লাইনের বদলে মার্কার হিসেবে দেখায়। একক ইভেন্টের সীমা: স্ট্রিং মান ২৫৬ বাইট, dict/list মান ৪,০৯৬ বাইট JSON, সর্বোচ্চ ১৬টি tag। ### লগ এই প্যাকেজে লগ ফাইল আপলোড নেই, `logging.Handler`-ও নেই। গুরুত্বপূর্ণ লগ লাইন Plexus-এ পাঠাতে চাইলে ইভেন্ট দিয়ে পাঠান: `px.event("log", {"level": "error", "msg": "..."})`। শুধু টাইমলাইনে দেখতে চান এমন লাইন ফরওয়ার্ড করুন (এরর, ওয়ার্নিং, স্টেট পরিবর্তন), প্রতিটি ডিবাগ লগ পাঠাবেন না। ## ভিডিও স্ট্রিমিং ভিডিওর জন্য পেইড প্ল্যান প্রয়োজন: ফ্রেম WebSocket দিয়ে যায়, ফ্রি প্ল্যানে গেটওয়ে প্রত্যাখ্যান করে। ফ্রেম রিয়েল-টাইমে দর্শকদের কাছে ফরওয়ার্ড হয়, শুধু অ্যাপে Record চাপলে সংরক্ষিত হয়, একক রেকর্ডিং সর্বোচ্চ ৪ ঘণ্টা। - `send_video_frame(frame, camera_id)`: নিজে ক্যাপচার লুপ নিয়ন্ত্রণ করলে ব্যবহার করুন (picamera2 কলব্যাক, OpenCV VideoCapture লুপ, নিজ-পরিচালিত FFmpeg পাইপ)। numpy ndarray গ্রহণ করে (opencv-python প্রয়োজন), JPEG বাইট (হুবহু পাস-থ্রু), অন্যান্য ইমেজ বাইট (Pillow দিয়ে ডিকোড করে JPEG-এ রি-এনকোড, `pip install plexus-python[video]` প্রয়োজন)। - `stream_camera(url, camera_id)`: RTSP স্ট্রিম বা ভিডিও ফাইল থাকলে এবং নিজে ক্যাপচার লুপ পরিচালনা করতে না চাইলে ব্যবহার করুন, SDK অভ্যন্তরীণভাবে FFmpeg চালায় (FFmpeg `$PATH`-এ থাকা প্রয়োজন)। `threading.Event` ফেরত দেয়, `.set()` কল করে থামান, ব্যাকগ্রাউন্ড থ্রেডে চলে। ## নিজের প্রোটোকল আনুন এই প্যাকেজে অ্যাডাপ্টার, অটো-ডিটেকশন বা ডেমন নেই, শুধু ক্লায়েন্ট। আপনি যে লাইব্রেরি আগে থেকেই ব্যবহার করেন তা দিয়ে মান `px.send()`-এ পাঠান, README-তে MAVLink (pymavlink), CAN (python-can), MQTT (paho-mqtt), I2C সেন্সর (Adafruit CircuitPython)-এর উদাহরণ আছে, `examples/`-এ চালানোর উপযোগী সংস্করণ আছে। ## নির্ভরযোগ্যতা প্রতিটি পাঠানো প্রথমে লোকালি বাফার হয় তারপর নেটওয়ার্কে যায়, এক্সপোনেনশিয়াল ব্যাকঅফ রিট্রাই সহ, নেটওয়ার্ক বিচ্ছিন্ন হলেও ডেটা রক্ষা করে। বাফার ডিফল্টভাবে ডিস্কে (SQLite), রিস্টার্ট ও পাওয়ার কাট জুড়ে টিকে থাকে; `persistent_buffer=False` হলে শুধু মেমোরিতে। `px.buffer_size()` ও `px.flush_buffer()` দিয়ে পয়েন্ট সংখ্যা দেখা ও ফ্লাশ করা যায়। ## টাইমস্ট্যাম্প ও ক্লক সংশোধন ডিফল্টভাবে SDK নিজেই সময় বেছে নেয়। WebSocket-এ প্রতিটি সংযোগে গেটওয়ে ক্লকের সাথে সিঙ্ক হয়, ফলে ডিভাইসের সিস্টেম ক্লক ভুল হলেও (প্রথম বুটে NTP নেই, RTC মেয়াদোত্তীর্ণ, নতুন সিস্টেম ইমেজ) ডেটা টাইমলাইনে সঠিক স্থানে পড়ে। নির্ভরযোগ্য বাহ্যিক সময়ের উৎস থাকলে (GPS, বিশ্বস্ত RTC, হোস্ট NTP) বা পরিচিত টাইমস্ট্যাম্পের ঐতিহাসিক ডেটা রিপ্লে করলে স্পষ্টভাবে `timestamp` পাঠানো উচিত। পরিচিত সীমাবদ্ধতা: ক্লক সিঙ্ক WebSocket পুনঃসংযোগে রিফ্রেশ হয়, দীর্ঘ সংযোগে RTC ড্রিফট থাকা ডিভাইসে পুনঃসংযোগের ব্যবধানে অসংশোধিত ড্রিফট জমে; HTTP ফলব্যাক পথে ক্লক সিঙ্ক পায় না; `send_batch()` ডিফল্টভাবে একটি টাইমস্ট্যাম্প শেয়ার করে। ## ট্রান্সপোর্ট ডিফল্টভাবে WebSocket দিয়ে গেটওয়ের `/ws/device`-এ সংযুক্ত হয়, যা কম লেটেন্সির টেলিমেট্রি স্ট্রিম এবং ড্যাশবোর্ড-ট্রিগার করা অ্যাকশন বহনকারী চ্যানেল দেয়। socket অনুপলব্ধ হলে স্বচ্ছভাবে `POST /ingest`-এ ফলব্যাক করে, ডেটা হারায় না। ট্রান্সপোর্ট সিলেক্টর নেই, SDK সর্বদা WebSocket-কে অগ্রাধিকার দেয়। ফ্রি প্ল্যানে গেটওয়ে ডিভাইস WebSocket প্রত্যাখ্যান করে (`streaming_requires_plan`), SDK নিজেই HTTP-তে ফলব্যাক করে, `send()`, `send_batch()`, `batch()`, `event()` তখনও কাজ করে; রিয়েল-টাইম স্ট্রিম ও ভিডিওর জন্য পেইড প্ল্যান প্রয়োজন, ফ্রি প্ল্যানে ৩টি ডিভাইস ও ৭ দিনের ইতিহাস সীমা। ## কমান্ড কোড কী কী কমান্ড গ্রহণ করতে পারে তা ঘোষণা করা যায়, প্রথম `send()`-এর আগে ঘোষণা করতে হবে (ঘোষণা অথেনটিকেশন ফ্রেমের সাথে পাঠানো হয়)। `@px.command(...)` দিয়ে হ্যান্ডলার ডেকোরেট করুন, প্যারামিটার সমর্থন করে string (maxLength, enum), integer/number (minimum, maximum, unit), boolean, সাথে title, description, default, required, সর্বোচ্চ ১৬টি এবং ফ্ল্যাট, নেস্টেড নয়। `danger` বিভাজন normal/dangerous/critical, `idempotent` সত্য হলে সংযোগ কাটার পরেই পুনরায় পাঠানো হয়, `expires_in` ৫–৩৬০০ সেকেন্ড, `concurrency` ঐচ্ছিক accept/reject। হ্যান্ডলার `handler(run, **params)` হিসেবে কল হয়, প্যারামিটার যাচাই ও রূপান্তরিত হয়, রিটার্ন মান run ফলাফল হয়, ব্যতিক্রম হলে run `failed` হয়। Receive commands অনুমতিসহ API key প্রয়োজন। SDK প্রতিটি run নিশ্চিত করে, একই run id পুনরায় চালায় না, মনোটনিক ক্লক দিয়ে মেয়াদোত্তীর্ণতা বিচার করে, পুনঃসংযোগের পর অস্বীকৃত অবস্থা রিপ্লে করে। `px.on_command()` ডেপ্রিকেটেড কিন্তু পুরনো সিগনেচারে এখনও কাজ করে। ## এনভায়রনমেন্ট ভেরিয়েবল `PLEXUS_API_KEY` (আবশ্যক), `PLEXUS_GATEWAY_URL` (ডিফল্ট `https://gateway.plexus.company`), `PLEXUS_GATEWAY_WS_URL` (ডিফল্ট `wss://gateway.plexus.company`)। ## Agent skills প্যাকেজের সাথে তিনটি skill আসে, যা কোডিং এজেন্টকে Plexus API ব্যবহার শেখায় (এন্ডপয়েন্ট, রিয়েল-টাইম স্ট্রিম, নীরব ৪০০ ঘটানো সাধারণ ভুল)। `plexus skills install` `~/.claude/skills`-এ ইনস্টল করে, `--project` যোগ করলে `./.claude/skills`-এ ইনস্টল হয় যা রিপোর সাথে যায়। বিশুদ্ধ Markdown, ইনস্টলেশন বা ক্রেডেনশিয়াল প্রয়োজন নেই। ## আর্কিটেকচার ``` Your code ── px.send() ── WebSocket /ws/device (অথবা HTTP POST /ingest) ──> plexus-gateway ──> ClickHouse + Dashboard ``` একটি হালকা পথ, কোনো agent নেই, ডেমন নেই, অ্যাডাপ্টার নেই। সম্পূর্ণ HardwareOps প্ল্যাটফর্ম (ড্যাশবোর্ড, অ্যালার্ট, RCA, ফ্লিট ভিউ) app.plexus.company-এর Web UI-তে। ## লাইসেন্স Apache 2.0।