-
المساهمات
46 -
تاريخ الانضمام
-
تاريخ آخر زيارة
آخر الزوار
1677 زيارة للملف الشخصي
إنجازات أروى عفان
عضو نشيط (3/3)
5
السمعة بالموقع
-
تملك أداة بودمان أداة تسمى بودمان كومبوز Podman Compose وهي بديلة عن أداة دوكر كومبوز Docker Compose وتُتيح لك العمل مع ملفاتها. وكما ذكرنا في مقالاتنا السابقة فإن بودمان يُعدّ بديلًا ممتازًا عن دوكر، لكن إحدى مساوئه هي أنه لا يُتيح ميزة سحب الصور وتشغيل الحاويات بدءًا من ملفات كومبوز. سنتعرف في مقالنا على هذه الأداة والفوائد التي تقدمها عند العمل مع الحاويات وكيفية حل هذه المشكلة من خلالها. ما هي أداة بودمان كومبوز Podman Compose تُتيح أداة دوكر خاصيّة تحديد جميع التفاصيل المهمة كاسم الحاوية، والصورة المُستَخدمة، وسياسة إعادة التشغيل restart policy، ووحدات التخزين، والمنافذ، والتسميات، وما شابه، في ملف واحد يدعى عادةً ملف docker-compose.yml. لكن هذه الخاصيّة ليست موجودةً في بودمان. لذلك يجب أن نستخدم أداة بودمان كومبوز لنحصل عليها. تتبع أداة بودمان كومبوز المواصفات نفسها التي تتبعها أداة دوكر Docker، مما يجعلها تتوافق مع ملفات docker-compose.yml (لكن قد توجد بعض الاختلافات البسيطة كوضع القيم بين علامتي الاقتباس المزدوجة (")، ولكن هذه الاختلافات يمكن حلها بمجرد النظر إلى الأخطاء الناتجة عن استعمال الأداة podman-compose.) تثبيت أداة بودمان كومبوز podman-compose تُعد أداة بودمان كومبوز أداةً جديدةً نسبيًا لذلك قد لا تجدها في مستودعات توزيعات لينكس المستقرة وذات الدعم طويل الأمد LTS distributions. لكن إليك الخيارات المتاحة من أجل تثبيتها: يمكنك تثبيت أداة بودمان كومبوز في توزيعة أوبنتو ذات الإصدار 22.10 نسخة كينيتك كودو Kinetic Kudu والنسخ الأحدث، وفي توزيعة ديبيان النسخة الثانية عشر بوكوورم Bookworm والنسخ الأحدث منها، باستخدام مدير الحزم apt على النحو التالي: sudo apt install podman-compose أما بالنسبة لمستخدمي الإصدار السادس والثلاثين من توزيعة فيدورا Fedora والإصدارات الأحدث (إصدار حزمة النسخة الخامسة والثلاثون من فيدورا هو 0.1.7-6.git) فيمكنهم استخدام مدير الحزم dnf لتثبيت أداة بودمان كومبوز كما يلي: sudo dnf install podman-compose أما لتثبيتها على نسخة OpenSUSE Tumbleweed أو Leap الإصدار الخامس عشر أو الإصدارات الأحدث فاستخدم الأمر التالي: sudo zypper install podman-compose أما مستخدمو Arch Linux فعليهم استخدام الأمر التالي: sudo pacman -Syu podman-compose التأكد من نجاح التثبيت للتأكد من نجاح عملية تثبيت أداة بودمان كومبوز وأن مسارها الصحيح موجود ضمن متغير البيئة path استخدم الأمر التالي والذي سيعرض لك نسخة بودمان المُستخدمة: podman-compose --version إليك خرج الأمر السابق على توزيعة فيدورا النسخة السادسة والثلاثون: $ podman-compose --version ['podman', '--version', ''] using podman version: 4.3.1 podman-composer version 1.0.3 podman --version podman version 4.3.1 exit code: 0 أساسيات أداة بودمان كومبوز إليك المقال التالي عن كيفية استخدام دوكر كومبوز. إليك ملف كومبوز الذي سنستخدمه في مقالنا: version: 3.7 services: reverse-proxy: image: docker.io/library/caddy:alpine container_name: caddy-vishwambhar command: caddy run --config /etc/caddy/Caddyfile restart: always ports: - "8080:80" - "8443:443" volumes: - /docker-volumes/caddy/Caddyfile:/etc/caddy/Caddyfile:Z - /docker-volumes/caddy/site:/srv:Z - /docker-volumes/caddy/caddy_data:/data:Z - /docker-volumes/caddy/caddy_config:/config:Z - /docker-volumes/caddy/ssl:/etc/ssl:Z labels: - io.containers.autoupdate=registry - pratham.container.category=proxy environment: - TZ=Asia/Kolkata depends_on: - gitea-web gitea-web: image: docker.io/gitea/gitea:latest container_name: gitea-govinda restart: always ports: - "8010:3000" - "8011:22" volumes: - /docker-volumes/gitea/web:/data:Z - /docker-volumes/gitea/ssh:/data/git/.ssh:Z - /etc/localtime:/etc/localtime:ro labels: - io.containers.autoupdate=registry - pratham.container.category=gitea environment: - RUN_MODE=prod - DISABLE_SSH=false - START_SSH_SERVER=true - SSH_PORT=22 - SSH_LISTEN_PORT=22 - ROOT_URL=https://git.mydomain.com - DOMAIN=git.mydomain.com - SSH_DOMAIN=git.mydomain.com - GITEA__database__DB_TYPE=postgres - GITEA__database__HOST=gitea-db:5432 - GITEA__database__NAME=gitea - GITEA__database__USER=gitea - GITEA__database__PASSWD=/run/secrets/gitea_database_user_password - GITEA__service__DISABLE_REGISTRATION=true - TZ=Asia/Kolkata depends_on: - gitea-db secrets: - gitea_database_user_password gitea-db: image: docker.io/library/postgres:14-alpine container_name: gitea-chitragupta restart: always volumes: - /docker-volumes/gitea/database:/var/lib/postgresql/data:Z labels: - io.containers.autoupdate=registry - pratham.container.category=gitea environment: - POSTGRES_USER=gitea - POSTGRES_PASSWORD=/run/secrets/gitea_database_user_password - POSTGRES_DB=gitea - TZ=Asia/Kolkata secrets: - gitea_database_user_password secrets: gitea_database_user_password: external: true تشغيل كل الحاويات من ملف كومبوز يمكننا باستخدام الأمر up إنشاء الخدمات المذكورة في ملف كومبوز (docker-compose.yml) وتشغيلها: podman-compose up -d يؤدي تشغيل الأمر up إلى تنفيذ كل الإجراءات اللازمة لتشغيل الخدمات والحاويات المذكورة في ملف كومبوز، بما فيه الخطوات التالية: سحب الصور غير المتوفرة محليًا. إنشاء الحاويات مع الخيارات المحددة (المنافذ، ووحدات التخزين، والشبكات، والمعلومات الحساسة secrets). تشغيل الحاويات وفق ترتيب معين (باستخدام القيود constrains مثل depends_on). إذا تمعّنت في المثال السابق ستلاحظ وجود الخيار d- الذي يُشغّل الحاويات في الخلفية ويفصلها عن الصدفة الحالية. يمكنك التأكد من عمل الحاويات بتشغيل الأمر podman ps: $ podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d7b7f91c03aa docker.io/library/caddy:alpine caddy run --confi... 4 hours ago Up 4 hours ago 0.0.0.0:8080->80/tcp, 0.0.0.0:8443->443/tcp caddy-vishwambhar 1cfcc6efc0d0 docker.io/library/postgres:14-alpine postgres 4 hours ago Up 4 hours ago gitea-chitragupta 531be3df06d0 docker.io/gitea/gitea:latest /bin/s6-svscan /e... 4 hours ago Up 4 hours ago 0.0.0.0:8010->3000/tcp, 0.0.0.0:8011->22/tcp gitea-govinda إيقاف جميع الحاويات باستخدام ملف كومبوز لإيقاف جميع الحاويات المحددة في ملف كومبوز عليك استخدام الأمر down: podman-compose down يمكنك تحديد وقت إيقاف timeout لتتوقف فيه الحاويات عن العمل من تلقاء نفسها، باستخدام أحد الخيارين التاليين: podman-compose down -t TIMEOUT_IN_SECONDS podman-compose down --timeout TIMEOUT_IN_SECONDS يرجى الانتباه إلى أن الأمر down يوقف عمل الحاويات فقط، أما إن أردت حذف الحاويات فعليك حذفها يدويًا. تشغيل أو إيقاف خدمات معينة إن كررت استخدام المنافذ ووحدات التخزين ومتغيرات البيئة، فمن المحتمل أنك ستستخدم الأمر podman-compose up والأمر podman-compose down بشكل متكرر. لكن هذا سيؤدي إلى تشغيل كل الخدمات وإيقافها، على التوالي. أي إن أردت تشغيل خدمة معينة أو إيقافها، فعليك انتظار تشغيل جميع الخدمات المدرجة في ملف كومبوز وإيقافها، وهذا ليس أمرًا محبّذًا. ولحل هذه المشكلة، يمكنك استخدام الأمر start والأمر stop لتشغيل وإيقاف خدمة معينة. ويمكنك استخدام الأمر restart لإعادة التشغيل. إليك المثال التالي الذي يوضح تشغيل الخدمة gitea-db، وإيقافها ثم إعادة تشغيلها: $ podman-comopse start gitea-db $ podman-compose stop gitea-db $ podman-compose restart gitea-db سحب صور الحاويات الضرورية دفعةً واحدة لنفترض أن لديك عشر خدمات مختلفة في ملف كومبوز وأنك تريد تشغيل الحاويات معًا، إذًا بإمكانك استخدام أمر السحب pull كما يلي: podman-compose pull سيؤدي تشغيل الأمر pull إلى سحب كل الصور المحددة في ملف كومبوز. تغيير اسم ملف كومبوز قد ترغب بتغيير اسم ملف كومبوز (docker-compose.yml) إلى اسم آخر، لتنفيذ ذلك يمكنك استخدام أحد الخيارين التاليين: podman-compose -f COMPOSE_FILE_NAME podman-compose --file COMPOSE_FILE_NAME على النحو التالي: podman-compose --file my-compose-file.yml إن تشغيل الأمر السابق يجعل أداة بودمان كومبوز تغير اسم الملف من docker-compose.yml إلى my-compose-file.yml. الخلاصة تهانينا! لقد وصلت إلى نهاية سلسلتنا التعليمية عن أداة بودمان التي تُعدّ أداةً رائعةً لإدارة الحاويات، وعند استخدامها مع أداة بودمان كومبوز يصبح بإمكانك إنشاء حاويات متعددة وتخصيصها وفق الإعدادات التي تناسبك. بها! ننصحك بتجربتها وشاركنا استفساراتك في قسم الأسئلة والأجوبة في أكاديمية حسوب. ترجمة -وبتصرّف- للمقال Beginner's Guide to Using Podman Compose من موقع Linux Handbook. اقرأ أيضًا المقال السابق: إدارة الحاويات محدودة الصلاحية Rootless Containers باستخدام أداة بودمان Podman تشغيل الحاويات تلقائيًا باستخدام أداة بودمان Podman الفرق بين أداتي دوكر Docker وبودمان Podman نظام كوبيرنتس Kubernetes وكيفية عمله
-
ستتعلم في هذا المقال كيفية التعامل مع الحاويات محدودة الصلاحية Rootless Containers باستخدام أداة بودمان. إن كنت تستخدم الحاويات لنشر البرمجيات، أو تستخدم أداة بودمان، أو أنك ترغب في رفع مستوى الأمان عن طريق تشغيل الحاويات محدودة الصلاحية rootless containers، فهذا المقال مناسب لك. ما هي أداة بودمان Podman إن أداة بودمان Podman هي أحد منتجات شركة Red Hat طُرِحَت كبديل فعّال عن أداة دوكر Docker ويمكنها أداء 99% من المهام التي تؤديها أداة دوكر. بعض ميزات بودمان هي دعم الحاويات محدودة الصلاحية rootless containers، واستخدام نموذج fork/exec لتشغيل الحاويات، وأنه لا يعمل وفق مبدأ البرنامج الخفي أي إنه daemon-less، وثمة كثير من الميزات الأخرى. أما مزايا الحاويات محدودة الصلاحية فهي واضحة، فهي لا تحتاج لصلاحيات الجذر الذي يملك وصولًا كاملًا إلى جميع موارد وملفات النظام كي تعمل، لذلك فإن تشغيلها أكثر أمانًا. تشغيل حاويات بودمان محدودة الصلاحية Rootless Containers إذا كنت متمرسًا في مجال تقنية المعلومات، فمن المحتمل أنك وقعت في أحد الخطأين التاليين: تشغيل الأمر docker باستخدام Sudo، وبالتالي زيادة امتيازاته. إضافة مستخدم محدود الصلاحيات non-root إلى مجموعة دوكر docker group. تلك أخطاء تُضِر بأمان النظام بصورة كبيرة؛ لأنك تسمح لبرنامج دوكر الخفي Docker daemon بالوصول إلى جهازك. وهذا يعرضك للخطر بطريقتين: يعمل برنامج دوكر الخفي (dockerd) كجذر، فإذا كانت ثمة ثغرة أمنية فيه، سيكون نظامك بكامله عرضةً للخطر لأن dockerd هي عملية تابعة للمستخدم الجذر. قد تحتوي الصورة التي تستخدمها على ثغرات أمنية. تخيّل ماذا سيحدث عند استخدام هذه الصورة بواسطة حاوية تعمل كعملية للمستخدم الجذر root process. يمكن لأحد المخترقين استخدام هذه الصورة للوصول إلى كافة موراد النظام. الحل بسيط، عليك الامتناع عن تشغيل البرامج بصلاحيات الجذر، حتى لو كنت تثق بها. تذكر أنه لا يوجد شيء آمن بنسبة 100%. وهنا تأتي ميزة بودمان في إدارة الحاويات دون الحاجة إلى الوصول إلى الجذر. فعند تشغيل حاوية باستخدام بودمان كمستخدم غير جذر، لن تحصل تلك الحاوية على امتيازات إضافية، ولن يطلب منك بودمان كلمة مرور sudo. إليك المزايا التي توفرها أداة بودمان عند إدارة الحاويات محدودة الصلاحية root-less containers: يمكنك تخصيص مجموعة من الحاويات المشتركة لكل مستخدم محلي. (على سبيل المثال، بإمكانك تشغيل Nextcloud وMariaDB لدى المستخدم nextcloud_user وتشغيل الحاويات Gitea وPostgreSQL لدى المستخدم gitea_user). حتى لو اختُرِقَت الحاوية، فلا يمكن التحكم بالنظام المضيف بكامله، لأن المستخدم المسؤول عن الحاوية ليس جذرًا. لكنه لن يعود صالحًا للاستخدام. قيود استخدام حاويات بودمان محدودة الصلاحية عند استخدام أداتي بودمان ودوكر مع صلاحيات المستخدم الجذر أي بنمط عمل root-full، فأنت تمنحها امتيازات على مستوى المستخدم المسؤول أو المميز super-user. وهذا ليس أمرًا محمودًا، ولكنه يضمن أن جميع الوظائف تعمل على النحو المطلوب. ومن الناحية الأخرى، ثمة بعض القيود على تشغيل حاويات بودمان بدون امتيازات الجذر، إليك أهمها: لا يمكن تشارك صور الحاويات بين المستخدمين إذا سحب المستخدم user0 صورة الحاوية nginx:stable-alpine فيجب على المستخدم user1 سحبها بنفسه مرةً أخرى. لا توجد لحد الآن طريقة تسمح تشارك الصور بين المستخدمين، لكن يمكنك نسخ الصور من مستخدم لآخر باتباع هذا الدليل من شركة ريد هات Red Hat. لا يمكن ربط المنافذ ports binding ذوات الأرقام الأدنى من 1024، لكن ثمة طريقة لحل هذه المشكلة. لا يمكن للحاوية محدودة الصلاحية إرسال الطلب ping لأي من المضيفين hosts. لكن ثمة طريقة لحل هذه المشكلة. إذا عيّنت معرّفًا مميزًا UID لحاوية بودمان محدودة الصلاحية، فقد يفشل ذلك إن لم تسند المعرّف المميز UID إلى حاوية موجودة مسبقًا. إذًا، من الأفضل تشغيل بودمان من صدفة طرفية (shell) مستخدم موجود، والخيار الأفضل هو إنشاء خدمة systemd لتشغيلها تلقائيًا. تشغيل حاويات محدودة الصلاحية Rootless Containers باستخدام بودمان قبل أن تبدأ بتشغيل الحاويات محدودة الصلاحية، ثمة بعض المتطلبات التي عليك توفيرها. تثبيت حزمة slirp4netns تُستخدم الحزمة slirp4netns لتوفير خيارات الشبكة لوضع المستخدم user-mode networking لفضاءات أسماء الشبكة. يعد هذا الأمر ضروريًا كي تتفاعل الحاوية محدودة الصلاحية مع أي شبكة وبدونها لا يمكن للحاويات محدودة الصلاحية الاتصال بالإنترنت أو الشبكات الداخلية، مما يحد من فائدتها بشكل كبير. يمكنك تثبيت حزمة slirp4netns على التوزيعات المعتمدة على نظامي ديبيان Debian وأوبنتو Ubuntu باستخدام مدير الحزم apt: sudo apt install slirp4netns أما في التوزيعات المعتمدة على نظامي فيدورا Fedora وريد هات Red Hat فاستخدم مدير الحزم dnf لتثبيت الحزمة، على النحو التالي: sudo dnf install slirp4netns بالنسبة لمستخدمي Arch Linux فعليك استخدام الأمر pacman على النحو التالي: sudo pacman -Sy slirp4netns ضبط subuid و subgid على النحو الصحيح نظرًا لأن حاويات بودمان محدودة الصلاحية تُشَغّل بواسطة مستخدم موجود على النظام، فإن المستخدم يحتاج إلى إذن لتشغيل هذه الحاوية بمعرّف مميز UID مختلف عن معرف المستخدم. وهذا ينطبق أيضًا على معرّف المجموعة GID. يُمنح كل مستخدم نطاقًا من المعرفات التي يُسمح له باستخدامها، تذكر المعرفات الفريدة UID في الملف /etc/subuid، أما معرفات المجموعات GID فتذكر في الملف /etc/subgid. وصيغة الملف هي على النحو التالي: username:initial UID/GID allocated to user:range/size of allowed UIDs/GIDs فلنفرض أن اسم المستخدم pratham يريد مئة معرّف مميز، والمستخدم krishna يريد ألفًا، إذًا ستكون صيغة الملف /etc/subuid على النحو التالي: pratham:100000:100 Krishna:100100:1000 يعني هذا أن المستخدم pratham يمكنه استخدام المعرّفات UID من المعرّف 100000 إلى 100100، والمستخدم krishna يمكنه استخدامها بدءً من المعرّف 100100 إلى 101100. يكون هذا عادةً مُعَدًا مسبقًا لكل مستخدم تنشئه، ويُحَدد للنطاق 65536 معرفًا قابلًا للاستخدام سواء كان معرفًا مميزًا UID أم معرّف مجموعة GID. ولكن، يجب أن تضبطه يدويًا في بعض الحالات. ولكن ليس عليك ضبط ذلك يدويًا لكل مستخدم، إذ يمكنك استخدام الأمر usermod لهذا الغرض. إليك صيغة الأمر المطلوبة: sudo usermod --add-subuids START-RANGE --add-subgids START-RANGE USERNAME والآن استبدل كل من السلسلة START و RANGE و USERNAME بما يناسبك. ** تنبيه:** احرص على ضبط سماحيات الملفين /etc/subuid و/etc/subgid على القيمة 644 وأن يكونا تابعين للمستخدم الجذر root:root. ربط المنافذ ذات الأرقام الأدنى من 1024 إن استخدمت وكيلًا عكسيًا reverse proxy لبروتوكول SSL، فأنت تعلم أن المنفذين 80 و443 يجب أن يكونا متاحين لمزود الشهادات مثلLet's Encrypt. إذا حاولت ربط المنافذ الأقل من 1024 بحاوية بودمان محدودة الصلاحية، فستلاحظ أن ذلك غير متاح كميّزة جاهزة out of the box. إذ لا يُسمح للمستخدم غير الجذر بربط أي شيء على المنافذ الأدنى من المنفذ 1024. إذًا، كيف يمكن ربط المنافذ الأدنى بحاويات بودمان محدودة الصلاحية؟ عليك أولاً تحديد المنفذ الأدنى الذي تحتاجه. في حالتنا، تحتاج إلى المنفذين 80 و443 لنشر بروتوكول SSL، لذا فإن أقل منفذ تحتاجه هو المنفذ 80. والآن، أضف السطر التالي إلى الملف /etc/sysctl.conf: net.ipv4.ip_unprivileged_port_start=YOUR_PORT_NUMBER ما ستفعله هو تغيير قيمة net.ipv4.ip_unprivileged_port_start إلى قيمة أدنى منفذ تحتاجه، إذًا عليك استبدال YOUR_PORT_NUMBER بالقيمة 80 كي تربط المنفذ 80 بحاوية محدودة الصلاحية. أين توجد صور الحاويات كما ذكرنا سابقًا فأحد قيود عمل أداة بودمان هي أنها لا تتيح مشاركة الصور بين المستخدمين. فيجب أن يسحب كل مستخدم الصورة، أو يجب نسخ الصورة من مستخدم لآخر. كلا الخيارين سيحجز ضعف أو أضعاف المساحة، حسب عدد نسخ الصور.حيث تُخَزّن صور حاويات المستخدم في المجلد الرئيسي، وبالتحديد داخل المجلد ~/local/share/containers/storage/ والآن، بعد أن تحققتَ من توفر المتطلبات السابقة، يمكنك تشغيل الأمر podman run من صدفة خارجية non-root user's shell وإنشاء حاوية. سنستخدم خادم Caddy في مثالنا لنشر بروتوكول SSL. شغّل خادم Caddy في حاوية محدودة الصلاحية واربطه بمنفذ أدنى من المنفذ 1024 على النحو التالي: $ whoami pratham $ podman run -d --name=prathams-caddy -p 80:80 -p 443:443 caddy:alpine e6ed67eb90e6d0f3475d78b287af941bc873f6d62db60d5c13b1106af80dc5ff $ podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e6ed67eb90e6 docker.io/library/caddy:alpine caddy run --confi... 2 seconds ago Up 2 seconds ago 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp prathams-caddy $ ps aux | grep caddy pratham 3022 0.0 0.0 85672 2140 ? Ssl 06:53 0:00 /usr/bin/conmon --api-version 1 -c e6ed67eb90e6d0f3475d78b287af941bc873f6d62db60d5c13b1106af80dc5ff [...] pratham 3025 0.1 0.3 753060 32320 ? Ssl 06:53 0:00 caddy run --config /etc/caddy/Caddyfile --adapter caddyfile لاحظ أن المستخدم pratham ليس جذرًا وأنه لا حاجة لاستخدام الأمر sudo لزيادة صلاحيات المستخدم. إذ استطعت تشغيل حاوية خادم Caddy محدودة الصلاحية باستخدام أداة بودمان. يُظهِر خرج الأمر ps أن رمز العملية PID ذو الرقم 3022هو عملية تابعة للمستخدم pratham وهي حاوية خادم Caddy (لكننا لم نُظهِر الخرج كاملًا في مثالنا). أما العملية 3025 فهي تابعة child process للعملية 3022 وهما تابعتان للمستخدم نفسه. الخلاصة وضّحنا في هذا المقال كيفية إدارة الحاويات محدودة الصلاحية باستخدام أداة بودمان، وتحدثنا عن البرامج الضرورية لذلك، وتطرقنا إلى بعض المشكلات الشائعة التي قد تواجهها وكيفية حلها. إن واجهت مشكلةً لم نأتِ على ذكرها مع حاويات بودمان محدودة الصلاحية، فذلك لأن أداة بودمان لا تزال جديدةً بالنسبة للبرمجيات، لذا من المحتمل ظهور بعض المشكلات، في هذه الحالة، شاركنا استفسارك في قسم الأسئلة والأجوبة في أكاديمية حسوب. كما يمكنك الاطلاع على التوثيق الرسمي من موقع بودمان. ترجمة -وبتصرّف- للمقال Getting Started With Rootless Container Using Podman من Linux Handbook. اقرأ أيضًا المقال السابق: تحديث حاويات بودمان Podman تلقائيًا تعلم الحوسبة السحابيّة: المتطلبات الأساسيّة، وكيف تصبح مهندس حوسبة سحابيّة الفرق بين أداتي دوكر Docker وبودمان Podman الفرق بين دوكر Docker وكوبيرنيتيس Kubernetes؟ ما عليك معرفته عن الفرق بين دوكر والأجهزة الافتراضية أساسيات تنسيق الحاويات
-
سنقدم لك في هذا المقال دليلًا مفصلًا حول كيفية ضبط التحديثات التلقائية للحاويات المُدارة بواسطة أداة بودمان Podman وتفعيلها. فتحديث البرامج أمر محبّذ، لا سيما عندما تحتوي التحديثات على ميزات جديدة أو خيارات لزيادة الأمان. لتسهيل العمل سنستخدم في هذا المقال صورة الخادم Caddy من مستودع Docker Hub. تعيين مصدر جلب صور الحاويات كي تستطيع استخدام صورة حاوية (container image) يجب أولًا سحب هذه الصورة من أحد المصادر باستخدام أداة إدارة الحاويات بودمان، يدعى هذا المصدر بسياسة التحديث التلقائي auto-update policy وهي تتضمن قواعد أو إعدادات تحدد زمان وكيفية تحديث الصور أو الحاويات بشكل تلقائي دون تدخل يدوي، مثلاً عند إصدار تحديث جديد للصورة، يتم تحميل التحديث وتطبيقه بشكل تلقائي دون تدخل المستخدم وذلك على النحو التالي: سجل registry: عند إسناد سجل (موقع) ما إلى سياسة التحديث التلقائي auto-update policy فإن بودمان سيسحب الصورة من سجل خارجي remote registry مثل Docker Hub أو Quay.io. مصدر محلي local: عند إسناد الخيار local إلى سياسة التحديث التلقائي، فإن أداة بودمان ستجلب الصورة من الصور المحلية. يُعدّ هذا الخيار هذا الخيار مفيدًا للمطورين الذين يرغبون في اختبار التعديلات المحلية قبل دفعها إلى سجل بعيد. ملاحظة: نستخدم في أمثلة هذا المقال حاوية محدودة الصلاحية root-less container، وحاولنا قدر الإمكان ذكر الأوامر الخاصة بالحاويات كاملة الصلاحية root-full container. فإن استخدمت حاوية كاملة الصلاحية وواجهك خطأ يتعلق بصلاحيات المستخدم، فعليك استخدام الأمر sudo. تفعيل التحديثات التلقائية لحاويات Podman يمكنك الآن تفعيل التحديثات التلقائية لحاويات بودمان بعد أن أصبحت تعلم ما هو مفهوم سياسة التحديث التلقائي، وذلك باستخدام الأمر التالي: io.containers.autoupdate=AUTO_UPDATE_POLICY والآن استبدل السلسلة AUTO_UPDATE_POLICY بالخيار registry أو local. ولكن كيف ستتحدث الحاوية تلقائيًا وأداة بودمان لا تعمل كبرنامج خفي؟ ضبط خدمة systemd عليك إدارة الحاويات التي تحتاج إلى التحديث التلقائي بواسطة نظام التمهيد systemd، وذلك لأن أداة بودمان لا تعمل كبرنامج خفي. إن أردت تشغيل الحاويات تلقائيًا عند إقلاع النظام، فلا شك أنك تستخدم systemd. سنشرح في الخطوات التالية كيفية دمج حاويات بودمان سواء كانت حاويات كاملة أو محدودة الصلاحية، مع خدمة systemd وتشغيلها تلقائيًا عند الاقلاع. الخطوة التمهيدية، إنشاء الحاوية عليك التأكد أولًا أن لديك حاوية بودمان، سواء كانت قيد العمل أو متوقفة. استخدم الأمر التالي للتحقق من الحاويات الموجودة عندك: podman container list لتوضيح أمثلة هذا المقال، اسحب صورةً قديمةً من خادم Caddy (الإصدار 2.5.2-alpine) ثم أعد تسميتها بالاسم alpine، إذ ستساعد إعادة تسمية الصورة في توضيح عملية التحديث. ويمكنك التحقق من ذلك لأن معرف الصورتين هو نفسه. ثم أنشئ حاويةً من الصورة وسمّها prathams-caddy: $ podman images REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/library/caddy 2.5.2-alpine d83af79bf9e2 2 weeks ago 45.5 MB docker.io/library/caddy alpine d83af79bf9e2 2 weeks ago 45.5 MB $ podman container list CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 99d1838dd999 localhost/caddy:alpine caddy run --confi... 5 seconds ago Up 6 seconds ago prathams-caddy كما تلاحظ فإن لدينا حاويةً تدعى prathams-caddy تعمل على صورة Caddy (الإصدار الأقدم). عندما تنشئ الحاوية Prathams-caddy أسند سياسة التحديث التلقائي io.containers.autoupdate على خيار السجل registry كما تعلمنا في الخطوة السابقة. إذا كان لديك حاوية بدون هذا التعديل، فلست بحاجة إلى إعادة إنشاء حاوية جديدة. سنتحدث عن ذلك في الخطوة التالية. الخطوة الأولى، إنشاء ملف خدمة systemd للحاوية كي تتمكن من إدارة حاويات بودمان باستخدام نظام systemd، يجب عليك تحويله إلى خدمة، لتشغيل الحاويات عند إقلاع النظام وإيقافها عند إيقاف تشغيل النظام. إذًا، يجب تشغيل الحاوية كخدمة systemd. ولكن كي لا تضطر إلى كتابة ملف خدمة systemd لكل حاوية، أوجد مطورو أداة بودمان حلًا لذلك، وهو تشغيل أمر معين لكل حاوية. عليك تشغيل الأمر التالي للحاويات كاملة الصلاحية root-full container: sudo podman generate systemd -f --new --name CONTAINER_NAME والأمر التالي للحاويات محدودة الصلاحية root-less container: podman generate systemd -f --new --name CONTAINER_NAME ثم استبدل CONTAINER_NAME باسم حاويتك، وسيتولد بعدها ملف باسم الحاوية كما يلي: $ podman generate systemd -f --new --name prathams-caddy /home/pratham/container-prathams-caddy.service لاحظ من الخرج السابق إنشاء حاوية باسم container-prathams-caddy.service في الملف الحالي. سبق أن ضبطتَ ميزة التحديث التلقائي لهذه الحاوية. أما بالنسبة للحاويات التي لم تضبط فيها هذه الميزة، فليس عليك إعادة إنشاء الحاوية بل يكفي تعديل ملف خدمة systemd وإضافة السطر التالي إلى حقل ExecStart على النحو التالي: [...] ExecStart=/usr/bin/podman run \ [...] --label io.containers.autoupdate=registry [...] وهكذا يستدعي ملف خدمة systemd أمر تشغيل حاويات بودمان podman run. وكل ما عليك فعله هو إضافة io.containers.autoupdate إلى الأمر podman run. الخطوة الثانية، نقل ملف خدمة systemd قبل تفعيل خدمة systemd، يجب عليك نقل ملف الخدمة إلى أحد المجلدين التاليين: /etc/systemd/system/ : إذا كانت الحاوية كاملة الصلاحية وتحتاج إلى امتيازات المستخدم المسؤول superuser. ~/.config/systemd/user/ : إذا كانت الحاوية محدودة الصلاحية، ضعها في مجلد المستخدم الذي سيشغلها. إن الحاوية Prathams-caddy في مثالنا هي حاوية محدودة الصلاحية، لذا عليك نقلها إلى مجلد المستخدم الخاص بك: $ mv -v container-prathams-caddy.service ~/.config/systemd/user/ renamed 'container-prathams-caddy.service' -> '/home/pratham/.config/systemd/user/container-prathams-caddy.service' الخطوة الثالثة، تفعيل خدمة systemd أصبح بإمكانك الآن تفعيل خدمة systemd بعد أن نقلت ملف الخدمة إلى المجلد المناسب. لكن، يجب أولاً إعلام نظام systemd بالخدمة التي أنشأتها قبل إعادة تشغيل حاسوبك. وذلك بإعادة تحميل systemd باستخدام الأمر التالي إذا كانت الخدمة خاصةً بحاوية كاملة الصلاحية: sudo systemctl daemon-reload والأمر التالي للحاويات محدودة الصلاحية: systemctl --user daemon-reload أصبح بإمكانك الآن استخدام الأمر systemctl enable لتفعيل الخدمة: # للحاويات كاملة الصلاحية sudo systemctl enable SERVICE_NAME.service # للحاويات محدودة الصلاحية systemctl --user enable SERVICE_NAME.service تحقق من حالة الخدمة، ستلاحظ أنها غير نشطة inactive (dead) وذلك لأن الخدمة تعمل عند إعادة إقلاع الحاسوب أو النظام، ولم ننفذ ذلك بعد. $ systemctl --user enable container-prathams-caddy.service Created symlink /home/pratham/.config/systemd/user/default.target.wants/container-prathams-caddy.service → /home/pratham/.config/systemd/user/container-prathams-caddy.service. $ systemctl --user status container-prathams-caddy.service ○ container-prathams-caddy.service - Podman container-prathams-caddy.service Loaded: loaded (/home/pratham/.config/systemd/user/container-prathams-caddy.service; enabled; vendor preset: enabled) Active: inactive (dead) Docs: man:podman-generate-systemd(1) والآن أوقف عمل الحاوية ثم استخدم الأمر التالي لحذفها podman container rm وأعد إقلاع جهازك بعدها. $ podman stop prathams-caddy prathams-caddy $ podman container rm prathams-caddy 99d1838dd9990b2f79b4f2c83bc9bc16dfbaf3fdeeb6c6418ddd6e641535ce21 الخطوة الرابعة، تفعيل بقاء المستخدم نشطًا (اختيارية) إذا كانت حاويتك محدودة الصلاحية فمن الأفضل أن يبقى المستخدم المسؤول عنها نشطًا، وذلك باستخدام الأمر التالي: sudo loginctl enable-linger الخطوة الخامسة، تفعيل خدمة التحديث التلقائي كل ما عليك فعله الآن هو تفعيل خدمة التحديث التلقائي في بودمان باستخدام الأمر التالي: sudo systemctl enable podman-auto-update.service بعد تفعيل خدمة التحديث التلقائي podman-auto-update في بودمان، سيتحقق systemd من وجود صورة بحاجة إلى تحديث. إذا كان هناك تحديثات، تُحدّث الصور التي جلبت أولاً، ثم يُعاد تشغيل الحاوية، مع الاحتفاظ بالصورة القديمة في حالة الحاجة إلى التراجع عن التحديث لعدة أسباب. ملاحظة: على الرغم من أن خدمة التحديث التلقائي في بودمان podman-auto-update.service تُفعّل على مستوى النظام، إلا أن أداة بودمان ليست أساسية في عديد من التوزيعات غير التابعة لتوزيعة فيدورا Fedora. لذلك، ربما تحتاج إلى تشغيل الأمر التالي لتفعيل الخدمة عند المستخدمين محدودي الصلاحية: systemctl --user Enable --now podman-auto-update.service التحديث اليدوي إن لم تكن من محبي التحديثات التلقائية، فيمكنك تحديث الحاويات يدويًا باستخدام أمر واحد فقط، بشرط أن تكون مدارةً بواسطة systemd. هذا الأمر هو podman auto-update. وإن أردت التحقق من وجود تحديثات جديدة فقط، فأضف خيار dry-run-- حتى لا تُحَدّث أي حاوية. والآن لنتحقق من إمكانية تحديث صورة الحاوية "2.5.2-alpine" إلى الإصدار "2.6.1-alpine" باستخدام الأمر podman auto-update: $ podman container list CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a712a3c8846b docker.io/library/caddy:alpine caddy run --confi... 2 seconds ago Up 2 seconds ago prathams-caddy $ podman auto-update --dry-run UNIT CONTAINER IMAGE POLICY UPDATED container-prathams-caddy.service a712a3c8846b (prathams-caddy) caddy:alpine registry pending لاحظ أن حالة العمود updated في خرج أمر التحديث التلقائي هي pending أو معلقة وهذا يعني أنه ثم تحديث متوفر. كي تحدّث الحاوية، أزل الخيار dry-run-- من الأمر السابق. الخلاصة قد تبدو عملية تفعيل التحديثات التلقائية لحاويات بودمان معقدةً بعض الشيء، ولكنها ستؤتي ثمارها على المدى الطويل. تُحدّث جميع الحاويات المُدارة عادة بصورة تلقائية عند منتصف الليل في حال وجود التحديثات. وإن حدثت اي مشكلة في الحاوية فإن systemd سيعيدها إلى صورة قديمة، بحيث تستمر الحاوية في العمل. ترجمة وبتصرّف للمقال Automatically Updating Podman Containers من Linux Handbook. اقرأ أيضًا المقال السابق: تشغيل الحاويات تلقائيًا باستخدام أداة بودمان Podman أساسيات تنسيق الحاويات ما الفرق بين دوكر Docker وكوبيرنيتيس Kubernetes؟ ما عليك معرفته عن الفرق بين دوكر والأجهزة الافتراضية
-
لا شك أن أداة بودمان ممتازة لإدارة الحاويات بما تقدمه من ميزات متعددة، لكنها لا توفر خاصية التشغيل التلقائي للحاويات عند إقلاع النظام، سنتعلم في هذا المقال كيف نجد حلًا لهذه المشكلة. على الرغم من أن أداة بودمان لا تعمل كبرنامج خفي daemon، وتسمح للمستخدم محدود الصلاحيات unprivileged user بتشغيل الحاويات دون الحاجة إلى الوصول إلى الجذر، مما يزيد من أمان النظام. لكنها ليست أداةً مثاليةً بالكامل فهي لا تُتيح إعادة تشغيل الحاويات تلقائيًا بعد إقلاع الخادم. سياسة إعادة تشغيل الحاويات عند الاطلاع على صفحة التعليمات man الخاصة بالأمر podman-run ستجد أن خيار إعادة التشغيل restart-- لا يعيد تشغيل الحاويات عندما يقلع النظام. وسبب هذا يرجع إلى أن بنية بودمان لا تعتمد مبدأ البرنامج الخفي، أي إن بودمان لا يعمل تلقائيًا عند إقلاع النظام، وبالتالي فإن الحاويات لا تعمل عند الإقلاع أيضًا. على عكس أداة دوكر التي تعتمد مبدأ البرنامج الخفي الذي يعمل عند إقلاع النظام ويُشَغّل الحاويات المحددة. حل مشكلة عدم التشغيل التلقائي للحاويات أيًّا كانت توزيعة نظام التشغيل التي تعمل عليها فلا بد أنها تستخدم systemd كنظام تمهيد init، وهذا ما سنحاول الاستفادة منه في إيجاد حل للمشكلة. الخطوة الأولى: إعداد الحاوية وتشغيلها ثمة عدة طرق ممكنة لتشغيل الحاوية. إن كان لديك حاوية بسيطة فبإمكانك استخدام الأمر podman run. أو يمكنك استخدام ملف دوكر إن أردت حاويةً بإعدادات معقدة واحتجت لمزيد من التحكم بهذه الإعدادات. لتوضيح ذلك، سننشئ حاويةً من صورة الحاوية mariadb وسنسميها chitragupta-db. $ podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 422eed872347 docker.io/library/mariadb:latest --transaction-iso... 58 seconds ago Up 58 seconds ago chitragupta-db يمكنك إيقاف الحاوية الجديدة لاحقًا. الخطوة الثانية: إنشاء خدمة systemd كما ذكرنا سابقًا، فإن بودمان ليس برنامجًا خفيًا أي إنه daemon-less لإدارة الحاويات. إذًا، فإن تشغيل حاويات بودمان يحتاج إلى تشغيل يدوي أو خارجي. سننفذ ذلك من خلال إنشاء خدمة systemd. حيث إن خدمة systemd هي نظام تمهيد init يدير الخدمات والبرامج الخفية في أنظمة تشغيل لينكس. إنشاء ملف وحدة systemd ليس عليك إنشاء ملف وحدة systemd يدويًا، إذ يمكن تنفيذ ذلك باستخدام الأمر podman generator systemd على النحو التالي: podman generate systemd --new --name CONTAINER_NAME لإنشاء ملف وحدة systemd للحاوية استخدم الأمر podman generate systemd متبوعًا باسم الحاوية، اسم الحاوية في مثالنا هو chitragupta-db: كما تلاحظ فإن الأمر السابق نفّذ العمل المطلوب، ولكننا لم ننته من العمل بعد. إن خرج الأمر podman generate systemd هو ما يجب أن يكون موجودًا في ملف وحدة systemd، لكن ثمة خيار مفيد يمكنك الاستعانة به بدلًا من نسخ الخرج ولصقه، وهو الخيار files -- أو اختصارًا f-. إذ سيؤدي استخدام هذا الخيار أولًا إلى ملء الملف بالمحتوى المطلوب بدلاً من طباعته على الطرفية، وثانيًا، إنشاء ملف باسم Container-CONTAINER_NAME.service في مجلد العمل الحالي. $ podman generate systemd --new --name chitragupta-db -f /home/pratham/container-chitragupta-db.service $ ls *.service Container-chitragupta-db.service لاحظ أن اسم الحاوية في مثالنا هو chitragupta-db، وأنه أصبح لدينا ملف باسم container-chitragupta-db.service في المجلد الحالي. بما أن الأمر podman generate systemd سوف ينشئ ملف وحدة systemd فإن بإمكانك استخدام الخيارات التالية =after=, --requires=, --wants-- لتحديد الاعتماديات للحاويات. نقل ملف خدمة systemd إلى موقع محدد كما لاحظت فإن الأمر السابق سينشئ ملف وحدة systemd جديد في مجلد العمل الحالي، لكن ذلك ليس الخيار الأنسب. إليك المسار المناسب للملف بالنسبة للمستخدم المسؤول superuser: /etc/systemd/system/ أما بالنسبة للمستخدم محدود الصلاحيات non-root user فهو: ~/.config/systemd/user/ والآن عليك نقل الملف إلى المجلد المناسب. بما أن الحاوية في مثالنا هي حاوية محدودة الصلاحية، فعليك نقلها إلى المجلد config/systemd/user/.~. $ mv -v container-chitragupta-db.service ~/.config/systemd/user/ renamed 'container-chitragupta-db.service' -> '/home/pratham/.config/systemd/user/container-chitragupta-db.service' وهكذا بعد أن أنشأت ملف وحدة systemd بالاستعانة بأوامر الطرفية ونقلته إلى المجلد الصحيح، ما تبقى عليك الآن هو تفعيله. الخطوة الثالثة: تفعيل حاوية خدمة systemd عليك الآن أن تعيد إقلاع systemd كي تتفعل الخدمة التي أنشأتها في الخطوة السابقة. استخدم الأمر التالي لإعادة تشغيل خدمة systemd للمستخدم الجذر: sudo systemctl daemon-reload أما بالنسبة للمستخدم محدود الصلاحيات فعليك إزالة الأمر sudo وإضافة الخيار user--، كي يصبح الأمر على الشكل التالي: systemctl --user daemon-reload وهكذا سيُعاد تشغيل خدمة systemd دون إعادة إقلاع النظام، وسيُحدّث وتظهر الخدمة الجديدة container-chitragupta-db.service. والآن أصبح بإمكانك تفعيل الخدمة الجديدة. استخدم الأمر التالي لتفعيل الخدمة للمستخدم الجذر: sudo systemctl enable SERVICE_NAME.service أما بالنسبة للمستخدم محدود الصلاحيات فعليك إزالة الأمر sudo وإضافة الخيار user--، كي يصبح الأمر على الشكل التالي: systemctl --user enable SERVICE_NAME.service ستحصل على الخرج التالي عند تفعيل الحاوية محدودة الصلاحية root-less container: $ systemctl --user enable container-chitragupta-db.service Created symlink /home/pratham/.config/systemd/user/default.target.wants/container-chitragupta-db.service → /home/pratham/.config/systemd/user/container-chitragupta-db.service. يمكنك التحقق من حالة الخدمة بعد تفعيلها بإضافة الأمر status على الأمر السابق للمستخدم الجذر والمستخدم محدود الصلاحية وفقًا لما يلي: # للمستخدم الجذر sudo systemctl status SERVICE_NAME.service # للمستخدم محدود الصلاحية systemctl --user status SERVICE_NAME.service إليك حالة الخدمة container-chitragupta-db: $ systemctl --user status container-chitragupta-db.service ○ container-chitragupta-db.service - Podman container-chitragupta-db.service Loaded: loaded (/home/pratham/.config/systemd/user/container-chitragupta-db.service; enabled; vendor preset: disabled) Active: inactive (dead) Docs: man:podman-generate-systemd(1) لا تقلق لأن حالة الخدمة تظهر غير نشطة inactive (dead)، إذ فعّلنا الخدمة الآن ويجب أن تعمل الخدمة عند إقلاع النظام، وليس الآن، وهذا هو المطلوب. إذا لم توقف الحاوية في الخطوة الأولى، فهذا هو الوقت المناسب لإيقافها عن طريق استخدام الأمر podman stop ثم استخدام الأمر podman container rm لحذفها، وإعادة إقلاع النظام بعدها لتشغيل خدمة الحاوية. الخطوة الرابعة: تفعيل خدمة إعادة التشغيل قد تحتاج في بعض التوزيعات إلى تفعيل خدمة إعادة التشغيل في بودمان أيضًا. ينطبق هذا على التوزيعات غير المعتمدة على نظام فيدورا، وخاصةً توزيعة NixOS. لتفعيل خدمة إعادة التشغيل عليك استخدام الأمر التالي: systemctl --user enable podman-restart.service يحرص الأمر podman-restart على إعادة تشغيل جميع الحاويات التي ضُبطت ليُعاد تشغيل دائمًا أي عند ضبط الأمر restart-policy على الخيار always. الخطوة الخامسة، تفعيل بقاء المستخدم محدود الصلاحية نشطًا (خطوة اختيارية) بما أنك فعّلت هذه الخدمة بواسطة مستخدم عادي محدود الصلاحية وليس المستخدم الجذر، هذا يعني أن المستخدم يحتاج إلى تسجيل الدخول عند التشغيل ويجب أن يظل نشطًا إن خرج من جلسة واجهة المستخدم الرسومية GUI أو من الطرفية. ويمكن تحقيق ذلك باستخدام الأمر loginctl من طرفية المستخدم نفسه، على النحو التالي: sudo loginctl enable-linger يضمن هذا الأمر تفعيل جلسة المستخدم عند الإقلاع وبقاءها نشطةً حتى بعد تسجيل الخروج من واجهة المستخدم الرسومية أو الطرفية. وبهذا تكون قد فعّلتَ إعادة تشغيل حاويات بودمان عند الإقلاع. حيث ستؤدي إعادة تشغيل النظام إلى التشغيل التلقائي للحاويات التي أنشأت لها ملف وحدة systemd. تعديل خدمة systemd نعلم جميعًا أن الإعدادات الافتراضية تفيد المبتدئين دائمًا، إذ تساعد على تخفيف شعور الارتباك لديهم. تُعد الإعدادات الإفتراضية لملف systemd الذي أنشأته مثاليةً لمعظم الأشخاص، لكن إن لم تكن مبتدئًا فبإمكانك إضافة مزيد من التعديلات من خلال تعديل ملف systemd أو إنشاء خدمة مخصصة جديدة من الصفر. الخلاصة تعلمنا في هذا المقال كيفية إنشاء ملفات وحدة systemd للتشغيل التلقائي لحاويات بودمان عند إقلاع النظام. حيث أن استخدام خدمة systemd سيساعدك في مراقبة الحاويات التي تستخدم واجهة systemd. ترجمة وبتصرّف للمقال Autostarting Podman Containers من موقع Linux Handbook. اقرأ أيضًا المقال السابق: إنشاء الحاويات وحذفها باستخدام أداة بودمان Podman نظام كوبيرنتس Kubernetes وكيفية عمله كيفية تأمين الحاويات عن طريق سي لينكس SELinux الفرق بين أداتي دوكر Docker وبودمان Podman
-
هل أنت حديث العهد باستخدام أداة بودمان؟ إن كان جوابك نعم، فلا تقلق، سنتعلم في هذا المقال كيفية إنشاء الحاويات وكيفية عرضها وإيقافها وحذفها باستخدام بودمان. هذا المقال جزء من سلسلة مقالات بودمان Podman وهي تهدف لتعريفك على هذه الأداة كي تستطيع عند نهاية هذه المقالات، التعرف على الفرق بين دوكر وبودمان، وبدء استخدام بودمان بكفاءة عند العمل مع الحاويات. ما ستتعلمه في سلسلة تعرف على أداة بودمان Podman سنتعلم في هذه سلسلة ما يلي: الفرق بين أداتي دوكر وبودمان إنشاء الحاويات وحذفها باستخدام أداة بودمان تفعيل حاويات بودمان تلقائيًا عند إقلاع النظام تحديث الحاويات مفهوم الحاويات محدودة الصلاحية Rootless containers مفهوم بودمان كومبوز Podman Compose متطلبات هذه السلسلة معرفة مسبقة بمفهوم الحاويات تجربة مسبقة في التعامل مع دوكر خبرة في التعامل مع سطر الأوامر أو الطرفية Terminal في لينكس كما تعلمنا في مقال سابق فإن أداة بودمان هي أداة بديلة عن دوكر تستخدم لإدارة الحاويات، ولها بنية أوامر مشابهة لأوامر دوكر. وسنتعلم في مقال اليوم كيفية إنشاء الحاويات وحذفها. سحب الصور من سجل الصور باستخدام بودمان عند إنشاء الحاويات، ستحتاج أولًا إلى صورة للحاوية image، إذ لا يمكنك تنفيذ شيء بدون الصورة. ولذلك عليك سحب pull الصورة من سجل الصور. إليك بعض سجلات الصور الشهيرة: Docker Hub Quay.io سجلات الصور المستضافة مثل linuxserver.io ولسحب صورة باستخدام بودمان فعليك استخدام الصيغة التالية: podman pull [OPTIONS] FULLY_QUALIFIED_IMAGE_NAME[:tag|@digest] لمعرفة معنى اسم الصورة المؤهل بالكامل FULLY_QUALIFIED_IMAGE_NAME واختصارًا FQIN، ألقِ نظرةً على الأمرين التاليين: # باستخدام اسم الصورة المؤهل تمامًا podman pull docker.io/library/debian # بدون اسم الصورة المؤهل تمامًا podman pull debian كما تلاحظ، في اسم الصورة المؤهل بالكامل، يكون التنسيق على النحو التالي: السجل/اسم المستخدم/اسم الصورة. في مثالنا فإن docker.io هو عنوان سجل دوكر hub.docker.com. لسحب وسم tag محدد، اكتب اسم الوسم بعد اسم الصورة، مسبوقًا بنقطتين (:). إليك مثالًا عن سحب الوسم stable-slim لصورة ديبيان: podman pull docker.io/library/debian:stable-slim عرض الصور المتاحة بعد سحب صورة أو أكثر، يمكنك معاينة الصور المتوفرة محليًا باستخدام الأمر podman Images. عند سحب صورة debian:stable-slim، ستحصل على الخرج التالي: $ podman images REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/library/debian stable-slim 86f9b934c377 2 days ago 77.8 MB والآن بعد أن حصلت على الصورة يمكنك إنشاء حاوية جديدة إنشاء حاوية جديدة لإنشاء حاوية جديدة في بودمان، عليك استخدام الأمر podman run بالطريقة التالية: podman run [OPTIONS] image [COMMAND [ARGS]] والآن، سنضيف بعض الخيارات options على الأمر السابق، سنضيف أولًا الخيار d- لتشغيل الحاوية باستمرار في الخلفية، والخيار t- لتخصيص طرفية زائفة pseudo-TTY لصورة ديبيان كي تعمل باستمرار. يمكنك الاطلاع على قائمة الخيارات المتاحة من توثيقات بودمان. والآن، سننشئ حاوية بسيطة تعتمد على صورة توزيعة ديبيان stable-slim التي سحبناها مسبقًا. podman run -d -t debian:stable-slim عند نجاح إنشاء الحاوية، ستحصل في الخرج output على سلسلة عشوائية من الأحرف والأرقام. هذه السلسلة هي معرف الحاوية الفريد unique container ID. 61d1b10b5818f397c6fd8f1fc542a83810d21f81825bbfb9603b7d99f6322845 عرض الحاويات أولًا، لعرض الحاويات قيد التشغيل، عليك استخدم الأمر podman ps، وهو يشبه الأمر ps في لينكس، لكن بدلاً من إظهار عمليات النظام، فإنه يظهر الحاويات قيد التشغيل وتفاصيلها. بما أننا استخدمنا الخيار t- لتشغيل حاوية دبيان، فلنرَ كيف تبدو نتيجة الأمر podman ps: $ podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 61d1b10b5818 docker.io/library/debian:stable-slim bash 44 seconds ago Up 44 seconds ago gallant_mahavira يمكنك الحصول على معلومات عن الحاوية باستخدام الأمر ps كمعرّف الحاوية الفريد القصير، والصورة المستخدمة لإنشاء هذه الحاوية، ومتى أُنشِئت الحاوية، ومنافذ الجهاز المضيف المسندة إلى منافذ الحاوية واسمها. ونلاحظ من الخرج أن الصورة المستخدمة هي debian:stable-slim أُنشِئت قبل 44 ثانية، أما اسم الحاوية فهو gallant_mahavira. يمكنك تسمية الحاوية عند إنشائها باستخدام الخيار name CONTAINER_NAME--، فعندما لا تحدد اسم الحاوية، يُولَد اسم عشوائي لها. ثانيًا، لعرض الحاويات المتوقفة عن العمل Stopped containers عليك استخدام الأمر التالي: podman container list -a والآن، سنتعلم كيفية إيقاف الحاويات. إيقاف الحاويات لإيقاف الحاويات عليك استخدام الأمر podman stop مع معرّف الحاوية أو اسمها، وذلك وفق الصيغة التالية: podman stop [CONTAINER_NAME|CONTAINER_ID] والآن سنوقف الحاوية الجارية باستخدام اسمها: $ podman stop gallant_mahavira gallant_mahavira والآن بإمكانك استخدام الأمر السابق لعرض جميع الحاويات الجارية والمتوقفة: $ podman container list -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 61d1b10b5818 docker.io/library/debian:stable-slim bash 14 minutes ago Exited (137) 3 minutes ago gallant_mahavira ملاحظة: ترتبط كل من الأوامر podman container list and podman container ls، podman ps، podman container ps بنفس الملف الثنائي binary ولها نفس الاستخدام وتعطي نفس الخرج. إعادة تشغيل الحاوية لإعادة تشغيل حاوية ما بعد إيقاف عملها أو فشله، عليك استخدام الأمر podman start. فلنفترض أن الحاوية التي أنشأتها من صورة ديبيان فشلت لسبب ما، إذًا يمكنك إعادة تشغيلها عن طريق كتابة اسمها أو معرّفها بعد الأمر podman start كالتالي: $ podman start 61d1b10b5818f397c6fd8f1fc542a83810d21f81825bbfb9603b7d99f6322845 حذف الحاويات قبل حذف حاوية أو تدميرها عليك أولًا إيقافها، وبعدها يمكنك استخدام الأمر podman rm لحذفها. بمجرد حذف الحاوية، فإنها ستختفي ولن تظهر في خرج الأمر podman Container list -a. إليك المثال التالي على إيقاف وحذف حاوية باستخدام بودمان، والذي استخدمنا فيه اسم الحاوية ومعرفها. $ podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 61d1b10b5818 docker.io/library/debian:stable-slim bash 44 minutes ago Up 1 second ago gallant_mahavira $ podman stop gallant_mahavira gallant_mahavira $ podman rm 61d1b10b5818 61d1b10b5818f397c6fd8f1fc542a83810d21f81825bbfb9603b7d99f6322845 $ podman container list -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES كما ترى فإن الحاوية اختفت تمامًا. يمكنك الآن إن أردت، إنشاء حاوية جديدة باستخدام أي صورة وفق الأوامر الخطوات التي تعلمتها. الخاتمة تهانينا، لقد وصلت إلى نهاية المقال الثالث في سلسلتنا التعليمية حول أداة بودمان، وتعلمت كيفية إنشاء الحاويات وعرضها وإيقافها وحذفها، تابع قراءة باقي المقالات كي تتعلم المزيد حول بودمان. ترجمة -وبتصرف- للمقال Creating and Destroying Containers Using Podman من موقع Linux Handbook. اقرأ أيضًا المقال السابق: الفرق بين أداتي دوكر Docker وبودمان Podman مدخل إلى حاويات لينكس LXC ما هي صورة الحاوية container image؟ نظرة عامّة على إعداد الحاويات containerization على Docker
-
إن أداة بودمان Podman هي أداة مقدمة ومدعومة من قبل توزيعة ريد هات Red Hat كبديل عن أداة دوكر Docker. فأداة بودمان شبيهةً بدوكر ويمكنك بدء استخدامها إن كنت على معرفة بدوكر. عندما نأتي على ذكر الحاويات، ستخطر الأداة دوكر Docker في ذهنك، لكنها ليست الأداة الوحيدة للتعامل مع الحاويات. إذ ستجد أن أداة بودمان المقدمة من ريد هات أداة واعدة وتلبي احتياجاتك وليس عليك تعلم كيفية التعامل معها من الصفر، لأنها مشابهة لدوكر. تهدف هذه السلسلة إلى تعريفك على أداة بودمان، كي تستطيع عند نهاية هذه المقالات، التعرف على الفرق بين دوكر وبودمان، وبدء استخدام بودمان عند العمل مع الحاويات. ما ستتعلمه سلسلة التعرف على أداة بودمان Podman سنتعلم في هذه السلسلة ما يلي: الفرق بين أداتي دوكر وبودمان. إنشاء الحاويات وحذفها باستخدام أداة بودمان. تفعيل حاويات بودمان تلقائيًا عند إقلاع النظام. تحديث الحاويات. مفهوم الحاويات محدودة الصلاحية Rootless containers. مفهوم بودمان كومبوز Podman Compose. متطلبات هذه السلسلة معرفة مسبقة بمفهوم الحاويات Containers. تجربة مسبقة في التعامل مع دوكر. خبرة في التعامل مع سطر الأوامر أو الطرفية Terminal في لينكس Linux. سنناقش في مقال اليوم الفرق بين أداتي دوكر وبودمان بالتفصيل، حيث يترافق مصطلح الحاويات Containers في ذهننا مع أداة دوكر Docker، لكن دعونا نتعرف في مقالنا على الفرق بينها وبين أداة بودمان Podman التي ازداد استخدامها مع الحاويات. ومع انتشار استخدام الحاويات أصبحت أداة دوكر، التي ظهرت في عام 2014، أشهر أداة لإدارة الحاويات. ونشرت شركة ريد هات Red Hat في عام 2018، أداة بودمان كبديل عن دوكر. وبما أن الأداتين لهما الغرض نفسه، سنتعرف في هذا المقال على مزايا كل منهما. مفهوم الحاويات لنفترض أنك تعمل كمهندس برمجيات وطُلِب منك نشر مجموعة برامج ذات مهام حرجة. ماذا ستفعل لو كان البرنامج الأول والبرنامج الثاني لهما نفس الاعتمادية dependency ولكنهما يعملان على إصدارات مختلفة من نفس الاعتمادية؟ أو لو كانت تبعية البرنامج الأول تتعارض مع الاعتمادية البرنامج الثاني؟ في هذه الحال عليك نشرهما في جهازين افتراضيين Virtual Machine مختلفين، لكن هذا يلغي قابلية التوسع scalability، لأنه عند تشغيل جهازين افتراضيين على نفس الجهاز، سيرث البرنامج 50% فقط من إجمالي قدرة الجهاز الحاسوبية. وعند زيادة عدد البرامج من برنامجين إلى عشرة سيتضح لك أن هذا الحل غير فعّال. حيث إن إحدى مساوئ الآلات الافتراضية هي أنها تعمل بنظام تشغيل كامل، وهذا يُعد أمرًا سلبيًا في حالتنا. فلو كان عندنا عشرة أجهزة افتراضية تعمل بنظام تشغيل ريد هات RHEL، سيصبح عندنا عشر نسخ من نفس الثنائيات binaries، وسيؤدي ذلك إلى استهلاك غير فعّال لذاكرة الوصول العشوائي RAM. حتى إن أبسط عملية تثبيت installation ستحجز أكثر من 4 جيجابايت من مساحة القرص لكل جهاز افتراضي. لذلك بدلًا من استخدام جهاز افتراضي، حيث يكون لديك نظام تشغيل كامل على الجهاز بالإضافة إلى برنامجك واعتمادياته، يمكنك استخدام صورة الحاوية container image. إذ تحتوي صور الحاوية على البرنامج واعتمادياته فقط. ومن مزايا صور الحاويات أن حجمها يكون عادةً أقل من 300 ميجابايت. فالمشكلة تكمن في طبيعة عمل الآلات الافتراضية؛ فعندما تنشئ آلةً افتراضية، تُنشَأ نسخة افتراضية من العتاد hardware. أي نسخة افتراضية من وحدة المعالجة المركزية وذاكرة الوصول العشوائي، وذاكرة التخزين والموارد الأخرى، ولا بد أن لهذا حمل على الجهاز. أما عند استخدام الحاويات، تُنشَأ نسخ من البرنامج مع اعتماديّاته، وهذا له حمل منخفض مقارنةً بالآلات الافتراضية. الغرض من استخدام دوكر أو بودمان ربما استخدمت برنامج فيرتشوال بوكس VirtualBox المُقدَّم من أوراكل Oracle لإدارة الآلات الافتراضية، والذي يُتيح لك إنشاء آلات افتراضية وتشغيلها أو إيقافها، وتعديلها، وحذفها. تُتيح كل من أداتي دوكر وبودمان ذلك، ولكنها تتعامل مع البرامج الموجودة في حاويات، وليس الآلات الافتراضية. وعلى الرغم من أن كِلا الأداتين تعملان وفق فلسفتين مختلفين، إلا أن كلتاهما تساعدان على إدارة الحاويات. لذلك سنتعرف الفروق بينهما وأي منهما هو الأفضل وفقًا لغرض الاستخدام الذي تريده. دوكر أم بودمان يُعد كل من دوكر و بودمان من البرامج الممتازة لإدارة الحاويات. وعندما أعلنت شركة ريد هات عن طرحها لبودمان كبديل عن دوكر قالت إن بودمان متوافق مع واجهة سطر أوامر دوكر، أي إن الانتقال من دوكر إلى بودمان لا يتطلب تغييرات كبيرة على الشيفرة البرمجية. هذا يعني أنه يمكنك استبدال أمر docker بالأمر podman وسيعمل البرنامج. ولكن ثمة بعض الاختلافات الأساسية، التي سنتعرف عليها: أولًا، مفهوم البرنامج الخفي Daemon إن الفرق الرئيسي الذي يميز بين أداتي دوكر وبودمان هو طريقة عملهما على نظام التشغيل. حيث تعمل نواة دوكر Docker core كبرنامج خفي dockerd، أي إنه يعمل دائمًا في الخلفية ويدير الحاويات. أما أداة بودمان فتشبه البرنامج العادي؛ أي إنه يبدأ العمل عند تنفيذ إجراء ما فيه (بدء أو إيقاف حاوية). تتميز طريقة عمل دوكر المعتمدة على البرنامج الخفي Daemon-based approach بما يلي: يتيح تشغيل الحاويات تلقائيًا وبسهولة عند تشغيل النظام. لا حاجة إلى مدير خدمة خارجي مثل systemd نظرًا لأن دوكر هو برنامج خفي. لكن هذا لا يعني أن أداة بودمان سيئة، إليك المزايا التي تتميز بها أداة بودمان عن دوكر: عند تعطل برنامج دوكر الخفي، فستكون حالة الحاويات غير معروفة. لكن يمكن تجنب ذلك عند استخدام أداة بودمان. يمكنك استخدام systemd لإدارة الحاويات، إذ يمنحك ذلك قدرة غير محدودة على ضبط وإدارة الحاويات مقارنةً بدوكر. يتيح ربط بودمان مع systemd تحديث الحاويات قيد التشغيل بأقل وقت توقف عن العمل downtime. كما يمكنك تلافي التحديثات السيئة. ثانيًا، الأمان Security إن أهم سبب لاستخدام بودمان بدلًا من دوكر هو الأمان، إذ طُرح بودمان كبديل أكثر آمنًا من دوكر. فإذا كنتَ مهتمًا بالأمان، فستجذبك اثنتان من ميزات بودمان الأساسية. ذكرنا آنفًا أن ما يميز بودمان عن دوكر هو أن بودمان لا يعمل كبرنامج خفي. أما الميزة الأساسية الثانية لبودمان هي أنه يمكنه تشغيل الحاويات دون صلاحيات الوصول إلى الجذر root. هذا يعني أنك لست بحاجة إلى امتيازات المستخدم المميز superuser لإدارة الحاويات. والآن، إليك ثلاثة أسباب تجعلك تفضل استخدام بودمان بدلًا عن دوكر إن كنت مهتمًا بالحصول على مستوى أعلى من الأمن. السبب الأول، يعمل الأمر dockerd كمستخدم جذر كما تعلم فإن نواة دوكر تعمل كبرنامج نظام خفي system daemon، أي كبرنامج ينفذه المستخدم المسؤول أو الجذر root user. سبق وذكرنا فوائد البرنامج الخفي، لكن ثمة بعض المشاكل الأمنية عند تشغيل البرنامج الخفي كمستخدم جذري. أولًا، إذا اختُرق برنامج دوكر الخفي (dockerd)، فيمكن لأحدهم أن يخترق نظامك من خلال الوصول إلى الجذر. ولا شك أنك لا تود حدوث ذلك. وهنا تتضح ميّزة بودمان إذ إنه لا يستخدم برنامجًا خفيًا وليس له متطلبات صارمة للوصول إلى الجذر. وهذا يقودنا إلى السبب الثاني. السبب الثاني، يدعم بودمان الحاويات دون صلاحيات جذر ربما سمعت أن بودمان يدعم تشغيل الحاويات دون الوصول إلى الجذر أو ما يعرف Root-less containers، وهذا أمر صحيح وأكثر أمنًا. والآن، لنفترض أن برنامج دوكر الخفي آمن، وأن صورة الحاوية التي تستخدمها فيها ثغرة أمنية. ولكن المطور لا يعرف ذلك. إذا شَغّلتَ هذه الصورة في حاوية تابعة للمستخدم الجذر، فاعلم أن الحظ ليس حليفك. أما عند استخدام بودمان، فيمكنك تشغيل الحاوية دون الحاجة إلى امتيازات الجذر. هذا يعني أنه إن احتوت صورة الحاوية على ثغرة أمنية، فلن يتعرض للخطر سوى المستخدم الذي يملك تلك الحاوية. أما بقية مستخدمي النظام فهم بأمان، ولا سيما المستخدم الجذر. وعلى الرغم من أن دوكر حصل مؤخرًا على دعم لتشغيل الحاويات محدودة الصلاحية Rootless containers ، لكن لا يزال ينقصه بعض الميزات، وهي أن دعم AppArmor غير موجود. وهو نظام التحكم الإلزامي بالوصول (MAC) الافتراضي الخاص بتوزيعتي ديبيان وأوبنتو السبب الثالث، تحديث الصور تلقائيًا قد يخطر في ذهنك أن تحديث الصور تلقائيًا لا يمكن أن يكون ميزة، لكنها كذلك. تذكر السبب الثاني الذي ذكرناه وافترض أن المطورين يعلمون بوجود الثغرة الأمنية، ثم أصدروا إعلانًا بذلك ونشروا الصورة المصححة. لكن ميزة التحديث التلقائي ليست مدمجة built in في دوكر، فماذا عن بودمان؟ يعتمد الجواب على كيفية تعريفنا لكلمة "مدمجة". نظرًا لأنه ليس لبودمان برنامج خفي، فإنه لا يمكنه إجراء فحوصات منتظمة للحصول على التحديثات. لكن بما أن بودمان هو أحد منتجات ريد هات Red Hat، فيمكن تحديث الحاويات تلقائيًا عن طريق systemd لأنه يتوافق معه، وهذا ما سنتحدث عنه في مقالنا التالي من هذه السلسلة. ملاحظة: لا تعني الأسباب التي ذكرناها أن دوكر غير آمن وأنه يجب على الجميع استخدام بودمان، إذ لا يوجد شيء آمن بنسبة 100%. لكن وجب تسليط الضوء عليها من باب الاحتياط وأخذ الحذر. ثالثًا، النهج المتبع في بودمان ربما لاحظت أن دوكر يتّبِع نهج "الحل الواحد" وأن بودمان يتّبع نهجًا مختلفًا. وهذا يعني أنه ليس عليك سوى تثبيت الملف الثنائي binary لدوكر على نظامك. ويمكنك استخدام الأمر docker لإنشاء الصور ونشرها (إلى السجلات مثل سجل hub.docker.com) وإدارة الحاويات. ولكن بالنسبة لبودمان، نشرت شركة ريد هات Red Hat ثلاثة ثنائيات منفصلة. فعليك استخدام الأمر buildah لبناء الصور. ولنشرها على سجل مثل سجل hub.docker.com، فعليك استخدام الأمر skopeo. ولإدارة الحاويات، فاستخدم الأمر podman. كلا النهجين يؤدي الغرض المرجو منه، إذًا فالأمر يعتمد على ما تفضّله، هل تفضّل استخدام نهج الحل الشامل الذي يقدمه دوكر أم تفضل نهج الحل المتشعب لبودمان. رابعًا، أداة دوكر سوارم Docker Swarm تُعدّ أداة دوكر سوارم Docker Swarm مفيدةً لتوسيع نطاق الحاويات باستخدام عدة أجهزة حقيقية وافتراضية. إذ يمكنك وضع عدة حواسيب ضمن "سرب" أو swarm من أجل غرض محدد. فيمكن أن تخصص سربًا للتعامل مع طلبات قاعدة البيانات فقط، وسربًا آخر للتعامل مع خادم ويب. في حين أن هذه الميزة غير متوفرة في بودمان، إلا أنه يمكنك الاستفادة منها باستخدام Kubernetes. ويمكننا القول إن Kubernetes يستخدم على نطاق أوسع من Docker Swarm، وعند الحاجة إلى التوسع واستخدام عدة أجهزة، فإن Kubernetes يلبي احتياجاتك على أفضل وجه. الخاتمة تُعد أداة دوكر مرادفةً للحاويات. لكن أنشأت شركة ريد هات Red Hat أداة بودمان لإدارة الحاويات للتغلب على بعض أوجه القصور في عمل دوكر. وتوافق بودمان مع أوامر دوكر يُسهل التوجه نحو استخدامها دون الحاجة إلى ترك ما تعلمته عن دوكر. لا يعني ذلك أن المسؤولين عن أداة دوكر لا يعملون على تحسينها، إذ إن إضافة ميزة الحاويات محدودة الصلاحية rootless containers هي خير دليل على ذلك. والآن فإن الخيار متروك لك في استخدام الأداة التي تفضلها، وللتعرف على المزيد حول أداة بودمان، تابع مقالنا التالي. ترجمة وبتصرّف للمقال Understanding the Differences Between Podman and Docker من سلسلة Container Management With Podman. اقرأ أيضًا مدخل إلى دوكر Docker ما الفرق بين دوكر Docker وكوبيرنيتيس Kubernetes؟ كيفية تأمين الحاويات عن طريق سي لينكس SELinux نظام كوبيرنتس Kubernetes وكيفية عمله
-
تتطلع الشركات في وقتنا الحالي إلى العمل بأسلوب ذي وتيرة إنجاز سريع والتركيز على جعل التحديثات "مملة"، لأنها أصبحت بسيطةً ومتوقعة، وهذه هي الخصائص الأساسية لنشر البرامج بصورة مستمرة وبثقة والتعامل مع التحديثات على أنها نشاط اعتيادي. تحدث كل من (دايفيد فارلي) و(جيز هامبل) في عام 2010 في كتابهما التسليم المستمر (Continuous Delivery) عن التصدير المستمر للبرمجيات، إذ ستجد في كتابهما عدة ممارسات لا تزال صالحة في يومنا هذا. إذًا، فالتسليم المستمر Continuous Delivery ليس مفهومًا جديدًا، لكن العديد من المؤسسات لا تزال لا تجيد تطبيقه. ستجد في هذا المقال مفاهيمًا تساعدك على فهم مبدأ النشر المستمر ونصائح لكيفية تطبيق ممارسات عملية لتحسين تقييمات العملاء التي تحصل عليها بعد كل إصدار. ما هو النشر المستمر CD الغرض من النشر هو استخدامه كطريقة للحصول على آراء العملاء، إذ ستحصد أكبر قدر ممكن من تعليقات العملاء عند كل نشر. لكن، للحصول على تعليقات قيّمة، يجب أن تأخذها من مستخدمي برامجك. ولذلك، تحتاج إلى إصدار التحديثات في بيئة الإنتاج production environment. وهذا هو جوهرالنشر المستمر Continuous Deployment أي نشر التعليمات البرمجية في بيئة الإنتاج بصورة آمنة ومستمرة وآلية ومؤتمتة دون الحاجة لإجراء أي تحقق يدوي. ملاحظة: بيئة الانتاج هي مكان نشر التطبيق وجعله متاحًا للمستخدمين، كمثال عليها Play Store أو الموقع الخاص بشركة ما بحيث ترفع تطبيقها عليه على سبيل المثال. قد يخطر في ذهنك أن هذا المفهوم غير مُستَخدَم على أرض الواقع وأنه مفهوم نظري وحسب، لكن تطبق الشركات الكبرى كشركة نتفليكس Netflix وايتسي Etsy وتسلا Tesla مفهوم النشر المستمر لنشر التحديثات البرمجية لتطبيقاتها المختلفة، فعند نشر التحديثات البرمجية تحصل الشركات على آراء المستخدمين بعد الاستخدام الفعلي، وتترجمها إلى خدمات أو تستخدمها لتطوير منتجاتها. وهذا هو الفرق الأساسي بين التسليم المستمر Continuous Delivery والنشر المستمر Continuous Deployment. ما الفرق بين النشر المستمر والتسليم المستمر إن النشر المستمر والتسليم المستمر هما أساس DevOps لكن الاعتقاد أن النشر المستمر هو نفس التسليم المستمر هو خطأ شائع، إذ إنه ثمة فرق بينهما يتعلق بوقت نشر التحديث. فالتسليم المستمر هو القدرة على تجهيز التحديثات البرمجية بحيث تكون جاهزة للإصدار. أي أن التحديثات مرت في أنابيب تجزئة تنفيذ التعليمات ونجحت في جميع الاختبارات، وليس هناك حاجة للعمل عليها. إذًا، أصبحت التحديثات البرمجية مؤهلة للإصدار. أما النشر المستمر فهو استراتيجية إصدار أو نشر تُستخدم في النشر المستمر Continuous Delivery، إن كان التحديث جاهزًا للنشر فيُدفع إلى بيئة الإنتاج تلقائيًا، أي يُصدر. فلا يمكن تطبيق النشر المستمر دون تطبيق التسليم المستمر، وبالتالي فإن التسليم المستمر هو الخطوة الأولى لإصدار التحديثات آليًّا وبسرعة وأمان وبطريقة "مملة" تحتاج إلى تنفيذ بعض الآليات المهمة بدءًا من التكامل المستمر. وللتعرف على المزيد من المعلومات حول أبرز الفروقات بين النشر المستمر والتسليم المستمر ننصحك بمشاهدة الفيديو التالي: ما سبب أهمية التكامل المستمر يُعد التكامل المستمر إحدى الممارسات المهمة لبناء خط تجزئة يصَدّر البرمجيات آليًّا مع التركيز على الجودة. توجد ثلاث قواعد أساسية للتكامل المستمر: يبنى البرنامج من فرع واحد من مجلد الشيفرة البرمجية code repository. يستخدم خط التجزئة مجموعة اختبارات مؤتمتة وموثوقة. إذا فشل بناء البرنامج، تتوقف عملية التكامل وتُلغى التعديلات. وبهذه الطريقة، تحرص على أن جميع التعديلات مؤهلة للإصدار، حتى لو أجلت الإصدار إلى وقت آخر أو منصة آخرى. لكن القاعدة الأهم هي إجراء اختبارات مؤتمتة موثوق بها. كما ستحتاج إلى إجراء اختبارات سريعة وتعمل بالتوازي، واختبارات لجميع السيناريوهات المهمة في تطبيقك، مثل اختبار المسار السعيد happy path test، واختبار للبيانات التي عطلت الإنتاج سابقًا، واختبار إدخال بيانات غير صحيحة. لا تحتاج إلى الحصول على درجة تغطية الشيفرة code coverage بنسبة 100%، ولكن يجب عليك زيادة عدد الاختبارات التي تجريها تدريجيًا قبل الإعلان عن جاهزية التعديلات البرمجية. لن تجري الأمور بسلاسة دائمًا كما خططت، وهذا أمر متوقع. ولهذا يجب أن تكون لديك القدرة على حل المشكلات فورًا. لا تترك خط التجزئة معطوبًا أبدًا. فالهدف هو ترك مسار متوفر في حال احتجت إلى إجراء تغيير طارئ، والاستمرار في استخدام خط التجزئة المؤتمت الذي أنشأته. وبطبيعة الحال، لن تصل إلى هذه النقطة بين عشية وضحاها، لذلك يجب أن تتبنى عقلية التحسين المستمر كي تنجح. والآن سنتعمق أكثر في كيفية تطبيق النشر المستمر. كيفية تطبيق النشر المستمر الخطوة الأولى، هي التدرب على أجزاء صغيرة من العمل، لا تنتظر حتى تجمّع تعديلات كافيةً أو مهمةً كي تنشر تحديثًا في بيئة الإنتاج. فكلما كانت التعديلات صغيرة، كان اختبارها ونشرها أسهل وأسرع. وتستطيع بهذه الطريقة التدرب مرارًا حتى تصل إلى نقطة يكون فيها وضع التعديلات مستقرًا. كما أن استخدام الأدوات هو أمر مهم، لذلك يجب أن تستخدم أدوات تساعدك في بناء، واختبار، وتحزيم، ونشر، وإصدار البرامج بصورة آليّة. إن إدارة الميزات Feature Management تُعد مفيدة للغاية، إذ يمكنك أن تفعّل التحديثات البرمجية للعملاء بنقرة واحدة. وبهذه الطريقة، تجعل الشيفرة البرمجية جاهزة للإصدار حتى لو لم تكن مكتملة. إذ يمكنك تفعيل ميزة ما لكي تختبرها، أو تفعيلها في جزء معين من الشيفرة لإجراء اختبارات ألف/باء أو A/B tests وأي اختبار آخر. فكل ذلك متاح بالإضافة إلى الحصول على آراء العملاء القيمة فورًا، وإنتاج برامج أفضل مع كل إصدار. لكن يجب أن تطبق النشر المستمر لغرض واضح مثل الابتكار، أو تحسين جودة البرامج، أو إصدار الميزات في الوقت المناسب. حتى إن وُجِدت قيود لا تسمح لك بتطبيق النشر المستمر، فإن الاستعداد لذلك سيساعدك على تقليل الوقت والجهد اللازمين لكل إصدار. الخاتمة لنلخص ما ورد في مقالنا، النشر المستمر هو القدرة على إصدار التحديثات البرمجية آليًّا دون أي تدخل بشري. تحتاج لتطبيق ذلك إلى الاعتماد على مجموعة اختبارات مُحكمَة الإعداد لتلافي حدوث الأخطاء، كما أن تقسيم التغييرات الكبيرة إلى تغييرات أصغر يسمح لك بالتدرب أكثر وتقليل احتمالات ظهور الأخطاء (كما يسهل التراجع عن عن هذه التغييرات الصغيرة). لا يمكنك تطبيق النشر المستمر بين عشية وضحاها، إذ إنه ثمة سلسلة من الخطوات التي عليك اتباعها أولاً. وترتيب هذه الخطوات هو كالتالي: التكامل المستمر، ثم التسليم المستمر، ثم النشر المستمر. كما يمكنك التدرب في بيئة التطوير أو الاختبار، وليس ضروريًا أن تبدأ في بيئة الإنتاج، ولكن عليك أن تحدد ما تريد إنجازه، مثلًا هل تريد تحقيق وقت تسويق قصير Time To Market، أم تريد تحقيق مدة توريد Lead Time قصيرة، أم تريد إجراء المزيد من التجارب. يمكنك اعتماد فحص يدوي أخير إذا كنت تحتاج إلى ذلك (على سبيل المثال، للتحقق من التوافق، أو التحقق من متاجر تطبيقات الأجهزة المحمولة، أو الأجهزة الطبية)، ولكن هذا يُعد تسليمًا مستمرًا، ولا بأس في ذلك. إذ يمكن تطبيق الممارسات والأدوات المذكورة في مقالنا، بغض النظر عن مجال عملك أو كميته. وإذا كان لديك من الاستفسارات حول ما ورد في مقالنا، أو أردت الحصول على الدعم والمساعدة أضف سؤالك في قسم التعليقات أسفل المقال، أو اكتبه في قسم الأسئلة والأجوبة في أكاديمية حسوب. ترجمة -وبتصرف- للمقال What Is Continuous Deployment? A Complete Explanation من موقع Cloudbees. اقرأ أيضًا مدخل إلى التكامل المستمر والنشر المستمر CI/CD أفضل ممارسات منهج التكامل المستمر والتسليم المستمر CI/CD إعداد التكامل المستمر والنشر المستمر باستخدام الخدمتين CircleCI وCoveralls التكامل المستمر: تثبيت Concourse CI على أوبنتو محاكاة عقلية DevOps
-
تعد الصور ذات الصيغ التالية JPG و PNG و GIF إحدى أكثر صيغ الصور الشائعة منذ التسعينات. لكن، بخلاف صور JPG و PNG، فإن صور GIF تحتوى على إطارات متعددة من الرسوم المتحركة، وهي منتشرة انتشارًا واسعًا في شبكة الإنترنت. تعد صور GIF أو نسق الرسومات المتبادلة تقنيةً قديمةً وقد أصبحت أقل فاعلية من تضمين مقاطع الفيديو الويب، لأن معظم فيديوهات الويب تستخدم تقنيات ضغط حديثة وبرامج ترميز Codecs أحدث من المستخدمة في الصور المتحركة GIF. تُستخدم برامج الترميز Codecs (أو المرمازات) لترميز مقاطع الفيديو وفك ترميزها، وتحتوي معظم المنصات على عتاديات مخصصة لتشغيل برامج الترميز هذه. أما ملفات GIF، يُفَك ترميزها مباشرةً باستخدام وحدة المعالجة المركزية CPU، حيث إن حمل وحدة المعالجة المركزية اللازم لمعالجة ملف GIF منخفض الدقة ذو إطارات متحركة قليلة لا يكاد يذكر، ولكن يمكنك من الناحية الفنية إنشاء ملف GIF بدقة ومعدل إطارات مماثل لمقاطع فيديوهات YouTube، وسوف تتفاجأ بعدد موارد النظام التي يستهلكها ذلك. وعلى الرغم من ذلك، لا تزال ملفات GIF مفيدة لأنها تُعد صورًا وليست مقاطع فيديو، ونظرًا لطريقة عمل الويب والتطبيقات الأخرى، فهذا يعني أنها ستُعرض وتحرك تلقائيًا في عدة تطبيقات، ولن تحتاج إلى تضمينها أو ربطها على نحو منفصل. ويُعد استخدام صور GIF مفيدًا في صور التفاعل، أو لتطوير الخيال التفاعلي، أو في تنسيقات العروض الأخرى. سنتعرف في هذا المقال على عدة أدوات لإنشاء الصور المتحركة GIF من مقاطع الفيديو، وعلى كيفية تحسين حجمها ودقتها، وطريقة استخدامها في عدة مجالات. كما يمكنك دمج هذه الأدوات واستخدامها في حزمة تطبيقات أخرى. المتطلبات سنزودك في هذا المقال بإرشادات تثبيت خادم أوبنتو 22.4، يمكنك الاستعانة بالمقال التالي لتثبيته. كما ستحتاج إلى تثبيت مدير الحزم Homebrew لتثبيت إحدى الأدوات التي سنتحدث عنها في مقالنا. الخطوة الأولى: تثبيت الأدوات ffmpeg وGifski وGifsicle ستحتاج إلى ثلاثة أدوات كي تستطيع متابعة خطوات هذا المقال. أول أداة ستحتاجها هي ffmpeg التي سنستخدمها لقص الفيديو والتعديل عليه، ثم سنستخدم Gifski لإنشاء صور GIF، و Gifsicle لتحسين الصور والتعديل عليها. ستجد هذه الأدوات متاحة في أغلب المنصات. كلا الأداتان ffmpeg و gifsicle متاحتان في مستودعات أوبنتو، ويمكنك تنزيلها باستخدام مدير الحزم apt. أولًا، حَدّث الحزم باستخدام الأمر apt update: sudo apt update ثم ثبت حزمتي ffmpeg و gifsicle باستخدام الأمر apt install: sudo apt install ffmpeg gifsicle أما الأداة الثالثة gifski فهي متاحة بواسطة Homebrew ويمكنك تثبيتها بواسطة الأمر brew install: brew install gifski قد يستغرق ذلك بضع دقائق لأن Homebrew سيثبت بعض الاعتماديات dependencies. والآن، بعد أن ثبّت جميع الأدوات اللازمة على جهازك، عليك اختيار فيديو لإنشاء صورة GIF منه. الخطوة الثانية: تنزيل وفحص ملف الفيديو بإمكانك إنشاء صورة GIF من أي مقطع فيديو على جهازك، أو يمكنك استخدام الفيديو التعريفي بمنصة تطبيقات DigitalOcean. لتنزيل نسخة من الفيديو من باستخدم الأمر curl: curl -O https://deved-images.nyc3.digitaloceanspaces.com/gif-cli/app-platform.webm curl هي إحدى أدوات سطر الأوامر تخولك من إنشاء مختلف طلبات الويب web request، مثلًا عند استخدام الراية -o مع عنوان URL فهذا يوّجه curl إلى تنزيل ملف من الإنترنت وتخزينه على جهازك بنفس الاسم. والآن، بعد أن أصبح عندك نسخةً من الفيديو على جهازك، بإمكانك التحقق من بياناته الوصفية metadata لأن ذلك مفيد عند إنشاء صورة GIF ذات جودة عالية. بعد تثبيت الأداة ffmpeg يمكنك استخدام الأمر ffprobe الذي يسمح لك التحقق من الدقة resolution، ومعدل الإطارات framerate، والمعلومات الأخرى في ملفات الوسائط. استعرض هذه المعلومات باستخدام الأمر ffprobe على الفيديو app-platform.webm الذي نزلته: ffprobe app-platform.webm ستحصل على الخرج التالي: Output … Input #0, matroska,webm, from 'app-platform.webm': Metadata: ENCODER : Lavf59.27.100 Duration: 00:01:59.04, start: -0.007000, bitrate: 1362 kb/s Stream #0:0(eng): Video: vp9 (Profile 0), yuv420p(tv, bt709), 1920x1080, SAR 1:1 DAR 16:9, 25 fps, 25 tbr, 1k tbn (default) Metadata: DURATION : 00:01:59.000000000 Stream #0:1(eng): Audio: opus, 48000 Hz, stereo, fltp (default) Metadata: DURATION : 00:01:59.041000000 يعرض الخرج التدفقات Streams الموجودة في الملف (عادةً فيديو واحد ودفق صوتي واحد على الأقل)، بالإضافة إلى معدل العينات sample rate، وبرامج الترميز Codecs، والخصائص الأخرى للتدفقات. لاحظ أن المعلومات المظللة في الخرج تدلنا أن الفيديو مرمز بدقة 1080 بكسل، ويُشَغل بمعدل 25 إطارًا في الثانية، كما أن طوله دقيقتين تقريبًا، وهو طويل جدًا بالنسبة لصورة GIF واحدة! أصبح عندنا المعلومات الكافية للانتقال إلى الخطوة التالية حيث سنقص مقطعًا من هذا الفيديو لإنشاء صورة GIF منه. الخطوة الثالثة، قص مقطع من الفيديو الآن أصبح لديك مقطع فيديو مدته دقيقتان وأصبحت تعرف خصائصه. قبل تحويله إلى صورة GIF عليك تقصير الفيديو،. ولا يُستحسن تشغيل مقطع الفيديو في الطرفية، لذا شاهد الفيديو على YouTube لتختار المقطع الذي تريده. اخترنا في مقالنا المقطع من الثانية 00:00:09 إلى الثانية 00:00:12، مما ينتج لدينا مقطعًا متحركًا سلسًا على النحو التالي: يمكنك قص الفيديو app-platform.webm باستخدام الأداة ffmpeg كالتالي: ffmpeg -ss 00:00:09 -to 00:00:12 -i app-platform.webm -c copy clip.webm إليك الشرح التفصيلي للأمر السابق: يعبر الجزء الأول -ss 00:00:09 -to 00:00:12 عن كيفية فهم ffmpeg للشيفرة الزمنية، من نقطة البدء إلى نقطة النهاية. كما يمكنك القص اعتمادًا على المدة أو أجزاء من الثانية. الجزء -i app-platform.webm هو مسار الفيديو مسبوقًا بـ -i. نحدد بعد الجزء -c copy مرماز فيديو الخرج أو الصوت للأداة ffmpeg، واستخدمنا للأمر copy بدلًا عن برنامج ترميز كي نحصل على الفيديو الجديد بسرعة، وبدون ترميز، ولنتفادى انخفاض دقة الفيديو. وبما أننا سننشأ صورة GIF فلا بأس إن حافظنا على نفس الصيغة في ملف الخرج لتوفير الوقت، لأننا سنحول الفيديو الناتج إلى صورة متحركة. الجزء clip.webm هو مسار الفيديو الناتج. ستحصل بعدها على فيديو مدته ثلاث ثواني باسم clip.webm، ويمكنك التأكد من حجمة باستخدام الأمر ls -lh: ls -lh clip.webm ستحصل على النتيجة التالية: Output -rw-r--r-- 1 sammy sammy 600K Nov 16 14:27 clip.webm لاحظ أن حجم ثلاث ثوانٍ من مقطع الفيديو هو 600K، بامكانك استخدام هذا الحجم كمرجع للمقارنة عندما تنشأ صورة GIF في الخطوة التالية. ملاحظة: إن كنت تستعمل جهازك المحلي، فيمكنك استخدام الأداة Lossless Cut وهي أداة واجهة رسوميات مفتوحة المصدر تستخدم لقص مقاطع الفيديو. تُعد هذه الأداة مفيدةً لأنها تنفذ نفس أوامر ffmpeg لاستخراج وقص مقاطع فيديو بسرعة استنادًا إلى الشيفرة الزمنية، دون إعادة ترميز الفيديو. بخلاف تشغيل ffmpeg في الطرفية، فإن Lossless Cut تحتوي على مشغل فيديو مدمج وواجهة تنقل. الخطوة الرابعة، تحويل الفيديو إلى صورة GIF بعد أن أصبح لديك مقطع فيديو مدته ثلاث ثوان وأصبحت تعرف معدل الإطارات والدقة اللازمة، بإمكانك الآن إنشاء صورة GIF منه. كما يمكنك تطوير خط آلي لتحويل مقاطع الفيديو إلى صور GIF، وحينها تستخدم الأداة ffprobe لاستخراج دقة الفيديو ومعدل الإطارات تلقائيًا من الفيديو وتمريرها مباشرةً إلى الأوامر اللاحقة. في مقالنا، سندخل يدويًا قيم الدقة ومعدل الإطارات للخرج المطلوب. لدينا عدة خيارات لإنشاء صور GIF في سطر الأوامر، يمكننا استخدام ffmpeg لوحدها لكن صيغة أوامرها صعبة الفهم والتغيير: ffmpeg -filter_complex "[0:v] fps=12,scale=w=540:h=-1,split [a][b];[a] palettegen [p];[b][p] paletteuse" -i clip.webm ffmpeg-sample.gif لاحظ أننا في مثالنا قلصنا الدقة ومعدل الإطارات إلى النصف، لنحصل على معدل إطارات 12fps ودقة بمقدار 540p بكسل، وتعد هذه بدايةً جيدة بالنسبة لصور GIF لأنها تعامل معاملة الصور العادية، إذ تُنَزل بالكامل عند تحميل صفحة ويب، بخلاف مقاطع الفيديو التي لا تُحَمّل تدريجيًا بدقة أقل. يمكنك استخدام شبكات توزيع المحتوى CDN لتحسين تسليم الأصول الثابتة للموقع مثل الصور، ولكن يجب أن تتفادى عرض الصور الضخمة دون هدف محدد. ولذا يجب ألا تنشأ صور GIF ذات حجم أعلى من 3 ميغا بايت، والآن، لنتحقق من حجم الصورة التي أنشأتها بواسطة الأمر ls -lh: ls -lh ffmpeg-sample.gif وستحصل على الخرج التالي: -rw-r--r-- 1 sammy sammy 2.0M Nov 16 14:28 ffmpeg-sample.gif أنشأنا بهذه الطريقة صورة GIF حجمها 2 ميغا بايت. لكن يمكننا الحصول على نتيجة أفضل باستخدام صياغة برمجية أقل تعقيدًا بواسطة gifski: gifski --fps 12 --width 540 -o gifski-sample.gif clip.webm لاحظ أننا ذكرنا التفاصيل المهمة كمعدل الإطارات والدقة، بالإضافة إلى اسمي ملفي الدخل والخرج. تحقق من الملف الناتج باستخدام الأمر التالي: ls -lh gifski-sample.gif لتحصل على الخرج التالي: -rw-r--r-- 1 sammy sammy 1.3M Nov 16 14:33 gifski-sample.gif حصلت على صورة GIF متحركة حجمها 1.3 ميغابايت وذلك يعد تحسنًا ملحوظًا عن النتيجة السابقة خاصةً أننا حافظنا على نفس الجودة. قد ترغب في إنشاء صورة ذات معدل إطارات كامل وبالدقة الكاملة كي تستطيع المقارنة وملاحظة الفرق: gifski --fps 25 --width 1080 -o gifski-high.gif clip.webm تحقق من حجم الملف الناتج: ls -lh gifski-high.gif الخرج -rw-r--r-- 1 sammy sammy 6.9M Nov 16 14:37 gifski-high.gif لاحظ أن حجم 6.9 ميغا بايت هو حجم كبير جدًا خصيصًا أن حجم الفيديو الأصلي هو 0.6 ميغا بايت وحسب! وتذكر أن صور GIF ليست ذات فاعلية مقارنةً ببرامج ترميز الفيديو الحديثة، فعليك التضحية قليلًا عندما تخفّض حجمها إلى حجم مقبول. سنتعلم في الخطوة التالية كيفية تحسين صور GIF. ملاحظة: إذا كنت تستخدم خادمًا بعيدًا لتنفيذ خطوات مقالنا، فيمكنك تنزيل الملفات وفحصها محليًا على جهازك، أو يمكنك نقلها إلى مجلد يمكن الوصول إليه من الويب كي تستعرضها في متصفح الويب. بهذه الطريقة سيصبح لديك مرجع مرئي لجودة الرسوميات. الخطوة الخامسة: تحسين صورة GIF والتحقق منها وعرضها سنستخدم الأداة gifsicle في الخطوة الأخيرة من مقالنا لتحسين جودة صورة GIF إذ إن ميزات استخدام gifsicle مع ملفات GIF تشابه ميزات استخدام ffmpegمع ملفات الصوت والفيديو وتمكننا من فعل أي شيء نرغبه، ولكن استخدامها قد يكون معقدًا جدًا. ولذلك، سنستخدم gifski لإنشاء صور GIF، وسنركز على بعض أوامر gifsicle لتحسين الصور أو معالجتها. أولًا، شَغّل أمر تحسين gifsicle القياسي: gifsicle -O3 --lossy=80 --colors 256 gifski-sample.gif -o optimized.gif لاحظ أننا في الأمر السابق طبقنا الخيار الثالث -O3 للحصول على أفضل تحسين، وطبقنا الخيار lossy 80-- لتحديد نسبة 20% كالحد الأقصى المسموح به لانخفاض الجودة عن الملف الأصلي، واخترنا --colors 256 لتطبيق 256 لون كحد أقصى في الصورة الناتجة. سيُنتِج ذلك صورةً ذات جودة أعلى من المتوقع بدون خسارة ملحوظة في الجودة لأن صور GIF لا تستخدم خوارزميات ضغط الإطارات الداخلية الحديثة، ولا تستخدم تقنيات ضغط صور JPEG. كما يشير 256 لونًا هنا إلى أي لوحة ألوان مكونة من 256 لونًا وفقًا للألوان الموجودة في ملف GIF، ولا يعبر عن لوحة ألوان محددة مكونة من أشيع 256 لون. وبصورة عامة، لا يكون ضغط GIF ملحوظًا. والآن، تحقق من حجم الصورة المحسنة optimized.gif: ls -lh optimized.gif وستحصل على الخرج التالي: -rw-r--r-- 1 sammy sammy 935K Nov 16 14:44 optimized.gif لاحظ أن الخطوة الأخيرة خفضت حجم الملف بنجاح إلى 935 كيلو بايت أي أكثر من حجم الفيديو الأصلي بقليل، وهو حجم مقبول لصورة متحركة. وهي نفس الصورة التي عرضناها سابقًا في مقالنا. يمكنك الاطلاع على دليل Gifsicle للتعرف على الطرق الأخرى لمعالجة صور GIF. على سبيل المثال، يمكنك "تقسيم" ملف GIF إلى ملفات صور متعددة، واحد لكل إطار رسوم متحرك باستخدام الأمر التالي: gifsicle --explode optimized.gif الذي ينشأ عدة ملفات اسمائها على نسق optimized.gif.000، optimized.gif.001 وهكذا، لكل صورة. استخدم الأمر ls -lh لعرض ملفات الصور: ls -lh optimized* لتحصل على الخرج التالي: -rw-r--r-- 1 sammy sammy 935K Nov 16 14:46 optimized.gif -rw-r--r-- 1 sammy sammy 20K Nov 16 14:54 optimized.gif.000 -rw-r--r-- 1 sammy sammy 17K Nov 16 14:54 optimized.gif.001 -rw-r--r-- 1 sammy sammy 22K Nov 16 14:54 optimized.gif.002 -rw-r--r-- 1 sammy sammy 22K Nov 16 14:54 optimized.gif.003 … كما يمكنك تدوير الصورة باستخدام خيار التدوير بمقدار 90 درجة --rotate-90 أو 180 درجة --rotate-180: gifsicle --rotate-90 optimized.gif -o rotated.gif على الرغم من عدم كفاءتها، لا تزال صور GIF مفيدةً لأنه يمكن استخدامها في عدة مواضع، عند الحاجة إلى مقطع متحرك قصير مثلًا، أو عند الحاجة إلى استخدام صيغة الصورة وليس الفيديو، أحيانًا لن تجد بديلًا عن صورة GIF. الخاتمة استخدمنا في مقالنا عدة أدوات لإنشاء صورة GIF من مقطع فيديو وتحسينها. كما تعرفنا على أدوات معالجة الفيديو مفتوحة المصدر وأدوات معالجة ملفات GIF، بالإضافة إلى بعض الخيارات لتعديل ملفات GIF. تعد صور GIF تقنيةً قديمةً ومثيرةً للاهتمام، لكن على الرغم من أنها ليست حديثة، إلا أنه لا يوجد لها بديل في بعض السياقات، كما أن أدوات التعامل مع صور GIF ذات أداء ودعم جيد.. والآن، أنشأ صور GIF وطبق ما تعلمناه في مقالنا هذا. وفي حال كان لديك مزيد من الاستفسارات حول ما ورد في المقال، أو أردت الحصول على الدعم والمساعدة أضف سؤالك في قسم الأسئلة والأجوبة في أكاديمية حسوب. ترجمة -وبتصرف- للمقال How To Make and Optimize GIFs on the Command Line. اقرأ أيضًا نصائح لإنشاء صور GIF دائمة الحركة كيف تنشئ صورًا متحركة بصيغة GIF من مجموعة صور PNG باستخدام ImageMagick وسطر الأوامر 10 أدوات وتطبيقات مجانية تسهل عليك تحسين الصور البحث عن الملفات والمجلدات على لينكس باستخدام الأمر find
-
تتطلب الأنظمة الحاسوبية الإدارة والمراقبة المناسبة، إذ تساعد مراقبة عمل النظام على اكتشاف المشكلات وحلها بسرعة. وثمة عدة أدوات أُنشئت لهذا الغرض، سنُعَرّفك في هذا المقال على أهم هذه الأدوات والتطبيقات. المتطلبات الأساسية لمتابعة خطوات هذا المقال، ستحتاج إلى ما يلي: حاسوب يعمل بنظام تشغيل لينكس Linux. يمكنك استخدام خادم خاص افتراضي VPS والاتصال به باستخدام بروتوكول SSH أو استخدام جهازك المحلي. استخدمنا في مقالنا خادم أوبنتو 20.04، لكن يمكنك اتباع أمثلتنا باستخدام أي من توزيعات لينكس. إن كنت تستخدم خادمًا بعيدًا فننصحك بالإطلاع على دليل إعداد الخادم الأولي لإعداد بيئة عمل آمنة على الخادم، ومستخدم غير جذري ذي صلاحيات sudo وجدار حماية، كما أن ذلك سيحسن مهاراتك في التعامل مع أنظمة لينكس. الخطوة الأولى: عرض العمليات الجارية Running Processes في لينكس يمكنك استعراض العمليات قيد التنفيذ في خادمك باستخدام الأمر top: top وستحصل على الخرج التالي: Output top - 15:14:40 up 46 min, 1 user, load average: 0.00, 0.01, 0.05 Tasks: 56 total, 1 running, 55 sleeping, 0 stopped, 0 zombie Cpu(s): 0.0%us, 0.0%sy, 0.0%ni,100.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Mem: 1019600k total, 316576k used, 703024k free, 7652k buffers Swap: 0k total, 0k used, 0k free, 258976k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1 root 20 0 24188 2120 1300 S 0.0 0.2 0:00.56 init 2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd 3 root 20 0 0 0 0 S 0.0 0.0 0:00.07 ksoftirqd/0 6 root RT 0 0 0 0 S 0.0 0.0 0:00.00 migration/0 7 root RT 0 0 0 0 S 0.0 0.0 0:00.03 watchdog/0 8 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 cpuset 9 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 khelper 10 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kdevtmpfs لاحظ أن الأسطر الأولى من الخرج تزودنا بمعلومات أو إحصائيات statistics عن النظام، مثل حمل استخدام وحدة المعالجة المركزية والذاكرة والعدد الإجمالي للمهام قيد التشغيل. لاحظ أن هناك عملية واحدة قيد التشغيل، و 55 عملية خاملة Sleeping لأنها لا تستخدم وحدة المعالجة المركزية ويُظهر باقي الخرج العمليات الجارية وإحصائيات استخدامها. يرتب الأمر top هذه العمليات تلقائيًا حسب استخدام وحدة المعالجة المركزية، كي ترى العمليات الأكثر استهلاكًا للموارد أولاً. يستمر top في العمل في سطر الأوامر shell إلى أن توقفه باستخدام المفتاحين Ctrl + C للخروج من العملية الجارية.إذ يُرسل هذا إشارة إيقاف kill، ويطلب من العملية التوقف بأمان إذا كان ذلك ممكنًا. كما تتوفر في معظم مستودعات الحزم نسخة محسنة من الأمر top، تدعى htop. يمكنك تثبيت هذا الأمر على خادم أوبنتو باستخدام الأمر apt: sudo apt install htop شغّل بعد ذلك الأمر htop إذ أصبح متاحًا على جهازك: htop وستحصل على الخرج التالي: Mem[||||||||||| 49/995MB] Load average: 0.00 0.03 0.05 CPU[ 0.0%] Tasks: 21, 3 thr; 1 running Swp[ 0/0MB] Uptime: 00:58:11 PID USER PRI NI VIRT RES SHR S CPU% MEM% TIME+ Command 1259 root 20 0 25660 1880 1368 R 0.0 0.2 0:00.06 htop 1 root 20 0 24188 2120 1300 S 0.0 0.2 0:00.56 /sbin/init 311 root 20 0 17224 636 440 S 0.0 0.1 0:00.07 upstart-udev-brid 314 root 20 0 21592 1280 760 S 0.0 0.1 0:00.06 /sbin/udevd --dae 389 messagebu 20 0 23808 688 444 S 0.0 0.1 0:00.01 dbus-daemon --sys 407 syslog 20 0 243M 1404 1080 S 0.0 0.1 0:00.02 rsyslogd -c5 408 syslog 20 0 243M 1404 1080 S 0.0 0.1 0:00.00 rsyslogd -c5 409 syslog 20 0 243M 1404 1080 S 0.0 0.1 0:00.00 rsyslogd -c5 406 syslog 20 0 243M 1404 1080 S 0.0 0.1 0:00.04 rsyslogd -c5 553 root 20 0 15180 400 204 S 0.0 0.0 0:00.01 upstart-socket-br يزودنا htop بتصور أفضل لخيوط وحدة المعالجة المركزية CPU threads وبدعم أفضل للعمليات في الطرفيات الحديثة، وخيارات فرز أوسع، بالإضافة لعدة ميزات أخرى. وبخلاف الأمر top، لا تجد htop مُنَزَلًا تلقائيًا ولكن عليك تنزيله، ويمكن أن تَعُده بديلًا عن top. كما يمكنك الخروج من الأمر htop باستخدام المفتاحين Ctrl+C. إليك بعض الاختصارات التي ستساعدك في استخدام htop بفاعلية أكبر: M: فرز العمليات حسب استهلاك المساحة P: فرز العمليات حسب استهلاك المعالج ?: المساعدة K: إيقاف العملية الجارية F2: ضبط إعدادات htop وضبط خيارات العرض /:: البحث في العمليات كما توجد عدة خيارات أخرى يمكنك الوصول إليها من خلال خيار المساعدة أو الضبط، ارجع إليها لاستكشاف وظائف htop. أما عن خطوتنا التالية، فسنتعلم فيها كيفية مراقبة النطاق الترددي للشبكة. الخطوة الثانية: مراقبة النطاق الترددي للشبكة إذا شعرت بازدياد الحمل على اتصال الشبكة، ولم تدرِ ما هو التطبيق الذي يستهلك الاتصال فيمكنك الاستعانة ببرنامج nethogs لمعرفة ذلك. ثبّت nethogs على خادم أوبنتو باستخدام الأمر التالي: sudo apt install nethogs سيصبح بعدها الأمر nethogs متاحًا للاستخدام: nethogs وستحصل عند تشغيله على الخرج التالي: NetHogs version 0.8.0 PID USER PROGRAM DEV SENT RECEIVED 3379 root /usr/sbin/sshd eth0 0.485 0.182 KB/sec 820 root sshd: root@pts/0 eth0 0.427 0.052 KB/sec ? root unknown TCP 0.000 0.000 KB/sec TOTAL يعرض برنامج nethogs استخدام كل برنامج للشبكة. إليك بعض الاختصارات التي ستسهل عليك التعامل معه: M: تغيير واحدة عرض النطاق الترددي إلى “kb/s” أو “kb” أو “b” أو “mb” R: الفرز حسب حجم البيانات المستلمة S: الفرز حسب حجم البيانات المُرسَلة Q: خروج كما يمكنك استخدام iptraf-ng لمراقبة استهلاك الشبكة، إذ يوفر عدة واجهات مراقبة تفاعلية. ملاحظة: يتطلب IPTraf حجم شاشة لا يقل عن 80 عمودًا و 24 سطرًا. ثبّت iptraf-ng على خادم أوبنتو باستخدام الأمر التالي: sudo apt install iptraf-ng لتشغيل الأمر iptraf-ng يجب أن تعطيه صلاحيات المستخدم الجذري، لذا عليك أن تستخدمه مع sudo: sudo iptraf-ng ستظهر قائمة تستخدم إطار عمل واجهة الطرفية الشائع المسمى ncurses: يمكنك بواسطة هذه القائمة اختيار الواجهة التي تود الوصول إليها. مثلًا، لإلقاء نظرة عامة على حركة البيانات في الشبكة، يمكنك اختيار القائمة الأولى ثم النقر على خيار جميع الواجهات "All interfaces"، وبعدها ستظهر لك شاشة كالتالية: سترى في هذه الواجهة جميع عناوين IP المستخدمة في واجهات شبكتك. إذا أردت تحويل عناوين IP هذه إلى نطاقات، فيمكنك تفعيل البحث العكسي عن DNS عن طريق الخروج من شاشة حركة بيانات الشبكة، ثم النقر على خيار الضبط configure، ثم Reverse DNS lookups. كما يمكنك تفعيل TCP/UDP service names أي أسماء خدمات بروتوكولي TCP/UDP لعرض أسماء الخدمات الحالية بدلًا عن أرقام منافذها. ستبدو الشاشة كالتالي، عند تفعيل الخيارين السابقين: ولدينا أيضًا الأمر netstat الذي يُعد أداةً متعددة الاستخدامات للحصول على معلومات عن الشبكة. والذي يوجد عادةً تلقائيًا في الأنظمة الحديثة، كما يمكنك تثبيته يدويًا من مستودع حزم الخادم الافتراضي package repository. الحزمة التي تحتوي على الأمر netstat في معظم أنظمة لينكس ومن ضمنها أوبنتو، هي net-tools: sudo apt install net-tools يطبع الأمر netstat من تلقاء نفسه قائمة بالمآخذ sockets المفتوحة: netstat ويعرض لك الخرج التالي: Active Internet connections (w/o servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 192.241.187.204:ssh ip223.hichina.com:50324 ESTABLISHED tcp 0 0 192.241.187.204:ssh rrcs-72-43-115-18:50615 ESTABLISHED Active UNIX domain sockets (w/o servers) Proto RefCnt Flags Type State I-Node Path unix 5 [ ] DGRAM 6559 /dev/log unix 3 [ ] STREAM CONNECTED 9386 unix 3 [ ] STREAM CONNECTED 9385 . . . إذا أضفت الخيار a-، فسوف يعرض جميع المنافذ المفتوحة listening والمغلقة not listening netstat -a وستحصل على النتيجة التالية: Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 *:ssh *:* LISTEN tcp 0 0 192.241.187.204:ssh rrcs-72-43-115-18:50615 ESTABLISHED tcp6 0 0 [::]:ssh [::]:* LISTEN Active UNIX domain sockets (servers and established) Proto RefCnt Flags Type State I-Node Path unix 2 [ ACC ] STREAM LISTENING 6195 @/com/ubuntu/upstart unix 2 [ ACC ] STREAM LISTENING 7762 /var/run/acpid.socket unix 2 [ ACC ] STREAM LISTENING 6503 /var/run/dbus/system_bus_socket . . . إذا أردت تصفية النتائج لعرض اتصال TCP فقط أو UDP فقط، فعليك استخدام الراية t- أو u- : netstat -at الخرج Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 *:ssh *:* LISTEN tcp 0 0 192.241.187.204:ssh rrcs-72-43-115-18:50615 ESTABLISHED tcp6 0 0 [::]:ssh [::]:* LISTEN ولاحظ النتائج عند استخدام الراية s- netstat -s الخرج Ip: 13500 total packets received 0 forwarded 0 incoming packets discarded 13500 incoming packets delivered 3078 requests sent out 16 dropped because of missing route Icmp: 41 ICMP messages received 0 input ICMP message failed. ICMP input histogram: echo requests: 1 echo replies: 40 . . . إذا أردت تحديث الخرج باستمرار، يمكنك استخدام الراية c-. ثمة عدة خيارات متاحة للأمر netstat يمكنك التعرف عليها من خلال مراجعة صفحة دليلها التعليمي. سنتعرف، في الخطوة التالية، على بعض الطرق المفيدة لمراقبة استخدام قرص التخزين الخطوة الثالثة: مراقبة استخدام القرص استخدم الأمر df لإلقاء نظرة سريعة على مساحة القرص المتبقية على محرك الأقراص المرفق: df وستحصل على الخرج التالي: Filesystem 1K-blocks Used Available Use% Mounted on /dev/vda 31383196 1228936 28581396 5% / udev 505152 4 505148 1% /dev tmpfs 203920 204 203716 1% /run none 5120 0 5120 0% /run/lock none 509800 0 509800 0% /run/shm يعرض هذا الأمر المساحة المستخدمة بالبايتات، مما قد يجعلها صعبة القراءة، لحل هذه المشكلة اعرض الخرج بطريقة يَسهُل قراءتها على البشر human-readable، وذلك بإضافة الخيار h-: df -h وستحصل على الخرج التالي: Filesystem Size Used Avail Use% Mounted on /dev/vda 30G 1.2G 28G 5% / udev 494M 4.0K 494M 1% /dev tmpfs 200M 204K 199M 1% /run none 5.0M 0 5.0M 0% /run/lock none 498M 0 498M 0% /run/shm استخدم الخيار total-- لعرض إجمالي مساحة القرص المتاحة في جميع أنظمة الملفات، حينها ستُعرض المعلومات في سطر جديد في الأسفل، كما يلي: df -h --total الخرج Filesystem Size Used Avail Use% Mounted on /dev/vda 30G 1.2G 28G 5% / udev 494M 4.0K 494M 1% /dev tmpfs 200M 204K 199M 1% /run none 5.0M 0 5.0M 0% /run/lock none 498M 0 498M 0% /run/shm total 32G 1.2G 29G 4% لاحظ أن الأمر df يزوّدنا بمعلومات مفيدة، أما الأمر du فيستخدم التصنيف حسب المجلد، إذ يحلل الاستخدام للمجلد الحالي والمجلدات الفرعية. يبدو خرج du عند تشغيله في مجلد رئيسي فارغ كما يلي: du الخرج 4 ./.cache 8 ./.ssh 28 . كما يمكنك عرض الخرج بطريقة سهلة القراءة، وذلك بإضافة الخيار h-: du -h وستحصل على الخرج التالي: 4.0K ./.cache 8.0K ./.ssh 28K . ولعرض حجم الملفات والمجلدات، استخدم الخيار a- du -a الخرج 0 ./.cache/motd.legal-displayed 4 ./.cache 4 ./.ssh/authorized_keys 8 ./.ssh 4 ./.profile 4 ./.bashrc 4 ./.bash_history 28 . استخدم الخيار c- لإضافة سطر لعرض المحصلة: du -c وسيصبح الخرج كالتالي: 4 ./.cache 8 ./.ssh 28 . 28 total إذا أردت الحصول على المحصلة فقط دون التفاصيل استخدم الخيار s- du -s وسيكون الخرج كالتالي: 28 . كما توجد واجهة ncurses للأمر du تدعى ncdu ويمكنك تثبيتها باستخدام الأمر التالي: sudo apt install ncdu والذي سيمثل استخدام القرص بيانيًا كالتالي: ncdu الخرج --- /root ---------------------------------------------------------------------- 8.0KiB [##########] /.ssh 4.0KiB [##### ] /.cache 4.0KiB [##### ] .bashrc 4.0KiB [##### ] .profile 4.0KiB [##### ] .bash_history يمكنك التنقل في نظام الملفات باستخدام مفتاح السهم العلوي والسهم السفلي في لوحة المفاتيح والنقر على مفتاح enter لاستعراض المجلد. ستتعلم في الفقرة الأخيرة كيفية مراقبة استخدام الذاكرة. الخطوة الرابعة: مراقبة استخدام الذاكرة يمكنك عرض استخدام الذاكرة الحالي على نظام التشغيل باستخدام الأمر free: free وسيبدو الخرج كما يلي: total used free shared buff/cache available Mem: 1004896 390988 123484 3124 490424 313744 Swap: 0 0 0 لتسهيل قراءة الخرج، استخدم الخيار m- لعرض الحجم بواحدة الميغا بايت: free -m الخرج total used free shared buff/cache available Mem: 981 382 120 3 478 306 Swap: 0 0 0 يحتوي سطر mem على تفاصيل الذاكرة المستخدمة للتخزين المؤقت buffering and caching التي تفرغ محتوياتها عند الحاجة لاستخدامها في عملية أخرى. أما ذاكرة سواب swap فهي مكتوبة على ملف swapfile على القرص للمحافظة على الذاكرة النشطة Active memory. يعرض الأمر vmstat معلومات متعددة عن النظام بما في ذلك معلومات الذاكرة، ومعلومات الذاكرة swap، ومعلومات وحدة المعالجة المركزية، ومداخل ومخارج الأقراص. يمكنك استخدام vmstat لعرض معلومات استخدام الذاكرة: Vmstat الخرج procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu---- r b swpd free buff cache si so bi bo in cs us sy id wa 1 0 0 99340 123712 248296 0 0 0 1 9 3 0 0 100 0 اعرض الخرج بواحدة الميغا بايت عن طريق كتابة الواحدة M بعد الراية S- vmstat -S M Output 495 M total memory 398 M used memory 252 M active memory 119 M inactive memory 96 M free memory 120 M buffer memory 242 M swap cache 0 M total swap 0 M used swap 0 M free swap . . . استخدم الأمر التالي للحصول على معلومات عامة عن استخدام الذاكرة: vmstat -s -S M Output Cache Num Total Size Pages ext4_groupinfo_4k 195 195 104 39 UDPLITEv6 0 0 768 10 UDPv6 10 10 768 10 tw_sock_TCPv6 0 0 256 16 TCPv6 11 11 1408 11 kcopyd_job 0 0 2344 13 dm_uevent 0 0 2464 13 bsg_cmd 0 0 288 14 . . . أما للحصول على معلومات عن استخدام عمليات النظام الفردية لذاكرة التخزين المؤقت cache فاستخدم الأمر التالي: vmstat -m -S M وستحصل على الخرج التالي: Cache Num Total Size Pages ext4_groupinfo_4k 195 195 104 39 UDPLITEv6 0 0 768 10 UDPv6 10 10 768 10 tw_sock_TCPv6 0 0 256 16 TCPv6 11 11 1408 11 kcopyd_job 0 0 2344 13 dm_uevent 0 0 2464 13 bsg_cmd 0 0 288 14 . . . الذي سيزودك بتفاصيل حول المعلومات المخزنة في ذاكرة التخزين المؤقت. الخاتمة أصبحت الآن قادرًا على مراقبة خادمك من سطر الأوامر باستخدام الأدوات التي تعلمتها في مقالنا. وعلى الرغم أنه ثمة عدة أدوات مراقبة أخرى تُستخدم لأغراض مختلفة، إلا أن هذه تُعد انطلاقةًجيدة. ننصحك بعد قراءة هذا المقال بالتعرف على إدارة عمليات لينكس باستخدام ps وkill وnice. لمزيد من الاستفسارات حول ما ورد في مقالنا، أو للحصول على الدعم والمساعدة أضف سؤالك في قسم الأسئلة والأجوبة في أكاديمية حسوب. ترجمة -وبتصرف- للمقال How To Use Top, Netstat, Du, & Other Tools to Monitor Server Resources لصاحبيه Justin Ellingwood و Alex Garnett. اقرأ أيضًا إعداد خادم اختبار محلي مراقبة شهادات SSL/TLS في الموقع باستخدام أداة Checkmk مدخل إلى خادم الويب عشرون أمرا في لينكس يفترض أن يعرفها كل مدير نظم تعرف على عناوين بروتوكول الإنترنت والشبكات الفرعية والتوجيه غير الصنفي بين النطاقات
-
يُعد إطار Express أحد الإطارات الشائعة لبناء تطبيقات الويب السريعة وواجهات برمجة التطبيقات API باستخدام بيئة التشغيل Node.js. منصة تطبيقات DigitalOcean عبارة عن منتج منصة على أساس خدمة PaaS لضبط إعدادات التطبيقات ونشرها من مستودع شيفرات برمجية، فهي توفر طريقة سريعة وفعالة لنشر تطبيقات Express. سنتعلم في دليلنا هذا، كيفية نشر تطبيق Express على منصة تطبيقات DigitalOcean ثم توسيع نطاقه عن طريق إضافة التخزين المؤقت باستخدام إضافة متجر DigitalOcean Marketplace المخصصة لـ MemCachier. إذ يتوافق MemCachier مع نظام memcached للتخزين المؤقت للكائنات ولديه عدة مزايا، مثل تحسين سيناريوهات الفشل باستخدام مجموعة حواسيب عالية التوفر. سننشئ أولاً تطبيق Express يحسب عددًا أوليًا، ويحتوي على زر "أعجبني"، ويستخدم محرك قوالب Template engine. ستمكنك هذه الميزات من تنفيذ عدة استراتيجيات تخزين مؤقت لاحقًا. ثم ستدفع شيفرة التطبيق على Git Hub لتنشره بعدها على منصة التطبيقات App Platform. وأخيرًا، ستطبق ثلاث تقنيات تخزين مؤقت للكائنات لتسريع التطبيق وجعله سهل التطوير والتوسع. بنهاية هذا المقال، ستكون قادرًا على نشر تطبيق Express على منصة App Platform، وتطبيق تقنيات التخزين المؤقت لتخزرين العمليات ذات الاستخدام الكثيف للموارد، وتخزين طرق العرض المصيّر rendered views، والجلسات sessions. المتطلبات الأساسية لمتابعة خطوات هذا المقال التعليمي، ستحتاج إلى ما يلي: تثبيت بيئة تشغيل Node.js على جهازك العامل بنظام أوبنتو 22.04، ننصحك باتباع خطوات المقال التالي. أما إن كنت تستخدم نظام تشغيل آخر، فعليك اتباع المقال التالي. خادم Express مُثبّت عليه Node.js، ووللقيام بذلك ننصحك بالإطلاع على الخطوتين الأولى والثانية في هذا المقال. حساب غيت هب GitHub و تثبيت غيت Git على جهازك، إذ سننشر التطبيق في حسابك على غيت هب GitHub ثم سننشره على منصة تطبيقات DigitalOcean، اتبع الخطوات الواردة في المقال التالي لتثبيت غيت على جهازك. حساب على DigitalOcean لنشر التطبيق على منصة App Platform، وننبهك إلى أن نشر التطبيقات على هذه المنصة مأجور، لذا اطّلع على أجور منصة App Platform قبل البدء. متصفح إنترنت مثل متصفح كروم Chrome أو فايرفوكس Fire Fox. فهم أساسيات عمل موّلد قوالب Express. فهم آلية عمل البرمجيات الوسيطة middle-ware . الخطوة الأولى: ضبط قالب عرض مصيّر سنثبّت في هذه الخطوة موّلد قوالب Express، وننشئ قالبًا للمسار الرئيسي للتطبيق GET/، ثم سنحدّث المسار كي يستخدم هذا القالب. تمَكّننا القوالب من استخدام التخزين المؤقت للعرض المصيّر rendered view، مما يزيد سرعة معالجة الطلب ويقلل استخدام الموارد. لبدء العمل، انتقل إلى مجلد مشروع خادم Express باستخدام المحرر، سنثبّت محرك قوالب Express لاستخدام القوالب الثابتة في التطبيق، حيث يستبدل محرك القوالب المتغيرات الموجودة في ملف القالب بالقيم ثم يحول القالب إلى ملف HTML، ثم يُرسَل كرد أو استجابة response على طلب request. إذ يؤدي استخدام القوالب إلى تسهيل العمل باستخدام HTML. والآن، ثبّت مكتبة قوالب جافا سكربت المضمنة ejs، كما يمكنك استخدام أحد محركات القوالب التي يدعمها Express مثل Mustache أو Pug أو Nunjucks. npm install ejs بعد تثبيت مكتبة ejs، عليك ضبط إعدادات تطبيق Express كي يستخدمها، وذلك عن طريق فتح الملف server.js في محرر النصوص البرمجية، وإضافة السطر الثالث كما يلي: server.js const express = require('express'); const app = express(); app.set('view engine', 'ejs'); app.get('/', (req, res) => { res.send('Successful response.'); }); ... يعدّل هذا السطر إعدادات التطبيق ويعين خاصيّة view engine على ejs. ثم احفظ الملف بعد ذلك. ملاحظة: سنستخدم في هذا المقال الإعداد view engine، كما يمكنك استخدام الإعداد views الذي يدّل تطبيق Express على مكان وجود ملفات القوالب، وقيمته الافتراضية هي views/. والآن، أنشئ مجلد views ثم أنشئ فيه الملف views/index.ejs وافتحه في محرر النصوص البرمجية. وأضف توصيف القالب إلى الملف: views/index.ejs <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Find the largest prime number</title> </head> <body> <h1>Find the largest prime number</h1> <p> For any number N, find the largest prime number less than or equal to N. </p> </body> </html> ثم احفظ الملف. بعد أن أنشأت القالب، عليك تعديل المسار كي تتمكن من استخدامه. افتح الملف server.js وأضف ما يلي إليه: ... app.get('/', (req, res) => { res.render('index'); }); ... لاحظ أن دالة رد النداء render تأخذ اسم القالب كوسيط أول، وفي مثالنا يتوافق index مع اسم الملف views/index.ejs. والآن، أعد تشغيل التطبيق لكي تطبق التغيرات التي أجريتها. أوقف عمل الخادم في الطرفية باستخدام المفتاحين Ctrl+C ثم أعد تشغيل الخادم باستخدام الأمر التالي: node server.js الآن انتقل إلى localhost:3000 في المتصفح لمشاهدة محتوى القالب، ستحصل على نتيجة مماثلة لما يلي: والآن، أصبح تطبيقك يتمتع بعرض مُصَيّر للقوالب، لكنه لا ينفذ شيئًا الآن. سنضيف في الخطوة التالية وظيفة للعثور على عدد أولي. الخطوة الثانية، إضافة الوظائف إلى تطبيق Express سنضيف في هذه الخطوة ميّزة العثور على عدد أولي، وميّزة إبداء الإعجاب باستخدام زر "أعجبني Like". سنستخدم هذه الميزات للتفاعل مع التطبيق بعد نشره على منصة App Platform في الخطوة الرابعة من هذا المقال. العثور على العدد الأولي سنضيف الآن دالة إلى تطبيقنا وظيفتها العثور على أكبر عدد أولي أقل من أو يساوي N، حيث يشير N إلى عدد ما. سنرسل العدد N عبر استمارة باستخدام التابع GET إلى المسار الرئيسي (/) مع إضافة N كوسيط للاستعلام query، كما يلي: localhost:3000/?n=10 تمثل القيمة 10 هنا عينة الاستعلام، ويمكن أن يحتوي المسار الرئيسي على عناوين URL متعددة تنتج طرق عرض مصيّرة، كما يمكن تخزينها مؤقتًا بصورة فردية. أضف نموذجًا كالتالي يحتوي على عنصر إدخال لإدخال N في الملف views/index.ejs: ... <p> For any number N, find the largest prime number less than or equal to N. </p> <form action="/" method="get"> <label> N <input type="number" name="n" placeholder="e.g. 10" required> </label> <button>Find Prime</button> </form> ... لاحظ أن إجراء النموذج form يُرسَل إلى المسار الرئيسي /، الذي سيُعالَج بواسطة المسار الرئيسي (...'/')get.app في ملف server.js. وبما أن التابع هو get، فستضاف بيانات n إلى عنوان URL كوسيط للاستعلام. بعد ذلك، عند إجراء طلب باستخدام وسيط استعلام n، ستُمَرَر تلك البيانات إلى القالب. أضف الأسطر التالية بعد التابع get على الملف server.js، ثم احفظ الملف: ... app.get('/', (req, res) => { const n = req.query.n; if (!n) { res.render('index'); return; } const locals = { n }; res.render('index', locals); }); ... تتحقق الأسطر السابقة من وجود طلب له وسيط استعلام ذو القيمة n، فإذا تحقق ذلك يُصيَّر الملف index مع تمرير القيمة n إليه، وإلا فيُعرض الملف index بدون بيانات. ملاحظة: لا يمكن الوثوق دائمًا بالبيانات التي يدخلها المستخدم، لذا لإنشاء تطبيق جاهزًا للنشر يُنصح بالتحقق من المدخَلات باستخدام مكتبة joi. لاحظ أن للتابع render وسيط ثاني اختياري locals يُعَرّف المتغيرات المحلية التي تمرر إلى القالب لتصيير العرض. يحدد اسم الواصف المختصر الخاصية n للكائن المحلي locals، فعندما يكون للمتغير نفس اسم واف الكائن المُسند إليه، يمكن حذف اسم المتغير. لذلك يمكن كتابة { n: n } بالشكل { n }. والآن، أصبح بإمكاننا عرض القالب بعد أن أضفنا إليه البيانات. أضف الأسطر التالية على ملف views/index.ejs: <% if (locals.n) { %> <p>N: <%= n %></p> <% } %> ... وهكذا يعرض التطبيق المتغيرات المحلية n إن وجدت. احفظ الملف، ثم أعد تشغيل الخادم لتحديث التطبيق. سيُعرَض النموذج مع زر لإيجاد العدد الأولي Find Prime، حيث يأخذ التطبيق المدخلات من المستخدم ويعرضها تحت النموذج: أدخل عددًا ما ولاحظ أن العنوان URL سيتغير وسيضاف إليه العدد الذي أدخلته، على سبيل المثال، إن أدخلت العدد 40 سيصبح العنوان كالتالي: http://localhost:3000/?n=40 كما سيُعرض العدد الذي أدخلته أسفل النموذج على الشكل التالي N: 40. والآن بعد أن أصبح بإمكاننا إدخال قيمة للعدد N وعرضها، علينا إضافة دالة للعثور على أكبر عدد أولي أصغر أو مساوي للعدد N، وعرض النتيجة على الشاشة. أنشئ مجلد utils، ثم أنشئ الملف utils/findPrime.js. افتح الملف findPrime.js في المحرر ثم أضف الكود التالية لتعريف وظيفة أو دالة للعثور على العدد الأولي، ولا تنسَ حفظ الملف بعدها: utils/findPrime.js /** * Find the largest prime number less than or equal to `n` * @param {number} n A positive integer greater than the smallest prime number, 2 * @returns {number} */ module.exports = function (n) { let prime = 2; // initialize with the smallest prime number for (let i = n; i > 1; i--) { let isPrime = true; for (let j = 2; j < i; j++) { if (i % j == 0) { isPrime = false; break; } } if (isPrime) { prime = i; break; } } return prime; }; يوّثق تعليق JSDoc عمل الدالة، إذ تبدأ الخوارزمية بالعدد الأولي الأول 2، ثم ثم تكرر العمل بدءًا من العدد n وتنقص الرقم بمقدار 1 في كل حلقة. وتستمر الدالة في حلقة التكرار والبحث عن عدد أولي حتى يصبح الرقم 2، وهو أصغر رقم أولي. تفترض كل حلقة أن العدد الحالي هو عدد أولي، ثم تتحقق من صحة هذا الافتراض، عن طريق التحقق من وجود عامل آخر للعدد الحالي آخر غير 1 ونفسه. إذا أمكن قسمة العدد الحالي على أي رقم أكبر من 1 وأقل من العدد نفسه دون باقي، فهو ليس عددًا أوليًا. ثم ستتحق الدالة بعد ذلك من العدد التالي. بعدها، أضف السطر الثاني إلى ملف server.js لاستيراد دالة العدد الأولي: const express = require('express'); const findPrime = require('./utils/findPrime'); ... عدّل على المسار الرئيسي لإيجاد العدد الأولى وتمرير قيمته إلى القالب من خلال إضافة السطر التالي إلى ملف server.js، ثم احفظ الملف: const prime = findPrime(n); والآن، لعرض النتيجة في القالب وإظهار قيمة N أضف الشيفرة التالية في ملف views/index.ejs: <% if (locals.n && locals.prime) { %> <p> The largest prime number less than or equal to <%= n %> is <strong><%= prime %></strong>. </p> <% } %> ... بدلًا عن: <% if (locals.n) { %> <p>N: <%= n %></p> <% } %> ولا تنسَ حفظ الملف، ثم أعد تشغيل الخادم. اختبر عمل الدالة عن طريق إدخال عدد ما، كالعدد 10، ستظهر رسالة: The largest prime number less than or equal to 10 is 7 ومفادها أن العدد الأولي الأعظمي الأصغر أو يساوي العدد 10 هو العدد 7. أصبح بإمكان التطبيق إيجاد وعرض رقم أولي وفقًا لرقم يدخله المستخدم، والآن علينا إضافة زر أعجبني. إضافة زر أعجبني ينتج تطبيقنا حاليًا طرق عرض ونتائج مختلفة بناءً على كل عدد N ندخله، ومن المرجح أن يظل المحتوى كما هو. سيوفر لنا زر أعجبني Like طريقة لتحديث محتوى العرض. يوضح لنا هذا الزر الحاجة إلى إبطال طريقة العرض المخزنة مؤقتًا عند تغير محتوياتها، إذ سيفيدنا ذلك عند التخزين المؤقت لطرق العرض المصيّرة لاحقًا في مقالنا. عند استخدام زر "أعجبني"، يجب تخزين بيانات الإعجاب في مكان ما. على الرغم من أن التخزين الثابت persistent storage مثالي، إلا أننا ستخزن الإعجابات في الذاكرة نظرًا لأن إنشاء قاعدة بيانات يقع خارج نطاق مقالنا. هكذا، ستكون البيانات سريعة الزوال، مما يعني أننا سنفقد كل البيانات عندما يتوقف الخادم. افتح ملف server.js وأضف المتغير التالي: /** * Key is `n` * Value is the number of 'likes' for `n` */ const likesMap = {}; يُستخدم الغرض likesMap كخريطة لتخزين إعجابات الأعداد. المفتاح هو n وقيمه هي عدد إعجابات n. يجب تهيئة إعجابات العدد عند إرساله. أضف السطر الثاني والثالث على ملف server.js لتهيئة إعجابات N: ... const prime = findPrime(n); // Initialize likes for this number when necessary if (!likesMap[n]) likesMap[n] = 0; const locals = { n, prime }; res.render('index', locals); .. تتحقق عبارة if من وجود إعجابات للعدد الحالي. في حالة عدم وجود إعجابات، يُهيَّئ likesMaps على القيمة 0. ثم أضف الإعجابات كمتغير محلي للعرض، عن طريق تعديل سطر المتغيرات المحلية ليصبح كما يلي ولا تنسَ حفظ الملف: const locals = { n, prime, likes: likesMap[n] }; res.render('index', locals); بعد أن أصبح لدينا بيانات الإعجابات، أصبح بإمكاننا عرض قيمتها وإضافة زر أعجبني. عدّل على ملف views/index.ejs لإضافة توصيف Markup لزر أعجبني كما يلي: <% if (locals.n && locals.prime) { %> <p> The largest prime number less than or equal to <%= n %> is <strong><%= prime %></strong>. </p> <form action="/like" method="get"> <input type="hidden" name="n" value="<%= n %>"> <input type="submit" value="Like"> <%= likes %> </form> <% } %> يجب أن يبدو ملف views/index.ejs على النحو التالي: <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Find the largest prime number</title> </head> <body> <h1>Find the largest prime number</h1> <p> For any number N, find the largest prime number less than or equal to N. </p> <form action="/" method="get"> <label> N <input type="number" name="n" placeholder="e.g. 10" required> </label> <button>Find Prime</button> </form> <% if (locals.n && locals.prime) { %> <p> The largest prime number less than or equal to <%= n %> is <strong><%= prime %></strong>. </p> <form action="/like" method="get"> <input type="hidden" name="n" value="<%= n %>"> <input type="submit" value="Like"> <%= likes %> </form> <% } %> </body> </html> لا تنسَ حفظ الملف. ثم أعد تشغيل الخادم. سيظهر على الشاشة زر أعجبني له القيمة 0 بعد ظهور نتيجة العدد الأولي. يؤدي النقر فوق زر "أعجبني" إلى إرسال طلب GET إلى المسار like/، بالقيمة الحالية لـ N كوسيط استعلام عبر إدخال غير مرئي. لكن ستحصل على رسالة خطأ 404 والعبارة Cannot GET /like، لأن التطبيق ليس لديه مسار مطابق بعد. سنضيف الآن المسار اللازم للتعامل مع الطلب، وذلك عبر إضافة الأسطر التالية: app.get('/like', (req, res) => { const n = req.query.n; if (!n) { res.redirect('/'); return; } likesMap[n]++; res.redirect(`/?n=${n}`); }); ... يتحق المسار الجديد من وجود n وفي حال عدم وجودها نعود إلى المسار الرئيسي. أما في حال وجودها، فيزيد التطبيق عدد الإعجابات لهذا العدد. ثم يوجهنا إلى شاشة العرض التي ضغطنا فيها على زر "أعجبني". يجب أن يبدو الملف على النحو التالي: const express = require('express'); const findPrime = require('./utils/findPrime'); const app = express(); app.set('view engine', 'ejs'); /** * Key is `n` * Value is the number of 'likes' for `n` */ const likesMap = {}; app.get('/', (req, res) => { const n = req.query.n; if (!n) { res.render('index'); return; } const prime = findPrime(n); // Initialize likes for this number when necessary if (!likesMap[n]) likesMap[n] = 0; const locals = { n, prime, likes: likesMap[n] }; res.render('index', locals); }); app.get('/like', (req, res) => { const n = req.query.n; if (!n) { res.redirect('/'); return; } likesMap[n]++; res.redirect(`/?n=${n}`); }); const port = process.env.PORT || 3000; app.listen(port, () => console.log(`Example app is listening on port ${port}.`) ); احفظ الملف، ثم أعد تشغيل التطبيق واختبر زر "أعجبني"، يجب أن يزداد عدد الإعجابات مع كل نقرة. ملاحظة: يمكنك استخدام تابع POST بدلاً من GET لهذا المسار، والذي يوافق نمط RESTful أكثر لأننا حدثنا أحد الموارد. نستخدم في مقالنا تابع GET بدلاً من التعامل مع طلب POST حتى تتمكن من العمل مع وسطاء استعلام الطلب المألوفة. أصبح التطبيق مكتملًا الآن ويعمل جيدًا، ويمكنك الاستعداد لنشره على منصة App Platform. في الخطوة التالية، سنُوْدِع الشيفرة في غيت Git، ثم ندفعها إلى مستودع غيت هب GitHub. الخطوة الثالثة، إنشاء مستودع الشيفرات البرمجية سننشئ في هذه الخطوة مستودع شيفرات برمجية Code Repository كي نخزّن فيه الملفات اللازمة للنشر. سنُوْدِع commit الشيفرة في غيت Git، ثم ندفعها push أو نضيفها إلى مستودع غيت هب GitHub، الذي سنستخدمه لنشر التطبيق على App platform. إيداع الشيفرة في جيت سنُودع الشيفرة في جيت كي تصبح جاهزةً لإضافتها أو دفعها إلى جيت هب. ملاحظة: إن لم تسجل الدخول إلى حسابك وتضبط الإعدادات، فاحرص على إعداد غيت و مصادقته حسابك على غيت هب باستخدام بروتوكول SSH. أولًا، عليك تهيئة مستودع غيت: git init ثم عليك استبعاد اعتماديات التطبيق dependencies، وذلك بإنشاء ملف اسمه gitignore. وإضافة الشيفرة التالية فيه: .gitignore node_modules # macOS file .DS_Store ملاحظة: السطر DS_Store. خاص بالأجهزة التي تعمل باستخدام نظام ماك أو إس mac OS ولا حاجة لإضافة إن كان نظام التشغيل مختلفًا. والآن احفظ الملف. ثم أضف كل الملفات إلى غيت: git add . وأَودِع التغييرات بواسطة الأمر التالي: git commit -m "Initial commit" يُستخدم الخيار m- لتحديد رسالة إيداع من اختيارك. والآن بعد إيداع الشيفرة، ستحصل على خرج مماثل لما يلي: Output [main (root-commit) deab84e] Initial commit 6 files changed, 1259 insertions(+) create mode 100644 .gitignore create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 server.js create mode 100644 utils/findPrime.js create mode 100644 views/index.ejs أي أنك أودعت الشيفرة في غيت، والآن عليك دفعها إلى غيت هب. دفع الشيفرة إلى مستودع غيت هب أصبح بإمكانك الآن دفع الشيفرة إلى غيت هب، ثم ربط الشيفرة بمنصة App Platform ونشره. أولاً، سجل الدخول إلى غيت هب من المتصفح وأنشئ مستودعًا جديدًا باسم Express-memcache. ثم أنشئ مستودعًا فارغًا بدون ملفات README أو gitignore. أو ملفات الشهادات. يمكنك جعل المستودع خاصًا أو عامًا. كما يمكنك مراجعة توثيق غيت هب حول كيفية إنشاء مستودع جديد. ثم عد إلى الطرفية، وأضف المستودع الذي أنشأته بمثابة remote origin، وحدّث اسم المستخدم الخاص بك: git remote add origin https://github.com/your_username/express-memcache.git يوجه الأمر السابق غيت إلى المكان الذي يجب عليه إضافة الشيفرة فيه. ثم سمّي الفرع الافتراضي فرعًا رئيسيًا main: git branch -M main ثم أضف الشيفرة إلى مستودعك: git push -u origin main ثم أدخل بياناتك إذا طُلب منك ذلك. وستحصل على خرج مشابه لما يلي: Enumerating objects: 10, done. Counting objects: 100% (10/10), done. Delta compression using up to 8 threads Compressing objects: 100% (7/7), done. Writing objects: 100% (10/10), 9.50 KiB | 9.50 MiB/s, done. Total 10 (delta 0), reused 0 (delta 0), pack-reused 0 To https://github.com/your_username/express-memcache.git * [new branch] main -> main Branch 'main' set up to track remote branch 'main' from 'origin'. وبهذا أصبحت شيفرة التطبيق موجودةً على غيت هب، وأصبح التطبيق جاهزًا للنشر على منصة App Platform. الخطوة الرابعة، نشر التطبيق على منصة App Platform سننشر في هذه الخطوة، تطبيقنا على منصة تطبيقات App Platform. سننشئ حسابًا على المنصة ونسمح له بالوصول إلى مستودع غيت هب لنشر التطبيق. سنحدّث أولًا إعدادات البيئة كي يُتاح لها قراءة الضبط بواسطة عنوان البيئة PORT. تحديث إعدادات بيئة التطبيق سنسمح في هذه الفقرة لمتغيرات البيئة بالوصول وقراءة إعدادات منفذ التطبيق، لأن هذه الإعدادات ربما تتغير عند النشر، لذا فإن هذه الخطوة ستُمكّن التطبيق من الوصول إلى المنفذ من بيئة منصة التطبيقات. افتح ملف server.js في محرر النصوص البرمجية وتأكد من إضافة الأسطر التالية: ... const port = process.env.PORT || 3000; app.listen(port, () => console.log(`Example app is listening on port ${port}.`) ); تنّص هذه الأسطر على استخدام متغير البيئة port في حال وجوده، أو استخدام المنفذ الافتراضي 3000. والآن، أصبح التطبيق قادرًا على القراءة من منفذ بيئة منصة التطبيقات التي سننشره عليها. إنشاء ونشر التطبيق على منصة App Platform سنُعدّ التطبيق للنشر على منصة App Platform، ولكن تذكر أن هذه الخطوة مأجورة، وعليك دفع رسوم تشغيل التطبيق على منصة App Platform بالثانية (بدءًا من دقيقة واحدة على الأقل). يمكنك الإطلاع على الأسعار في صفحة المعاينة Review، كما يمكنك الاطلاع على نظام تسعير منصة App Platform للحصول على تفاصيل أكثر. أولاً، سجل الدخول إلى حسابك على DigitalOcean، ثم انقر على إنشاء create من لوحة تحكم التطبيقات Apps Dashboard. كما يمكنك الاطلاع على توثيق كيفية إنشاء التطبيقات في منصة App Platform. ثم ادخل إلى صفحة Create Resource From Source Code screen، واختر غيت هب كمزود الخدمة Service Provider، وامنح الإذن لـDigitalOcean للوصول إلى مستودعك. ننصحك بتحديد المستودع الذي تريد نشره فقط. سُتطالب بتثبيت تطبيق DigitalOcean GitHub. حدد مستودعك من القائمة وانقر فوق التالي Next. في شاشة الموارد Resources، انقر على تعديل الشريحة Edit Plan لتحديد حجم الاشتراك. سنستخدم في مقالنا الاشتراك الأساسي ذو خدمات الويب الأصغر حجمًا (512 ميغابايت من ذاكرة الوصول العشوائي vCPU | RAM) مخصصة لمورد express-memcache. إذ يوفر الاشتراك الأساسي وأصغر خدمة ويب موارد كافيةً لتطبيقنا التدريبي. بعد اختيار الاشتراك، انقر على رجوع Back. ثم انقر على علامة تبويب المعلومات info في شريط التنقل الأيسر وانتبه على المنطقة التطبيق، إذ سنحتاج إلى ذلك في الخطوة التالية لإضافة MemCachier من متجر DigitalOcean. أخيرًا، انقر على نافذة المعانية Review، ثم زر إنشاء موارد Create Resources لإنشاء التطبيق ونشره. سيستغرق الأمر بعض الوقت لإنشاء التطبيق ونشره. ستصلك رسالة عند الانتهاء فيها رابط التطبيق بعد نشره. بهذا نكون قد أنشأنا تطبيق Express يمكنه العثور على رقم أولي ويحتوي على زر أعجبني. ثم أَودَعنا شيفرة التطبيق إلى غيت ودفعناه إلى غيت هب، ثم نشرنا التطبيق على App Platform. والآن، لجعل تطبيق Express أسرع وأكثر قابلية للتوسع، سوف ننفذ ثلاث استراتيجيات للتخزين المؤقت للكائنات. ستحتاج إلى ذاكرة تخزين مؤقت Cache، والتي سننشئها في الخطوة التالية. الخطوة الخامسة، إعداد ذاكرة تخزين مؤقت للكائنات باستخدام MemCachier في هذه الخطوة، سننشئ ونضبط إعدادات ذاكرة تخزين مؤقت للكائنات. يمكنك استخدام أي ذاكرة تخزين مؤقت متوافقة مع memcached. سنستخدم في مقالنا إضافة MemCachier من متجر DigitalOcean. وذاكرة التخزين المؤقت MemCachier هي عبارة عن ذاكرة تخزين مؤقت تخزن البيانات على هيئة قيمة-مفتاح. أولًا، علينا إضافة MemCachier من متجر Digital Ocean، وللقيام بذلك انتقل إلى صفحة إضافة MemCachier، ثم انقر على Add MemCachier، ثم اختر المنطقة المناسبة لتطبيقك، يجب أن تختار المنطقة نفسها للتطبيق والذاكرة كي تخفف من التأخير بقدر الإمكان. كما يمكنك مراجعة إعدادات التطبيق للتأكد من المنطقة واختيار اشتراك معين. ثم، انقر على Add MemCachier لإضافة الذاكرة المؤقتة. ملاحظة: لمعرفة اختصارات اسماء المناطق، ننصحك بزيارة مركز بيانات DigitalOcean، فمثلًا منطقة سان فرانسيسكو اختصارها هو sfo3. والآن، عليك ضبط إعدادات التطبيق لاستخدام الذاكرة. انتقل إلى لوحة تحكم الإضافات Add-Ons dashboard ثم انقر على إضافة MemCachier للانتقال إلى لوحة التحكم. بعدها، انقر على زر عرض Show متغيرات الإعدادات Configuration Variables لعرض القيم التالية MEMCACHIER_USERNAME، MEMCACHIER_PASSWORD، MEMCACHIER_SERVERS. انتبه على هذه القيم لأننا سنحتاجها لاحقًا. سنحفظ الآن متغيرات إعدادات MemCachier كمتغيرات بيئة للتطبيق. انتقل إلى لوحة تحكم التطبيق ثم انقر على الإعدادات Settings. ثم من Components انقر على express-memc وانتقل لقسم متغيرات البيئة Environment Variables وانقر على تعديل Edit ثم أضف متغيرات إعدادات MemCachier ذات المفاتيح: (MEMCACHIER_USERNAME، MEMCACHIER_PASSWORD، MEMCACHIER_SERVERS) وأضف القيم كل منها وفقًا للقيم الموجودة في لوحة تحكم MemCachier> انقر على خيار التشفير Encrypt بجانب المفتاح MEMCACHIER_PASSWORD لتشفير كلمة المرور، ثم انقر على حفظ Save. والآن، علينا ضبط عميل ذاكرة memcache client في التطبيق باستخدام المتغيرات التي أدخلنا كي يستطيع التطبيق التخاطب مع الذاكرة. ثبّت المكتبة memjs في الطرفية: npm install memjs ثم أنشأ مجلد خدمات services، وأنشأ فيه الملف services/memcache.js وافتحه في المحرر. ثم استورد مكتبة memjs في أعلى الملف واضبط إعدادات عميل الذاكرة cache client: const { Client } = require('memjs'); module.exports = Client.create(process.env.MEMCACHIER_SERVERS, { failover: true, timeout: 1, keepAlive: true, }); ولا تنسَ حفظ الملف. تنشأ الشيفرة السابقة عميل لذاكرة التخزين المؤقتة MemCachier. أما بالنسبة للخيار failover، ضبطناه على القيمة true لاستخدام مجموعة حواسيب MemCachier عالية التوفر في حال حدوث الفشل. إذ إنه في حالة فشل الخادم، ستُرسل أوامر المفاتيح المخزنة على هذا الخادم تلقائيًا إلى الخادم التالي المتاح. ينصح باستخدام مهلة timeout مدتها ثانية واحدة إذ إنها أفضل للتطبيقات المنشورة من المهلة الافتراضية البالغة 0.5 ثانية. أما السطر keepAlive: true فيبقي الاتصال مع ذاكرة التخزين المؤقت مفتوحًا حتى في وضع الخمول، وهو أمر محبّذ لأن عملية إجراء الاتصال بطيئة، ويجب أن تكون ذاكرة التخزين المؤقت سريعة لتكون فعالة. حصلنا في هذه الخطوة على ذاكرة تخزين مؤقت باستخدام إضافة MemCachier من متجر DigitalOcean. ثم أضفنا إعدادات ذاكرة التخزين المؤقت كمتغيرات بيئة في منصة التطبيقات، كي نستطيع إعداد عميل باستخدام مكتبة memjs ويتمكن التطبيق من الاتصال بذاكرة التخزين المؤقت. والآن، أصبحنا جاهزين لتطبيق للتخزين المؤقت في Express، وهو ما سنتعلمه في خطوتنا التالية. الخطوة السادسة، تطبيق تقنيات التخزين المؤقت في Express باستخدام إضافة MemCachier أصبح بإمكانك الآن استخدام ذاكرة التخزين المؤقت للكائنات بعد نشر التطبيق وإضافة ميزة التخزين المؤقت MemCachier. إذ سننفذ في هذه الخطوة ثلاث تقنيات للتخزين المؤقت للكائنات. سنبدأ بالتخزين المؤقت للعمليات ذات الاستخدام الكثيف للموارد لتحسين سرعة الاستخدام وكفاءته. بعد ذلك، سنطبق تقنيات لتخزين طرق العرض المصيّرة بعد الإدخال لتحسين معالجة الطلب وتخزين الجلسات القصيرة مؤقتًا لإتاحة المجال لتوسيع نطاق تطبيقك فيما بعد. التخزين المؤقت للعمليات ذات الاستخدام الكثيف للموارد سنخزن العمليات الحوسبية ذات الاستخدام الكثيف للموارد تخزينًا مؤقتًا لتسريع التطبيق، مما يؤدي إلى استخدام وحدة المعالجة المركزية بكفاءة أكبر. إذ تُعد الدالة findPrime عملية حسابية تستخدم الموارد بكثافة عند إدخال عدد كبير. سنخزن نتائج الدالة مؤقتًا عند توفرها بدلاً من تكرار العملية الحسابية. أولاً، افتح ملف server.js لإضافة عميل الذاكرة memcache: const express = require('express'); const findPrime = require('./utils/findPrime'); const memcache = require('./services/memcache'); ... ثم خزّن عددًا أوليًا محسوبًا من قبل في الذاكرة المؤقتة كما يلي: ... const prime = findPrime(n); const key = 'prime_' + n; memcache.set(key, prime.toString(), { expires: 0 }, (err) => { if (err) console.log(err); }); ... ولا تنسَ حفظ الملف. لاحظ أن التابع set يقبل مفتاحًا key كوسيط أول، وقيمة للسلسلة أي value كوسيطه الثاني. لذا حولنا العدد الأولي إلى سلسلة، أما الشرط الثالث فيحرص على عدم انتهاء مدة العنصر المُخزّن، والشرط الرابع والأخير هو تابع استدعاء اختياري عند حدوث خطأ ما. ملاحظة1: يجب التعامل مع أخطاء ذاكرة التخزين المؤقت بحذر. إذ تعد هذه ذاكرة بمثابة تحسين ويجب ألا تؤدي إلى تعطل التطبيق. في من الممكن أن يعمل التطبيق على نحو جيد، وإن كان أبطأ، بدون ذاكرة التخزين المؤقت. ملاحظة 2: بإمكان التطبيق الآن العمل محليًا ولكن بدون تخزين مؤقت، وسيظهر خطأ في الخرج عند استدعاء memcache.set لأن التطبيق لن يستمكن من إيجاد خادم تخزين مؤقت، وستحصل حينها على خرج مشابه للتالي: Output MemJS: Server <localhost:11211> failed after (2) retries with error - connect ECONNREFUSED 127.0.0.1:11211 Error: No servers available ... لن تحتاج إلى التخزين المحلي لإكمال باقي خطوات المقال. إذا يمكنك تشغيل localhost:11211 في العنوان الذي يُعد العنوان الافتراضي لـ memjs. والآن، عليك إيداع التغييرات: git add . && git commit -m "Add memjs client and cache prime number" ثم أضف هذه التغييرات إلى غيت هب، والتي ستُنشر إلى منصة التطبيقات تلقائيًا: git push ستظهر رسالة على لوحة تحكم منصة التطبيقات تشير إلى أن تطبيقك قيد الإنشاء، بعد أن كانت حالته Deployed أي منشور. وعند اكتمال إنشاء التطبيق، افتح التطبيق في متصفحك وأدخل عددًا للعثور على أكبر عدد أولي أصغر أو مساوٍ له. ملاحظة: قد تظهر رسالة "Waiting for service" على لوحة التحكم، وتعني حالة انتظار الخدمة، وهذه الرسالة ستختفى من تلقاء نفسها، ولكن إن طال ظهورها عليك تحديث التطبيق للتأكد أن التطبيق قد نُشر بعد اكتمال إنشائه. والآن، عليك الرجوع إلى صفحة إضافات لوحة التحكم ثم النقر على View MemCachier لعرض لوحة تحليلات ذاكرة التخزين المؤقت. في هذه اللوحة، زدنا الخيار Set Cmds في لوحة All Time Stats وحالة العناصر Items في لوحة التخزين Storage بمقدار 1. في كل مرة ترسل عددًا، سيزداد كل من Set Cmds وItems. ويجب عليك الضغط على زر التحديث لتحميل الإحصائيات الجديدة. ملاحظة: يُعد التحقق من سجلات التطبيق على منصة App Platform أمرًا مفيدًا لتصحيح الأخطاء. يمكنك النقر من لوحة تحكم التطبيق على Runtime Logs لعرض الأخطاء. يمكن الاستفادة من العناصر المخزنة في الذاكرة المؤقتة. ستتحقق الآن مما إذا كان العنصر قد خُزّن مسبقًا، وإذا كان الأمر كذلك، فسوف يُعرض من ذاكرة التخزين المؤقت، وإلا سيبحث التطبيق عن العدد الأولي كما في السابق. عّدل ملف server.js، إذ عليك تعديل بعض الأسطر وإضافة بعد الاسطر الجديدة كما يلي: ... app.get('/', (req, res) => { const n = req.query.n; if (!n) { res.render('index'); return; } let prime; const key = 'prime_' + n; memcache.get(key, (err, val) => { if (err) console.log(err); if (val !== null) { // Use the value from the cache // Convert Buffer string before converting to number prime = parseInt(val.toString()); } else { // No cached value available, find it prime = findPrime(n); memcache.set(key, prime.toString(), { expires: 0 }, (err) => { if (err) console.log(err); }); } // Initialize likes for this number when necessary if (!likesMap[n]) likesMap[n] = 0; const locals = { n, prime, likes: likesMap[n] }; res.render('index', locals); }); }); ... تهيئ الشبفرة السابقة العدد الأولي prime بدون قيمة، باستخدام الكلمة المفتاحية Let، حيث أُعيدَ تعيين قيمتها. ثم يحاول تابع memcache.get استرداد العدد الأولي المخزن. توجد معظم شيفرة المتحكم الآن في تابع الاستدعاء memcache.get لأن نتيجته لازمة لتحديد كيفية التعامل مع الطلب. فإن كان ثمة قيمة مخزنة متاحة، فعليه استخدامها، وإلا عليه إجراء الحسابات اللازمة للعثور على العدد الأولي وتخزين النتيجة في ذاكرة التخزين المؤقت. إن القيمة التي يستدعيها تابع الاستدعاء memcache.get هي قيمة تخزين مؤقتة Buffer، لذا عليك تحويلها إلى سلسلة قبل تحويل التابع prime إلى عدد. أودع التغييرات ثم ادفعها إلى غيت هب لتنشرها: git add . && git commit -m "Check cache for prime number" && git push عندما ترسل رقمًا لم يخزّن بعد في التطبيق، ستزداد إحصائيات Set Cmds وحالة العناصر Items وإحصائيات الأخطاء get misses في لوحة تحكم MemCachier بمقدار 1. تحدث حالة الخطأ miss عند محاولة الحصول على العنصر من ذاكرة التخزين المؤقت قبل تعيينه، فالعنصر غير موجود في ذاكرة التخزين المؤقت، مما يؤدي إلى حدوث خطأ، ثم يخزّن العنصر بعد ذلك. عند إدخال عدد مخزّن مسبقًا، سيزداد عدد مرات الحصول على النتائج get hits. وهكذا نكون قد خزّنا العمليات ذات الاستخدام الكثيف للموارد تخزينًا مؤقتًا. بعد ذلك، سنخزّن طرق عرض التطبيق المصيّرة مؤقتًا. تخزين طرق العرض المصيّرة سنخزّن الآن طرق عرض التطبيق مؤقتًا باستخدام برنامج وسيط. أعددنا في خطوة سابقة ejs كمولد قوالب وأنشأنا قالبًا لعرض كل رقم مُدخل n. قد يستهلك إنشاء العرض كثيرًا من الموارد، لذا فإن تخزينه مؤقتًا يمكن أن يسرع معالجة الطلب ويستخدم موارد أقل. أولًا، أنشئ مجلدًا للبرنامج الوسيط وسمّه middleware. ثم أنشئ الملف middleware/cacheView.js وافتحه في المحرر. ثم أضف هذه الأسطر في ملف CacheView.js لدالة البرنامج الوسيط: const memcache = require('../services/memcache'); /** * Express middleware to cache views and serve cached views */ module.exports = function (req, res, next) { const key = `view_${req.url}`; memcache.get(key, (err, val) => { if (err) console.log(err); if (val !== null) { // Convert Buffer string to send as the response body res.send(val.toString()); return; } }); }; استوردنا في الشيفرة السابقة عميل الذاكرة memcache. ثم عرفنا عن مفتاح، مثل view_/?n=100. وبعدها، تحققنا من وجود عرض لهذا المفتاح في ذاكرة التخزين المؤقت باستخدام التابع memcache.get. إذا لم يكن هناك خطأ ووُجدت قيمة لهذا المفتاح، ينتهي الطلب عن طريق إرسال العرض مرةً أخرى إلى العميل. بعد ذلك، إذا لم يكن العرض مخزنًا، فعليك تخزينه مؤقتًا، عن طريق تعديل override التابع res.send بإضافة الأسطر التالية على ملف middleware/cacheView.js: const originalSend = res.send; res.send = function (body) { memcache.set(key, body, { expires: 0 }, (err) => { if (err) console.log(err); }); originalSend.call(this, body); }; يجب أن يصبح محتوى الملف middleware/cacheView.js كالتالي: const memcache = require('../services/memcache'); /** * Express middleware to cache views and serve cached views */ module.exports = function (req, res, next) { const key = `view_${req.url}`; memcache.get(key, (err, val) => { if (err) console.log(err); if (val !== null) { // Convert Buffer string to send as the response body res.send(val.toString()); return; } const originalSend = res.send; res.send = function (body) { memcache.set(key, body, { expires: 0 }, (err) => { if (err) console.log(err); }); originalSend.call(this, body); }; }); }; يمكنك تعديل التابع res.send باستعمال دالة تخزن العرض في ذاكرة التخزين المؤقت قبل استدعاء دالة الإرسال الأساسية send كالمعتاد. إذ يمكنك استدعاء دالة الإرسال الأساسية send باستخدام تابع الاستدعاء call الذي يستخدم this والذي يعبر عن context الحالي بعد تعليمة الذاكرة memcache.set. احرص على استخدام دالة مجهولة (وليس دالة سهمية)، كي تحدد قيمة this الصحيحة. بعد ذلك، مرر التحكم إلى البرنامج الوسيط عن طريق إضافة الأمر next: ... /** * Express middleware to cache views and serve cached views */ module.exports = function (req, res, next) { const key = `view_${req.url}`; memcache.get(key, (err, val) => { if (err) console.log(err); if (val !== null) { // Convert Buffer to UTF-8 string to send as the response body res.send(val.toString()); return; } const originalSend = res.send; res.send = function (body) { memcache.set(key, body, { expires: 0 }, (err) => { if (err) console.log(err); }); originalSend.call(this, body); }; next(); }); }; ... إن إضافة التابع next يؤدي استدعاء دالة البرنامج الوسيط التالي في التطبيق. لكن لا يوجد في مثالنا برامج وسيط آخر، لذلك يُستدعى المتحكم controller. يوّلد التابع res.render الخاص بـ Express صفحة عرض view، ثم يستدعي التابع res.send داخليًا باستخدام طريقة العرض. والآن، في وحدة تحكم المسار الرئيسي، يُستدعى تابع التعديل override عند استدعاء res.render، ليخزّن العرض في ذاكرة التخزين المؤقت قبل استدعاء دالة send الأصلية لإكمال الرد. ملاحظة: يمكنك تمرير استدعاء للتابع render في المتحكم، ولكن عليك تكرار شيفرة التخزين المؤقت للعرض في وحدة التحكم لكل مسار يخزن مؤقتًا. والآن، استورد البرنامج الوسيط في الملف server.js: const express = require('express'); const findPrime = require('./utils/findPrime'); const memcache = require('./services/memcache'); const cacheView = require('./middleware/cacheView'); ... ثم أضف الوسيط cacheView لاستخدامه في المسار الرئيسي مع التابع / Get: ... app.get('/', cacheView, (req, res) => { ... }); ... ثم أودع التغييرات وادفعها إلى غيت هب لنشرها: git add . && git commit -m "Add view caching" && git push عند إدخال عدد جديد، ستزداد إحصائيات لوحة تحكم MemCachier لكل من Set Cmds وItems وget misses بمقدار اثنين: مرة لحساب العدد الأولي ومرة للعرض. عند تحديث التطبيق بنفس الرقم، فسترى زيادةً بمقدار 1 في get hit لوحة التحكم. لأن صفحة العرض استُرِدت من ذاكرة التخزين المؤقت، لذلك لا توجد حاجة لجلب نتيجة العدد الأولي من التطبيق ملاحظة: إن خيار view cache مفعّل تلقائيًا في الإنتاج، لكن هذا الخيار لا يخزن محتوى خرج القالب، بل يخزن القالب فقط.ويعاد عرض الصفحة مع كل طلب، حتى عندما تكون ذاكرة التخزين المؤقت قيد التشغيل. إذًا فخيار view cache، مختلف ولكنه مكمل للتخزين المؤقت للعرض الذي طبقناه. قد تلاحظ بعد أن خزّنا العرض أن زر الاعجاب لا يعمل. إذا سجلت عدد الإعجابات، فستلاحظ أنها تتغير وتزداد، لكن العرض المخزّن بحاجة إلى التحديث عندما يتغير عدد الإعجابات. إذًا يجب إيقاف العرض المخزن مؤقتًا عند تغيير العرض. ثم سنوقف العرض المخزّن عندما يتغير عدد الإعجابات likes وذلك عن طريق حذفه من ذاكرة التخزين المؤقت. عدّل دالة إعادة التوجيه redirect في ملف server.js عن طريق إضافة الأسطر التالية: likesMap[n]++; // The URL of the page being 'liked' const url = `/?n=${n}`; res.redirect(url); لتصبح الدالة كما يلي: ... app.get('/like', (req, res) => { const n = req.query.n; if (!n) { res.redirect('/'); return; } likesMap[n]++; // The URL of the page being 'liked' const url = `/?n=${n}`; res.redirect(url); }); ... بعد تغير عدد الاعجابات في صفحة العرض، ستصبح النسخة المخزنة غير صالحة، لذا أضف الأسطر التالية لحذف عدد الإعجابات من ذاكرة التخزين المؤقت عندما تتغير الإعجابات likes: ... const url = `/?n=${n}`; // The view for this URL has changed, so the cached version is no longer valid, delete it from the cache. const key = `view_${url}`; memcache.delete(key, (err) => { if (err) console.log(err); }); res.redirect(url); ... يجب أن يكون ملف server.js مماثلًا لما يلي: const express = require('express'); const findPrime = require('./utils/findPrime'); const memcache = require('./services/memcache'); const cacheView = require('./middleware/cacheView'); const app = express(); app.set('view engine', 'ejs'); /** * Key is `n` * Value is the number of 'likes' for `n` */ const likesMap = {}; app.get('/', cacheView, (req, res) => { const n = req.query.n; if (!n) { res.render('index'); return; } let prime; const key = 'prime_' + n; memcache.get(key, (err, val) => { if (err) console.log(err); if (val !== null) { // Use the value from the cache // Convert Buffer string before converting to number prime = parseInt(val.toString()); } else { // No cached value available, find it prime = findPrime(n); memcache.set(key, prime.toString(), { expires: 0 }, (err) => { if (err) console.log(err); }); } // Initialize likes for this number when necessary if (!likesMap[n]) likesMap[n] = 0; const locals = { n, prime, likes: likesMap[n] }; res.render('index', locals); }); }); app.get('/like', (req, res) => { const n = req.query.n; if (!n) { res.redirect('/'); return; } likesMap[n]++; // The URL of the page being 'liked' const url = `/?n=${n}`; // The view for this URL has changed, so the cached version is no longer valid, delete it from the cache. const key = `view_${url}`; memcache.delete(key, (err) => { if (err) console.log(err); }); res.redirect(url); }); const port = process.env.PORT || 3000; app.listen(port, () => console.log(`Example app is listening on port ${port}.`) ); لا تنسَ حفظ الملف، ثم أودع التغييرات وادفعها للنشر: git add . && git commit -m "Delete invalid cached view" && git push والآن سيعمل زر الاعجاب في التطبيق وستتغير الإحصائيات التالية في لوحة تحكم MemCachier عند النقر على الزر: delete hits تزداد عند حذف العرض. get misses تزداد عند حذف العرض وعدم وجوده في ذاكرة التخزين المؤقت. get hits تزداد عند العثور على العدد الأولي في ذاكرة التخزين المؤقت. Set Cmds تزداد عند إضافة العرض إلى ذاكرة التخزين المؤقت. Items تبقى على حالها عند حذف أو إضافة العرض. وهكذا نكون قد طبقنا التخزين المؤقت للعرض وأبطلنا استخدام صفحات العرض المخزنة عند تغييرها. أما التقنية الأخيرة التي سننفذها هي التخزين المؤقت للجلسة. التخزين المؤقت للجلسات سنتعلم في هذه الفقرة كيفية إضافة جلسات Sessions وتخزينها مؤقتًا في تطبيق Express، مما يجعل ذاكرة التخزين المؤقت مخزنًا للجلسات. وحيث إن إحدى الاستخدامات الشائعة للجلسات هي تسجيل دخول المستخدم user login، لذا يمكننا اعتبار هذه الفقرة خطوةً أوليةً لتنفيذ نظام تسجيل دخول المستخدم في المستقبل (على الرغم من أن نظام تسجيل دخول المستخدم خارج عن نطاق مقالنا). يمكن أن يكون تخزين الجلسات قصيرة الأمد في ذاكرة التخزين المؤقت أسرع وأكثر قابليةً للتوسع من تخزينها في قواعد البيانات. ملاحظة: تعتبر ذاكرة التخزين المؤقت مثالية لتخزين الجلسات القصيرة التي انتهت مدتها. ومع ذلك، فإن ذاكرة التخزين المؤقت ليست دائمة؛ لذا تعد حلول التخزين الدائمة كقواعد البيانات أكثر ملاءمةً لتخزين الجلسات طويلة الأمد. والآن، ثبّت أداة الجلسات express-session كي تضيف جلسات إلى التطبيق وإلى مكتبة connect-memjs لاستخدام MemCachier كمخزن للجلسات: npm install express-session connect-memjs استورد ملف express-session و connect-memjs إلى ملف server.js: const express = require('express'); const findPrime = require('./utils/findPrime'); const memcache = require('./services/memcache'); const cacheView = require('./middleware/cacheView'); const session = require('express-session'); const MemcacheStore = require('connect-memjs')(session); ... تُمرَر جلسة البرنامج الوسيط يتم تمرير البرنامج الوسيط للجلسة إلى وحدة الاتصال connect في memcached، مما يسمح لها بالوراثة من Express.session.Store. عدّل إعدادات البرنامج الوسيط للجلسة كي يستخدا ذاكرة التخزين المؤقت كمخزن له، وذلك بإضافة الأسطر التالية: ... app.set('view engine', 'ejs'); app.use( session({ secret: 'your-session-secret', resave: false, saveUninitialized: true, store: new MemcacheStore({ servers: [process.env.MEMCACHIER_SERVERS], prefix: 'session_', }), }) ); ... يستخدم secret لتسجيل ملفات تعريف الارتباط للجلسة أو ما يُعرف باسم cookie. لا تنسَ استبدال your-session-secret بسلسلة مميزة. ملاحظة: يجب استخدام متغيرات البيئة لضبط secret لمراحل الإنتاج، وذلك بإضافة السطر secret: process.env.SESSION_SECRET || 'your-session-secret' لكن عندها يجب ضبط متغير البيئة في لوحة تحكم App Platform. يجبر الأمر Resave الجلسة على إعادة الحفظ إذا تُعدَل أثناء الطلب. ولأننا لا نريد تخزين العنصر في الذاكرة التخزين المؤقت مرة أخرى، لذا علينا ضبط قيمته على false. saveUninitialized: false is useful when you only want to save modified sessions, as is often the case with login sessions where a user property might be added to the session after authentication. In this case, you will store all sessions indiscriminately, so you set it to true. يُعد الأمر saveUninitialized: false مفيدًا لحفظ الجلسات المعدلة فقط، كما هو الحال غالبًا مع جلسات تسجيل الدخول، حيث يمكن إضافة خاصية مستخدم إلى الجلسة بعد المصادقة، حينها سنخزّن جميع الجلسات بصورة عشوائية، لذلك سنضبطها على القيمة true. أخيرًا، اربط قيمة store مع ذاكرة التخزين المؤقتة، واضبط بادئة ذاكرة التخزين المؤقت للجلسة على ._session وهذا يعني أن مفتاح عنصر الجلسة في الذاكرة سيبدو كالتالي: session_<session ID>. بعدها، أضف برامجًا وسيطًا لتصحيح الأخطاء على مستوى التطبيق، والتي ستساعد في تحديد الجلسات المخزنة قيد التنفيذ: ... app.use( session({ ... }) ); /** * Session sanity check middleware */ app.use(function (req, res, next) { console.log('Session ID:', req.session.id); // Get the item from the cache memcache.get(`session_${req.session.id}`, (err, val) => { if (err) console.log(err); if (val !== null) { console.log('Session from cache:', val.toString()); } }); next(); }); ... وهكذا سيسجل البرنامج الوسيط معرف الجلسة لكل طلب. ثم سيحصل على جلسة هذا المعرف من ذاكرة التخزين المؤقت ويسجل محتوياتها. حيث توضح هذه الطريقة أن الجلسات تعمل وتخزّن. احفظ الملف، ثم أودع التغييرات وادفعها للنشر: git add . && git commit -m "Add session caching" && git push أدخل رقمًا في التطبيق ثم تحقق من سجلات وقت التشغيل **Runtime Logs ** في لوحة التحكم للوصول إلى رسائل تصحيح الأخطاء. ستجد معرف الجلسة والقيمة التي سجلتها، مما يوضح أن الجلسات تعمل وتخزّن بصورة صحيحة. في لوحة تحكم MemCachier، عند تخزين العرض والجلسة، سترى ثلاث نتائج لكل تحديث للصفحة: واحدة لصفحة العرض، وواحدة للجلسة، وواحدة لجلسة برنامج تصحيح الأخطاء الوسيط. والآن، يمكنك التوقف عند هذه الخطوة، أو يمكنك الاطلاع على الخطوة السابعةالإضافية. الخطوة السابعة، حذف الموارد (اختيارية) ثمة رسوم عليك دفعها عند نشر التطبيق على منصة App platform، لذا يمكنك حذف التطبيق وإضافة MemCachier عند الانتهاء. انقر على الإجراءات Actions من لوحة التحكم ثم انقر على حذف التطبيق Destroy App. لحذف إضافة MemCachier، انقر على الإضافات Add-Ons، ثم على MemCachier، وانقر بعدها على الإعدادات والحذف Settings and Destroy. تلغى ذاكرة MemCachier المجانية بعد 30 يومًا من عدم استخدامها، ولكن يُعد تنظيف الادوات أمرًا جيدًا. ختامًا تعلمنا في مقالنا كيفية إنشاء تطبيق Express للعثور على عدد أولي باستخدام وكيفية إضافة زر "أعجبني". ثم رفعنا هذا التطبيق على غيت هب ونشرناه على منصة تطبيقات DigitalOcean. ثم سرّعنا التطبيق وجعلناه قابلًا للتوسع من خلال تنفيذ ثلاث تقنيات للتخزين المؤقت للكائنات باستخدام إضافة MemCachier للتخزين المؤقت للعمليات ذات الاستخدام الكثيفة للموارد، ومن خلال العرض view، والجلسات sessions. يمكنك الاطلاع على ملفات هذا المقال في مستودع مجتمع DigitalOcean، تحتوي المفاتيح في كل استراتيجيات التخزين المؤقت التي نفذناها على بادئة: _prime و _view و _session prime_ و view_ وsession_. بالإضافة إلى ميزة فضاء الاسم، توفر البادئة فائدةً إضافيةً وهي السماح بتحديد أداء ذاكرة التخزين المؤقت. استخدمنا في مقالنا شريحة المطورين developer plan في MemCachier، ولكن يمكنك تجربة شريحة مُدارة بالكامل تأتي مع مجموعة ميزات االفحص الدقيق Introspection، مما يتيح لك تتبع أداء البادئات الفردية. على سبيل المثال، يمكنك مراقبة معدل النقر hit rate أو نسبة النقر hit ratio على أي بادئة، مما يوفر رؤية تفصيلية لأداء ذاكرة التخزين المؤقت. إن أردت متابعة استخدام MemCachier، يمكنك مراجعة التوثيقات التالية. إذا واجهت مشاكلًا عند تطبيق إحدى هذه الخطوات، يمكنك الحصول على الدعم والمساعدة عبر إضافة سؤالك في قسم الأسئلة والأجوبة في أكاديمية حسوب. ترجمة -وبتصرف- [للمقال ](How To Deploy an Express Application and Scale with MemCachier on DigitalOcean App Platform) من موقع DigitalOcean لكاتبيه Patrick O'Hanlon و Caitlin Postal. اقرأ أيضًا مدخل إلى إطار عمل الويب Express وبيئة Node دليل استخدام Node.js وإطار العمل Express للمبتدئين نشر تطبيق Express في بيئة الإنتاج مقدمة إلى القوالب Template في Express: إنشاء القالب الأساسي لموقع مكتبة محلية مثالًا
-
تعد إدراة السجلات جزءًا أساسيًا من إدارة الخوادم، ولتفادي ظهور المشاكل في خادم الويب، ينصح بإعداد السجلات Logging لتوثيق الأحداث والأنشطة المهمة على الخادم إذ إن معلومات السجلات الموجودة على خادمك تزوّدك بالبيانات اللازمة لاستكشاف الأخطاء وإصلاحها وتقييم المشاكل عند ظهورها. سنلقي في هذا المقال نظرةً على إمكانات سجلات خادم Nginx ونتعلم كيفية ضبطها لتخدم احتياجاتك على أفضل وجه، وذلك باستخدام خادم افتراضي خاص VPS يعمل بنظام تشغيل أوبنتو Ubuntu 22.04، ولكن يمكنك استخدام أي توزيعة حديثة لنظام لينكس. المتطلبات: لإكمال هذا المقال بنجاح، ستحتاج إلى تجهيز بيئة العمل المكونة من: خادم أوبنتو 22.04 يحتوي على مستخدم غير جذري non-root user ذي صلاحيات sudo و مثبت عليه جدار حماية. يمكنك اعداده بالعودة إلى دليل إعداد الخادم الأولي تثبيت Nginx على خادمك. يمكنك الاستعانة بالمقال التالي لتثبيته على خادمك. أصبحت جاهزًا لبدء العمل بعد أن ثبّتَ Nginx على خادم أوبنتو 22.04. فهم آلية عمل سجل الأخطاء Error_log يستخدم خادم Nginx عدة سجلات للتحكم في سجلات النظام. ويسمى السجل المستخدم في الوحدة الأساسية بسجل الأخطاء أو Error_log صياغة سجل الأخطاء Error_log يُستخدم سجل الأخطاء Error_log لتسجيل رسائل الخطأ العادية. إن استخدمت خادم أباتشي Apache ستجد أن هذا السجل مشابه لسجل أخطاء أباتشي ErrorLog. يعتمد سجل الأخطاء Error_log على الصياغة التالية: /etc/nginx/nginx.conf error_log log_file log_level يحدد log_file الملف الذي ستُحفظ فيه السجلات، أما log_level فيحدد أدنى مستوى تسجيل ترغب في تسجيله. مستويات التسجيل يمكن ضبط سجل الأخطاء Error_log لتسجيل معلومات وفق ما تحتاجه. أما مستوى التسجيل فهو أحد المستويات التالية: emerg: يظهر في حالات الطوارئ حيث يكون النظام في حالة غير مستقرة alert: يظهر في المواقف الخطيرة التي تتطلب اتخاذ إجراء فورًا crit: يظهر عند حدوث المشاكل المهمة التي تحتاج إلى معالجة error: يظهر عند حدوث خطأ ما وفشل عملية ما warn: يظهر عند حدوث أمر غير مألوف، لكنه لا يدعو للقلق notice: يظهر عند حدوث أمر عادي، لكن يجب التنبيه عليه info: رسالة توضيحية debug: معلومات عن تصحيح الأخطاء تفيد في تحديد مكان حدوث المشكلة تعتبر المستويات الأعلى في القائمة السابقة ذات أولوية أعلى، فإذا حددت مستوىً ما، فإن السجل سيلتقط هذا المستوى، والمستويات الأعلى منه. على سبيل المثال، إذا حددت المستوى error فإن السجل سوف يجلب الرسائل التالية errorو crit و alert و emerg، وتجد مثالًا على هذا السجل في ملف الإعدادات الرئيسي.استخدم محرر النصوص الذي تفضله للوصول إلى ملف الإعدادات التالي، سوف نستخدم في مثالنا محرر النصوص نانو nano: sudo nano /etc/nginx/nginx.conf اذهب إلى أسفل الملف، إلى قسم إعدادات التسجيل Logging Settings # ولاحظ السجلات التالية: /etc/nginx/nginx.conf . . . ## # Logging Settings ## access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; . . . إن أردت بأن لا يسجل error_log شيئًا، فعليك إرسال خرجه إلى /dev/null: . . . /etc/nginx/nginx.conf error_log /dev/null crit; . . . أما سجل access_log فسوف نناقشه في فقرة تالية. فهم آلية عمل سجل HttpLogModule يُعد سجل error_log جزءًا من الوحدة الأساسية core module، أما سجل access_log فيُعد جزءًا من وحدة HttpLogModule التي تزودنا بإمكانية تخصيص السجلات. كما توجد بضع سجلات أخرى في هذه الوحدة تساعد في إعداد السجلات المخصصة custom logs. سجل log_format يُستخدم سجل log_format لوصف التنسيق المستخدم في السجلات باستخدام النص العادي والمتغيرات. ثمة تنسيق جاهز يأتي مع Nginx ويسمى التنسيق المدمج combined، وهو تنسيق شائع مُستَخدم في عدة خوادم. إليك مثالًا على التنسيق المدمج إن لم يكن مُعَّرفًا مسبقًا واضطررت إلى تعريفه مع سجل log_format: /etc/nginx/nginx.conf log_format combined '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent"'; لاحظ أن التعريف يتضمن عدة أسطر وينتهي عند الفاصلة المنقوطة (;). أما الأسطر التي تبدأ بالعلامة ($) فهي تعبر عن المتغيرات، وتُفسَر المحارف التالية - ، [ ، ] حرفيًا. أما الصياغة العامة للسجل فهي كالتالي: /etc/nginx/nginx.conf log_format format_name string_describing_formatting; يمكنك استخدام المتغيرات التي تدعمها الوحدة الأساسية وذلك لصياغة سلاسل تسجيل logging strings خاصة. فهم آلية عمل سجل access_log يستخدم سجل access_log صياغة مشابهة لصياغة سجل الأخطاء Error_log، لكنه أكثر مرونة، ولذلك يستخدم لضبط التسجيل المخصص Custom logging. الصياغة العامة لسجل access_log هي كالتالي: /etc/nginx/nginx.conf access_log /path/to/log/location [ format_of_log buffer_size ]; إن القيمة الافتراضية لسجل access_log هي التنسيق المدمج combined الذي تحدثنا عنه سابقًا في سجل log_format، لكن يمكنك استخدام أي تنسيق معَرَّف في سجل log_format. قمة المخزّن المؤقت Buffer هي الحجم الأعظمي للبيانات التي يحتفظ بها خادم Nginx قبل أن ينقلها إلى السجل. ويمكنك أن تضغط حجم ملف السجل بواسطة إضافة المحدد gzip ضمن تعريف السجل، كما يلي: /etc/nginx/nginx.conf access_log /path/to/log/location format_of_log gzip; وبخلاف سجل الأخطاء Error_log، إن لم تُرِد التسجيل فبإمكانك إلغاؤه من ملف الإعدادات كالتالي، ولا حاجة لإرساله إلى /dev/null: /etc/nginx/nginx.conf . . . ## # Logging Settings ## access_log off; error_log /var/log/nginx/error.log; . . . تدوير السجلات مع ازدياد ملفات السجل، يصبح من الضروري إدارة آليات التسجيل لتجنب امتلاء مساحة القرص، وتدوير السجلات Log rotation هي عملية تبديل ملفات السجل وأرشفة الملفات القديمة لمدة زمنية محددة. لا يوفر Nginx أدوات لإدارة ملفات السجلات، لكنه يحتوي على آليات للمساعدة في تدوير السجلات. تدوير السجلات يدويًا يمكنك إنشاء سكربت لتدوير السجلات يدويًا، على سبيل المثال، لنقل ملف السجل الحالي إلى ملف جديد وأرشفته، يمكنك إتباع الخطة التالية: أعد تسمية أحدث سجل بإضافة اللاحقة .0 إلى اسمه، ثم أعد تسمية الملفات القديمة بإضافة اللاحقة .1 وهكذا على التوالي: mv /path/to/access.log /path/to/access.log.0 إن الأمر الذي يدوّر ملفات السجل هو التالي kill -USR1 `cat /var/run/nginx.pid` لا ينهي هذا الأمر عمليات خادم Nginx، لكنه يرسل لها إشارةً لتعيد تحميل ملفات السجل. سيؤدي هذا إلى تسجيل الطلبات الجديدة في ملف السجل المحدَّث: kill -USR1 `cat /var/run/nginx.pid` يخزّن خادم Nginx معرف العملية الرئيسة PID في الملف /var/run/nginx.pid الموجود أعلى ملف الإعدادات /etc/nginx/nginx.conf في السطر الذي يبدأ بكلمة pid: sudo nano /etc/nginx/nginx.conf /etc/nginx/nginx.conf user www-data; worker_processes auto; pid /run/nginx.pid; include /etc/nginx/modules-enabled/*.conf; ... بعد تدوير السجلات، نفّذ الأمر sleep 1 كي تكتمل عملية النقل. كما يمكنك بعدها أن تضغط الملفات القديمة في ملف بصيغة .zip أو أن تجري العملية التي ترغب بها: sleep 1 [ post-rotation processing of old log file ] تدوير السجلات باستخدام برنامج logrotate يُستخدم برنامج logrotate لتدوير السجلات، وهو برنامج يُنَزّل تلقائيًا على نظام أوبنتو، كما يوجد سكربت مخصص لبرنامج logrotate على خادم nginx العامل بنظام أوبنتو. استخدم محرر النصوص الذي تفضله للوصول إلى ملف الإعدادات التالي، سوف نستخدم في مثالنا محرر النصوص nano : sudo nano /etc/logrotate.d/nginx عليك تذكر أن السطر الأول من الملف يحدد الموقع الذي ستُطَبق فيه أوامر الأسطر اللاحقة، إن غيّرت موقع تسجيل الملفات في ملف إعدادات Nginx، أما بقية الملف فيُشير إلى أن السجلات ستُدَور يوميًا وسيُحتَفظ ب 52 سجل قديم. لاحظ أن قسم postrotate يحتوي على أمر مشابه لآليات التدوير اليدوية التي طبقناها سابقًا: /etc/logrotate.d/nginx . . . postrotate [ ! -f /var/run/nginx.pid ] || kill -USR1 `cat /var/run/nginx.pid` endscript . . . يوجه القسم السابق Nginx إلى إعادة تحميل ملفات السجل عند اكتمال التدوير. خاتمة توفر إدارة السجلات وضبطها على نحو صحيح الوقت والجهد في حال حدوث مشكلة في الخادم، إذ إن الوصول إلى المعلومات التي تساعدك على تشخيص المشكلة يعد عاملًا مهمًا في حل المشكلة بسلاسة وسهولة. كما أن الاطلاع الدوري على سجلات الخادم يُعدّ أمرًا مهمًا لضمان عمل الموقع على نحو صحيح وعدم كشف أي بيانات حساسة. تعرفنا في هذا المقال على مقدمة عن التعامل مع السجلات في خادم Nginx يعمل بنظام تشغيل أوبنتو، كما يمكنك قراءة المزيد حول كشف المشاكل الشائعة للمواقع على خادوم لينكس. وللحصول على الدعم والمساعدة، أضف سؤالك في قسم الأسئلة والأجوبة في أكاديمية حسوب. ترجمة -وبتصرف- للمقال How To Configure Logging and Log Rotation in Nginx on an Ubuntu VPS لكاتبه Justin Ellingwood. اقرأ أيضًا كيف تستعرض وتدير سجلات لينكس على أوبنتو وCentOS إدارة الحزم، أتمتة المهامّ ومراقبة السّجلات في Red Hat Enterprise Linux تثبيت وضبط خادم Nginx تثبيت خادم ويب Caddy على أوبنتو 16.04 دليل إعداد خادم ويب محلي خطوة بخطوة
-
قد تواجه عدة أخطاء شائعة عند ضبط نطاق موقعك أو عند ضبط إعدادات دعم بروتوكول HTTPS. وإن إصلاح مشاكل بروتوكول DNS أو ما يُعرف ببروتوكول نظام تسمية النطاقات (Domain Name System) ليس بالأمر السهل، إذ يصعُب الجزم أن سبب الأخطاء هو بروتوكول DNS، فقد يكون سببها قد يكون في مكان آخر في بنيتك الشبكية. وفي حال طلبت من مسؤول الصيانة حل المشكلات المرتبطة بضبط نطاق موقعك ستسمع غالبًا منه العبارات التالية تباعًا: فكثيرًا ما تتكرر مشكلات DNS عند محاولة تنصيب شهادة SSL/HTTPS وضبط إعداداتها على خوادمك، عند استخدامك لخدمة Let's Encrypt على سبيل المثال. وسنراجع في هذا المقال بعض الأخطاء الشائعة التي قد تواجهها عند التعامل مع بروتوكولي DNS و HTTPS عند التعامل مع خدمة Let's Encrypt على وجه الخصوص، وسنُقدّم لك مجموعة نصائح وتوصيات يمكن تطبيقها سواء أكنت تستخدم خدمة DNS من مزود ديجيتال أوشن DigitalOcean أو من أي مزود آخر. سجلات DNS إن بروتوكول DNS هو المسؤول عن تعيين وتوجيه حركة البيانات إلى خوادم الويب باستخدام أسماء النطاقات، مثل your_domain.com بدلًا من الحاجة لاستخدام عناوين IP للمواقع. وتزوّد جميع مزودات النطاقات مستخدميها بواجهة خاصة لإدارة سجلات DNS. ولمطالعة مزيد من المعلومات حول أنواع سجلات نظام أسماء النطاق (DNS) يمكنك الرجوع إلى مقالنا مقدّمة إلى مُصطَلحات وعناصر ومفاهيم نظام أسماء النطاقات. إن أحد أكثر سجلات الـ DNS شيوعًا هو السجل A، والذي يشكّل رابطًا أساسيًا من اسم النطاق domain name إلى عنوان الخادم server address. لذا سنرّكز في هذا المقال على السجل A لكونه السجل الذي تحتاج إليه لإسناد أسماء النطاقات الأساسية إلى عناوين IP للخوادم. عند استخدام خدمة DNS من مزود DigitalOcean على سبيل المثال سيكون السجل A مضبوطًا كما في الصورة التالية: تحديث أو ترحيل سجلات DNS إذا جربت تعديل سجلات DNS، فقد يستغرق تطبيق هذه التعديلات بعض الوقت بحدود نصف ساعة، ونظرًا لأنه لا يمكنك اختبار DNS مباشرةً بعد تطبيق التعديلات، فقد تكون الأخطاء مضللة. ولن تتمكن من ضبط إعدادات خدمة LetsEncrypt على نطاقك حتى تنتقل إعدادات DNS نطاقك إلى معظم أو جميع خوادم أسماء النطاقات العالمية المسؤولة عن توجيه حركة المرور عبر الإنترنت وتحويل طلبات البحث عن عناوين IP للنطاقات إلى سجلات DNS المتعلقة بها. يمكنك الاستعانة بموقع whatsmydns.net للتحقق من أن تعديلات سجل DNS قد نُشرت إلى معظم خوادم أسماء النطاقات العالمية المستخدمة للبحث عن سجلات DNS. فإذا لم تعدل السجلات لديك محليًا يمكنك التحقق فيما إذا كانت قد عدلت في معظم المواقع العالمية، فقد يكون سبب المشكلة هو أن مزود خدمة الانترنت الذي تستخدمه ربما يكون أبطأ في إجراء التعديلات من المخدمات العالمية، لكن لن يستغرق الأمر أكثر من بضع دقائق في معظم الحالات. إن أردت التحقق من سجل DNS بعد فترة قصيرة من نشر التعديلات، فقد تحصل على نتائج مختلفة ومربكة من خادمك البعيد ومن متصفح الانترنت المحلي، ويحدث هذا الأمر عندما يطبق الخادم البعيد التعديلات قبل مزود خدمة الإنترنت الذي تتعامل معه. لاستبعاد احتمال حدوث هذا، استخدم الأمر nslookup لمعرفة ما هو عنوان IP الذي يشير إليه اسم النطاق، كالتالي: nslookup digitalocean.com $ Output … Name: digitalocean.com Addresses: 2606:4700::6810:b50f 2606:4700::6810:b60f 104.16.181.15 104.16.182.15 يمكنك بهذه الطريقة التأكد أن النتائج المحلية تطابق نتائج خوادم أسماء النطاقات العالمية. إن استخدام قيمة TTL مرتفعة أو ما يعرف بمدة البقاء Time-To-Live عند ضبط DNS، سيجعل التحديث يستغرق وقتًا أطول. إذ إن قيمة TTL الافتراضية المعتمدة في معظم مسجلي أسماء النطاقات هي 3600 ثانية، أو ساعة واحدة، وتُدرج عادةً هذه القيمة بجوار سجل A. تساعد قيمة مدة البقاء TTL الطويلة على تخزين الطلبات بفاعلية أكبر، ولكنها بالمقابل قد تجعل تغييرات DNS تستغرق وقتًا أطول في النشر. ننصحك في ضبط مدة TTL قصيرة مؤقتًا إذا أردت إجراء أو اختبار بعض التغييرات على DNS. أخطاء المتصفح ومشاكل إعدادات بروتوكول HTTPS قد تظن أحيانًا أنك ضبطت إعدادات بروتوكول HTTPS وإعدادات DNS على نحو صحيح، لكن قد تظهر لك رسائل خطأ في متصفح الويب عند طلب الموقع. للحصول على دليل عام حول رموز أخطاء HTTP، ننصحك بمراجعة المقال التالي حول كيفية إصلاح رموز أخطاء HTTP الشائعة. لا تشير معظم هذه الرموز إلى الخطأ بشكل صريح ومباشر ولكنها تنتج عن الإعدادات غير الصحيحة. على سبيل المثال، إذا استخدمت خادم إنجن إكس كوسيط عكسي Nginx Reverse Proxy لتوفير بوابة HTTPS لتطبيق آخر يعمل على خادمك، ولم تضبط إعدادات البوابة على نحو صحيح، فقد يظهر لك الخطأ ذو الرمز 502 الذي يدل على أن إنجن إكس غير قادر على إحالة الطلب. وأحد الأخطاء التي قد تظهر لك هو رسالة انتهاء صلاحية الشهادة، إذ إن شهادات LeysEncrypt تبقى صالحة لمدة ثلاثة أشهر فقط، على عكس شهادات HTTPS التجارية. وعند عدم تجديد الشهادة قبل انتهاء مدة الصلاحية يتسبب في ظهور الخطأ ERR_CERT_DATE_INVALID لكل من يحاول الوصول إلى موقعك. يبدو هذا الخطأ، عند استخدام متصفح كروم Chrome على النحو التالي: عندما تضبط إعدادات LetsEncrypt لأول مرة، تُفَعّل خاصيّة تجديد الشهادة تلقائيًا. كما ترسل خدمة LetsEncrypt بريدًا إلكترونيًا لتذكيرك عندما تكون شهادتك على وشك الانتهاء، لكن إن ضبطت هذه العملية بشكل خاطئ، أو لم ينجح تشغيلها، يمكنك تجديد الشهادة يدويًا عن طريق إعادة تشغيل الأمر certbot باستخدام الوسيط renew: sudo certbot renew --nginx -d example.com -d www.example.com ربما ستحتاج إلى إعادة تشغيل خادم الويب بعد تجديد الشهادة،وفي حال لم تقم بإجراء أي تعديلات أخرى على إعدادات خادمك يمكنك عندها أتمتة هذه العملية (عن طريق إضافته إلى أداة الجدولة cron) بواسطة تشغيل الأمر systemctl restart nginx بعد تجديد الشهادة. المحتوى المختلط عند تهجير محتوى برمجي معقد أو مختلط من بروتوكول HTTP إلى HTTPS قد تلاحظ فشلًا في عرض بعض الصور أو بعض مكونات الموقع. عندما تفتح طرفيّة أدوات المطور Developer Console ستجد أن هذه الأخطاء تعزى إلى "المحتوى المختلط"، كما في الصورة التالية: وسبب ذلك هو سياسة الويب الافتراضية التي تنص على عدم استخدام أو تضمين محتوى بروتوكول HTTP في المواقع التي تستخدم بروتوكول HTTPS. قد يظهر هذا الخطأ عندما يُحَمل موقع ما محتوىً من خادمي ويب مختلفين، أو عندما نُخَدّم تطبيق ويب بواسطة بوابة خادم Nginx لكن إعادة توجيه SSL لا تعمل على وجه صحيح. إذا كنت تستخدم خادم Nginx وتوجه البيانات/حركة البيانات إلى تطبيق آخر يعمل خلف خادم الويب، وظهرت لك رسالة تحذير المحتوى المختلط، يمكنك حينها إضافة معلومات لضبط توجيه SSL وذلك ضمن كتلة الموقع location: … location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Proto https; } وعدا عن ذلك، احرص على استخدام بروتوكول HTTPS في جميع المواقع التي تُخَدمها. كما يمكنك الاطلاع على المقال التالي عن أخطاء المحتوى المختلط الأخطاء التي تظهر عند تشغيل سكربت LetsEncrypt Certbot قد تظهر لك بعض الأخطاء عند تشغيل سكربت Certbot المتوفر من خدمة LetsEncrypt، بعض الأخطاء لها خرج يشرح سبب الخطأ ويمكنك اتباع الإرشادات المذكورة، وبعضها الآخر قد لا يكون واضحًا. على سبيل المثال، إذا ظهر لك خطأ انتهاء المدة أو Timing out في السكربت، فالأرجح أن المشكلة متعلقة بجدار الحماية Firewall : certbot --nginx -d example.com -d www.example.com الخرج Press Enter to Continue Waiting for verification… Cleaning up challenges Failed authorization procedure. example.com (http-01): urn:ietf:params:acme:error:connection :: The server could not connect to the client to verify the domain :: Fetching http://example.com/.well-known/acme-challenge/EWbLNaAWwRZGM1UCqSvbIIxFFaoH09wPUEwVuYucCb0: 93 Timeout during connect (likely firewall problem) وتحدث عادةً أخطاء انتهاء المدة أو Timeout بسبب عدم قدرة الاتصال على الحصول على استجابة أو تأكيد للعملية لأن جدار الحماية يهمل أو يتخلص من حركة البيانات. لتلافي حدوث هذا الخطأ، تأكد أن جدار الحماية لا يحجب المنفذ رقم 80 ولا المنفذ 443 قبل تشغيل certbot. تشير بعض الوثائق أنك ستحتاج إلى فتح واحد من المنفذين، إما المنفذ 80 أو المنفذ 443، ولكن افتح كلا المنفذين لاستبعاد إمكانية حدوث الأخطاء. إن كنت تستخدم UFW، أو Uncomplicated Firewall أي الجدار الناري غير المعقَّد، يمكنك تنفيذ ما سبق عن طريق تفعيل أمر الضبط الكامل Nginx Full: sudo ufw allow 'Nginx Full' ثم أعد تشغيل certbot بعد أن غيّرت إعدادات جدار الحماية. لكن، إن أعدت تشغيل certbot عدة مرات متتالية خلال مدة قصيرة فقد يظهر لك خطأ “failed validation limit” الذي يخبرك أنك وصلت إلى الحد المسموح به من محاولات التحقق: الخرج too many failed authorizations recently: see https://letsencrypt.org/docs/failed-validation-limit/ يجب عليك الانتظار لمدة ساعة قبل أن تستطيع إعادة المحاولة مجددًا من حسابك. يمكنك الاطلاع على التوثيق التالي للحصول على معلومات أكثر عن الحد المسموح به لمحاولات التحقق وأخطاء certbot الأخرى. إذا تلقيت أخطاء أخرى عند تشغيل certbot غير الأخطاء المتعلقة بالمدة Timeout أو أخطاء DNS أو مشاكل الاتصال، فمن المحتمل أن يكون سبب هذه الأخطاء مشكلةً في بيئةPython على خادمك والتي ضُبطت إعداداتها بواسطة certbot. يمكن إصلاح هذه الأخطاء دائمًا عن طريق إزالة certbot ثم إعادة تنزيله من الصفر. لن يؤثر ذلك على إعدادات HTTPS الحالية، بل سيؤثر فقط على الأدوات المستخدمة للحفاظ على تلك الإعدادات وتجديدها. لتنفيذ ذلك، يمكن اتباع الإرشادات في مقال كيف تؤمّن خادم ويب NGINX على أوبنتو حالة عدم عمل بروتوكول HTTPS مع عدم ظهور أخطاء مرئية إن تأكدت من أن Certbot وDNS يعملان على نحو صحيح، لكن موقعك لم ينتقل من استخدام HTTP إلى استخدام HTTPS، فسبب هذا عادةً هو مشكلة في إعدادات خادم الويب. يحدث certbot تلقائيًا إعدادات ضبط خادم الويب أولًا ثم يعمل بعدها، ولهذا يجب عليك تحديد الخادم nginx عند كتابة أمر تشغيل certbot كي يعلم ما هو نوع إعدادات الخادم الذي عليه تحديثها بعد تجديد الشهادة. لكن، إن كانت إعدادات خادم الويب الحالية معقدةً جدًا، فقد يفشل Certbot في تحديثه للانتقال إلى استخدام بروتوكول HTTPS، وستحتاج حينها إلى إجراء التغييرات بنفسك. أولًا، تأكد من إضافة كتلة اسم خادمك server_name في ملف ضبط إعدادات الخادم، إذ إنه بدون هذه الخطوة، لن يعلم certbot ما هي الإعدادات الواجب تحديثها. إن واجهت مشاكل بعد هذه الخطوة، فقد تحتاج إلى تشغيل certbot في الوضع المستقل Standalone mode يجلب الشهادة فقط، ثم ستحتاج إلى ضبط إعدادات خادم الويب يدويًا لاستخدام بروتوكول HTTPS. تتضمن الإعدادات الأساسية لخادم Ngnix الذي يستخدم بروتوكول HTTPS السطر التالي listen 443 ssl ومسار شهادة SSL والمفتاح Key كما يلي: … listen 443 ssl; # RSA certificate ssl_certificate /etc/letsencrypt/live/your_domain/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/your_domain/privkey.pem; # Redirect non-https traffic to https if ($scheme != "https") { return 301 https://$host$request_uri; } … عند ضبط إعدادات خادم Nginx تذكر أنه يمكنك التحقق من التعديلات التي أجريتها على إعدادات خادم Nginx وتأكيدها بواسطة الأمر nginx -t قبل إعادة تشغيل الخادم. عند الانتهاء من التعديلات بإمكانك إعادة تشغيل خادم Nginx كي تأخذ الإعدادات الجديدة مفعولها باستخدام الأمر systemctl restart nginx sudo systemctl restart nginx ختامًا راجعنا في هذا المقال عدة أخطاء شائعة قد تظهر عند استخدام خدمة LetsEncrypt وتعلمنا خطوات إصلاحها، إذ إن الهدف من خدمة LetsEncrypt هو إتاحة استخدام البروتوكول الآمن HTTPS لجميع الأفراد في أي مكان ودون دفع أي تكاليف، وهي تُعد خدمةً سهلة الاستخدام عندما تعمل تلقائيًا بدون ظهور أيّة أخطاء، ولكن قد يكون التعامل معها مربكًا لمن لا يملك خبرةً كافية في ضبط إعدادات شهادة SSL أو DNS. إذا واجهت أي مشكلات عند استخدام خدمة LetsEncrypt يمكنك الحصول على الدعم والمساعدة عبر إضافة سؤالك في قسم الأسئلة والأجوبة في أكاديمية حسوب. ترجمة -وبتصرف- للمقال How To Fix Common LetsEncrypt Errors من موقع DigitalOcean. اقرأ أيضًا مقدمة إلى خدمة Let’s Encrypt تنصيب شهادة SSL مجانية عبر خدمة Let's encrypt على خادوم لينكس كيفية استخدام وضع Certbot المستقل للحصول على شهادات SSL من Let’s Encrypt على دبيان 10 كيف تستعمل SSL و HTTPS مع ووردبريس
-
ستتعلم في هذا المقال كيفية إنشاء لعبة حسية تفاعلية، لتخفيف التوتر وتحسين مستوى تركيز الفرد، أو لتوفير وسيلة للتواصل مع الآخرين. ستعمل في هذا المشروع على: توظيف مهاراتك لتصميم وتنفيذ آلة حسية يتفاعل معها المستخدم. استخدام عناصر دخل إلكترونية، مثل الأزرار buttons والمقاومات المتغيرة potentiometers للتحكم بعمل عناصر خرج، مثل مصابيح الليد LED والأجراس buzzers. تحسين آلتك بناءً على ملاحظات المستخدمين. معلومة: تدفع الألعاب الحسية المستخدمين على الاستمرار في استخدامها والتفاعل معها، ومنها ألعاب النقر المتكرر fidget toys التي تساعد في تخفيف التوتر وتحسين مستوى تركيز الفرد، وأيضًا الألعاب الحسية التكيُّفية التي توفر وسيلة للأشخاص ذوي الإعاقات الجسدية للتواصل مع الآخرين. قد تحفز الألعاب الحسية جميع الحواس أو تركز فقط على إحداها. سيعتمد المقال على ملف المشروع codes.zip لذا يمكنك تحميله وبدء العمل. الدليل الموجز لإنشاء لعبة إلكترونية تفاعلية تحفز الحواس إليك شرحًا مختصرًا عن أهداف هذا المشروع: استخدام عناصر دخل وخرج إلكترونية متنوعة. إنشاء لعبة تفاعلية متينة تشد المستخدمين. توفير بيئة عمل وتجربة استخدام مريحة. تصفير الإعدادات بناءً على مدخلات المستخدمين، أو بعد مدة زمنية معينة. تصميم اللعبة وفق نمط أو موضوع معين. معلومة: يُعنى علم الهندسة البشرية Ergonomics بتحسين الطريقة التي يتفاعل فيها البشر مع البيئة المحيطة بهم وإيجاد حلول للمشكلات التي قد تواجههم، وسنحصل عند تطبيقه على أدوات سهلة الاستخدام ومريحة. متطلبات المشروع يتطلب المشروع توفر العتاد الآتي: لوحة حاسوب راسبيري باي بيكو Raspberry Pi Pico مع أرجل مثبتة عليها. كبل USB لنقل البيانات ذو نهايات من النوع USB A و micro USB. عناصر إلكترونية وأسلاك توصيل. أما من ناحية البرمجيات، فلا بد من توفر الآتي: برنامج ثوني Thonny: وهو البيئة البرمجية التي سنستخدمها لكتابة الشيفرة بلغة بايثون. تثبيت برنامج Thonny سنعرض في الآتي طريقة تثبيت برنامج ثوني Thonny في أنظمة التشغيل المختلفة. تثبيت برنامج Thonny على نظام تشغيل راسبيري باي يأتي برنامج ثوني Thonny مثبتًا مع نظام تشغيل راسبيري باي، المعروف سابقًا براسبيان Raspbian، لكن قد تحتاج إلى تحديثه. انقر على الأيقونة في الزاوية العلوية اليسرى من الشاشة لفتح نافذة الطرفية Terminal، أو اضغط المفاتيح التالية معًا Ctrl+Alt+T. ثم اكتب الأمر التالي لتحديث نظام التشغيل وبرنامج Thonny: sudo apt update && sudo apt upgrade -y تثبيت برنامج Thonny على أنظمة التشغيل الأخرى يمكنك تثبيت ثوني Thonny على الحواسيب العاملة بنظام تشغيل لينكس، أو ويندوز، أو ماك، وذلك من الموقع الرسمي thonny.org. انقر على رابط التنزيل الموافق لنظام تشغيل حاسوبك من الزاوية العلوية اليمنى في الموقع، ثم انقر على الملفات بعد تنزيلها، وقد تظهر لك الرسالة التالية على نظام ويندوز: انقر على خيار المزيد من المعلومات "More info" ثم على التشغيل على أي حال "Run anyway". التعرف على واجهة برنامج Thonny عند فتح Thonny ستظهر لك الواجهة التالية: يمكنك الكتابة بلغة بايثون في النافذة الرئيسية الكبيرة، ثم النقر على زر التشغيل الأخضر Run للتنفيذ، ستظهر لك رسالة لحفظ الملف قبل تشغيله. اكتب الأمر التالي وشغّله: print('Hello World!') تغيير السمة والخط يمكنك التحكم بلون الخط وحجمه وتغيير السمة المُستخدمة في واجهة البرنامج، وذلك بالنقر على قائمة الأدوات Tools من الشريط أعلى الشاشة، ثم النقر على خيارات Options، ثم انقر بعدها على نافذة الخط والسمة Theme & Font واختر نوع الخط والسمة التي تفضلها من النافذة المنسدلة ثم انقر على زر موافق OK عند الانتهاء. ننصحك باختيار الخطوط البسيطة الواضحة والابتعاد عن الخطوط المزخرفة أو المشابهة لخط اليد لأنها قد تجعل القراءة أصعب. إعداد مكتبة picozero سنعمل في هذه الخطوة على إعداد مكتبة picozero وتوصيل لوحة راسبيري باي بيكو وإعداد برنامج مايكرو بايثون. أولًا، صِل الطرف الصغير لكبل USB إلى لوحة راسبيري باي والطرف الآخر إلى حاسوبك لتتمكن من برمجة اللوحة عن طريقه. ثانيًا، افتح محرر Thonny، ولاحظ ما هو الإصدار المستخدم من بايثون بقراءة النص الموجود في الزاوية السفلية اليمنى من الشاشة، انقر على النص واختر "MicroPython (Raspberry Pi Pico)"، إذا لم يكن هذا الخيار محددًا. سيطالبك Thonny بتثبيت برنامج MicroPython على حاسوب راسبيري باي بيكو إذا لم تستخدمه مسبقًا، فقط انقر على زر التثبيت Install. ثالثًا، أضف حزمة بيكو زيرو picozero من خلال النقر على قائمة الأدوات Tools من شريط القوائم في برنامج Thonny، ثم النقر على خيار إدارة الحزم Manage Packages. ثالثًا، اكتب "picozero"، ثم انقر على زر البحث Search on PyPi. رابعًا، انقر على picozero من نتائج البحث ثم انقر على زر التثبيت Install. استلهم أفكارك اطلع على المشاريع التالية واستلهم منها بعض الأفكار لصنع آلتك التفاعلية: مشروع الأضواء الليلية شغّل الفيديو، وشاهد كيف أحدثنا ثقوبًا صغيرةً في ورقة سوداء اللون للحصول على سماء مرصّعة بالنجوم داخل غرفتك. استخدم مصباح الليد متعدد الألوان RGB LED للحصول على تأثير الوميض، واستخدم الأزرار buttons لتشغيل وإطفاء الأضواء. يمكنك الاطلاع على الشيفرة اللازمة لتنفيذ هذا المشروع والموجودة باسم "night_sky.py" من ملف المشروع codes.zip. مشروع النحلة الطنانة شغّل الفيديو ولاحظ أنه عند الضغط على أجنحة النحلة يصدر صوت طنين، إذ وضعنا ورق قصدير تحت الأجنحة وعند الضغط عليها تلامس قطعةً أخرى من القصدير، وهذا يجعل الجرس يصدر نغمةً ما، إذ يُصدر كل جناح صوتًا مختلفًا؛ كما أضفنا مقاومةً متغيرة للتحكم في مصباح ليد أزرق. يمكنك الاطلاع على الشيفرة اللازمة لتنفيذ هذا المشروع والموجودة باسم "The buzzy bee.py" من ملف المشروع codes.zip. مشروع السيف المضيئ شغّل الفيديو ولاحظ كيف يضيء نصل السيف عند الضغط على الزر ويصدر الجرس الإلكتروني صوت طنين خافت، وعند تدوير قرص المقاومة المتغيرة يتغير لون النصل وحِدّة الطنين؛ ولإطفاء السيف علينا تدوير قرص المقاومة بالاتجاه المعاكس. يمكنك الاطلاع على الشيفرة اللازمة لتنفيذ هذا المشروع والموجودة باسم "saber.py" من ملف المشروع codes.zip. مشروع الشمعة الإلكترونية استخدمنا في هذا المشروع مصباح ليد متعدد الألوان RGB LED يضيء باستمرار، وعند النفخ على الشمعة ينطفئ المصباح كما شعلة اللهب الحقيقية؛ حيث يؤدي النفخ إلى تلامس قطعتين من ورق القصدير فتنطفئ الشعلة مدةً قصيرةً، ثم تعود للعمل بعدها. يمكنك الاطلاع على الشيفرة اللازمة لتنفيذ هذا المشروع والموجودة باسم "candle.py" من ملف المشروع codes.zip. إعداد فكرة اللعبة يجب عليك وضع خطة للعبتك وكيف سيتفاعل اللاعب معها، لذلك خطط عن طريق التفكير، أو الكتابة والرسم، أو عن طريق التعديل وإصلاح بعض أجزاء اللعبة، فالخيار متروك لك. تحديد غرض اللعبة فكر مليًّا في الهدف من اللعبة التي ستصممها، ما الغرض منها، هل تود تعريف طفل ما على الأصوات والأشكال؟ أم تريدها وسيلةً لتخفيف التوتر عن طريق الضغط على الأزرار وسماع الأصوات الموافقة لكل زر؟ أم تود تصميم أداة لمساعدة الأشخاص على التواصل والتعبير عن احتياجاتهم؟ تحديد الجمهور فكر مليًا في الجمهور المستهدف من اللعبة، من هم؟ هل تود تصميم اللعبة لتناسب احتياجات صديق ما، أو أحد أفراد العائلة، أو أحد الصفوف الدراسية، أو الأشخاص الذين يمارسون هواية ما؟ كما يمكنك استهداف جمهور أحد الموسيقيين، أو أن تصمم اللعبة لنفسك. تحديد مميزات اللعبة فكر مليًا في العناصر التي تود استخدامها في لعبتك؛ إذ تحتوي لوحة راسبيري باي بيكو على ثمانية أرجل أرضية GND، لذا يمكنك توصيل ثمانية عناصر فقط، وقد تستطيع توصيل أكثر من ثمانية عناصر إذا كان من الممكن أن يشترك بعضها برجل الأرض GND. عليك أخذ النقاط التالية في الحسبان عند التخطيط للعبتك: تُشَغّل مكبرات الصوت Speakers كل نغمة على حدى، لذلك ستحتاج لعدة مكبرات صوت لتشغيل عدة نغمات في نفس الوقت. توجد رجل تغذية واحدة ذات جهد 3 فولت على لوحة بيكو؛ أي يمكنك استخدام مقاومة متغيرة واحدة، كما أنه يوجد حدٌّ لقيمة التيار الذي توفره لوحة بيكو. إليك بعض الاقتراحات لعناصر الدخل والخرج التي يمكنك استخدامها معًا: مقاومة متغيرة واحدة وجرس إلكتروني واحد. أربعة أزرار جاهزة وجرس إلكتروني واحد. ثمانية مبدلات يدوية الصنع وجرس إلكتروني واحد. مقاومة متغيرة واحدة وجرسان، وزران. عدة أزرار وأجراس لعزف عدة نغمات في نفس الوقت. يمكنك استخدام ما يزيد عن ثمانية عناصر، ولكن عليك حينها استخدام رجل أرضية مشتركة GND. حدد هل تود استخدام الأزرار ومقاومة متغيرةً كعناصر دخل؟ أم تريد استخدام قواطع يدوية الصنع؟ وهل تريد عزف صوت معين، أم لحنًا ما أو عدة ألحان؟ هل تريد استخدام مصباح ليد ذو لون واحد؟ أم تفضل استخدام المصباح متعدد الألوان؟ اعتماد التصميم الخارجي للعبة حدد كيف تريد أن يبدو الشكل الخارجي للعبة: هل تريد اعتماد تصميم موجود مسبقًا، مثل شكل المكعب أو المفرقعات؟ هل تفضل اعتماد موضوع برنامجك التلفزيوني أو سلسلتك المفضلة من القصص المصورة، أو حتى أغنيتك المفضلة؟ هل تريد صنع غلاف خارجي للعبة من صناديق الورق المقوى، أو من القماش، أو البلاستيك؟ الآن، حضّر العناصر التي ستحتاجها لتنفيذ لعبتك قبل البدء، من عناصر دخل وخرج إلكترونية، وأسلاك توصيل، ولوحة بيكو، واختبر سلامة اللوحة عن طريق توصيلها بحاسوبك والتحقق من عمل مصباح الليد الموجود على اللوحة، باستخدام الشيفرة التالية: from picozero import pico_led from time import sleep pico_led.on() sleep(1) pico_led.off() تنفيذ اللعبة واختبارها حان الآن وقت إعداد لعبتك وتنفيذها. تذكر أنك تصنع لعبتك الخاصة وفقًا لما تهواه وتراه مناسبًا لك، لذا ليس عليك التقيد بالعناصر المقترحة في مقالنا، اختر منها ما تريد. قد تجد في أمثلتنا أن إحدى الأرجل مستخدمة لغرض ما، عندها استخدم رجلًا عامة أخرى ورجلًا أرضية، واحرص على تدوين أرقام الأرجل المستخدمة عند كتابة الشيفرة. إليك تذكرةً ببعض المهارات التي تعلمناها والتي ستفيدك في إنشاء لعبتك: توصيل عناصر الخرج استخدام رجل أرضية مشتركة تحتوي لوحة بيكو على ثمانية أرجل أرضية GND، لذلك لاستخدام ما يزيد عن ثمانية عناصر إلكترونية عليك إعادة استخدام إحدى الأرجل الأرضية، وستحتاج لما يلي: سلك توصيل نوع دبوس- مقبس. رقائق قصدير، وشريط لاصق ناقل، أو أي مادة ناقلة للتيار الكهربائي. شريط لاصق. أولًا، أنشئ شريطًا من ورق القصدير، أو من أي مادة ناقلة. ثانيًا، استخدم الشريط اللاصق لتوصيل سلك أحد الأرجل الأرضية مع شريط القصدير، كما يلي: ثالثًا، صِل القطب الموجب للعنصر الأول مع أحد الأرجل العامة GP على لوحة بيكو، والقطب السالب للعنصر مع شريط القصدير. رابعًا، لتوصيل المزيد من العناصر، صِل القطب الموجب للعنصر مع إحدى أرجل الأغراض العامة GP، والقطب السالب مع شريط القصدير. توصيل مصابيح الليد ذات اللون الواحد لتوصيل مصباح ليد واحد ستحتاج إلى ما يلي: لوحة راسبيري باي بيكو. مصباح ليد باللون الذي تفضله. مقاومة. سلكي توصيل نوع مقبس- مقبس. يجب توصيل مقاومة مع الرجل الموجبة الطويلة لمصباح الليد، وتوصيلها مع الرجل GP13 على لوحة بيكو. وتوصيل الرجل السالبة للمصباح مع أقرب رجل أرضية، كما هو موضح في المخطط التالي: أما لتوصيل عدة مصابيح ليد ذات اللون الواحد، ستحتاج إلى ما يلي: لوحة راسبيري باي بيكو. عدة مصابيح ليد باللون الذي تفضله. مقاومة لكل مصباح. سلكي توصيل نوع مقبس- مقبس لكل مصباح. يجب توصيل مقاومة مع الرجل الموجبة الطويلة لكل مصباح ليد؛ وتوصيل الرجل الموجبة للمصباح الأول مع الرجل GP13 على لوحة بيكو والسالبة مع أقرب رجل أرضية GND؛ وتوصيل الرجل الموجبة للمصباح الثاني مع الرجل GP8، والسالبة مع أقرب رجل أرضية GND؛ وتوصيل الرجل الموجبة للمصباح الثالث مع الرجل GP5، والسالبة مع أقرب رجل أرضية GND، كما هو موضح في المخطط التالي: إسناد مصابيح ليد إلى رجل معينة أو عدة أرجل على اللوحة استخدم الشيفرة التالية لإسناد مصباح وحيد إلى الرجل الموصول معها على لوحة بيكو: from picozero import LED led = LED(13) أما لإسناد عدة مصابيح ليد إلى أرجل لوحة بيكو: استورد تابع المصباح LED من مكتبة picozero، ثم استخدم الشيفرة التالية لإسناد المصابيح إلى الأرجل الموصولة معها على لوحة بيكو: from picozero import LED led_1 = LED(13) led_2 = LED(8) led_2 = LED(5) ننصحك بتسمية المتغيرات بأسماء تدل على عملها، كأن تسمّي المصباح المسؤول عن تشغيل المصباح باللون المسؤول عنه، كما يلي: red_led = LED(13) green_led = LED(8) pink_led = LED(5) إضافة الشيفرة اللازمة لتشغيل مصباح ليد واحد أو عدة مصابيح إليك الدالة اللازمة لتشغيل المصباح: def excited(): # دالة تشغل اللون الموافق لمزاجك purple.on() # شغّل اللون البنفسجي أما الشيفرة اللازمة لتشغيل عدة مصابيح فهي على النحو التالي: def excited(): # شغّل اللون الموافق لشعورك بالحماس purple.on() # شغّل المصباح البنفسجي blue.off() # أطفئ المصباح الأزرق def worried(): # شغّل اللون الموافق لشعورك بالقلق purple.off() # أطفئ المصباح البنفسجي blue.on() # شغّل المصباح الأزرق توصيل مصابيح الليد متعددة الألوان ستحتاج لتوصيل مصباح ليد متعدد الألوان إلى ما يلي: لوحة راسبيري باي بيكو. مصباح ليد متعدد الألوان ذو مهبط مشترك. ثلاث مقاومات. أسلاك توصيل نوع مقبس- مقبس (عدد 8). يجب عليك توصيل مقاومة مع الأرجل الثلاثة الطويلة لمصباح الليد، أما الرجل الطويلة فهي رجل الأرضية ولا تحتاج إلى مقاومة. معلومة: لاحظ أنه لمصباح الليد متعدد الألوان أربعة أرجل، لذلك أمسك المصباح بحيث تكون الرجل الأرضية هي ثاني رجل من اليسار، وبحيث يصبح ترتيب الأرجل على النحو التالي: الرجل المسؤولة عن اللون الأحمرRed، ثم الرجل الأرضية GND، ثم الرجل المسؤولة عن اللون الأخضرGreen، فالأزرق Blue، وذلك ليسهُل عليك تذكر وظيفة كل رجل. صِل أرجل مصباح الليد وفقًا لما يلي: صِل الرجل المسؤولة عن اللون الأحمرR مع الرجل GP1 على لوحة بيكو. صِل الرجل الأرضية GND مع رجل الأرض GND على لوحة بيكو. صِل الرجل المسؤولة عن اللون الأخضرG مع الرجل GP2 على لوحة بيكو. صِل الرجل المسؤولة عن اللون الأزرق B مع الرجل GP3 على لوحة بيكو. لإسناد مصباح الليد متعدد الألوان إلى أرجل لوحة بيكو: استورد تابع المصباح متعدد الألوان RGBLED من مكتبة picozero، ثم استخدم الشيفرة التالية لإسناد المصباح إلى الأرجل الموصول معها على لوحة بيكو: from picozero import RGBLED rgb = RGBLED(red = 1, green = 2, blue = 3) استخدم الدالة اللازمة لتشغيل مصباح متعدد الألوان كما هو موضح في الشيفرة التالية: def happy(): # الشعور بالسعادة rgb.color = (0, 255, 0) # شغّل اللون الموافق لشعورك بالسعادة def sad(): # الشعور بالحزن rgb.color = (255, 0, 0) # شغّل اللون الموافق لشعورك بالحزن تمثيل الألوان بصيغة RGB: يمكننا تمثيل الألوان بصيغة يفهمها الحاسوب وذلك بالتعبير عن نسبة ما يحتويه اللون من اللون الأحمر والأخضر والأزرق، إذ تخزن هذه القيم في بايت (ثمانية بتات) وتكون قيمتها من 0 إلى 255. إليك جدولًا يوضح بعض القيم اللونية: اللون الأحمر الأخضر الأزرق أحمر 255 0 0 أخضر 0 255 0 أزرق 0 0 255 أصفر 255 255 0 أرجواني 255 0 255 سماوي 0 255 255 كما يمكنك الاستعانة بمنتقي الألوان من موقع w3schools للحصول على القيم الموافقة للون الذي تريده. توصيل مكبرات الصوت والأجراس الإلكترونية ستحتاج لتوصيل جرس إلكتروني واحد مع لوحة بيكو إلى سلكي توصيل نوع مقبس- مقبس. ابدأ بوصل الرجل الطويلة الموجبة للجرس مع الرجل GP5 على لوحة بيكو، وصِل الرجل السالبة مع أقرب رجل تأريض GND. لمعرفة الرجل الموجبة للجرس، ابحث عن الرجل الأطول، أو عن إشارة الموجب + أعلى الجرس. وتكون الشيفرة اللازمة لتوصيل جرس واحد على النحو التالي: from picozero import Speaker speaker = Speaker(5) أما لتوصيل جرسين إلكترونيين مع لوحة بيكو لخلق تأثير الصوت المجسم ستحتاج إلى أربعة أسلاك توصيل نوع مقبس- مقبس. أولًا، صِل الرجل الطويلة الموجبة للجرس الأول مع الرجل GP5 على لوحة بيكو، وصِل الرجل السالبة مع أقرب رجل تأريض GND، ثم صِل الرجل الموجبة للجرس الثاني مع الرجل GP10 على لوحة بيكو، والرجل السالبة مع أقرب رجل تأريض GND. وتكون الشيفرة اللازمة لتوصيل جرسين على النحو التالي: from picozero import Speaker speaker_1 = Speaker(5) speaker_2 = Speaker(10) ننصحك بتسمية المتغيرات Variables بأسماء تدل على وظيفتها، مثلًا عند إسناد صوت الطبل للمتغير Speaker_1 فسمّه drum_beat. ستحتاج لتوصيل السمّاعات مع لوحة بيكو إلى وصلة ذات نهاية بقطر 3 أو 5 مم (وليس وصلة USB)، وثلاثة مشابك تثبيت، وإلى اتباع الخطوات التالية: 1.صِل أحد المشابك مع أحد أرجل الأرض GND القريبة، وصِل المشبكين الآخرين مع الرجل GP5 والرجل GP10، كما هو موضح في الصورة أدناه. صِل نهاية المشبك الأول الموصول مع الرجل GP5، مع نهاية وصلة السمّاعات. صِل نهاية المشبك الثاني الموصول مع الرجل GP10،مع منتصف وصلة السمّاعات. صِل نهاية المشبك الموصول مع رجل الأرض GND مع جذر وصلة السمّاعات. معلومات مفيدة يجب معرفتها عن الصوت دعنا نطلع على بعض المعلومات المفيدة عن الأصوات قبل كتابة الشيفرة. النغمات المتاحة: تُوفر لنا مكتبة picozero ثمان وثمانين علامةً موسيقية، تتبع التدوين الغربي للموسيقا وتشمل جميع العلامات الموجودة في لوحة مفاتيح موسيقية كاملة الحجم. إليك بعض العلامات المُتاحة: b0 c1 c#1 d1 d#1 e1 f1 f#1 طول النغمة: توجد عدة طرق لتحديد طول النغمة: أولًا، تحديد طول نغمة واحدة باستخدام القيم، إذ يمكنك تحديد مدة النغمة الواحدة بإدخال قيمة في حقل الوسيط الثاني في دالة العزف: speaker.play(c_note, 0.1) # اعزف النغمة لمدة 0.1 ثانية ستُعزَف النغمة C في مثالنا لمدة 0.1 ثانية. ثانيًا، تحديد طول نغمة واحدة باستخدام الثوابت، إذ يمكنك تحديد مدة النغمة الواحدة بالتصريح عن أحد الثوابت في حقل الوسيط الثاني في دالة العزف بدلًا عن القيمة، وتعريف هذا الثابت كما يلي: BEAT = 1 # BEAT تعريف الثابت speaker.play(c_note, BEAT) # اعزف النغمة لمدة ثانية واحدة لاحظ أنه يمكننا استخدام الثابت BEAT لتحديد طول أي نغمة. ثالثًا، تحديد طول مجموعة من النغمات باستخدام القيم؛ فعند عزف لحن ما، يُفضل تخزين النغمات وطول كل منها في قائمة list، كما في مثالنا التالي، إذ خزّنا كل نغمة مع طولها في قائمة، وجمعنا النغمات الثلاث في قائمة: my_tune = [ ['d5', 1], ['d#5', 0.5], ['f5', 1.2]] # قائمة بالنغمات وطول كل منها احرص على كتابة النغمة ضمن علامتي اقتباس ' '. رابعًا، تحديد طول مجموعة من النغمات باستخدام الثوابت: ابدأ أولًا بتحديد طول النغمة الذي تريده باستخدام الثابت BEAT، اخترنا في مثالنا القيمة 0.4، ثم صرّح عن النغمات التي تود عزفها في قائمة ضمن علامتي ' ' واستخدم الثابت BEAT لتحديد طول النغمات: BEAT = 0.4 # طول النغمة الواحدة my_tune = [ ['d5', BEAT], ['d#5', BEAT / 2], ['f5', BEAT * 1.5]] # قائمة بالنغمات وطول كل منها يمكنك التحكم بعدد النغمات في الدقيقة BPM عن طريق تقسيم الثابت BEAT على عدد ما للحصول على نغمات أقصر، مثلًا 2 / BEAT، أو مضاعفته بضربه بعدد ما للحصول على نغمات أطول، مثلًا BEAT * 1.5 استخدام الأرقام عوضا عن النغمات: يمكنك الاستعاضة عن النغمات باستخدام قيم الترددات الموافقة لها، والتي تتراوح بين القيمة 150 إلى 10000، إليك المثال التالي لعزف نغمة ذات التردد 523 لثانية واحدة: speaker.play(523, 1) # اعزف النغمة ذات التردد 523 لثانية واحدة تحويل المقطوعات الموسيقية إلى نغمات: تُتيح لنا مكتبة "picozero" عزف المقطوعات الموسيقية الشهيرة واستخدامها في مشاريعنا، إذ تُستخدم الأحرف الإنجليزية للتعبير عن العلامات الموسيقية، وتستخدم الأرقام للتعبير عن موقع العلامة في السلم الموسيقي الكبير. على سبيل المثال، توجد العلامة C الوسطى في منتصف السلم الموسيقي ويعبر عنها بالرمز C4، وتزداد الأرقام المعبرة عن العلامة كلما صعدنا في السلم الكبير، وتنقص عند النزول. تحتوي المقطوعة الموسيقية علامات حادة يُعَبر عنها بالرمز # وتدعى "دييز". في مثالنا أدناه، توجد عدة علامات موسيقية حادة، أولها العلامة C الحادة والتي يرمز لها c#4. وقد تحتوي المقطوعة الموسيقية على علامات بسيطة يُشار إليها بالرمز ♭ وتدعى "بيمول"، لكن سنشير إليها في مشروعنا بالرمز # لعدم احتواء مكتبة picozero على شيفرة خاصة للتعبير عن العلامات البسيطة، وعلينا النزول نصف درجة في السلم الموسيقي للتحويل من علامة بسيطة إلى حادة. إليك الأمثلة التالية: تتحوّل العلامة البسيطة D إلى C حادة أو c#4. تتحوّل العلامة البسيطة E إلى D حادة أو d#4. تتحوّل العلامة البسيطة G إلى F حادة أو f#4. تتحوّل العلامة البسيطة A إلى G حادة أو g#4. أمثلة عن بعض الشيفرات الموسيقية الشيفرة اللازمة لعزف علامة موسيقية واحدة إليك مثالًا عن الشيفرة اللازمة لعزف العلامة C الوسطى لمدة نصف ثانية: def c_note(): speaker.play('c4', 0.5) # اعزف العلامة لمدة نصف ثانية الشيفرة اللازمة لعزف لحن موسيقي خزّن النغمات وطول كل منها في قائمة للحصول على لحن ما ، ثم شغّل اللحن باستخدام الدالة play: BEAT = 0.4 liten_mus = [ ['d5', BEAT / 2], ['d#5', BEAT / 2], ['f5', BEAT], ['d6', BEAT], ['a#5', BEAT], ['d5', BEAT], ['f5', BEAT], ['d#5', BEAT], ['d#5', BEAT], ['c5', BEAT / 2],['d5', BEAT / 2], ['d#5', BEAT], ['c6', BEAT], ['a5', BEAT], ['d5', BEAT], ['g5', BEAT], ['f5', BEAT], ['f5', BEAT], ['d5', BEAT / 2], ['d#5', BEAT / 2], ['f5', BEAT], ['g5', BEAT], ['a5', BEAT], ['a#5', BEAT], ['a5', BEAT], ['g5', BEAT], ['g5', BEAT], ['', BEAT / 2], ['a#5', BEAT / 2], ['c6', BEAT / 2], ['d6', BEAT / 2], ['c6', BEAT / 2], ['a#5', BEAT / 2], ['a5', BEAT / 2], ['g5', BEAT / 2], ['a5', BEAT / 2], ['a#5', BEAT / 2], ['c6', BEAT], ['f5', BEAT], ['f5', BEAT], ['f5', BEAT / 2], ['d#5', BEAT / 2], ['d5', BEAT], ['f5', BEAT], ['d6', BEAT], ['d6', BEAT / 2], ['c6', BEAT / 2], ['b5', BEAT], ['g5', BEAT], ['g5', BEAT], ['c6', BEAT / 2], ['a#5', BEAT / 2], ['a5', BEAT], ['f5', BEAT], ['d6', BEAT], ['a5', BEAT], ['a#5', BEAT * 1.5] ] def play_liten_mus(): speaker.play(liten_mus) الشيفرة اللازمة لتوليد تأثيرات صوتية مختلفة باستخدام الترددات يمكننا توليد تأثيرات صوتية ممتعة، أو مزعجة، وذلك بعزف نغمات قصيرة ذات ترددات مختلفة، إذ أنه كلما تغير التردد تختلف العلامة الموسيقية التي نسمعها وتختلف نغمتها. إليك الشيفرة التالية التي ترتفع فيها الترددات تدريجيًا لخلق صوت مبهج: def win(): # ترددات متزايدة for i in range(2000, 5000, 100): speaker.play(i, 0.05) # اعزف النغمة لمدة قصيرة جدًا أما المثال التالي فخفضنا فيه الترددات تدريجيًا لتوليد صوت زقزقة العصافير: def chirp(): # توليد صوت زقزقة العصافير for _ in range(2): # ترددات متناقصة for i in range(5000, 2999, -100): speaker.play(i, 0.02) # اعزف النغمة لمدة قصيرة جدًا sleep(0.2) غَيّر الترددات المستخدمة في حلقة التكرار for واستخدم الترددات ضمن المجال من 150 إلى 10000. الشيفرة اللازمة لتوليد ضجيج أبيض من صوت قرع الطبل إليك الشيفرة التالية: from picozero import Speaker from time import sleep from random import randint speaker = Speaker(5) for i in range(100): speaker.play(randint(500, 5000), duration=None) sleep(0.001) speaker.stop() sleep(0.5) الشيفرة اللازمة لعزف النغمات بصورة متكررة أنشئ قائمةً بالنغمات التي تريد عزفها وطول كل منها للحصول على لحن ما، ثم استخدم حلقة تكرار for لتشغيل اللحن نغمةً نغمة، أو علامةً علامة باستخدام الدالة play: BEAT = 0.4 liten_mus = [ ['d5', BEAT / 2], ['d#5', BEAT / 2], ['f5', BEAT], ['d6', BEAT], ['a#5', BEAT], ['d5', BEAT], ['f5', BEAT], ['d#5', BEAT], ['d#5', BEAT], ['c5', BEAT / 2],['d5', BEAT / 2], ['d#5', BEAT], ['c6', BEAT], ['a5', BEAT], ['d5', BEAT], ['g5', BEAT], ['f5', BEAT], ['f5', BEAT], ['d5', BEAT / 2], ['d#5', BEAT / 2], ['f5', BEAT], ['g5', BEAT], ['a5', BEAT], ['a#5', BEAT], ['a5', BEAT], ['g5', BEAT], ['g5', BEAT], ['', BEAT / 2], ['a#5', BEAT / 2], ['c6', BEAT / 2], ['d6', BEAT / 2], ['c6', BEAT / 2], ['a#5', BEAT / 2], ['a5', BEAT / 2], ['g5', BEAT / 2], ['a5', BEAT / 2], ['a#5', BEAT / 2], ['c6', BEAT], ['f5', BEAT], ['f5', BEAT], ['f5', BEAT / 2], ['d#5', BEAT / 2], ['d5', BEAT], ['f5', BEAT], ['d6', BEAT], ['d6', BEAT / 2], ['c6', BEAT / 2], ['b5', BEAT], ['g5', BEAT], ['g5', BEAT], ['c6', BEAT / 2], ['a#5', BEAT / 2], ['a5', BEAT], ['f5', BEAT], ['d6', BEAT], ['a5', BEAT], ['a#5', BEAT * 1.5] ] for note in liten_mus: speaker.play(note) الشيفرة اللازمة لعزف عدة نغمات متزامنة إذا أردت عزف لحن ما مثلًا، وتشغيل لحن أو تأثير صوتي آخر بالتزامن معه، فيمكنك ذلك بوضع wait=False في حقل الوسيط الثاني للدالة play . في مثالنا التالي، أنشأنا قائمةً بالنغمات التي نريد عزفها وطول كل منها، ثم عرّفنا اللحن الآخر المزعج، الذي سينطلق بالتزامن مع اللحن الأول عند الضغط على الزر، وسيتوقف معه عند إيقاف الشيفرة: BEAT = 0.4 liten_mus = [ ['d5', BEAT / 2], ['d#5', BEAT / 2], ['f5', BEAT], ['d6', BEAT], ['a#5', BEAT], ['d5', BEAT], ['f5', BEAT], ['d#5', BEAT], ['d#5', BEAT], ['c5', BEAT / 2],['d5', BEAT / 2], ['d#5', BEAT], ['c6', BEAT], ['a5', BEAT], ['d5', BEAT], ['g5', BEAT], ['f5', BEAT], ['f5', BEAT], ['d5', BEAT / 2], ['d#5', BEAT / 2], ['f5', BEAT], ['g5', BEAT], ['a5', BEAT], ['a#5', BEAT], ['a5', BEAT], ['g5', BEAT], ['g5', BEAT], ['', BEAT / 2], ['a#5', BEAT / 2], ['c6', BEAT / 2], ['d6', BEAT / 2], ['c6', BEAT / 2], ['a#5', BEAT / 2], ['a5', BEAT / 2], ['g5', BEAT / 2], ['a5', BEAT / 2], ['a#5', BEAT / 2], ['c6', BEAT], ['f5', BEAT], ['f5', BEAT], ['f5', BEAT / 2], ['d#5', BEAT / 2], ['d5', BEAT], ['f5', BEAT], ['d6', BEAT], ['d6', BEAT / 2], ['c6', BEAT / 2], ['b5', BEAT], ['g5', BEAT], ['g5', BEAT], ['c6', BEAT / 2], ['a#5', BEAT / 2], ['a5', BEAT], ['f5', BEAT], ['d6', BEAT], ['a5', BEAT], ['a#5', BEAT * 1.5] ] sound = [ [523, 0.1], [None, 0.1], [523, 0.4] ] def annoying_sound(): speaker2.play(sound, wait=False) # شغّل بالتزامن مع اللحن الأول button.when_pressed = annoying_sound try: speaker.play(liten_mus) finally: speaker.off() #أطفئ مكبر الصوت الأول عند إيقاف البرنامج speaker2.off() # أطفئ مكبر الصوت الثاني عند إيقاف البرنامج توصيل عناصر الدخل توصيل الأزرار مع لوحة بيكو ستحتاج لتوصيل زر واحد مع لوحة بيكو إلى ما يلي: لوحة راسبيري بيكو. زر إلكتروني. سلكي توصيل نوع مقبس-مقبس. صِل سلكي التوصيل مع أرجل الزر واستخدم الشريط اللاصق لتثبيتهما إن لزم الأمر، ثم صِل أحد السلكين مع الرجل GP18 والسلك الآخر مع أقرب رجل أرضية، لا يهمنا ترتيب توصيل الأسلاك إذ إنه لا توجد قطبية للزر. لتوصيل عدة أزرار إلكترونية مع لوحة بيكو ستحتاج إلى ما يلي: لوحة راسبيري بيكو. أزرار إلكترونية. سلكي توصيل نوع دبوس-مقبس لكل زر. توضح الصورة التالية طريقة توصيل ثلاثة أزرار مع لوحة بيكو، وإذا أردت توصيل زر رابع فما عليك سوى توصيله مع إحدى أرجل الأغراض العامة GP ورجل أرضية. استخدم سلكي توصيل نوع دبوس- مقبس لتوصيل الزر الأول مع الرجل GP18 ومع أقرب رجل أرضية GND، ثم صِل الزر الثاني مع الرجل GP22، والثالث مع الرجل GP28 بنفس الطريقة. استيراد تابع الزر Button من مكتبة picozero: إليك الشيفرة اللازمة لاستيراد تابع الزر Button من مكتبة picozero: from picozero import Button الشيفرة اللازمة لتوصيل زر إلكتروني واحد: لتوصيل زر إلكتروني علينا إسناده إلى الرجل الموصول معها على لوحة بيكو، كما يلي: from picozero import Button button = Button(18) الشيفرة اللازمة لتوصيل عدة أزرار إلكترونية: استورد تابع الزر Button من مكتبة picozero، ثم استخدم الشيفرة التالية لإسناد عدة أزرار إلى الأرجل الموصولة معها على لوحة بيكو: from picozero import Button button_1 = Button(18) button_2 = Button(22) button_3 = Button(28) ننصحك بتسمية المتغيرات بأسماء تدل على عملها، كأن تسمّي الزر المسؤول عن تشغيل المصباح الأحمر red_button أو أي اسم آخر تراه مناسبًا. تشغيل نغمة معينة عند الضغط على كل زر: يمكنك إضافة عدة أزرار يستدعي كل منها دالة صوتية مختلفة عند الضغط عليها، وذلك باستدعاء الدالة الموافقة عند الضغط على الزر عن طريق ذكر اسمها بدون استخدام الأقواس. كما في المثال التالي: happy_button.when_pressed = happy sad_button.when_pressed = sad angry_button.when_pressed = angry تشغيل النغمة التالية عند الضغط على الزر: عرّف متغيرًا ما، وليكن option، لتخزين النغمة الحالية فيه واستدعاء الدالة التالية، واحرص على مطابقة أسماء الدوال في الشيفرة للدوال التي استخدمتها في الفقرة السابقة: option = 0 # خزّن النغمة الحالية في هذا المتغير def choice(): # استدعي الدالة الصوتية التالية وعدّل قيمة متغير التخزين global option if option == 0: energised() # دالة النغمة الأولى elif option == 1: calm() # دالة النغمة الثانية elif option == 2: focused() # دالة النغمة الثالثة elif option == 3: rgb.off() # انتقل إلى الخيار الثاني if option == 3: option = 0 else: option = option + 1 button.when_pressed = choice # استدعي الدالة التالية عند الضغط على الزر توصيل المبدل مع لوحة بيكو والشيفرة اللازمة لذلك توصيل مبدل يدوي الصنع أو زر مع لوحة بيكو: ستحتاج إلى سلكي توصيل نوع دبوس-مقبس. صِل أحدهما مع الرجل GP18 والسلك الآخر مع أقرب رجل أرضية، كما يلي: ثم يمكنك صنع مبدّل يدوي، كما تعلمنا في مشروع سابق، وتوصيلها مع اللوحة وذلك بتوصيل النهاية الحرة للأسلاك مع الجزء الناقل من المبدّل، مثل النحاس أو ورق القصدير. توصيل عدة قواطع يدوية أو أزرار مع لوحة بيكو: ستحتاج إلى سلكي توصيل نوع دبوس-مقبس لكل قاطعة تود توصيلها مع لوحة بيكو. استخدم سلكي توصيل نوع دبوس- مقبس لتوصيل المبدّل الأول مع الرجل GP18 ومع أقرب رجل أرضية GND، ثم صِل المبدّل الثاني مع الرجل GP22 ومع أقرب رجل أرضية، والثالث مع الرجل GP28 ورجل الأرضية بنفس الطريقة، كما هو موضح في المخطط التالي: لكتابة الشيفرة اللازمة لتوصيل المبدّل لا بُد من استيراد تابع المبدل Switch من مكتبة picozero كما هو موضح في الشيفرة التالية: from picozero import Switch استورد تابع المبدّل Switch من مكتبة picozero، ثم استخدم الشيفرة التالية لإسناد المبدّل إلى الرجل الموصولة معه على لوحة بيكو: from picozero import Switch switch = Switch(18) ولتوصيل عدة مبدّلات: استورد تابع المبدّل Switch من مكتبة picozero، ثم استخدم الشيفرة التالية لإسناد عدة مبدّلات إلى الأرجل الموصولة معها على لوحة بيكو: from picozero import Switch switch_1 = Switch(18) switch_2 = Switch(22) switch_3 = Switch(28) ننصحك بتسمية المتغيرات بأسماء تدل على عملها، كأن تسمّي القاطعة المسؤولة عن تشغيل المصباح الأحمر red_switch أو أي اسم آخر تراه مناسبًا. توصيل المقاومات المتغيرة مع لوحة بيكو ستحتاج لتوصيل مقاومة متغيرة مع اللوحة إلى ما يلي: لوحة راسبيري بيكو. مقاومة متغيرة. أسلاك توصيل نوع مقبس-مقبس (عدد 3). توجد للمقاومة المتغيرة ثلاثة أرجل: رجل الأرضية GND، ورجل تشابهية Analogue، ورجل التغذية 3V3، وعند تدوير قرص المقاومة المتغيرة إلى أقصى اليسار سيشير السهم إلى الرجل الأرضية GND، وعند تدويره إلى أقصى اليمين سيشير السهم إلى رجل التغذية 3V3، أما الرجل الوسطى للمقاومة فهي الرجل التشابهية التي تستمد منها لوحة بيكو القيم لقراءتها. صِل سلك توصيل ذو نهايات مقبس-مقبس مع كل من أرجل المقاومة الثلاث، ثبت التوصيلات بالشريط اللاصق إن لزم الأمر. صِل النهاية الحرة للسلك الموصول مع رجل المقاومة ذات الرقم 1 مع رجل الأرض GND الموجودة بين الرجلين GP21 وGP22. صِل رجل المقاومة الوسطى مع الرجل GP26_A0 على لوحة بيكو. صِل رجل المقاومة ذات الرقم 3 مع رجل التغذية 3V3. استيراد تابع المقاومة المتغيرة Pot من مكتبة picozero: إليك الشيفرة اللازمة لاستيراد تابع المقاومة المتغيرة Pot من مكتبة picozero: from picozero import Pot وتكون الشيفرة اللازمة لتوصيل مقاومة متغيرة على النحو التالي: from picozero import Pot dial = Pot(0) # Connected to pin A0 (GP_26) عند استخدام مقاومة متغيرة للتحكم في الخرج، سنحتاج إلى تقسيم قيم المقاومة إلى أجزاء متساوية. كأن نستخدم التابع dial.value للحصول على قيم تتراوح بين 0 و 1، كما يمكننا ضرب القيمة ب 100 للحصول على نسبة مئوية؛ فإذا كان لديك خمس قيم يمكنك التحقق ما إذا كانت القيمة أقل من 20 أو 40 أو 60 أو 80 أو 100؛ أما إذا كان لديك ثلاث قيم يمكنك تقسيم القراءات للتحقق ما إذا كانت القيمة أقل من 33 أو 66 أو 100. إليك المثال التالي: while True: mood = dial.value * 100 # تحويل إلى نسبة مئوية print(mood) if mood < 20: happy() elif mood < 40: good() elif mood < 60: okay() elif mood < 80: unsure() else: unhappy() sleep(0.1) الآن، شغّل دارتك وتحقق أن جميع عناصر الدخل والخرج تعمل كما يجب، واستعن بفقرة تصحيح الأخطاء أدناه إذا واجهتك أي مشكلة. تصميم الهيكل الخارجي تثبيت العناصر داخل الورق المقوى أو البلاستيك بإمكانك تثبيت مصابيح الليد أو الأجراس أو المقاومات المتغيرة داخل قطع من الورق المقوى أو البلاستيك، وذلك بصنع ثقوب وإدخال العناصر وأسلاك التوصيل فيها، كما هو موضح: افصل الأسلاك عن العنصر، ثم أدخله في الثقب الذي أحدثته، ثم أعد توصيل الأسلاك. ستحتاج إلى استخدام أداة حادة لإحداث ثقب في المواد البلاستيكية. اطلب مساعدة أحد البالغين إذا لزم الأمر، واحرص على تذكر ما هي أرقام الأرجل الموصولة مع الأسلاك. استخدم الشريط اللاصق لتثبيت العناصر في مكانها. تبديد الضوء المنبعث من مصباح الليد نحصل عند تبديد ضوء مصباح الليد، أو نشره، على تأثير لطيف، وخاصة عند استخدام مصابيح الليد الشفافة، ذات اللون الواحد أو متعددة الألوان، وذلك بوضع المصباح خلف ورقة رقيقة أو شفافة، أو خلف شريط لاصق شفاف، مما سيجعل الضوء ينتشر على مساحة أوسع وبسطوع أقل، فيصبح أكثر راحةً للعين. كما يمكنك توجيه الضوء في اتجاه معين باستخدام ورقة بيضاء، وذلك لتحصل على أكبر قدر ممكن من الضوء. تثبيت أسلاك التوصيل باستخدام الشريط اللاصق يمكنك تثبيت أسلاك التوصيل باستخدام الشريط اللاصق، وإزالة الشريط اللاصق فيما بعد بكل سهولة لإعادة استخدام العناصر عند الحاجة. استخدام سكين الحرف تُعد سكاكين الحرف Crafts مفيدةً عند صنع الحرف اليدوية، لكن يجب أن تكون حذرًا جدًا عند استخدامها لأنها حادة جدًا ويمكن أن تسبب جروحًا وإصابات. احرص على وجود شخص بالغ عند استخدامك للسكاكين، أو اطلب منه استخدامها عوضًا عنك، كما ننصحك باستخدام لوح القص لحماية الأسطح، أو باستخدام لوح التقطيع الخشبي المتوفر في كل المطابخ. توصيل الأسلاك ببعضها قد تحتاج إلى أسلاك توصيل طويلة جدًا لتوصيل مصابيح الليد مع أرجل لوحة بيكو، أو يمكنك وصل الأسلاك ببعضها للحصول على سلك طويل، وذلك عبر توصيل سلك ذو نهايات دبوس-مقبس مع سلك ذو نهايات مقبس-مقبس للحصول على سلك مقبس-مقبس طويل جدًا، ويُطلق على هذه الطريقة اسم سلسلة الأقحوان daisy chaining. ننصحك باستخدام سلكين لهما اللون نفسه ليسهل تتبع السلك ومعرفة العنصر الموصول معه. تكمن مشكلة هذه الطريقة في أن الأسلاك قد تنفصل عن بعضها، ولذلك ينصح بلصقها بقطعة صغيرة من الشريط اللاصق. إنشاء مبدل فوري يعمل عند الإسقاط ستحتاج لإنشاء مبدّل فوري Drop switch ما يلي: لوحة راسبيري بيكو. سلكي توصيل نوع دبوس-مقبس. ورق قصدير. شريط لاصق. أولًا، أنشئ شريطين من ورق القصدير، أو من أي مادة ناقلة. ثانيًا، ثبت سلكي التوصيل مع شريطي القصدير باستخدام الشريط اللاصق، كما يلي: ثالثًا، الصق قطعةً من القصدير أسفل المجسم الذي ستضعه فوق شريط القصدير لإغلاق المبدّل. احرص على أن تكون قاعدة المجسم واسعةً بما يكفي لتوفير تماس بين سطحي القصدير. رابعًا، صِل النهايات الحرة للسلكين مع لوحة بيكو وأسقط المجسم لإغلاق المبدّل. إنشاء قاطعة يدوية تعمل عند السحب إليك ما سنحتاج إليه: مقص. ورق مقوى. رقائق القصدير. غراء وشريط لاصق. شرائط ملونة وورق ملون. قلم رصاص ومسطرة (اختياري). أولًا، قُصَّ الورق المقوى إلى ثلاثة مستطيلات متساوية الحجم. ثانيًا، قُصَّ مستطيلًا صغيرًا في منتصف المستطيل الأول، واحتفظ به لاستخدامه لاحقًا. ثالثًا، قُصَّ قطعًا من ورق القصدير بحجم المستطيلات الكبيرة، ثم الصقها عليها باستخدام الغراء، واحرص على عدم وضع الغراء على الوجه الخارجي لورق القصدير حتى لا تتأثر التوصيلات لاحقًا. رابعًا، قُصَّ أطراف المستطيل الصغير للحصول على شكل مدبب أو بشكل حرف V، ثم قلّم الأطراف بمقدار بضع ملميترات كي يتسع المستطيل الصغير في الفتحة. خامسًا، غلّف المستطيل الصغير بكامله بورق القصدير، واحرص على استخدام ورقة قصدير واحدة، إذ ستسمح هذه القطعة بمرور التيار عند إغلاق المبدّل. سادسًا، استخدم الشريط اللاصق لتثبيت على الوجه العلوي للمستطيلات. احرص على أن يكون الدبوس المعدني للسلك ملامسًا لورق القصدير، وأن يكون الجزء البلاستيكي الأسود ملامسًا لحافة المستطيل. سابعًا، أضف مزيدًا من الشريط اللاصق لتثبيت السلك ومنع انفكاكه عن طريق الخطأ. ثامنًا، ادهن بعض الغراء على المستطيل الذي فرّغنا منتصفه (الموجود في يسار الصورة) والصقه مع المستطيل المغطى بالقصدير (يمين الصورة)، واحرص على ألا تتلامس طبقتي القصدير الموجودة على حواف المستطيلات، قُصّها إذا لزم الأمر: أصبح المبدّل جاهزًا للاستخدام في مشروعك. تثبيت الأسلاك والعناصر باستخدام الشريط اللاصق يمكنك تثبيت العناصر مع أسلاك التوصيل، أو تثبيتها في مكانها باستخدام الشريط اللاصق، وإزالة الشريط اللاصق بكل سهولة لإعادة استخدام العناصر فيما بعد: أخيرًا، اختبر المشروع بعد انتهائك من تنفيذ التصميم الخارجي، واعرضه على أفراد العائلة أو الأصدقاء للحصول على ملاحظاتهم، وقرر هل تود إجراء أي تعديل؟ تصحيح الأخطاء قبل التعرف على المشاكل التي قد تواجهك عند تنفيذ المشروع وكيفية إصلاحها، عليك أولًا التحقق من سلامة لوحة بيكو: التحقق من سلامة لوحة بيكو باستخدام مصباح الليد استخدم مصباح الليد الموجود على لوحة بيكو للتحقق من سلامة اللوحة، وذلك بجعل المصباح يومض عند تشغيل الشيفرة بإضافة الشيفرة التالية في البداية: from picozero import pico_led from time import sleep pico_led.on() sleep(2) pico_led.off() تصحيح الأخطاء الموجودة في الشيفرة تحقق من وجود أي رسائل خطأ في نافذة صدفة Thonny وتحقق من محتواها، إن وجدت. راجع الشيفرة التي كتبتها وتحقق من خلوها من الأخطاء، مثل نسيان علامة : مثلًا، أو وجود مسافة بادئة دون الحاجة لها. تأكد من استيراد توابع العناصر التي ستستخدمها في مشروعك من مكتبة picozero مثل تابع مصباح الليد RGBLED أو الزر Button. استخدم تعليمة الطباعة print لإضافة شرح مختصر عند كل خطوة، مثل (البدء)print أو (ضبط المصباح على اللون الأخضر)print. لا تعمل بعض العناصر الإلكترونية كما يجب تأكد أن جميع العناصر متصلة ببعضها جيدًا، وتحقق من ثبات نقاط توصيل الأسلاك مع اللوحة ومع العناصر. تأكد أن أرقام الأرجل المستخدمة في الشيفرة مطابقة لأرقام الأرجل الموصولة مع مصباح الليد، وتأكد من إعادة وصل الأرجل في حال فصلتها عند العمل على تصميم شكل الآلة الموسيقية. تحقق من وصل العناصر وفق القطبية الصحيحة، إذ قد تحتوي بعض العناصر على قطب موجب + وآخر سالب -. في حال تحققت من جميع النقاط السابقة ولا زالت آلتك لا تعمل، فجرّب تبديل العناصر الإلكترونية بأخرى جديدة. لا يحدث شيء عند تشغيل الشيفرة تأكد أن جميع العناصر متصلة ببعضها جيدًا، وأنها موصولة مع الأرجل الصحيحة على اللوحة. تحقق من صدفة Thonny عند تشغيل الشيفرة؛ لربما نسيت نسيت تعريف بعض الدوال أو المتغيرات، أو قد تكون نسيت تعديل الشيفرة لتتناسب مع مشروعك. تحقق من صحة الشيفرة التي كتبتها، واستخدم تابع الطباعة print لإيضاح عمل الشيفرة. تحقق أنك استدعيت الدوال في الشيفرة. إليك مثالًا عن طريقة استدعاء الدالة، إذا عرفنا الدالة happy أولًا، ثم استدعيناها عن طريق التصريح عن اسمها (بدون وسطاء داخل الأقواس): def happy(): # الدالة الأولى rgb.color = (0, 255, 0) # اللون الموافق للدالة الأولى def sad(): # الدالة الثانية rgb.color = (255, 0, 0) # اللون الموافق للدالة الثانية happy() لا يضيء مصباح الليد عند استدعاء الدالة المسؤولة عن تشغيله تأكد من مطابقة الأرجل الموصول معها المصباح على لوحة بيكو للأرجل المسند إليها في الشيفرة. لا يضيء مصباح الليد باللون الصحيح تحقق من الشيفرة التي كتبتها وأن القيم اللونية مطابقة للون المستخدم، واستخدم منتقي الألوان التالي للتحقق من اللون المستخدم. لا تصدر النغمات أو أن صوتها مختلف عن الصوت المطلوب من غير المرجح أن تكون المشكلة في الشيفرة التي كتبتها، بما أنها كانت سليمةً قبل تنفيذ التصميم الخارجي للعبة، لذا عليك التحقق من التوصيلات والعناصر. تأكد من توصيل العناصر مع الأرجل الصحيحة، ستجدها في بداية الشيفرة. تأكد أن جميع العناصر موصولة مع بعضهًا جيدًا، واستخدم الشريط اللاصق لإحكام تثبيت العناصر. تأكد من عدم تغطية العناصر الناقلة في دارتك، مثل ورق القصدير بالغراء أو الشريط اللاصق. وذلك للمشاكل الآتية: يتأخر عزف النغمة عند الضغط على زر ما: عند استخدام أحد الأحداث events مثل حدث الضغط when_pressed لتشغيل دالة ما، فإن هذه الدالة ستُنفَذ حتى انتهائها وستمنع تشغيل أي شيء آخر في الشيفرة. sound = [ [523, 0.1], [None, 0.1], [523, 0.4] ] def annoying_sound(): speaker.play(sound, wait=False) # لا تؤخر تشغيل الشيفرة button.when_pressed = annoying_sound طول الأسلاك غير مناسب: إذا وجدت أن الأسلاك التي استخدمتها لا تفي بالغرض المطلوب بسبب قصر طولها، فما عليك إلا زيادة طولها، وفقًا لما تعلمناه في فقرة توصيل الأسلاك ببعضها. لا تثبُت الأسلاك والعناصر في مكانها: قد تكون بعض التوصيلات أمتن من غيرها، لذا ننصحك باستخدام الشريط اللاصق لإحكام تثبيت الأسلاك. حاول حل المشاكل الأخرى التي قد تواجهك عند التنفيذ وشاركنا طريقة الحل في منصة حسوب IO أو في أكاديمية حسوب. ترقية المشروع يمكنك ترقية مشروعك حين يتسنى لك ذلك، بإضافة مزيد من عناصر الدخل والخرج عليه، وتحسين تصميمه الخارجي، ولا تنسى اختباره مع الأصدقاء والعائلة لتحسين تجربة الاستخدام وفقًا لآرائهم، واطّلع على المشاريع التي أوردناها في مقدمة المقال لتستلهم منها بعض الأفكار. استخدمنا في النسخة الأصلية لمشروع الأضواء الليلية مصباح ليد متعدد الألوان وأحدثنا ثقوبًا صغيرةً في ورقة ليخرج منها الضوء ونحصل على تأثير مشابه لسماء مرصّعة بالنجوم، وأضفنا زرًا تشغيل وإطفاء المصباح. شاهد الفيديو ولاحظ كيف عملنا على ترقية المشروع بإضافة مصباح آخر متعدد الألوان لزيادة السطوع، ونشرنا الضوء على نطاق أوسع بوضع المصباح ضمن غلاف بلاستيكي شفاف، واستبدلنا الورق المقوى ذو الثقوب بمجسم ذي اثني عشر وجهًا، وحفرنا على كل وجه رمزًا لأحد الأبطال الخارقين في الرسوم المتحركة. الخاتمة تهانينا، فقد أتممت مشروع تصميم وتنفيذ لعبة حسية تفاعلية باستخدام لوحة راسبيري باي بيكو. إذا واجهت مشاكلًا عند تنفيذ هذا المشروع فيمكنك الحصول على الدعم والمساعدة عبر إضافة سؤالك في قسم الأسئلة والأجوبة في أكاديمية حسوب. ترجمة -وبتصرف- للمقال Sensory gadget من الموقع الرسمي لراسبيري باي. اقرأ أيضًا تصميم وتنفيذ آلة موسيقية باستخدام لوحة راسبيري باي بيكو صنع جهاز لعرض الحالة المزاجية باستخدام لوحة راسبيري باي بيكو صنع قلب نابض باستخدام لوحة راسبيري باي بيكو
-
سنعمل في هذا المشروع على إنشاء آلة تصدر أصواتًا وموسيقى مختلفة باستخدام الأزرار buttons، والمبدّلات الإلكترونية switches، والمقاومات المتغيرة potentiometer. لنحصل على آلة مشابهة لما يلي: اصنع لوحة تصدر تأثيراتٍ صوتيةً مختلفةً عند الضغط عليها، وذلك باستخدام الورق المقوى ورقائق القصدير، ويمكنك الاطلاع على الشيفرة اللازمة لتنفيذ هذا المشروع من ملف codes.zip. ستتعلم في هذا المشروع ما يلي: كيفية تصميم جهاز صوتي يعمل وفق غرضٍ معين. برمجة الجرس الإلكتروني buzzer لتشغيل تأثيرات صوتية وموسيقى. إنشاء واجهة تتيح للمستخدم التحكم بالأصوات. معلومة: تملك الأصوات تأثيرًا على حالتنا النفسية، فقد تكون مهدئةً، أو مزعجةً، أو منشِطة، فعلى سبيل المثال، يجد بعض الأطفال الرُضع لآلة الضجيج الأبيض Whitenoise تأثيرًا مهدئًا يساعدهم على الاسترخاء والنوم؛ بينما يستخدم منسقو الأغاني DJs أجهزةً محمولة لتوليد النغمات، ويستخدم محبو الدُعابة أجهزةً تصدر تأثيرات صوتية لإضحاك الناس. ماذا عنك؟ هل توجد آلة صوتية تستخدمها يوميًا؟ متطلبات المشروع عتاد: لوحة حاسوب راسبيري باي بيكو Raspberry Pi Pico مع أرجل مثبتة عليها. كبل USB لنقل البيانات ذو نهايات من النوع USB A و micro USB. مقاومات متغيرة potentiometer وأزرار buttons. جرس إلكتروني غير فعّال passive. أسلاك توصيل. بعض مستلزمات الأشغال اليدوية، مثل الورق المقوى، ورقائق القصدير، وشريط لاصق. مصباح ليد عادي أو متعدد الألوان RGB LED ذو مهبط مشترك common cathode، ومقاومات وأسلاك توصيل. (اختياري) جرس إلكتروني إضافي غير فعّال لخلق تأثير الصوت المجسم stereo. (اختياري) برمجيات برنامج ثوني Thonny: وهو البيئة البرمجية التي سنستخدمها لكتابة الشيفرة بلغة بايثون. تثبيت برنامج ثوني على نظام تشغيل راسبيري باي يأتي برنامج ثوني مثبتًا مع نظام تشغيل راسبيري باي، المعروف سابقًا براسبيان Raspbian، لكن قد تحتاج إلى تحديثه. انقر على الأيقونة في الزاوية العلوية اليسرى من الشاشة لفتح نافذة الطرفية Terminal، أو اضغط المفاتيح التالية معًا Ctrl+Alt+T. ثم اكتب الأمر التالي لتحديث نظام التشغيل وبرنامج ثوني: sudo apt update && sudo apt upgrade -y تثبيت برنامج ثوني على أنظمة التشغيل الأخرى يمكنك تثبيت ثوني على الحواسيب العاملة بنظام تشغيل لينكس، أو ويندوز، أو ماك، وذلك من الموقع الرسمي thonny.org انقر على رابط التنزيل الموافق لنظام تشغيل حاسوبك من الزاوية العلوية اليمنى في الموقع، ثم انقر على الملفات بعد تنزيلها، قد تظهر لك الرسالة التالية على نظام ويندوز: انقر على خيار المزيد من المعلومات "More info" ثم على التشغيل على أي حال "Run anyway". التعرف على واجهة برنامج ثوني ستظهر لك الواجهة التالية عند فتح ثوني: يمكنك الكتابة بلغة بايثون في النافذة الرئيسية الكبيرة، ثم النقر على زر التشغيل الأخضر Run للتنفيذ، ستظهر لك رسالة لحفظ الملف قبل تشغيله. اكتب الأمر التالي وشغّله: print('Hello World!') تغيير السمة والخط يمكنك التحكم بلون الخط وحجمه وتغيير السمة المُستخدمة في واجهة البرنامج، وذلك بالنقر على قائمة الأدوات Tools من الشريط أعلى الشاشة، ثم النقر على خيارات Options، ثم انقر بعدها على نافذة الخط والسمة Theme & Font واختر نوع الخط والسمة التي تفضلها من النافذة المنسدلة ثم انقر على زر موافق OK عند الانتهاء. ننصحك باختيار الخطوط البسيطة الواضحة والابتعاد عن الخطوط المزخرفة أو المشابهة لخط اليد لأنه قد تجعل القراءة أصعب. إعداد مكتبة picozero سنعمل في هذه الخطوة على إعداد مكتبة picozero وتوصيل لوحة راسبيري باي بيكو وإعداد برنامج مايكرو بايثون. أولًا، صِل الطرف الصغير لكبل USB إلى لوحة راسبيري باي والطرف الآخر إلى حاسوبك لتتمكن من برمجة اللوحة عن طريقه. ثانيًا، افتح محرر ثوني، ولاحظ ما هو الإصدار المستخدم من بايثون بقراءة النص الموجود في الزاوية السفلية اليمنى من الشاشة، انقر على النص واختر "MicroPython (Raspberry Pi Pico)"، إذا لم يكن هذا الخيار محددًا. سيطالبك ثوني بتثبيت برنامج MicroPython على حاسوب راسبيري باي بيكو إذا لم تستخدمه مسبقًا، فقط انقر على زر التثبيت Install. ثالثًا، أضف حزمة بيكو زيرو picozero من خلال النقر على قائمة الأدوات Tools من شريط القوائم في برنامج ثوني، ثم النقر على خيار إدارة الحزم Manage Packages. ثالثًا، اكتب "picozero"، ثم انقر على زر البحث Search on PyPi. رابعًا، انقر على picozero من نتائج البحث ثم انقر على زر التثبيت Install. استلهم أفكارك اطلع على المشاريع التالية واستلهم منها بعض الأفكار لصنع آلتك الموسيقية: لوحة العزف السحرية باستخدام مبدّل فوري أنشئ مبدّلًا فوريًا drop switch بلصق قطعة قصدير على مجسم شخصية ما وضعها فوق ورق القصدير ليبدأ العزف السحري. يمكنك الاطلاع على الشيفرة اللازمة لتنفيذ هذا المشروع باسم drop_switch_player.py ضمن الملف المرفق codes.zip. آلة الإنذار شغّل الفيديو ولاحظ أنه عند سحب قطعة الورق المقوى، كما في مشروع مفرقعات الحفلات، ستتلامس قطعتا القصدير (الملصقتان على مشبك الملابس) وتغلق المبدّل، مما سيؤدي إلى تشغيل سلسلة من الأضواء والأصوات المزعجة. يمكنك الاطلاع على الشيفرة اللازمة لتنفيذ هذا المشروع باسم soundalarm.py ضمن الملف المرفق الذكور سابقًا والمتاح بنهاية المقال. آلة موسيقية بسيطة شغّل الفيديو ولاحظ كيف تتحكم المقاومة المتغيرة بسرعة عزف النغمة من الجرس الأول، أما عند الضغط على الزر فتَصدُر عدة نغمات قصيرة من الجرس الثاني. يمكنك الاطلاع على الشيفرة اللازمة لتنفيذ هذا المشروع باسم dj_desk.py ضمن الملف المرفق. تصميم الآلة الموسيقية فكِّر في الغرض من آلتك الموسيقية؟ وما هي الآلية التي سيتبعها المستخدم للتحكم بأصوات الآلة؟ أولًا، يجب عليك اختيار الآلة التي تود صنعها واختيار الغرض منها، ثم اختيار طريقة العزف، واختيار الجمهور المناسب لها، ويمكنك اختيار إحدى الاقتراحات التالية: صنع محاكاة لآلة موسيقية ما. صنع مشغل موسيقى. صنع آلة لتوليد التأثيرات الصوتية. *صنع آلةٍ تولّد أنغامًا مهدئةً، أو مزعجة. ثانيًا، عليك اختيار نوع الصوت الذي ستصدره الآلة، هل تريد: تشغيل نغمات موسيقية محددة، أو أغانٍ كاملة. تشغيل أصوات من الطبيعة، مثل صوت الرعد أو زقزقة العصافير. تشغيل الصوت حتى انتهائه، أم مقاطعة الصوت عند تشغيل صوت آخر. استخدام مقاومة متغيرة للتحكم بطبقة الصوت وسرعته. عدد العناصر التي يمكن توصيلها مع لوحة راسبيري باي بيكو تحتوي لوحة راسبيري باي بيكو على ثمانية أرجل أرضية GND، لذا يمكنك توصيل ثمانية عناصر فقط، وقد تستطيع توصيل أكثر من ثمانية عناصر إذا كان من الممكن أن يشترك بعضها برجل الأرض GND. عليك أخذ النقاط التالية في الحسبان عند التخطيط لآلتك: تُشَغّل مكبرات الصوت Speakers كل نغمة على حدى، لذلك ستحتاج لعدة مكبرات صوت لتشغيل عدة نغمات في نفس الوقت. توجد رجل تغذية واحدة ذات جهد 3 فولت على لوحة بيكو؛ أي يمكنك استخدام مقاومة متغيرة potentiometer واحدة، كما أنه يوجد حدٌّ لقيمة التيار الذي توفره لوحة بيكو. إليك بعض الاقتراحات لعناصر الدخل والخرج التي يمكنك استخدامها معًا: مقاومة متغيرة واحدة وجرس إلكتروني واحد. أربعة أزرار جاهزة وجرس إلكتروني واحد. ثمانية أزرار يدوية الصنع وجرس إلكتروني واحد. مقاومة متغيرة واحدة وجرسان، وزران. عدة أزرار وأجراس لعزف عدة نغمات في نفس الوقت. ثالثًا، قرر ما هو عدد الأزرار والأجراس التي تريد استخدامها عند تصميم آلتك؟ يمكن لآلتك أن تحتوي على: جرس إلكتروني واحد. جرسان لخلق تأثير الصوت المجسم، أو عزف النغمة وإيقاعها. سمّاعات، وستحتاج حينها إلى ثلاثة دبابيس تثبيت أو ما يُعرف بمشابك التمساح Alligator Clips لتوصيل السمّاعات. عدة أجراس إلكترونية. رابعًا، اختر ما هي العناصر التي تريد استخدامها؟ إليك بعض الاقتراحات: زر أو عدة أزرار. مقاومة متغيرة للتحكم بنغمة صوت الجرس وسرعة إيقاعه. أزرار أو مبدّلات يدوية الصنع. خامسًا، عليك اختيار الشكل الخارجي للآلة، وتحديد آلية توصيل عناصر الدخل والخرج معها. تساعدك الإجابة على الأسئلة التالية في اختيار التصميم الخارجي: هل تريد اعتماد تصميم مماثل لآلة موسيقية تقليدية، مثل البيانو مثلًا؟ صنع أزرار أو مبدّلات يدوية؟ وصنع هيكل خارجي للآلة؟ رسم مشهد ما واستخدام الأزرار لتوليد الأصوات. لا بأس إذا لم يكن لديك تصورٌ واضحٌ لتصميم الآلة في ذهنك، إذ يمكنك التعديل على تصميمك عند البدء بصنعه. إضافة الأصوات سنعمل في هذه الخطوة على توصيل الجرس الإلكتروني وكتابة الشيفرة اللازمة لإصدار الأصوات، ثم اختبارها، لذلك ننصحك بالبدء بتنفيذ الأساسيات أولًا، ثم العمل على ترقية المشروع حين يتسنى لك ذلك. توصيل الأجراس الإلكترونية والسماعات مع لوحة بيكو سنعرض فيما يلي كيفية توصيل الأجراس الإلكترونية والسماعات مع لوحة بيكو. توصيل جرس إلكتروني واحد مع لوحة بيكو ستحتاج إلى سلكي توصيل نوع مقبس- مقبس socket-socket. صِل الرجل الطويلة،الموجبة للجرس الإلكتروني غير الفعّال مع الرجل GP5 على لوحة بيكو، وصِل الرجل السالبة مع أقرب رجل تأريض GND. لمعرفة الرجل الموجبة للجرس، ابحث عن الرجل الأطول، أو عن إشارة الموجب + أعلى الجرس. توصيل جرسين لخلق تأثير الصوت المجسم stereo ستحتاج لتوصيل جرسين إلكترونيين غير فعّالين مع لوحة بيكو إلى أربعة أسلاك توصيل نوع مقبس- مقبس. أولًا، صِل الرجل الطويلة الموجبة للجرس الأول مع الرجل GP5 على لوحة بيكو، وصِل الرجل السالبة مع أقرب رجل تأريض GND، ثم صِل الرجل الموجبة للجرس الثاني مع الرجل GP10 على لوحة بيكو، والرجل السالبة مع أقرب رجل تأريض GND. توصيل السماعات مع لوحة بيكو ستحتاج لتوصيل السمّاعات مع لوحة بيكو إلى وصلة ذات نهاية بقطر 3 أو 5 مم (وليس وصلة USB)، وثلاثة مشابك تثبيت، وإلى اتباع الخطوات التالية: 1.صِل أحد المشابك مع أحد أرجل الأرض GND القريبة، وصِل المشبكين الآخرين مع الرجل GP5 والرجل GP10، كما هو موضح في الصورة أدناه. صِل نهاية المشبك الأول، الموصول مع الرجل GP5، مع نهاية وصلة السمّاعات. صِل نهاية المشبك الثاني، الموصول مع الرجل GP10،مع منتصف وصلة السمّاعات. صِل نهاية المشبك الموصول مع رجل الأرض GND مع جذر وصلة السمّاعات. استخدام رجل أرضية مشتركة تحتوي لوحة بيكو على ثمانية أرجل أرضية GND، لذلك لاستخدام ما يزيد عن ثمانية عناصر إلكترونية عليك إعادة استخدام إحدى الأرجل الأرضية، وستحتاج لما يلي: سلك توصيل دبوس- مقبس. رقائق قصدير، وشريط لاصق ناقل، أو أي مادة ناقلة للتيار الكهربائي. شريط لاصق. أولًا، أنشئ شريطًا من ورق القصدير، أو من أي مادة ناقلة. ثانيًا، استخدم الشريط اللاصق لتوصيل سلك أحد الأرجل الأرضية مع شريط القصدير كما يلي: ثالثًا،صِل القطب الموجب للعنصر الأول مع أحد الأرجل العامة GP على لوحة بيكو، والقطب السالب للعنصر مع شريط القصدير. رابعًا، لتوصيل المزيد من العناصر، صِل القطب الموجب للعنصر مع إحدى أرجل الأغراض العامة GP، والقطب السالب مع شريط القصدير. كتابة الشيفرة اللازمة لربط اللوحة مع الجرس استورد تابع المكبر الصوتي Speaker من مكتبة picozero، ثم أسند أرقام أرجل لوحة بيكو مع الجرس الوحيد للتابع Speaker: from picozero import Speaker speaker = Speaker(5) وتكون الشيفرة اللازمة لتوصيل جرسين على النحو التالي: from picozero import Speaker speaker_1 = Speaker(5) speaker_2 = Speaker(10) ننصحك بتسمية المتغيرات Variables بأسماء تدل على وظيفتها، مثلًا عند إسناد صوت الطبل للمتغير Speaker_1 فسمّه drum_beat. كتابة الشيفرة اللازمة لإصدار الصوت عرّف دالة الصوت بكتابة def قبل اسم الدالة، ثم اختر اسمًا مناسبًا ومعبرًا عن الصوت الذي ستصدره آلتك، فعلى سبيل المثال، إذا أردت أن تصدر آلتك صوتًا مزعجًا، فسمِّ دالة الصوت annoying_sound. def sound_1(): # استبدل الدالة باسم دالتك معلومة: موسيقا Chiptune الرُقاقة أو ما يُعرف بموسيقا الثمانية بتات، هي موسيقا صُنعية تُوَّلد بواسطة برمجة الرقائق المسؤولة عن إصدار الصوت في الحواسيب لتصدر أصواتًا ذات ترددات معينة، استعاضةً عن استخدام الآلات الموسيقية التقليدية. تجد هذا النوع من الموسيقا في ألعاب الفيديو ذات طراز الريترو Retro، وفي صالات الألعاب. على الرغم من تطور التقنيات المستخدمة في صناعة وبرمجة الموسيقا، إلا أن العديد من الأشخاص يستمتعون بإنشاء هذا النوع من الموسيقا والاستماع إليه بسبب طرازه القديم، كما يمكنك عزف أي مقطوعة موسيقية باستخدام هذه التقنية. معلومات مفيدة يجب معرفتها دعنا نطلع على بعض المعلومات المفيدة عن الأصوات قبل كتابة الشيفرة: النغمات المتاحة تُوفر لنا مكتبة "picozero" ثمان وثمانين علامةً موسيقية، تتبع التدوين الغربي للموسيقا وتشمل جميع العلامات الموجودة في لوحة مفاتيح موسيقية كاملة الحجم. إليك بعض العلامات المُتاحة: b0 c1 c#1 d1 d#1 e1 f1 f#1 طول النغمة توجد عدة طرق لتحديد طول النغمة، هي: أولًا، تحديد طول نغمة واحدة باستخدام القيم، إذ يمكنك تحديد مدة النغمة الواحدة بإدخال قيمة في حقل الوسيط الثاني في دالة العزف: speaker.play(c_note, 0.1) # اعزف النغمة لمدة 0.1 ثانية ستُعزَف النغمة C في مثالنا لمدة 0.1 ثانية. ثانيًا، تحديد طول نغمة واحدة باستخدام الثوابت، إذ يمكنك التصريح عن أحد الثوابت في حقل الوسيط الثاني في دالة العزف بدلًا عن القيمة، وتعريف هذا الثابت، وذلك كما يلي: BEAT = 1 # BEAT تعريف الثابت speaker.play(c_note, BEAT) # اعزف النغمة لمدة ثانية واحدة لاحظ أنه يمكننا استخدام الثابت BEAT لتحديد طول أي نغمة. ثالثًا، تحديد طول مجموعة من النغمات باستخدام القيم، فعند عزف لحن ما، يُفضل تخزين النغمات وطول كل منها في قائمة list، كما في مثالنا التالي، إذ خزّنا كل نغمة مع طولها في قائمة، وجمعنا النغمات الثلاث في قائمة: my_tune = [ ['d5', 1], ['d#5', 0.5], ['f5', 1.2]] # قائمة بالنغمات وطول كل منها احرص على كتابة النغمة ضمن علامتي اقتباس ' '. رابعًا، تحديد طول مجموعة من النغمات باستخدام الثوابت، بحيث نبدأ باستخدام الثابت BEAT، إذ اخترنا في مثالنا القيمة 0.4، ثم نصرّح عن النغمات التي نود عزفها في قائمة ضمن علامتي ' '، ونستخدم الثابت BEAT لتحديد طول النغمات: BEAT = 0.4 # طول النغمة الواحدة my_tune = [ ['d5', BEAT], ['d#5', BEAT / 2], ['f5', BEAT * 1.5]] # قائمة بالنغمات وطول كل منها للتحكم بعدد النغمات في الدقيقة BPM يمكنك تقسيم الثابت BEAT على عدد ما للحصول على نغمات أقصر، مثلًا 2 / BEAT، أو مضاعفته بضربه بعدد ما للحصول على نغمات أطول، مثلا BEAT*1.5. استخدام الأرقام عوضا عن النغمات يمكنك الاستعاضة عن النغمات باستخدام قيم الترددات الموافقة لها، والتي تتراوح بين القيمة 150 إلى 10000، إليك المثال التالي لعزف نغمة ذات التردد 523 لثانية واحدة: speaker.play(523, 1) # اعزف النغمة ذات التردد 523 لثانية واحدة تحويل المقطوعات الموسيقية إلى نغمات تُتيح لنا مكتبة picozero عزف المقطوعات الموسيقية الشهيرة واستخدامها في مشاريعنا، إذ تستخدم الأحرف الإنجليزية للدلالة على العلامات الموسيقية، والأرقام للدلالة على موقع العلامة في السلم الموسيقي الكبير. على سبيل المثال، توجد العلامة C الوسطى في منتصف السلم الموسيقي ويعبر عنها بالرمز C4. تزداد الأرقام التي تدل على العلامة كلما صعدنا في السلم الكبير، وتنقص عند النزول. تحتوي المقطوعة الموسيقية علامات حادة يُشار إليها بالرمز # وتدعى "دييز". في مثالنا أدناه، توجد عدة علامات موسيقية حادة، أولها العلامة C الحادة والتي يرمز لها c#4. وقد تحتوي المقطوعة الموسيقية على علامات بسيطة يُشار إليها بالرمز ♭ وتدعى "بيمول"، لكن سنشير إليها في مشروعنا بالرمز # لعدم احتواء مكتبة "picozero" على شيفرة خاصة للدلالة على العلامات البسيطة، وعلينا النزول نصف درجة في السلم الموسيقي للتحويل من علامة بسيطة إلى حادة. إليك الأمثلة التالية: تتحوّل العلامة البسيطة D إلى C حادة أو c#4. تتحوّل العلامة البسيطة E إلى D حادة أو d#4. تتحوّل العلامة البسيطة G إلى F حادة أو f#4. تتحوّل العلامة البسيطة A إلى G حادة أو g#4. أمثلة عن بعض الشيفرات الموسيقية إليك مثالًا عن الشيفرة اللازمة لعزف علامة موسيقية واحدة ولتكن العلامة C الوسطى مثلًا لمدة نصف ثانية: def c_note(): speaker.play('c4', 0.5) # اعزف العلامة لمدة نصف ثانية أما لعزف لحن موسيقي، لا بُد من تخزين النغمات وطول كل منها في قائمة للحصول على لحن ما، ثم تشغيل اللحن باستخدام دالة play، كما هو مبين في الشيفرة التالية: BEAT = 0.4 liten_mus = [ ['d5', BEAT / 2], ['d#5', BEAT / 2], ['f5', BEAT], ['d6', BEAT], ['a#5', BEAT], ['d5', BEAT], ['f5', BEAT], ['d#5', BEAT], ['d#5', BEAT], ['c5', BEAT / 2],['d5', BEAT / 2], ['d#5', BEAT], ['c6', BEAT], ['a5', BEAT], ['d5', BEAT], ['g5', BEAT], ['f5', BEAT], ['f5', BEAT], ['d5', BEAT / 2], ['d#5', BEAT / 2], ['f5', BEAT], ['g5', BEAT], ['a5', BEAT], ['a#5', BEAT], ['a5', BEAT], ['g5', BEAT], ['g5', BEAT], ['', BEAT / 2], ['a#5', BEAT / 2], ['c6', BEAT / 2], ['d6', BEAT / 2], ['c6', BEAT / 2], ['a#5', BEAT / 2], ['a5', BEAT / 2], ['g5', BEAT / 2], ['a5', BEAT / 2], ['a#5', BEAT / 2], ['c6', BEAT], ['f5', BEAT], ['f5', BEAT], ['f5', BEAT / 2], ['d#5', BEAT / 2], ['d5', BEAT], ['f5', BEAT], ['d6', BEAT], ['d6', BEAT / 2], ['c6', BEAT / 2], ['b5', BEAT], ['g5', BEAT], ['g5', BEAT], ['c6', BEAT / 2], ['a#5', BEAT / 2], ['a5', BEAT], ['f5', BEAT], ['d6', BEAT], ['a5', BEAT], ['a#5', BEAT * 1.5] ] def play_liten_mus(): speaker.play(liten_mus) الشيفرة اللازمة لتوليد تأثيرات صوتية مختلفة باستخدام الترددات يمكننا توليد تأثيرات صوتية ممتعة، أو مزعجة، وذلك بعزف نغمات قصيرة ذات ترددات مختلفة، إذ أنه كلما تغير التردد تختلف العلامة الموسيقية التي نسمعها وتختلف نغمتها. إليك الشيفرة التالية التي ترتفع فيها الترددات تدريجيًا لخلق صوت مبهج: def win(): # ترددات متزايدة for i in range(2000, 5000, 100): speaker.play(i, 0.05) # اعزف النغمة لمدة قصيرة جدًا أما المثال التالي، فقد خفضنا فيه الترددات تدريجيًا لتوليد صوت زقزقة العصافير: def chirp(): # توليد صوت زقزقة العصافير for _ in range(2): # decreasing frequency for i in range(5000, 2999, -100): speaker.play(i, 0.02) # اعزف النغمة لمدة قصيرة جدًا sleep(0.2) غَيّر الترددات المستخدمة في حلقة التكرار for واستخدم الترددات ضمن المجال من 150 إلى 10000. الشيفرة اللازمة لتوليد ضجيج أبيض من صوت قرع الطبل from picozero import Speaker from time import sleep from random import randint speaker = Speaker(5) for i in range(100): speaker.play(randint(500, 5000), duration=None) sleep(0.001) speaker.stop() sleep(0.5) الشيفرة اللازمة لعزف النغمات بصورة متكررة أنشئ قائمةً بالنغمات التي تريد عزفها وطول كل منها للحصول على لحن ما، ثم استخدم حلقة تكرار for لتشغيل اللحن نغمةً نغمة باستخدام الدالة play: BEAT = 0.4 liten_mus = [ ['d5', BEAT / 2], ['d#5', BEAT / 2], ['f5', BEAT], ['d6', BEAT], ['a#5', BEAT], ['d5', BEAT], ['f5', BEAT], ['d#5', BEAT], ['d#5', BEAT], ['c5', BEAT / 2],['d5', BEAT / 2], ['d#5', BEAT], ['c6', BEAT], ['a5', BEAT], ['d5', BEAT], ['g5', BEAT], ['f5', BEAT], ['f5', BEAT], ['d5', BEAT / 2], ['d#5', BEAT / 2], ['f5', BEAT], ['g5', BEAT], ['a5', BEAT], ['a#5', BEAT], ['a5', BEAT], ['g5', BEAT], ['g5', BEAT], ['', BEAT / 2], ['a#5', BEAT / 2], ['c6', BEAT / 2], ['d6', BEAT / 2], ['c6', BEAT / 2], ['a#5', BEAT / 2], ['a5', BEAT / 2], ['g5', BEAT / 2], ['a5', BEAT / 2], ['a#5', BEAT / 2], ['c6', BEAT], ['f5', BEAT], ['f5', BEAT], ['f5', BEAT / 2], ['d#5', BEAT / 2], ['d5', BEAT], ['f5', BEAT], ['d6', BEAT], ['d6', BEAT / 2], ['c6', BEAT / 2], ['b5', BEAT], ['g5', BEAT], ['g5', BEAT], ['c6', BEAT / 2], ['a#5', BEAT / 2], ['a5', BEAT], ['f5', BEAT], ['d6', BEAT], ['a5', BEAT], ['a#5', BEAT * 1.5] ] for note in liten_mus: speaker.play(note) الشيفرة اللازمة لعزف عدة نغمات متزامنة إذا أردت عزف لحن ما مثلًا، وتشغيل لحن أو تأثير صوتي آخر بالتزامن معه، فيمكنك ذلك بوضع wait=False في حقل الوسيط الثاني للدالة play. أنشأنا في مثالنا التالي قائمةً بالنغمات التي نريد عزفها وطول كل منها، ثم عرّفنا اللحن الآخر، المزعج، الذي سينطلق بالتزامن مع اللحن الأول عند الضغط على الزر، وسيتوقف معه عند إيقاف الشيفرة: BEAT = 0.4 liten_mus = [ ['d5', BEAT / 2], ['d#5', BEAT / 2], ['f5', BEAT], ['d6', BEAT], ['a#5', BEAT], ['d5', BEAT], ['f5', BEAT], ['d#5', BEAT], ['d#5', BEAT], ['c5', BEAT / 2],['d5', BEAT / 2], ['d#5', BEAT], ['c6', BEAT], ['a5', BEAT], ['d5', BEAT], ['g5', BEAT], ['f5', BEAT], ['f5', BEAT], ['d5', BEAT / 2], ['d#5', BEAT / 2], ['f5', BEAT], ['g5', BEAT], ['a5', BEAT], ['a#5', BEAT], ['a5', BEAT], ['g5', BEAT], ['g5', BEAT], ['', BEAT / 2], ['a#5', BEAT / 2], ['c6', BEAT / 2], ['d6', BEAT / 2], ['c6', BEAT / 2], ['a#5', BEAT / 2], ['a5', BEAT / 2], ['g5', BEAT / 2], ['a5', BEAT / 2], ['a#5', BEAT / 2], ['c6', BEAT], ['f5', BEAT], ['f5', BEAT], ['f5', BEAT / 2], ['d#5', BEAT / 2], ['d5', BEAT], ['f5', BEAT], ['d6', BEAT], ['d6', BEAT / 2], ['c6', BEAT / 2], ['b5', BEAT], ['g5', BEAT], ['g5', BEAT], ['c6', BEAT / 2], ['a#5', BEAT / 2], ['a5', BEAT], ['f5', BEAT], ['d6', BEAT], ['a5', BEAT], ['a#5', BEAT * 1.5] ] sound = [ [523, 0.1], [None, 0.1], [523, 0.4] ] def annoying_sound(): speaker2.play(sound, wait=False) # شغّل بالتزامن مع اللحن الأول button.when_pressed = annoying_sound try: speaker.play(liten_mus) finally: speaker.off() #أطفئ مكبر الصوت الأول عند إيقاف البرنامج speaker2.off() # أطفئ مكبر الصوت الثاني عند إيقاف البرنامج الشيفرة اللازمة لاستدعاء دالة ما لاستدعاء دالة ما عليك تعريفها أولًا، ثم التصريح عنها بكتابة اسمها. إليك المثال التالي الذي استدعينا فيه الدالة chirp: def chirp(): # توليد صوت زقزقة العصافير for _ in range(2): for i in range(5000, 2999, -100): speaker.play(i, 0.02) sleep(0.2) chirp() مرحلة التنفيذ أولًا، اكتب الشيفرة اللازمة لتشغيل آلتك الموسيقية، واحرص على عدم ترك مسافة قبل اسم الدالة عند استدعائها. ثانيًا، شغّل الشيفرة للتحقق من عمل آلتك وإصدارها للأصوات، إذ قد يستمر صوت الجرس حتى بعد إيقاف الشفرة، لذلك عليك استعمال try و finally كي يتوقف صوت عند إيقاف الشفرة، كما في المثال التالي: BEAT = 0.4 liten_mus = [ ['d5', BEAT / 2], ['d#5', BEAT / 2], ['f5', BEAT], ['d6', BEAT], ['a#5', BEAT], ['d5', BEAT], ['f5', BEAT], ['d#5', BEAT], ['d#5', BEAT], ['c5', BEAT / 2],['d5', BEAT / 2], ['d#5', BEAT], ['c6', BEAT], ['a5', BEAT], ['d5', BEAT], ['g5', BEAT], ['f5', BEAT], ['f5', BEAT], ['d5', BEAT / 2], ['d#5', BEAT / 2], ['f5', BEAT], ['g5', BEAT], ['a5', BEAT], ['a#5', BEAT], ['a5', BEAT], ['g5', BEAT], ['g5', BEAT], ['', BEAT / 2], ['a#5', BEAT / 2], ['c6', BEAT / 2], ['d6', BEAT / 2], ['c6', BEAT / 2], ['a#5', BEAT / 2], ['a5', BEAT / 2], ['g5', BEAT / 2], ['a5', BEAT / 2], ['a#5', BEAT / 2], ['c6', BEAT], ['f5', BEAT], ['f5', BEAT], ['f5', BEAT / 2], ['d#5', BEAT / 2], ['d5', BEAT], ['f5', BEAT], ['d6', BEAT], ['d6', BEAT / 2], ['c6', BEAT / 2], ['b5', BEAT], ['g5', BEAT], ['g5', BEAT], ['c6', BEAT / 2], ['a#5', BEAT / 2], ['a5', BEAT], ['f5', BEAT], ['d6', BEAT], ['a5', BEAT], ['a#5', BEAT * 1.5] ] try: for note in liten_mus: speaker.play(note) finally: speaker.off() # أطفئ مكبر الصوت عند إيقاف البرنامج تصحيح الأخطاء قبل التعرف على المشاكل التي قد تواجهك في هذه الخطوة وكيفية إصلاحها، عليك أولًا التحقق من سلامة لوحة بيكو، لذلك استخدم مصباح الليد الموجود على لوحة بيكو للتحقق من سلامة اللوحة، وذلك بجعل المصباح يومض عند تشغيل الشيفرة بإضافة الشيفرة التالية في ملف main.py: from picozero import pico_led from time import sleep pico_led.on() sleep(2) pico_led.off() تصحيح الأخطاء الموجودة في الشيفرة تحقق من وجود أي رسائل خطأ في نافذة صدفة shell ثوني وتحقق من محتواها، إن وجدت. راجع الشيفرة التي كتبتها وتحقق من خلوها من الأخطاء، مثل نسيان علامة :، أو وجود مسافة بادئة دون الحاجة لها. تأكد من استيراد توابع العناصر التي ستستخدمها في مشروعك من مكتبة "picozero"، مثل تابع مصباح الليد RGBLED أو الزر Button. استخدم تعليمة الطباعة print لإضافة شرح مختصر عند كل خطوة، مثل (البدء)print أو (ضبط المصباح على اللون الأخضر)print. لا تعمل بعض العناصر الإلكترونية كما يجب تأكد أن جميع العناصر متصلة ببعضها جيدًا، وتحقق من ثبات نقاط توصيل الأسلاك مع اللوحة ومع العناصر. تأكد أن أرقام الأرجل المستخدمة في الشيفرة مطابقة لأرقام الأرجل الموصولة مع مصباح الليد، وتأكد من إعادة وصل الأرجل، في حال فصلتها عند العمل على تصميم شكل الآلة الموسيقية. تحقق من وصل العناصر وفق القطبية الصحيحة، إذ قد تحتوي بعض العناصر على قطب موجب + وآخر سالب -. في حال تحققت من جميع النقاط السابقة ولازالت آلتك لاتعمل، فجرب تبديل العناصر الإلكترونية بأخرى جديدة. صوت النغمة مختلف عن الصوت المطلوب تحقق من خلو الشيفرة التي كتبتها من الأخطاء وأنها مطابقة للشيفرة في مثالنا. عَدّل على النغمات ومدتها للحصول على الصوت المطلوب. يتأخر عزف النغمة عند الضغط على زر ما عند استخدام أحد الأحداث events مثل حدث الضغط when_pressed لتشغيل دالة ما، فإن هذه الدالة ستُنفَذ حتى انتهائها وستمنع تشغيل أي شيء آخر في الشيفرة. إذا أردت عزف لحن ما مثلًا من حدث ما، وتشغيل لحن أو تأثير صوتي آخر بالتزامن معه، فيمكنك ذلك بوضع wait=False في حقل الوسيط الثاني للدالة play: sound = [ [523, 0.1], [None, 0.1], [523, 0.4] ] def annoying_sound(): speaker.play(sound, wait=False) # لا تؤخر تشغيل الشيفرة button.when_pressed = annoying_sound حاول حل المشاكل الأخرى التي قد تواجهك عند التنفيذ وشاركنا طريقة الحل في منصة حسوب IO. احرص على اتباع ما يلي عند كتابة الشيفرات اللازمة لإصدار النغمات الموسيقية، وعند اختبارها: تعريف الدالة. كتابة الشيفرة الصحيحة. استدعاء الدالة. اختبار الدالة. عند اختبار الشيفرة، ننصحك بإضافة رمز التعليق # قبل الدالة التي لا تريد تشغيلها، أو حذف استدعاء الدالة لتتمكن من سماع النغمة التي تريد اختبارها. التحكم بالأصوات سنعمل في هذه الخطوة على إنشاء وسيلة للمستخدم للتحكم في الأصوات باستخدام عناصر دخل مختلفة، وكتابة الشيفرة اللازمة لذلك. حدد أولًا ما هي عناصر الدخل التي تود استخدامها. إليك الاقتراحات التالية: استخدام زر خاص بكل نغمة، أو لحن أو تأثير. استخدام زر لتشغيل الصوت التالي. استخدام سلكين نوع دبوس-مقبس وتوصيلهما إما مع مبدّل إلكتروني أو زر. استخدام مقاومة متغيرة للتحكم بسرعة إيقاع النغمات. ستحتاج استخدام سلكي توصيل نوع مقبس-مقبس لكل زر، وثلاثة أسلاك نوع مقبس-مقبس للمقاومة المتغيرة. توصيل عناصر الدخل مع لوحة بيكو سنشرح في الآتي كيفية توصل عناصر الدخل مع لوحة بيكو توصيل زر إلكتروني واحد مع اللوحة لتوصيل زر مع لوحة بيكو ستحتاج إلى ما يلي: لوحة راسبيري بيكو. زر إلكتروني. سلكي توصيل نوع مقبس-مقبس. صِل سلكي التوصيل مع أرجل الزر واستخدم الشريط اللاصق لتثبيتهما إن لزم الأمر، ثم صِل أحد السلكين مع الرجل GP18 والسلك الآخر مع أقرب رجل أرضية. لا يهمنا ترتيب توصيل الأسلاك إذ لا توجد قطبية للزر. توصيل عدة أزرار مع اللوحة ستحتاج لتوصيل عدة أزرار مع لوحة بيكو إلى ما يلي: لوحة راسبيري بيكو. أزرار إلكترونية. سلكي توصيل نوع دبوس-مقبس لكل زر. توضح الصورة التالية طريقة توصيل ثلاثة أزرار مع لوحة بيكو، وإذا أردت توصيل زر رابع فما عليك سوى توصيله مع إحدى أرجل الأغراض العامة GP ورجل أرضية. استخدم سلكي توصيل نوع دبوس- مقبس لتوصيل الزر الأول مع الرجل GP18 ومع أقرب رجل أرضية GND. ثم صِل الزر الثاني مع الرجل GP22، والثالث مع الرجل GP28 بنفس الطريقة. توصيل مقاومة متغيرة مع اللوحة ستحتاج إلى ما يلي: لوحة راسبيري بيكو. مقاومة متغيرة. أسلاك توصيل نوع مقبس-مقبس (عدد 3). يوجد للمقاومة المتغيرة ثلاثة أرجل: رجل الأرضية GND، ورجل تشابهية Analogue، ورجل التغذية 3V3؛ وعند تدوير قرص المقاومة المتغيرة إلى أقصى اليسار سيشير السهم إلى الرجل الأرضية GND؛ وعند تدويره إلى أقصى اليمين سيشير السهم إلى رجل التغذية 3V3؛ أما الرجل الوسطى للمقاومة فهي الرجل التشابهية التي تستمد منها لوحة بيكو القيم لقراءتها . صِل سلك توصيل ذو نهايات مقبس-مقبس مع كلٍ من أرجل المقاومة الثلاث، وثبّت التوصيلات بالشريط اللاصق إن لزم الأمر. صِل النهاية الحرة للسلك الموصول مع رجل المقاومة ذات الرقم 1 مع رجل الأرض GND الموجودة بين الرجلين GP21 و GP22. صِل رجل المقاومة الوسطى مع الرجل GP26_A0 على لوحة بيكو. صِل رجل المقاومة ذات الرقم 3 مع رجل التغذية 3V3. توصيل مبدل يدوي أو زر مع لوحة بيكو ستحتاج إلى سلكي توصيل نوع دبوس-مقبس، وصِل أحدهما مع الرجل GP18 والسلك الآخر مع أقرب رجل أرضية، كما يلي: يمكنك أيضًا صنع قاطعة يدوية، كما تعلمنا في مشروع سابق، وتوصيلها مع اللوحة وذلك بتوصيل النهاية الحرة للأسلاك مع الجزء الناقل من المبدّل مثل النحاس أو ورق القصدير. توصيل عدة مبدلات يدوية أو أزرار مع لوحة بيكو ستحتاج إلى سلكي توصيل نوع دبوس-مقبس لكل مبدّل تود توصيله مع لوحة بيكو. استخدم سلكي توصيل نوع دبوس- مقبس لتوصيل المبدّل الأول مع الرجل GP18 ومع أقرب رجل أرضية GND، ثم صِل المبدّل الثاني مع الرجل GP22 ومع أقرب رجل أرضية، والثالث مع الرجل GP28 ورجل الأرضية بنفس الطريقة، كما هو موضح في المخطط التالي: إسناد عناصر الدخل إلى أرجل معينة على اللوحة علينا الآن إنشاء متغيرات لإسناد عناصر الدخل للأرجل الموصولة معها: حالة زر واحد استورد تابع الزر Button من مكتبة picozero، ثم استخدم الشيفرة التالية لإسناد الزر إلى الرجل الموصول معها على لوحة بيكو: from picozero import Button button = Button(18) حالة عدة أزرار استورد تابع الزر Button من مكتبة picozero، ثم استخدم الشيفرة التالية لإسناد عدة أزرار إلى الأرجل الموصولة معها على لوحة بيكو: from picozero import Button button_1 = Button(18) button_2 = Button(22) button_3 = Button(28) ننصحك بتسمية المتغيرات بأسماء تدل على عملها، كأن تسمّي الزر المسؤول عن تشغيل المصباح الأحمر red_button أو أي اسم آخر تراه مناسبًا. حالة مبدل واحد استورد تابع المبدّل Switch من مكتبة picozero، ثم استخدم الشيفرة التالية لإسناد المبدّل إلى الرجل الموصولة معه على لوحة بيكو: from picozero import Switch switch = Switch(18) حالة عدة مبدلات استورد تابع المبدّل Switch من مكتبة picozero، ثم استخدم الشيفرة التالية لإسناد عدة مبدّلات إلى الأرجل الموصولة معها على لوحة بيكو: from picozero import Switch switch_1 = Switch(18) switch_2 = Switch(22) switch_3 = Switch(28) ننصحك بتسمية المتغيرات بأسماء تدل على عملها، كأن تسمّي القاطعة المسؤولة عن تشغيل المصباح الأحمر red_switch أو أي اسم آخر تراه مناسبًا. حالة مقاومة متغيرة استورد تابع المقاومة المتغيرة Pot من مكتبة picozero، ثم استخدم الشيفرة التالية لإسناد المقاومة المتغيرة إلى الرجل الموصولة معها على لوحة بيكو: from picozero import Pot dial = Pot(0) # Connected to pin A0 (GP_26) الشيفرة اللازمة لتشغيل عناصر الدخل الآن، عليك استدعاء الدوال اللازمة لتشغيل عناصر الدخل: تشغيل نغمة معينة عند الضغط على كل زر يمكنك إضافة عدة أزرار يستدعي كل منها دالة صوتية مختلفة عند الضغط عليها، وذلك باستدعاء الدالة الموافقة عند الضغط على الزر عن طريق ذكر اسمها بدون استخدام الأقواس، كما في المثال التالي: annoying_button.when_pressed = annoying_sound calming_button.when_pressed = calming_sound happy_button.when_pressed = happy_sound تأكد من مطابقة أسماء الدوال في الشيفرة للدوال التي استخدمتها في مشروعك. تشغيل النغمة التالية عند الضغط على الزر عرّف متغيرًا ما، وليكن option، لتخزين النغمة الحالية فيه واستدعاء الدالة التالية، واحرص على مطابقة أسماء الدوال في الشيفرة للدوال التي استخدمتها في الفقرة السابقة: option = 0 # خزّن النغمة الحالية في هذا المتغير def choice(): # استدعي الدالة الصوتية التالية وعدّل قيمة متغير التخزين global option if option == 0: annoying_sound() # دالة النغمة الأولى elif option == 1: calming_sound() # دالة النغمة الثانية elif option == 2: happy_sound() # دالة النغمة الثالثة elif option == 3: rgb.off() # انتقل إلى الخيار الثاني if option == 3: option = 0 else: option = option + 1 button.when_pressed = choice # نستدعي الدالة التالية عند الضغط على الزر التحكم في سرعة عزف النغمة باستخدام المقاومة المتغيرة استخدم الشيفرة التالية للتحكم في سرعة عزف النغمة: BEAT = 0.4 liten_mus = [ ['d5', BEAT / 2], ['d#5', BEAT / 2], ['f5', BEAT], ['d6', BEAT], ['a#5', BEAT], ['d5', BEAT], ['f5', BEAT], ['d#5', BEAT], ['d#5', BEAT], ['c5', BEAT / 2],['d5', BEAT / 2], ['d#5', BEAT], ['c6', BEAT], ['a5', BEAT], ['d5', BEAT], ['g5', BEAT], ['f5', BEAT], ['f5', BEAT], ['d5', BEAT / 2], ['d#5', BEAT / 2], ['f5', BEAT], ['g5', BEAT], ['a5', BEAT], ['a#5', BEAT], ['a5', BEAT], ['g5', BEAT], ['g5', BEAT], ['', BEAT / 2], ['a#5', BEAT / 2], ['c6', BEAT / 2], ['d6', BEAT / 2], ['c6', BEAT / 2], ['a#5', BEAT / 2], ['a5', BEAT / 2], ['g5', BEAT / 2], ['a5', BEAT / 2], ['a#5', BEAT / 2], ['c6', BEAT], ['f5', BEAT], ['f5', BEAT], ['f5', BEAT / 2], ['d#5', BEAT / 2], ['d5', BEAT], ['f5', BEAT], ['d6', BEAT], ['d6', BEAT / 2], ['c6', BEAT / 2], ['b5', BEAT], ['g5', BEAT], ['g5', BEAT], ['c6', BEAT / 2], ['a#5', BEAT / 2], ['a5', BEAT], ['f5', BEAT], ['d6', BEAT], ['a5', BEAT], ['a#5', BEAT * 1.5]] for note in liten_mus: speaker.play(note) sleep(dial.value) # ترك مدة قصيرة بين النغمات اعتمادًا على قيمة المقاومة المتغيرة أخيرًا، شغّل الشيفرة وتحقق من عملها، وتأكد أنه بإمكانك التبديل بين النغمات عند النقر على الأزرار أو المبدّلات، وتغيير سرعة عزف النغمة باستخدام المقاومة المتغيرة. تصحيح الأخطاء قبل التعرف على المشاكل التي قد تواجهك في هذه الخطوة وكيفية إصلاحها، عليك أولًا التحقق من سلامة لوحة بيكو، لذلك استخدم مصباح الليد الموجود على لوحة بيكو للتحقق من سلامة اللوحة، وذلك بجعل المصباح يومض عند تشغيل الشيفرة بإضافة الشيفرة التالية في ملف main.py: from picozero import pico_led from time import sleep pico_led.on() sleep(2) pico_led.off() تصحيح الأخطاء الموجودة في الشيفرة تحقق من وجود أي رسائل خطأ في نافذة صدفة ثوني وتحقق من محتواها، إن وجدت. راجع الشيفرة التي كتبتها وتحقق من خلوها من الأخطاء، مثل نسيان علامة :، أو وجود مسافة بادئة دون الحاجة لها. تأكد من استيراد توابع العناصر التي ستستخدمها في مشروعك من مكتبة "picozero"، مثل تابع مصباح الليد RGBLED أو الزر Button. استخدم تعليمة الطباعة print لإضافة شرح مختصر عند كل خطوة، مثل (البدء)print أو (ضبط المصباح على اللون الأخضر)print. لا تعمل بعض العناصر الإلكترونية كما يجب تأكد أن جميع العناصر متصلة ببعضها جيدًا، وتحقق من ثبات نقاط توصيل الأسلاك مع اللوحة ومع العناصر. تأكد أن أرقام الأرجل المستخدمة في الشيفرة مطابقة لأرقام الأرجل الموصولة مع مصباح الليد، وتأكد من إعادة وصل الأرجل، في حال فصلتها عند العمل على تصميم شكل الآلة الموسيقية. تحقق من وصل العناصر وفق القطبية الصحيحة، إذ قد تحتوي بعض العناصر على قطب موجب + وآخر سالب -. في حال تحققت من جميع النقاط السابقة ولازالت آلتك لاتعمل، فجرب تبديل العناصر الإلكترونية بأخرى جديدة. إعداد الهيكل الخارجي للآلة سنعمل الآن على إعداد الهيكل الخارجي لآلتنا الموسيقية. أولًا، إليك بعض الأسئلة لتساعدك في اعتماد التصميم الخارجي لآلتك: ما هي المواد التي تود استخدامها؟ هل جميعها متوفرة لديك؟ هل تود استخدام أزرار أو مبدّلات يدوية؟ ما هو غرض عملها؟ كيف ستثبت العناصر بحيث تكون متينة وسهلة الاستخدام؟ معلومة: يختص مهندسو الصوت Acoustic engineers بدراسة علم الصوت وتوفير أفضل تجربة للحضور والمستمعين. الآن، مهندسنا الصغير، حان دورك لتصميم آلتك الموسيقية بحيث تصدر أصواتًا عالية الجودة وتوفر تجربة ممتعة. ثانيًا، جهّز المواد التي ستستخدمها لتنفيذ تصميمك. إليك بعض الاقتراحات: الورق المقوى. المواد البلاستيكية المعاد تدويرها. ألعاب قديمة أو قطع الليغو Lego. شريط لاصق. كما يمكنك استخدام الطابعة ثلاثية الأبعاد إن توفر لك ذلك. اطلب مساعدة أحد البالغين عند الحاجة لاستخدام المقص، أو مسدس السيليكون، أو سكين الحرف؛ واحرص على حفظ ملف الشيفرة، وتصغير نافذة ثوني عند البدء بتنفيذ التصميم؛ تجنبًا للنقر على لوحة المفاتيح والتعديل على الشيفرة دون قصد. ثالثًا، ابدأ بصنع المبدّلات اليدوية والأزرار التي تود استخدامها، إذ ستحتاج إلى استخدام مادة ناقلة مثل ورق القصدير لتكون بمثابة نقطة الأرض GND وتوصيل الأرجل ذات الأغراض العامة GP معها، إذ يمكن للوحة بيكو التحسس لحالة الأرجل فيما إذا كان متصلة أم لا. إنشاء مبدل فوري يعمل عند الإسقاط ستحتاج لإنشاء مبدّل فوري Drop switch إلى ما يلي: لوحة راسبيري بيكو. سلكي توصيل نوع دبوس-مقبس. ورق قصدير. شريط لاصق. أولًا، أنشئ شريطين من ورق القصدير، أو من أي مادة ناقلة. ثانيًا، ثبّت سلكي التوصيل مع شريطي القصدير باستخدام الشريط اللاصق، كما يلي: ثالثًا، ألصق قطعةً من القصدير أسفل المجسم الذي ستضعه فوق شريط القصدير لإغلاق المبدّل، واحرص على أن تكون قاعدة المجسم واسعةً بما يكفي لتوفير تماس بين السلكين. رابعًا، صِل النهايات الحرة للسلكين مع لوحة بيكو وأسقط المجسم لإغلاق المبدّل. إنشاء مبدل يدوي يعمل عند السحب إليك ما سنحتاج إليه: مقص. ورق مقوى. رقائق القصدير. غراء وشريط لاصق. شرائط ملونة وورق ملون. قلم رصاص ومسطرة (اختياري). أولًا، قُصَّ الورق المقوى إلى ثلاثة مستطيلات متساوية الحجم. ثانيًا، قُصَّ مستطيلًا صغيرًا في منتصف المستطيل الأول، واحتفظ به لاستخدامه لاحقًا. ثالثًا، قُصَّ قطعًا من ورق القصدير بحجم المستطيلات الكبيرة، ثم الصقها عليها باستخدام الغراء، واحرص على عدم وضع الغراء على الوجه الخارجي لورق القصدير حتى لا تتأثر التوصيلات لاحقًا. رابعًا، قُصَّ أطراف المستطيل الصغير للحصول على شكل مدبب أو بشكل حرف V، ثم قلّم الأطراف بمقدار بضع ملميترات كي يتسع المستطيل الصغير في الفتحة. خامسًا، غلّف كامل المستطيل الصغير بورق القصدير، واحرص على استخدام ورقة قصدير واحدة، إذ ستسمح هذه القطعة بمرور التيار عند إغلاق المبدّل. سادسًا، استخدم الشريط اللاصق لتثبيت نهايات الدبابيس على الوجه العلوي للمستطيلات، واحرص على أن يكون الدبوس المعدني للسلك ملامسًا لورق القصدير، وأن يكون الجزء البلاستيكي الأسود ملامسًا لحافة المستطيل. سابعًا، أضف مزيدًا من الشريط اللاصق لتثبيت السلك ومنع انفكاكه عن طريق الخطأ. ثامنًا، ادهن بعض الغراء على المستطيل الذي فرّغنا منتصفه (الموجود في يسار الصورة) والصقه مع المستطيل المغطى بالقصدير (يمين الصورة). واحرص على ألا تتلامس طبقتي القصدير الموجودتين على حواف المستطيلات، وقُصّها إن لزم الأمر. أصبح المبدّل جاهزًا للاستخدام في مشروعك. استخدام سكين الحرف تُعد سكاكين الحرف Crafts مفيدةً عند صنع الحرف اليدوية، لكن يجب أن تكون حذرًا جدًا عند استخدامها لأنها حادةً جدًا ويمكن أن تسبب جروحًا وإصابات. احرص على وجود شخص بالغ عند استخدامك للسكاكين، أو اطلب منه استخدامها عوضًا عنك، كما ننصحك باستخدام لوح القص لحماية الأسطح، أو باستخدام لوح التقطيع الخشبي المتوفر في كل المطابخ. ننصحك بتدوين أرقام الأرجل التي استخدمتها والعناصر الموصولة معها، إذ سيساعدك ذلك في إعادة توصيل العناصر بعد فصلها. ستجد الأرجل المستخدمة في بداية الشيفرة. أخيرًا، جمّع قطع آلتك الموسيقية معًا، وإذا احتوت آلتك على غطاء، فأجّل تركيبه حتى تتأكد من إضافة جميع العناصر اللازمة. واستخدم الشريط اللاصق لإحكام تثبيت الأسلاك. توصيل الأسلاك ببعضها قد تحتاج إلى أسلاك توصيل طويلة جدًا لتوصيل مصابيح الليد مع أرجل لوحة بيكو، أو يمكنك وصل الأسلاك ببعضها للحصول على سلك طويل، وذلك عبر توصيل سلك ذو نهايات دبوس-مقبس مع سلك ذو نهايات مقبس-مقبس للحصول على سلك مقبس-مقبس طويل جدًا، وتدعى هذه الطريقة بسلسلة الأقحوان daisy chaining. ننصحك باستخدام سلكين لهما اللون نفسه ليسهل تتبع السلك ومعرفة العنصر الموصول معه. تكمن مشكلة هذه الطريقة في أن الأسلاك قد تنفصل عن بعضها، ولذلك ينصح بلصقها بقطعة صغيرة من الشريط اللاصق. تثبيت العناصر داخل الورق المقوى أو البلاستيك يمكنك تثبيت مصابيح الليد أو الأجراس أو المقاومات المتغيرة داخل قطع من الورق المقوى أو البلاستيك، وذلك بصنع ثقوب وإدخال العناصر وأسلاك التوصيل فيها، كما هو موضح: افصل الأسلاك عن العنصر، ثم أدخله في الثقب الذي أحدثته، ثم أعد توصيل الأسلاك. ستحتاج إلى استخدام أداة حادة لإحداث ثقب في المواد البلاستيكية. اطلب مساعدة أحد البالغين إن لزم الأمر، واحرص على تذكر ما هي أرقام الأرجل الموصولة مع الأسلاك. استخدم الشريط اللاصق لتثبيت العناصر في مكانها. كما يمكنك تثبيت العناصر مع أسلاك التوصيل، أو تثبيتها في مكانها باستخدام الشريط اللاصق، وإزالة الشريط اللاصق بكل سهولة لإعادة استخدام العناصر فيما بعد. خامسًا، الآن بعد أن انتهيت من تنفيذ الهيكل الخارجي، عليك تشغيل الآلة والتحقق أنها تعمل كما ينبغي. تصحيح الأخطاء إليك بعض المشاكل التي قد تواجهك في هذه الخطوة وكيفية إصلاحها: طول الأسلاك غير مناسب إذا وجدت أن الأسلاك التي استخدمتها لا تفي بالغرض المطلوب بسبب قصر طولها، فما عليك إلا زيادة طولها، وفقًا لما تعلمناه في فقرة توصيل الأسلاك ببعضها. لا تثبُت الأسلاك والعناصر في مكانها قد تكون بعض التوصيلات أمتن من غيرها، لذا ننصحك باستخدام الشريط اللاصق لإحكام تثبيت الأسلاك. ترقية المشروع يمكنك ترقية مشروعك حين يتسنى لك ذلك. فكّر في المناسبات التي يمكنك استخدام آلتك الموسيقية فيها؟ مثل إنشاء مقاطع موسيقية لفيديو ما، أو عزف لحن هادئ عندما تحتاج إلى الاسترخاء، أو إزعاج أصدقائك بنغمة حادة ذات إيقاع سريع. إليك بعض الاقتراحات: اختبر أداء الآلة أمام جمهورك، ثم حدّد النقاط التي عليك تحسينها. أضف مزيدًا من الأزرار وعناصر التحكم مثل المقاومات المتغيرة والمبدّلات. أضف مزيدًا من البريق على آلتك باستخدام مصابيح الليد. أضف مزيدًا من التحسينات على الهيكل الخارجي لآلتك. إليك المشروع التالي إذ تتغير النغمة ولون مصباح الليد وفقًا للأزرار، كما يمكنك الاطلاع على المشاريع التي زودناك بها في مقدمة المقال لتستلهم منها بعض الأفكار، أو الاطلاع على معرض مشاريع الآلات الموسيقية. الخاتمة تهانينا، فقد أتممت مشروع تصميم وتنفيذ آلة موسيقية باستخدام لوحة راسبيري باي بيكو. ننصحك بتنفيذ مشروع تصميم وتنفيذ لعبة حسية تفاعلية باستخدام لوحة راسبيري باي بيكو ومقاومة متغيرة في خطوتك التالية. إذا واجهت مشاكلًا عند تنفيذ هذا المشروع، فيمكنك الحصول على الدعم والمساعدة عبر إضافة سؤالك في قسم الأسئلة والأجوبة في أكاديمية حسوب. ترجمة -وبتصرف- للمقال Sound machine من الموقع الرسمي لراسبيري باي. الملف المرفق للمشروع: codes.zip. اقرأ أيضًا صنع جهاز لعرض الحالة المزاجية باستخدام لوحة راسبيري باي بيكو صنع قلب نابض باستخدام لوحة راسبيري باي بيكو تصميم محاكاة لمفرقعات الحفلات باستخدام لوحة راسبيري باي بيكو
-
ستتعلم في هذا المقال كيفية تصميم وإنشاء جهاز للتعبير عن مشاعرك باستخدام مصابيح الليد، بحيث تحصل على نتيجة مشابهة لما يلي: تمعن في الصورة المتحركة أعلاه وحاول معرفة كيف يعمل هذا المصباح التفاعلي، لاحظ كيف تُستَخدم الإضاءة المختلفة للتعبير عن المشاعر، وكيف يغير المستخدم لون الإضاءة. كما يمكنك الاطلاع على الشيفرة اللازمة لتنفيذ هذا المشروع من code.zip. معلومة: يُعد الاهتمام بالمزاج والأحاسيس إحدى وسائل العناية بالصحة؛ إذ من الطبيعي الشعور بالحزن أو السعادة، أو الحماس. أعطِ كل شعور حقه، ودوّن مشاعرك وأخبر الآخرين حولك إذا احتجت ذلك، وهذا ما يُعرف بعملية التحقق من الحالة المزاجية Mood check-in. ستتعلم في هذا المشروع ما يلي: كيفية التعبير عن المشاعر باستخدام الأضواء. استخدام عناصر دخل إلكترونية لتمكين المستخدمين من التعبير عن مشاعرهم. كتابة الشيفرة اللازمة للتحكم بإضاءة مصابيح الليد وخلق تأثيرات مختلفة. متطلبات المشروع عتاد لوحة حاسوب راسبيري باي بيكو Raspberry Pi Pico مع أرجل مثبتة عليها. كبل USB لنقل البيانات ذو نهايات من النوع USB A و micro USB. مقاومات متغيرة potentiometer وأزرار buttons. مصباح ليد متعدد الألوان RGB LED ذو مهبط مشترك Common cathode أو مصباح ليد وحيد اللون. أسلاك توصيل ومقاومات عادية resistors. بعض مستلزمات الأشغال اليدوية، مثل الورق المقوى، ورقائق القصدير، وشريط لاصق. برمجيات برنامج ثوني Thonny: وهو البيئة البرمجية التي سنستخدمها لكتابة الشيفرة بلغة بايثون. تثبيت برنامج ثوني على نظام تشغيل راسبيري باي يأتي برنامج ثوني مثبتًا مع نظام تشغيل راسبيري باي، المعروف سابقًا براسبيان Raspbian، لكن قد تحتاج إلى تحديثه. انقر على الأيقونة في الزاوية العلوية اليسرى من الشاشة لفتح نافذة الطرفية Terminal، أو اضغط المفاتيح التالية معًا Ctrl+Alt+T. ثم اكتب الأمر التالي لتحديث نظام التشغيل وبرنامج ثوني: sudo apt update && sudo apt upgrade -y تثبيت برنامج ثوني على أنظمة التشغيل الأخرى يمكنك تثبيت ثوني على الحواسيب العاملة بنظام تشغيل لينكس، أو ويندوز، أو ماك، وذلك من الموقع الرسمي thonny.org. انقر على رابط التنزيل الموافق لنظام تشغيل حاسوبك من الزاوية العلوية اليمنى في الموقع، ثم انقر على الملفات بعد تنزيلها، وقد تظهر لك الرسالة التالية على نظام ويندوز: انقر على خيار المزيد من المعلومات "More info" ثم على التشغيل على أي حال "Run anyway". التعرف على واجهة برنامج ثوني ستظهر لك الواجهة التالية عند فتح ثوني: يمكنك الكتابة بلغة بايثون في النافذة الرئيسية الكبيرة، ثم النقر على زر التشغيل الأخضر Run للتنفيذ، ستظهر لك رسالة لحفظ الملف قبل تشغيله. اكتب الأمر التالي وشغّله: print('Hello World!') تغيير السمة والخط يمكنك التحكم بلون الخط وحجمه وتغيير السمة المُستخدمة في واجهة البرنامج، وذلك بالنقر على قائمة الأدوات Tools من الشريط أعلى الشاشة، ثم النقر على خيارات Options. انقر بعدها على نافذة الخط والسمة Theme & Font واختر نوع الخط والسمة التي تفضلها من النافذة المنسدلة ثم انقر على زر موافق OK عند الانتهاء. ننصحك باختيار الخطوط البسيطة الواضحة والابتعاد عن الخطوط المزخرفة أو المشابهة لخط اليد لأنه قد تجعل القراءة أصعب. إعداد مكتبة picozero سنعمل في هذه الخطوة على إعداد مكتبة picozero وتوصيل لوحة راسبيري باي بيكو وإعداد برنامج مايكرو بايثون. أولًا، صِل الطرف الصغير لكبل USB إلى لوحة راسبيري باي والطرف الآخر إلى حاسوبك لتتمكن من برمجة اللوحة عن طريقه. ثانيًا، افتح محرر ثوني، ولاحظ ما هو الإصدار المستخدم من بايثون بقراءة النص الموجود في الزاوية السفلية اليمنى من الشاشة، انقر على النص واختر "MicroPython (Raspberry Pi Pico)"، إذا لم يكن هذا الخيار محددًا. سيطالبك ثوني بتثبيت برنامج MicroPython على حاسوب راسبيري باي بيكو إذا لم تستخدمه مسبقًا، فقط انقر على زر التثبيت Install. ثالثًا، أضف حزمة بيكو زيرو picozero من خلال النقر على قائمة الأدوات Tools من شريط القوائم في برنامج ثوني، ثم النقر على خيار إدارة الحزم Manage Packages. ثالثًا، اكتب "picozero"، ثم انقر على زر البحث Search on PyPi. رابعًا، انقر على picozero من نتائج البحث ثم انقر على زر التثبيت Install. استلهم أفكارك اطلع على المشاريع التالية واستلهم منها بعض الأفكار: مشروع البطاقات التعبيرية لاحظ كيف غلفنا بطاقات ذات أحجام مختلفة بورق القصدير وكتبنا الحالة المزاجية عليها، وعند وضع البطاقات داخل الصندوق تُغلَق الدارة ويضيء المصباح باللون الموافق للبطاقة. لدينا ثلاث بطاقات، واحدة للتعبير عن الشعور بالسعادة، والثانية عن الحزن، والثالثة عن الغضب. يمكنك الاطلاع على الشيفرة اللازمة لتنفيذ هذا المشروع باسم drop_switch.py ضمن الملف المرفق code.zip. مشروع أيقونة الحالة المزاجية استخدمنا مقاومةً متغيرةً مع مصباح ليد متعدد الألوان كي يتمكن المستخدم من التعبير عن مزاجه بواسطة إدارة ذراع المقاومة لتغير لون المصباح إلى اللون الموافق لشعوره. يمكنك الاطلاع على الشيفرة اللازمة لتنفيذ هذا المشروع باسم mood_dial.py ضمن الملف المرفق code.zip. مشروع مؤشر التركيز استُخدمت ثلاثة مصابيح ليد عادية للتعبير عن ثلاث رموز يمكن استخدامها في القاعة الدراسية، إذ يعني الرمز الأول "يرجى التزام الهدوء وعدم الإزعاج"، أما الرمز الثاني فيعبر عن الحاجة للمساعدة، والرمز الأخير يعني أن المستخدم لا يحتاج إلى مساعدة. يمكنك الاطلاع على الشيفرة اللازمة لتنفيذ هذا المشروع باسم focus_indicator.py من هنا ضمن الملف المرفق code.zip. تصميم الجهاز عليك الآن التفكير في كيفية التعبير عن المشاعر المختلفة باستخدام أداتك أو جهازك؟ والآلية التي سيختار بها المستخدم الشعور المناسب. أولًا، فكر مليًّا في الغرض من الأداة التي ستصنعها، ولمن تريد توجيهها؟ هل تريد استخدامها للتواصل مع البالغين، أو الأصدقاء؟ هل تريد استخدامها لمساعدة الأشخاص الذين يجدون صعوبةً في التواصل؟ أم تفضل استخدامها لتراقب تغيرات مزاجك وتدونها؟ ثانيًا، قرر ما الذي تود التعبير عنه باستخدام أداتك. هل تود التعبير عما تشعر به، مثل السعادة، أو الحزن، أو الغضب؟ أم تود ضبط الجو العام لمكان ما؛ أي جو هادئ أو نشط؟ أم تريد استخدام أداتك في قاعة دراسية لطلب المساعدة، أو عدم الإزعاج؟ كما يمكنك استخدام أداتك عند البدء في أمر جديد للتعبير عن شعورك بالقلق، أو الحماس، أو التشتت. ثالثًا، فكر كيف تود التعبير عن المشاعر المختلفة باستخدام أنماط مختلفة من الأضواء والألوان. ما هي الألوان التي ستستخدمها؟ يُستخدم اللون الأحمر عادةً للتعبير عن الحب أو الغضب، أما اللون الأزرق فيستخدم للتعبير عن الحزن أو الشعور بالراحة. إليك لمحةً عن دلالات بعض الألوان حول العالم: يرمز اللون الأحمر في الثقافة الصينية للحظ والبهجة والسعادة. يعبر اللون الأصفر والبرتقالي والأحمر في معظم الثقافات عن السعادة. كما تعبر الألوان الساطعة عن الحماس. يستخدم اللون الأزرق والأخضر للتعبير عن السكينة والاسترخاء، لكن يُعد ارتداء اللون الأخضر على خشبة المسرح أمرًا جالبًا للحظ السيء. الآن دون ملاحظاتك على ورقة ما، أو ارسم التصميم الذي تود اعتماده في جهازك، كي تتشكل لديك خطةً لاتباعها عند العمل. رابعًا، قرر ما هو نوع المصابيح التي تود استخدامها. هل تود استخدام مصابيح ليد عادية (ذات لون واحد)؟ أم تفضل استخدام المصابيح متعددة الألوان؟ تحتوي لوحة بيكو على ثمانية أرجل أرضية GND، لذلك يمكنك توصيل ثمانية عناصر إلكترونية فقط مع لوحة بيكو، كما تحتوي اللوحة على رجل تغذية واحدة ذات جهد 3 فولت؛ أي يمكنك استخدام مقاومة متغيرة potentiometer واحدة، ويوجد حدٌّ لقيمة التيار الذي توفره لوحة بيكو، ولذلك ننصحك باستخدام مصباحي ليد متعددي الألوان، أو ستة مصابيح ليد عادية ذات لون واحد. إليك بعض الاقتراحات لعناصر الدخل والخرج التي يمكنك استخدامها معًا: ثلاثة أزرار وثلاثة مصابيح ليد وحيدة اللون. مقاومة متغيرة واحدة ومصباح ليد متعدد الألوان ذو مهبط مشترك. زر واحد ومصباح ليد متعدد الألوان ذو مهبط مشترك. أربعة أزرار ومصباح ليد متعدد الألوان ذو مهبط مشترك. خامسًا، قرر ما هي العناصر الإلكترونية التي تود استخدامها، إذ يمكنك استخدام الأزرار الجاهزة، أو المقاومات المتغيرة، أو الأزرار والمبدًلات يدوية الصنع. سادسًا، فكر مليًّا في التصميم الخارجي لأداتك، كيف ستوصل العناصر الإلكترونية معها؟ بإمكانك تثبيت العناصر داخل لعبة أو مجسم ما، أو جعل أداتك قابلة للارتداء، مثل سوار مثلًا؛ كما يمكنك أن تستوحي بعض الأفكار من المشاريع الموجودة في مقدمة مقالنا. لا بأس إن لم يكن لديك الآن تصوُّر واضح لأداتك، إذ يمكنك التعديل على التصميم أثناء العمل. إضافة الشيفرة اللازمة للتحكم بالإضاءة سنعمل في هذه الخطوة على توصيل مصابيح الليد مع لوحة بيكو وإضافة الشيفرة اللازمة للتحكم في إضاءتها، واختبار عملها. ننصحك بتنفيذ المشروع خطوةً خطوة، بدءًا من الأساسيات، ثم العودة وترقية المشروع حين يتسنى لك ذلك. معلومة: عند تنفيذ مشروع ما يُنصح بإنشاء نموذج أولي Prototyping، أي صنع نسخة مبسطة عن المشروع النهائي لتختبر عمله، وتتأكد أنه يقدم الحلول التي صُنع من أجلها. سنعمل الآن على إنشاء نموذج أولي لمشروعنا لاختبار التوصيلات والشيفرة، واكتشاف الأمور التي علينا تحسينها قبل البدء بتنفيذ التصميم النهائي للجهاز وتوصيل العناصر. أولًا، صِل مصابيح الليد مع لوحة بيكو بإتباع الإرشادات التالية: توصيل عدة مصابيح ليد ذات اللون الواحد ستحتاج لتوصيل عدة مصابيح ليد ذات اللون الواحد إلى ما يلي: لوحة راسبيري باي بيكو. عدة مصابيح ليد باللون الذي تفضله. مقاومة لكل مصباح. سلكي توصيل نوع مقبس- مقبس لكل مصباح. يجب توصيل مقاومة مع الرجل الموجبة الطويلة لكل مصباح ليد، كما هو موضح في المخطط التالي؛ إذ تُوصل الرجل الموجبة للمصباح الأول مع الرجل GP13 على لوحة بيكو والسالبة مع أقرب رجل أرضية GND؛ وتُوصل الرجل الموجبة للمصباح الثاني مع الرجل GP8، والسالبة مع أقرب رجل أرضية GND، وتُويل الرجل الموجبة للمصباح الثالث مع الرجل GP5، والسالبة مع أقرب رجل أرضية GND. توصيل مصباح ليد متعدد الألوان مع لوحة بيكو ستحتاج لتوصيل مصباح ليد متعدد الألوان إلى ما يلي: لوحة راسبيري باي بيكو. مصباح ليد متعدد الألوان ذو مهبط مشترك. ثلاث مقاومات. أسلاك توصيل نوع مقبس- مقبس (عدد 8). يجب عليك توصيل مقاومة مع الأرجل الثلاثة الطويلة لمصباح الليد، أما الرجل الطويلة فهي رجل الأرضية ولا تحتاج إلى مقاومة. معلومة: لاحظ أنه لمصباح الليد متعدد الألوان أربعة أرجل، لذلك أمسك المصباح بحيث تكون الرجل الأرضية هي ثاني رجل من اليسار، بحيث يصبح ترتيب الأرجل على النحو التالي: الرجل المسؤولة عن اللون الأحمرRed، ثم الرجل الأرضية GND، ثم الرجل المسؤولة عن اللون الأخضرGreen، فالأزرق Blue، وذلك ليسهُل عليك تذكر وظيفة كل رجل. صِل أرجل مصباح الليد وفقًا لما يلي: الرجل المسؤولة عن اللون الأحمر R مع الرجل GP1 على لوحة بيكو. الرجل الأرضية GND مع رجل الأرض GND على لوحة بيكو. الرجل المسؤولة عن اللون الأخضرG مع الرجل GP2 على لوحة بيكو. الرجل المسؤولة عن اللون الأزرق B مع الرجل GP3 على لوحة بيكو. ثانيًا، استورد تابع مصباح الليد العادي LED، أو متعدد الألوان RGBLED من مكتبة picozero، ثم استخدم الشيفرة اللازمة لإسناد المصباح إلى الأرجل الموصول معها على لوحة بيكو. استخدم الشيفرة التالية لإسناد مصابيح الليد العادية إلى الأرجل الموصولة معها على لوحة بيكو: from picozero import LED led_1 = LED(13) led_2 = LED(8) led_2 = LED(5) ننصحك بتسمية المتغيرات بأسماء تدل على عملها، كأن تسمّي المصباح المسؤول عن تشغيل المصباح باللون المسؤول عنه، كما يلي: red_led = LED(13) green_led = LED(8) pink_led = LED(5) استخدم الشيفرة التالية لإسناد مصباح الليد متعدد الألوان إلى أرجل لوحة بيكو بعد استيراد تابع المصباح متعدد الألوان RGBLED من مكتبة picozero: from picozero import RGBLED rgb = RGBLED(red = 1, green = 2, blue = 3) ثالثًا، أضف التأثير الضوئي الذي تفضله على المصابيح، وذلك باختيار إحدى الدوال التالية وإضافتها على الشيفرة: تُستخدم الشيفرة التالية لتشغيل وإطفاء عدة مصابيح ليد عادية: def excited(): # شغّل اللون الموافق لشعورك بالحماس purple.on() # شغّل المصباح البنفسجي blue.off() # أطفئ المصباح الأزرق def worried(): # شغّل اللون الموافق لشعورك بالقلق purple.off() # أطفئ المصباح البنفسجي blue.on() # شغّل المصباح الأزرق استخدم الدوال الثلاث التالية: blink و pulse و cycle لإضفاء مزيج من التأثيرات الضوئية على مشروعك، إذ يمكنك التبديل بين التأثيرات عند الضغط على زر وحيد. يمكنك إضفاء تأثير الوميض أو النبض على مصباح ليد عادي باستخدام دالة الوميض blink أو النبض pulse لتشغيل وإطفاء المصباح بصورةٍ متكررة، كما هو مبين في الشيفرة التالية: def available(): # شغّل الدالة الموافقة للشعور الأول red.off() # أطفئ المصباح الأحمر green.blink() def do_not_disturb(): # شغّل الدالة الموافقة للشعور الأول green.off() # أطفئ المصباح الأخضر red.pulse() امزج بين عدة ألوان واستخدم الدالتين السابقتين للحصول على التأثير الذي تريده في مشروعك. يمكنك كذلك استخدام دالة الوميض blink أو النبض pulse أو التكرار cycle لتشغيل وإطفاء مصباح ليد متعدد الألوان بصورةٍ متكررة، كما هو مبين في الشيفرة التالية: def energise(): rgb.blink() # شغّل المصباح الأحمر لثانية واحدة، والأخضر لثانية، والأزرق لثانية def neutral(): rgb.pulse(fade_times=3) # تفعيل تأثير النبض البطيء def relax(): rgb.cycle(fade_times=4) يمكنك الاستعانة بالشيفرة التالية لجعل مصباح الليد متعدد الألوان يضيء وفق لون معين: def happy(): #شغّل اللون الموافق لشعورك بالسعادة rgb.color = (0, 255, 0) # شغّل اللون الأخضر def sad(): # شغّل اللون الموافق لشعورك بالحزن rgb.color = (255, 0, 0) # شغّل اللون الأحمر ننصحك بإضافة تعليقات ضمن الشيفرة وكتابة اللون الموافق بجانب كل قيمة لونية ليسهُل عليك تذكر الألوان التي استخدمتها عند مراجعة الشيفرة. رابعًا، عليك التعديل على الشيفرة واستدعاء الدالة التي استخدمتها، وذلك بكتابة اسمها في سطر منفصل، بعد التعريف عنها، ثم اختبر الشيفرة. إليك المثال التالي، الذي استدعينا فيه الدالة happy في نهاية الشيفرة: def happy(): #شغّل اللون الموافق لشعورك بالسعادة rgb.color = (0, 255, 0) # شغّل اللون الأخضر def sad(): # شغّل اللون الموافق لشعورك بالحزن rgb.color = (255, 0, 0) # شغّل اللون الأحمر happy() # غيّر هذا السطر بما يوافق الدالة التي تريد استدعائها احرص على عدم ترك مسافات في بداية السطر الذي استدعيت فيه التابع. تمثيل الألوان بصيغة RGB يمكننا تمثيل الألوان بصيغة يفهمها الحاسوب وذلك بالتعبير عن نسبة ما يحتويه اللون من اللون الأحمر والأخضر والأزرق، إذ تخزّن هذه القيم في بايت (ثمانية بتات) وتكون قيمتها من 0 إلى 255. إليك جدولًا يوضح بعض القيم اللونية: table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } اللون الأحمر الأخضر الأزرق أحمر 255 0 0 أخضر 0 255 0 أزرق 0 0 255 أصفر 255 255 0 أرجواني 255 0 255 سماوي 0 255 255 كما يمكنك الاستعانة بمنتقي الألوان من موقع w3schools للحصول على القيم الموافقة للون الذي تريده. تصحيح الأخطاء إليك بعض المشاكل التي قد تواجهك في هذه الخطوة وكيفية إصلاحها: تصحيح الأخطاء الموجودة في الشيفرة تحقق من وجود أي رسائل خطأ في نافذة صدفة Shell ثوني وتحقق من محتواها، إن وجدت. راجع الشيفرة التي كتبتها وتحقق من خلوها من الأخطاء، مثل نسيان علامة : مثلًا، أو وجود مسافة بادئة دون الحاجة لها. تأكد من استيراد توابع العناصر التي ستستخدمها في مشروعك من مكتبة picozero، مثل تابع مصباح الليد متعدد الالوان RGBLED أو الزر Button. استخدم تعليمة الطباعة print لإضافة شرح مختصر عند كل خطوة، مثل ('البدء')print، أو ('ضبط المصباح على اللون الأخضر')print. لا تعمل بعض العناصر الإلكترونية كما يجب تأكد أن جميع العناصر متصلة ببعضها جيدًا، وتحقق من ثبات نقاط توصيل الأسلاك مع اللوحة ومع العناصر. تأكد أن أرقام الأرجل المستخدمة في الشيفرة مطابقة لأرقام الأرجل الموصولة مع مصباح الليد، وتأكد من إعادة وصل الأرجل، في حال فصلتها عند العمل على تصميم الهيكل الخارجي للجهاز. تحقق من وصل العناصر وفق القطبية الصحيحة، إذ قد تحتوي بعض العناصر على قطب موجب + وآخر سالب -. في حال تحققت من جميع النقاط السابقة ولا زال الجهاز لا يعمل، فجرب تبديل العناصر الإلكترونية بأخرى جديدة. لا يضيء مصباح الليد عند استدعاء الدالة المسؤولة عن تشغيله تأكد من تطابق الأرجل الموصول معها المصباح على لوحة بيكو للأرجل المسند إليها في الشيفرة. لا يضيء مصباح الليد باللون الصحيح تحقق من الشيفرة التي كتبتها وأن القيم اللونية مطابقة للون المستخدم، استخدم منتقي الألوان التالي للتحقق من اللون المستخدم. حاول حل المشاكل الأخرى التي قد تواجهك عند التنفيذ وشاركنا طريقة الحل في منصة حسوب IO أو في أكاديمية حسوب. اختيار الحالة المزاجية المناسبة سنضيف في هذه الخطوة وسيلةً تتيح للمستخدم اختيار المزاج المناسب باستخدام زر، أو مقاومة متغيرة. أولًا، حدد عناصر الدخل التي تود استخدامها. إليك الاقتراحات التالية: تخصيص زر لكل مزاج. استخدام زر واحد للتبديل بين المشاعر. استخدام مبدّل يدوي الصنع. استخدام مقاومة متغيرة لاختيار المزاج بناءً على قيمة المقاومة. ستحتاج إلى سلكي توصيل نوع مقبس-مقبس لكل زر تنوي استخدامه، أو ثلاثة أسلاك لكل مقاومة متغيرة. ثانيًا، صِل عناصر الدخل التي اخترتها مع لوحة بيكو باتباع الإرشادات التالية: توصيل زر إلكتروني واحد ستحتاج لتوصيل زر مع لوحة بيكو إلى ما يلي: لوحة راسبيري باي بيكو. زر إلكتروني. سلكي توصيل نوع مقبس-مقبس. صِل سلكي التوصيل مع أرجل الزر واستخدم الشريط اللاصق لتثبيتهما إذا لزم الأمر، ثم صِل أحد السلكين مع الرجل **GP18 **والسلك الآخر مع أقرب رجل أرضية. لا يهم ترتيب توصيل الأسلاك إذ لا توجد قطبية للزر. توصيل عدة أزرار إلكترونية ستحتاج لتوصيل عدة أزرار مع لوحة بيكو إلى ما يلي: لوحة راسبيري باي بيكو. أزرار إلكترونية. سلكي توصيل نوع دبوس-مقبس لكل زر. توضح الصورة التالية طريقة توصيل ثلاثة أزرار مع لوحة بيكو، وإذا أردت توصيل زر رابع فما عليك سوى توصيله مع إحدى أرجل الأغراض العامة GP ورجل أرضية. استخدم سلكي توصيل نوع دبوس- مقبس لتوصيل الزر الأول مع الرجل GP18 ومع أقرب رجل أرضية GND، ثم صِل الزر الثاني مع الرجل GP22، والثالث مع الرجل GP28 بنفس الطريقة. توصيل مقاومة متغيرة مع اللوحة ستحتاج إلى ما يلي: لوحة راسبيري باي بيكو. مقاومة متغيرة. أسلاك توصيل نوع مقبس-مقبس (عدد 3). يوجد للمقاومة المتغيرة ثلاثة أرجل: رجل الأرضية GND، ورجل تشابهية Analogue، ورجل التغذية 3V3، وعند تدوير قرص المقاومة المتغيرة إلى أقصى اليسار يشير السهم إلى الرجل الأرضية GND، وعند تدويره إلى أقصى اليمين، يشير السهم إلى رجل التغذية 3V3، أما الرجل الوسطى للمقاومة فهي الرجل التشابهية التي تستمد منها لوحة بيكو القيم لقراءتها. صِل سلك توصيل ذو نهايات مقبس-مقبس مع كل أرجل المقاومة الثلاث، وثبت التوصيلات بالشريط اللاصق إن لزم الأمر كما يلي: صِل النهاية الحرة للسلك الموصول مع رجل المقاومة ذات الرقم 1 مع رجل الأرض GND الموجودة بين الرجلين GP21 و GP22. صِل رجل المقاومة الوسطى مع الرجل GP26_A0 على لوحة بيكو. صِل رجل المقاومة ذات الرقم 3 مع رجل التغذية 3V3. توصيل مبدل يدوية الصنع أو زر مع لوحة بيكو ستحتاج إلى سلكي توصيل نوع دبوس-مقبس، بحيث تصِل أحدهما مع الرجل GP18 والسلك الآخر مع أقرب رجل أرضية، كما يلي: ثم يمكنك صنع مبدّل يدوي، كما تعلمنا في مشروع سابق، وتوصيلها مع اللوحة وذلك بتوصيل النهاية الحرة للأسلاك مع الجزء الناقل من المبدّل، مثل النحاس أو ورق القصدير. توصيل عدة مبدلات يدوية أو أزرار مع لوحة بيكو ستحتاج إلى سلكي توصيل نوع دبوس-مقبس لكل مبدّل تود توصيله مع لوحة بيكو. استخدم سلكي توصيل نوع دبوس- مقبس لتوصيل المبدّل الأول مع الرجل GP18 ومع أقرب رجل أرضية GND، ثم صِل المبدّل الثاني مع الرجل GP22 ومع أقرب رجل أرضية، والثالث مع الرجل GP28 ورجل الأرضية بنفس الطريقة، كما هو موضح في المخطط التالي: ثالثًا، عليك استيراد التابع الموافق لعنصر الدخل الذي استخدمته من مكتبة picozero، ثم إنشاء متغيرات لإسناد عناصر الدخل للأرجل الموصولة معها. لا تنس أنه بإمكانك استيراد عدة توابع معًا، كما يلي: from picozero import LED, Button لتوصيل زر إلكتروني واحد، علينا إسناده إلى الرجل الموصول معها على لوحة بيكو، كما يلي: from picozero import Button button = Button(18) ولتوصيل عدة أزرار إلكترونية، استورد تابع الزر Button من مكتبة picozero، ثم استخدم الشيفرة التالية لإسناد عدة أزرار إلى الأرجل الموصولة معها على لوحة بيكو: from picozero import Button button_1 = Button(18) button_2 = Button(22) button_3 = Button(28) ننصحك بتسمية المتغيرات بأسماء تدل على عملها، كأن تسمّي الزر المسؤول عن تشغيل المصباح الأحمر red_button أو أي اسم آخر تراه مناسبًا. من أجل توصيل مبدّل واحد، استورد تابع المبدّل Switch من مكتبة picozero، ثم استخدم الشيفرة التالية لإسناد المبدّل إلى الرجل الموصولة معه على لوحة بيكو: from picozero import Switch switch = Switch(18) أما لتوصيل عدة مبدّلات، استورد تابع المبدّل Switch من مكتبة picozero ثم استخدم الشيفرة التالية لإسناد عدة مبدّلات إلى الأرجل الموصولة معها على لوحة بيكو: from picozero import Switch switch_1 = Switch(18) switch_2 = Switch(22) switch_3 = Switch(28) ننصحك بتسمية المتغيرات بأسماء معبرة عن عملها، كأن تسمّي المبدّل المسؤول عن تشغيل المصباح الأحمر red_switch أو أي اسم آخر تراه مناسبًا. ويمكنك الاستعانة بالشيفرة التالية لتوصيل مقاومة متغيرة: from picozero import Pot dial = Pot(0) # A0 موصولة مع الرجل رقم رابعًا، أضف الشيفرة اللازمة لاستدعاء الدوال بناءً على عناصر الدخل التي استخدمتها. الشيفرة اللازمة لتشغيل الشعور التالي عند الضغط على الزر عرّف متغيرًا ما، وليكن option، لتخزين المزاج الحالي فيه واستدعاء الدالة التالية، واحرص على مطابقة أسماء الدوال في الشيفرة للدوال التي استخدمتها في الفقرة السابقة: option = 0 # خزّن الخيار الحالي في هذا المتغير def choice(): # استدعي الدالة التالية وعدّل قيمة متغير التخزين global option if option == 0: energised() # دالة المزاج الأول elif option == 1: calm() # دالة المزاج الثاني elif option == 2: focused() # دالة المزاج الثالث elif option == 3: rgb.off() # انتقل إلى الخيار الثاني if option == 3: option = 0 else: option = option + 1 button.when_pressed = choice # استدعي الدالة التالية عند الضغط على الزر الشيفرة اللازمة لتشغيل مزاج معين عند الضغط على زر معين يمكنك إضافة عدة أزرار يستدعي كل منها دالة موافقة لمزاج مختلف عند الضغط عليها وذلك عن طريق ذكر اسمها دون استخدام الأقواس، كما في المثال التالي: happy_button.when_pressed = happy sad_button.when_pressed = sad angry_button.when_pressed = angry الشيفرة اللازمة لاستدعاء دالة ما بناء على قيمة المقاومة المتغيرة عند استخدام مقاومة متغيرة للتحكم في الخرج، سنحتاج إلى تقسيم قيم المقاومة إلى أجزاء متساوية، كأن نستخدم التابع dial.value للحصول على قيم تتراوح بين 0 و 1، كما يمكننا ضرب القيمة بالرقم 100 للحصول على نسبة مئوية؛ فإذا كان لديك خمس قيم، يمكنك التحقق ما إذا كانت القيمة أقل من 20 أو 40 أو 60 أو 80 أو 100؛ أما إذا كان لديك ثلاث قيم يمكنك تقسيم القراءات إلى 33 و 66 و 100. إليك المثال التالي: while True: mood = dial.value * 100 # تحويل إلى نسبة مئوية print(mood) if mood < 20: happy() elif mood < 40: good() elif mood < 60: okay() elif mood < 80: unsure() else: unhappy() sleep(0.1) أخيرًا، شغّل الشيفرة لاختبار المشروع، وتحقق أنه يمكنك التبديل بين الحالات المزاجية المتاحة واختيار أحدها، وإذا واجهت مشاكل عند التنفيذ في هذه الخطوة فراجع فقرة تصحيح الأخطاء السابقة. تصحيح الأخطاء إليك بعض المشاكل التي قد تواجهك في هذه الخطوة وكيفية إصلاحها: تصحيح الأخطاء الموجودة في الشيفرة تحقق من وجود أي رسائل خطأ في نافذة صدفة ثوني وتحقق من محتواها، إن وجدت. راجع الشيفرة التي كتبتها وتحقق من خلوها من الأخطاء، مثل نسيان علامة : مثلًا، أو وجود مسافة بادئة دون الحاجة لها. تأكد من استيراد توابع العناصر التي ستستخدمها في مشروعك من مكتبة picozero، مثل تابع مصباح الليد متعدد الالوان RGBLED أو الزر Button. استخدم تعليمة الطباعة print لإضافة شرح مختصر عند كل خطوة، مثل ('البدء')print، أو ('ضبط المصباح على اللون الأخضر')print. لا تعمل بعض العناصر الإلكترونية بالدخل أو الخرج كما يجب تأكد أن جميع عناصر الدخل أو الخرج متصلة ببعضها جيدًا، وتحقق من ثبات نقاط توصيل الأسلاك مع اللوحة ومع العناصر. تأكد أن أرقام الأرجل المستخدمة في الشيفرة مطابقة لأرقام الأرجل الموصولة مع مصباح الليد، وتأكد من إعادة وصل الأرجل، في حال فصلتها عند العمل على تصميم الهيكل الخارجي للجهاز. تحقق من وصل العناصر وفق القطبية الصحيحة، إذ قد تحتوي بعض العناصر على قطب موجب + وآخر سالب -. في حال تحققت من جميع النقاط السابقة ولا زال الجهاز لا يعمل، فجرب تبديل العناصر الإلكترونية بأخرى جديدة. حاول حل المشاكل الأخرى التي قد تواجهك عند التنفيذ وشاركنا طريقة الحل في منصة حسوب IO أو في أكاديمية حسوب. تنفيذ الهيكل الخارجي حان الآن وقت تنفيذ الهيكل الخارجي لجهاز اختبار الحالة المزاجية. أولًا، أجب على الأسئلة التالية لتساعدك في اختيار التصميم الخارجي: ما هي المواد التي تود استخدامها؟ هل تتوفر جميعها لديك؟ ما نوع المبدّلات التي تود صنعها؟ وما هي آلية عملها؟ كيف ستُثبّت العناصر الإلكترونية، مثل المقاومة المتغيرة ومصباح الليد، بحيث تبقى متينةً وسهلة الاستخدام؟ وهل تود استخدام ناشرًا لضوء الليد؟ معلومة: في علم البصريات Optics الذي يُعنى بدراسة الضوء والإبصار، يُعَّرف الناشر Diffuser بأنه أي مادة قادرة على تشتيت الضوء؛ فقد يكون ضوء بعض مصابيح الليد موجهًا في اتجاه معين، وبالتالي لا يمكن رؤيته جيدًا من مسافة بعيدة؛ أو قد يكون ساطعًا ومؤلمًا للعين عند النظر إليه من زاوية معينة. يساعد استخدام الناشر في حل هذه المشكلات ونشر الضوء بطريقة مريحة للعين ومُرضية، كما أنه بسيط الصنع، إذ ما عليك سوى استخدام ورقة رقيقة لتغطية المصباح والحصول على ناشر. إليك المثال التالي الذي استخدمنا فيه بالونًا لنشر الضوء، كما استخدمنا عدة بطاقات مختلفة الحجم وغلّفناها بورق القصدير والنحاس لغلق الدارة وتفعيل الحالة المزاجية الموافقة للبطاقة. ثانيًا، جهز المواد التي ستستخدمها لتنفيذ الهيكل الخارجي لجهازك. إليك بعض الاقتراحات: الورق المقوى. المواد البلاستيكية المعاد تدويرها. ألعاب قديمة أو قطع الليغو Lego. شريط لاصق. كما يمكنك استخدام الطابعة ثلاثية الأبعاد إن توفر لك ذلك. لا تنسَ طلب مساعدة أحد البالغين عند الحاجة لاستخدام المقص، أو أي أداة حادة أو ساخنة. ثالثًا، اصنع الغلاف الخارجي والواجهة لجهازك بالاستعانة بالإرشادات التالية، واطلب مساعدة أحد البالغين عند الحاجة. تثبيت العناصر داخل الورق المقوى أو البلاستيك بإمكانك تثبيت مصابيح الليد أو الأجراس أو المقاومات المتغيرة داخل قطع من الورق المقوى أو البلاستيك، وذلك بصنع ثقوب وإدخال العناصر وأسلاك التوصيل فيها، كما هو موضح في الصورة التالية: افصل الأسلاك عن العنصر، ثم أدخله في الثقب الذي أحدثته، ثم أعد توصيل الأسلاك. ستحتاج إلى استخدام أداة حادة لإحداث ثقب في المواد البلاستيكية، اطلب مساعدة أحد البالغين إن لزم الأمر. واحرص على تذكر ما هي أرقام الأرجل الموصولة مع الأسلاك. استخدم الشريط اللاصق لتثبيت العناصر في مكانها. تبديد الضوء المنبعث من مصباح الليد نحصل عند تبديد أو نشر ضوء مصباح الليد على تأثير لطيف، وخاصة عند استخدام مصابيح الليد الشفافة، ذات اللون الواحد أو متعددة الألوان، وذلك بوضع المصباح خلف ورقة رقيقة أو شفافة، أو خلف شريط لاصق شفاف، مما سيجعل الضوء ينتشر على مساحة أوسع وبسطوع أقل، فيصبح أكثر راحةً للعين. كما يمكنك توجيه الضوء في اتجاه معين باستخدام ورقة بيضاء، وذلك لتحصل على أكبر قدر ممكن من الضوء. تثبيت أسلاك التوصيل باستخدام الشريط اللاصق يمكنك تثبيت أسلاك التوصيل باستخدام الشريط اللاصق وإزالة الشريط اللاصق فيما بعد بكل سهولة لإعادة استخدام العناصر عند الحاجة. استخدام سكين الحرف متعدد الاستخدامات تُعد سكاكين الحرف Crafts مفيدة عند صنع الحرف اليدوية، لكن يجب أن تكون حذرًا جدًا عند استخدامها لأنها حادة جدًا ويمكن أن تسبب جروحًا وإصابات. احرص على وجود شخص بالغ عند استخدامك للسكاكين، أو اطلب منه استخدامها عوضًا عنك، كما ننصحك باستخدام لوح القص لحماية الأسطح، أو باستخدام لوح التقطيع الخشبي المتوفر في كل المطابخ. رابعًا، ثبت العناصر الإلكترونية في الهيكل الخارجي لجهازك وصِلها مع واجهة الجهاز. توصيل الأسلاك ببعضها قد تحتاج إلى أسلاك توصيل طويلة جدًا لتوصيل مصابيح الليد مع أرجل لوحة بيكو، أو يمكنك وصل الأسلاك ببعضها للحصول على سلك طويل، وذلك عبر توصيل سلك ذو نهايات دبوس-مقبس مع سلك ذو نهايات مقبس-مقبس للحصول على سلك مقبس-مقبس طويل جدًا، وتدعى هذه الطريقة باسم سلسلة الأقحوان daisy chaining. ننصحك باستخدام سلكين لهما اللون نفسه ليسهل تتبع السلك ومعرفة العنصر الموصول معه. تكمن مشكلة هذه الطريقة في أن الأسلاك قد تنفصل عن بعضها، ولذلك ينصح بلصقها بقطعة صغيرة من الشريط اللاصق. خامسًا، شغّل الشيفرة واختبر عمل كل عنصر بدقة، وتأكد أن جميع العناصر تعمل كما ينبغي بعد أن ثبّتها في جهازك. واستعن بفقرة تصحيح الأخطاء إذا واجهت مشكلةً ما. ترقية المشروع بما أنك أصبحت على دراية بالمهارات المطلوبة لتصميم جهاز يعرض الحالة المزاجية وكتابة الشيفرة اللازمة لذلك، يمكنك ترقية المشروع حين يتسنى لك، بالبحث عن بعض الأجهزة والأدوات المماثلة، ثم قرر هل ترغب في تحسين جهازك أو إضافة بعض الميزات عليه؟ جرّب جهازك مع الآخرين للحصول على ملاحظاتهم وترقية المشروع بناءً عليها، وننصحك بالإطلاع على الشيفرة الخاصة بالمشاريع التي ذكرناها في المقدمة لتتعرف على آلية عملها وتستوحي بعض الأفكار منها. إليك بعض الاقتراحات التي يمكنك تنفيذها: اختبار الجهاز مع الأصدقاء والعائلة لتحسين تجربة الاستخدام وفقًا لآرائهم. إضافة المزيد من الحالات المزاجية، والألوان، والتأثيرات الضوئية. تحسين التصميم الخارجي للجهاز. إضافة الأصوات على الجهاز باستخدام الأجراس الإلكترونية Buzzers. كما يمكنك التعديل على شيفرة المشروع وتطوير نمط الوميض، والنبض والتكرار، أو إضافة توقيت، وألوان، أو تحديد عدد معين لمرات تكرار الأنماط، وذلك كما يلي: إضفاء تأثير الوميض أو النبض على مصباح ليد يمكنك إضفاء تأثير الوميض أو النبض على مصباح ليد عادي عن طريق استخدام دالة الوميض blink لتشغيل وإطفاء المصباح بصورةٍ متكررة. الشيفرة اللازمة لتطبيق تأثير الوميض على مصباح ليد عادي باستخدام دالة blink هي على النحو التالي: led.blink() # تشغيل المصباح لثانية واحدة ثم إطفاءه لثانية print("Blinking") # اطبع ما بين القوسين مباشرةً sleep(6) led.off() والشيفرة اللازمة لتطبيق تأثير الوميض عددًا معينًا من المرات، هي: led.blink(on_time=1, off_time=0.5, n=3, wait=True) print("Finished blinking") # اطبع ما بين القوسين بعد تشغيل المصباح وإطفاءه ثلاث مرات لاحظ أنه عند عدم ضبط مدة الإطفاء off_time، ستكون مدتها مطابقةً لمدة التشغيل on_time. أما الشيفرة اللازمة لزيادة سطوع المصباح تدريجيًا باستخدام تابع النبض pulse، تكون على النحو التالي: led.pulse() # زيادة السطوع لمدة ثانية واحدة ثم تخفيفه ثانية print("Pulsing") # اطبع ما بين القوسين مباشرةً توضح الشيفرة التالية الشيفرة اللازمة للتحكم في سرعة النبض وعدد مرات التكرار led.pulse(fade_in_time=2, fade_out_time=1, n=4, wait=True) #زيادة السطوع لمدة ثانيتين ثم تخفيفه لمدة ثانية print("Finished pulsing") # طبع ما بين القوسين بعد 4 نبضات كما يمكنك دمج التأثيرين السابقين للحصول على تأثيرات ساحرة: led.blink(on_time=1, off_time=1, fade_in_time=1, fade_out_time=1) # تشغيل المصباح لثانية واحدة ثم إطفاءه لثانية وتخفيف السطوع أثناء ذلك print("Fancy") # اطبع ما بين القوسين مباشرةً ملاحظة: يستمر تنفيذ دالتي الوميض blink والنبض pulse إلى أن يُستدعى تابع الإطفاء off أو إلى أن نستدعي الدالتين بإعدادات جديدة. استخدم التعليمة wait=True وحدد n والتي هي عدد مرات تنفيذ التأثير. إضفاء تأثير الوميض أو النبض أو التكرار على مصباح متعدد الألوان استخدم دالة الوميض blink لتبديل الألوان في مصباح الليد متعدد الألوان، كما هو مبين في الشيفرة التالية: rgb.blink() # تشغيل اللون الأحمر لمدة ثانية، ثم الأخضر لثانية، ثم الأزرق لثانية print("Blinking") # اطبع ما بين القوسين مباشرةً sleep(6) rgb.off() أما الشيفرة اللازمة لتطبيق تأثير الوميض على لون واحد في مصباح متعدد الألوان فهي على النحو التالي: # اجعل اللون البنفسجي يومض لمدة ثانيتين، ثم أطفئه لنصف ثانية rgb.blink(on_times=(2, 0.5), colors=((255, 0, 255), (0, 0, 0)), wait=True, n=3) print("Finished blinking") # اطبع ما بين القوسين بعد ثلاثة تكرارات اعتمد على الشيفرة التالية لتطبيق تأثير الوميض عددًا معينًا من المرات بتوقيت وألوان مختلفة: # اجعل اللون البنفسجي يومض لمدة ثانية، والأخضر لنصف ثانية، والأزرق لربع ثانية rgb.blink((1, 0.5, 0.25), colors=((255, 0, 0), (0, 255, 0), (0, 0, 255)), wait=True, n=2) print("Finished blinking") # اطبع ما بين القوسين بعد تكرارين لاحظ أنه عند عدم تحديد مدة الإطفاء off_time، ستكون مدتها مطابقة لمدة التشغيل on_time. استعن بالشيفرة التالية لتغيير سطوع المصباح متعدد الألوان ولونه تدريجيًا باستخدام تابع النبض pulse: rgb.pulse() # شغّل اللون الأحمر لمدة ثانية، ثم الأخضر لثانية، ثم الأزرق print("Pulsing") # اطبع ما بين القوسين مباشرةً للتحكم في سرعة النبض للمصباح متعدد الألوان وعدد مرات التكرار: # خفف سطوع اللون البنفسجي لمدة ثانيتين، ثم أطفئ المصباح لمدة نصف ثانية وكرر العملية 3 مرات rgb.pulse(fade_times=(2, 0.5), colors=((255, 0, 255), (0, 0, 0)), wait=True, n=3) print("Finished pulsing") # اطبع ما بين القوسين بعد ثلاثة تكرارات أما للتبديل بين الألوان تدريجيًا باستخدام تابع التكرار cycle، تكون الشيفرة على النحو التالي: rgb.cycle() # التدوير بين الألوان تدريجيًا من الأحمر للأخضر، ثم الأخضر للأزرق، ثم الأزرق للأحمر print("Cycle") # اطبع ما بين القوسين مباشرةً تساعد الشيفرة التالية في التحكم في اللون والمدة وعدد مرات التكرار # بدّل بين الألوان بترتيب معاكس وبسرعة أبطأ rgb.cycle(fade_times=3, colors=((0, 0, 255), (0, 255, 0), (255, 0, 0)), wait=True, n=2) rgb.off() ملاحظة: يستمر تنفيذ دالتي الوميض blink والنبض pulse إلى أن يُستدعى تابع الإطفاء off أو إلى أن نستدعي الدالتين بإعدادات جديدة. استخدم التعليمة wait=True واضبط n والتي هي عدد مرات تنفيذ التأثير. إليك الفيديو التالي ليوضح لك تأثير الوميض blink وخفوت الإضاءة عند تطبيق تأثير النبض pulse، كما يمكنك التعديل على جهازك لاحقًا وإضافة حالات مزاجية جديدة بناءً على المواقف التي تمر بها. والإطلاع على معرض مشاريع أداة اختبار الحالة المزاجية لتستوحي منها بعض الأفكار، ولا تنسى مشاركة مشروعك مع الأصدقاء أو مشاركته معنا على منصة حسوب IO. الخاتمة تهانينا، فقد أتممت مشروع تصميم وتنفيذ جهاز لعرض الحالة المزاجية باستخدام لوحة راسبيري باي بيكو ننصحك بتنفيذ مشروع تصميم وتنفيذ آلة موسيقية باستخدام لوحة راسبيري باي بيكو في خطوتك التالية، وإذا واجهت مشاكلًا عند تنفيذ هذا المشروع، يمكنك الحصول على الدعم والمساعدة عبر إضافة سؤالك في قسم الأسئلة والأجوبة في أكاديمية حسوب. ترجمة -وبتصرف- للمقال Mood indicator من الموقع الرسمي لراسبيري باي. اقرأ أيضًا صنع قلب نابض باستخدام لوحة راسبيري باي بيكو تصميم محاكاة لمفرقعات الحفلات باستخدام لوحة راسبيري باي بيكو إنشاء مصباح ليد يومض وفق نمط معين باستخدام حاسوب راسبيري باي بيكو