0%

أنواع المفاتيح العامة (مفتاح خاص و آخر عام ينشأ باستخدام Curve25519)
  • مفتاح التعريف، يتم إنشاؤه أثناء تركيب التطبيق.
  • مفتاح ابتدائي، ينشأ أثناء التركيب و يجدد بشكل دوري وموقع بواسطة مفتاح التعريف.
  • مفاتيح الاستخدام الواحد، تنشأ حسب الحاجة.
أنواع مفاتيح الجلسة (مفاتيح تماثلية)
  • مفتاح رئيس.
  • مفتاح تسلسلي، ينشأ بالمفتاح الرئيس.
  • مفاتيح الرسائل، تنشأ بالمفاتيح التسلسلية.

عند تركيب التطبيق يقوم البرنامج بإرسال المفاتيح العامة لكل من مفتاح التعريف والمفتاح الابتدائي ومجموعة من مفاتيح الاستخدام الواحد لخوادم الواتساب. يحتفظ الخادم بهذه المفاتيح مع حساب المستخدم. المفاتيح الخاصة تبقى دائما مع المستخدم فقط.

إعداد جلسة المحادثات بين طرفين

المراسلات في نظام التشفير الجديد كلها مشفرة وذلك يشمل رسائل الإعداد الأولي ولتحقيق ذلك يقوم المرسل باستخدام المفاتيح العامة للمستقبل والتي يحصل عليها من خادم الواتساب¹. يرسل الخادم للمرسل مفاتيح المستقبل وهي مفتاح التعريف ومفتاح ابتدائي و أحد مفاتيح الاستخدام الواحد². فيقوم المرسل باستخدام مفاتيحه الخاصة و مفاتيح المستقبل العامة لإنشاء المفتاح السري (باستخدام بروتوكول ECDH) ويستخدم المفتاح السري في عملية تشفير الرسائل قبل إرسالها للمستقبل. كما يقوم المرسل بإرفاق مفاتيحه العامة مع الرسائل الأولى إلى أن يتم إنهاء إعداد الجلسة. عندما تصل الرسائل للمستقبل يقوم باستخدام مفاتيحه الخاصة والمفاتيح العامة للمرسل والتي أرسلت له مع الرسالة وينشئ منها نفس المفتاح السري الذي أنشاءه المرسل (هذه هي عبقرية بروتوكول ديفي-هيلمان) ومن ثم يقوم باستخراج المفتاح الرئيس كما فعل المرسل ويستخدمه في عملية فك تشفير الرسائل وبهذا تكون الجلسة قد أعدت بين الطرفين وكلاهما يحمل مفاتيح تشفير الرسائل.

تشفير الرسائل

لكل رسالة تنشأ مفاتيح تشفير جديدة لدى الطرفين ولها هذه المميزات:

  1. المفاتيح لدي الطرفين متشابهة (شكرا لبروتوكول ديفي-هيلمان)و تنشأ من مفاتيحهم العامة والخاصة.
  2. مفتاح كل رسالة مستقل عن ما قبله وما بعده، فضياع الرسالة لا يوثر على سير التراسل. واكتشاف احد المفاتيح لا يمكن من فك تشفير الرسائل السابقة.
  3. لا يمكن استنباط المفاتيح الأصلية من مفاتيح الرسالة.
  4. المفتاح يستخدم لتشفير رسالة واحدة فقط ولا يعاد استخدامه؟

هذه المميزات تجعل عملية ربط رسالة مشفرة بمرسل معين مستحيلة، فالتحقق من صحة الرسالة ممكن لكن التحقق من هوية المرسل مستحيلة وهذه مفيدة في حال المراسلات الحساسة والتي يخشى فيها المرسل مثلا من محاكمته واتهامه بإرسال تلك الرسائل. لكن في نفس الوقت هذه الميزة تجعل عملية التحقق من هوية الطرف الآخر مستحيلة لذلك يتم استخدام مفتاح الاستخدام الواحد** وكذلك خاصية التحقق من خلال تطبيق الواتساب ومطابقة رمز التحقق يدويا مع الطرف الآخر لتجاوز هذه الثغرة. ملفات الوسائط (الفيديو والصور و الصوت) والمستندات يتم تشفيرها بنفس الأسلوب. وعند استقبال ملف من شخص وتمريره لشخص آخر تتم عملية تشفير الملف بمفاتيح خاصة بالشخص اﻵخر وإرسال الملف المشفر من جديد.

تشفير رسائل المجموعات

بأسلوب مشابه تقريباً لطريقة المراسلات بين طرفين يقوم المرسل عند إرسال رسالته الأولى بإنشاء جلسة للمجموعة وذلك بالتخاطب مع جميع أعضاء المجموعة كل على حدة وبتشفير مختلف عن الآخرين ويرسل لهم مفتاح موحد خاص به يسمى مفتاح المرسل. يقوم المرسل بعدها باستخدام ذلك المفتاح لإنشاء مفاتيح التشفير لكل رسالة (مفتاح تسلسلي ومفتاح الرسالة) ويستخدم تلك المفاتيح لتشفير رسائله وإرسالها للخادم والذي بدورة يقوم بتوزيع تلك الرسالة لجميع أعضاء المجموعة. جميع الأعضاء يملكون مفتاح المرسل فيقومون باستخدامه لاستخراج المفاتيح التي تتيح لهم فك تشفير تلك الرسالة والرسائل القادمة. عندما يقوم احدهم بمغادرة المجموعة يقوم بقية الأعضاء بمسح جميع مفاتيح المرسلين وإعادة إنشاء جلسات المجموعة من جديد.

التخاطب مع الخادم

بالإضافة لتشفير الرسائل بين المستخدمين فإن تطبيق الواتساب (في أجهزة الاندرويد والايفون والويندوز فون فقط) يقوم كذلك بتشفير قناة الاتصال مع الخادم وذلك يمنع من لديهم القدرة على التجسس على الشبكة من معرفة مالذي يقوم به المرسل ومع من يتحدث.

هل نثق في التطبيق الآن؟

يوفر تطبيق الواتساب خيار يمكن تفعيلة من خلال صفحة إعدادات الأمان لتنبيه المستخدم عندما يتغير مفتاح التعريف لأي من المستخدمين المعرفين لديه. ومفتاح التعريف يتغير عند تغيير جهاز الهاتف أو إعادة تركيب التطبيق أو قيام احدهم بانتحال شخصية الطرف الآخر لذا يجب التحقق من هوية الطرف الآخر ومطابقة رمز التحقق إذا كانت سرية المحادثة مهمة. * يصعب الوثوق في تطبيق الواتساب وتشفيره لعدة أسباب منها:

  1. كون التطبيق مغلق المصدر مما يصعب عملية التحقق من طريقة عملة ومطابقتها مع ما اعلن عن طريقة عمل بروتوكول التشفير.
  2. كون التطبيق لا يزال يدعم التراسل غير المشفر للتوافق مع الإصدارات القديمة التي لا تدعم التشفير وأن وعملية الانتقال للتشفير تمت بشكل تلقائي من الشركة بدون موافقة المستخدم أو القدرة على اختيار نوع التراسل فهذا يعني أن الشركة قادرة على تعطيل التشفير لشخص معين دون علمه. وبما أن التطبيق يدعم التراسل بالطريقتين فالتحقق من ما يقوم به التطبيق صعب ويحتاج مراقبة مستمرة.
  3. كون بروتوكول Signal مصمم في الأصل ليوفر خاصية الإنكار (repudiation وهو عكس non-repudiation) والتي تمكن المرسل من إنكار علاقته بالرسائل التي قام هو بإرسالها فإن عملية التحقق تعتمد على الثقة بخادم الواتساب بالإضافة لعملية مطابقة رمز التحقق يدويا من كلا الطرفين.

وضع الآمان في التطبيق بعد إضافة خاصية التشفير يعد افضل من السابق بمراحل عدة خصوصا للمستخدم العادي ويعتبر من أكثر الحلول المتوفرة أمناً في تطبيقات المحادثات المشهورة حالياً. أما من يبحث عن أمان مطلق فعليه استخدام أدوات ووسائل أخرى لا تتطلب الثقة بطرف ثالث أو استخدام عدة حلول بتقنيات مختلفة مع بعض.

المصادر: WhatsApp-Security-Whitepaper و whispersystems.org

¹ هذه احد نقاط الضعف في التشفير، إذ يجب الثقة في الخادم وان المفاتيح المرسلة تخص المستقبل الحقيقي.

² يقوم الخادم بحذف المفتاح بعد استخدامه ولا يقبل استخدامه مرة أخرى، وفي حال استنفذت جميع مفاتيح الاستخدام الواحد ولم يستطع الخادم طلب مفاتيح جديدة من المستقبل لعدم وجودة online فإن العملية تتم بدونها. وهذه نقطة ضعف أخرى إذ يستطيع المخترق استغلالها بإنشاء طلبات اتصال وهمية حتى تستنفذ جميع مفاتيح الاستخدام الواحد.

الكثير من الناس قد هجر النظام العجوز ويندوز XP لأسباب عديدة منها انه لم يعد متوفر في السوق والأجهزة الجديدة تأتي محلمة بالإصدارات الحديثة من ذلك النظام وكذلك بسبب إيقاف شركة مايكروسوفت الدعم لذلك النظام فلم يعد يستقبل التحديثات الأمنية وكل من لديه اهتمام ولو بسيط بأمن المعلومات يدرك مدى أهمية تلك التحديثات خصوصا لنظام مثل الويندوز.

لكن البعض قد يفضل استخدام XP بدلا من الإصدارات الأحدث لعدة أسباب منها كونه اخف واقل استهلاك لموارد الجهاز خصوصا في حال استخدامه كنظام وهمي (Virtual system) وكذلك كونه نظام قديم قد تلقى الكثير من التحديثات والاختبارات والترقيعات فغالبا سيكون اكثر أمنا واستقرارا من الإصدارات الجديدة والتي ما زالت تحتوي على العديد من المشاكل والثغرات غير المكتشفة وكذلك كونه لا يحتوي على إضافات مايكروسوفت الجديدة والتي تجمع وترسل بعض المعلومات عن المستخدم إلى خوادم الشركة كما في ويندوز 10.

مهما كانت أسباب اختيارك أو قناعتك بنظام XP فهناك طريقة تجعل النظام يستقبل تحديثات أمنية وبشكل رسمي من الشركة، وهذه الطريقة تعتمد على تغيير قيمة في سجلات النظام لتجعله يعتقد أنه نظام XP المخصص للأنظمة المدمجة كما في أجهزة البيع والأجهزة الطبية (Point of Service) إذ أن مايكروسوفت لا زالت تدعم تلك الإصدارة من النظام وذلك بسبب انتشارها في أجهزة كثيرة واستحالة تحديثها لإصدارات جديدة من نظام الويندوز.

التعديل سيجعل النظام يستقبل التحديثات والترقيعات بدون أن يؤثر في طريقة عمله وأنا شخصيا استخدمها منذ فترة طويلة وبدون مشاكل والكثير كذلك استخدموها ولم يواجهوا أي مشكلة. طريقة التعديل سهلة قم بإنشاء ملف نصي بامتداد reg مثلا xpupdate.reg واكتب بداخلة السطور التالية:

1
2
3
Windows Registry Editor Version 5.00 
[HKEY_LOCAL_MACHINE\SYSTEM\WPA\PosReady]
"Installed"=dword:00000001

ثم قم بتشغيل الملف (بالنقر عليه مرتين) بعدها اذهب لصفحة التحديثات (عن طريق متصفح إنترنت اكسبلورر) وقم بالبحث عن التحديثات (أو اتركها وسيقوم النظام بالبحث بشكل تلقائي فيما بعد) وستلاحظ أن أسماء التحديثات التي ستظهر بها كلمة WEPOS وذلك لأنها موجهة لذلك النظام.

هذه صورة تبين آخر التحديثات التي وصلت لي (بتاريخ اليوم، 22 مايو 2016):

تحديثات نظام ويندوز اكس بيتحديث نوفمبر 2017:

لا زالت التحديثات تصل لوندوز XP المعدل واحدثها وصل لشهر نوفمبر 2017 كما نشاهد في الصورة:

غالبية الألعاب وكذلك بعض التطبيقات تتطلب تحريك صور وشخصيات رسومية خلال الشاشة، تحريك الشخصيات يتم من خلال رسم الشخصية بحالات الحركة المطلوبة (sprite) ثم عرض تلك الرسومات واحدة تلو الأخرى لتعطي إيحاء الحركة كالصورة التالية: Animation Sprite وأما تحريك الخلفيات فغالبا يتم من خلال إنشاء صورة خلفية اكبر من حجم مساحة العرض ثم عرض جزء من الصورة وتغيير احداثياتها لتبدو كأنها تتحرك.

يوفر الاندرويد عنصر للصور (ImageView) لكن ذلك مخصص لعرض الصور الثابتة أو التي لا تتطلب تغييرات سريعة ولا يمكن استخدامه للصور المتحركة لأنه بطيء. للتعامل مع الصور المتحركة نحتاج إلى الرسم مباشرة على canvas (سطح الرسم) لكن توجد طريقة تبسط العملية وهي باستخدام عنصر SurfaceView والذي يمكنك من الرسم المباشر على canvas وبطريقة سهلة. عملية التحريك تحتاج أن تعمل في الخلفية لكي لا تعطل عمل التطبيق (لفهم عمليات الخلفية راجع الشرح السابق). لتنظيم العمل سنجعل النص الخاص بالحركة في كلاس (class) خاص سنسمية AnimGuy:

1
2
3
public class AnimGuy extends SurfaceView implements Runnable {
....
}

عملنا الكلاس كامتداد لكلاس SurfaceView وكذلك واجهة لكلاس Runnable وذلك لتشغيله في الخلفية كما سنرى لاحقا. في البداية نقوم بتحميل الصورة وهي عبارة عن ملف واحد مرسوم به إطارات متساوية في المقاس تمثل مراحل الحركة للشخصية (خطوات الركض). لدينا في تلك الصورة 6 إطارات فنحتاج عرضها واحد تلو الآخر إلى الأخير ثم نعود للإطار الأول وهكذا. الدالة run() هي التي نستخدمها لتحريك تلك الإطارات وهي تعمل في الخلفية. لنلقي نظرة على تلك الدالة:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Override
public void run() {
while (animate) {
if (surfaceHolder.getSurface().isValid()) {
Canvas canvas = surfaceHolder.lockCanvas();

// Clear any existing drawing from previous run
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);

x = frame * imgWidth;
Rect src = new Rect(x, 0, x + imgWidth, imgHeight);
Rect dst = new Rect(0, 0, imgWidth, imgHeight);
canvas.drawBitmap(guyImage, src, dst, null);

// This is a modulus operation to loop through all the frames and restart over
frame = ++frame % totalFrames;

surfaceHolder.unlockCanvasAndPost(canvas);
}

try {
Thread.sleep(120);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

نلاحظ أولا أننا نستخدم حلقة while بمتغير ثنائي animation للتحكم باستمرارية الحلقة، ونتحكم بقيمة هذا المتغير كما سنرى لاحقا لبدء ووقف التحريك. في داخل الحلقة نتأكد أولا من جاهزية السطح للرسم isValid() (في بعض الحالات مثل لحظة بدأ التطبيق لا يكون سطح الرسم جاهزاً بعد ومحاولة الرسم عليه ستؤدي إلى فشل التطبيق)، في حال كان جاهزاً نقوم بقفل السطح lockCanvas() لنظمن أن لا احد غير هذه الدالة يستطيع الرسم عليه. بعد ذلك نقوم بمسح محتوى سطح الرسم لكي لا تبقى به رسومات سابقة. نبدأ الآن بالرسم، أولا نحتاج رقم الإطار المراد رسمة وهو محفوظ في المتغير frame وفي البداية فيمته صفر فتكون الإحداثيات على المحور س تساوي صفر أي من أول الصورة. بعد ذلك نقوم بنسخ مساحة مستطيلة Rect من الصورة الأصلية تبدأ من س إلى س+عرض الإطار، أما الارتفاع (محور ص) فهو بكامل ارتفاع الصورة (يبدأ من صفر إلى ارتفاع الصورة). بعد ذلك نحدد المساحة التي سنرسم عليها dst في المثال هذا وللتبسيط جعلنا مساحة سطح الرسم مساوية لمساحة الإطار الواحد، لذلك فإن منطقة الرسم وحجمها يساوي المساحة الكاملة (يبدأ من الصفر إلى طول وعرض الإطار). نقوم الآن بالرسم بالأمر drawBitmap إذ نمرر له الصورة الكاملة ومعها إحداثياتها ومساحة الإطار المراد نسخة وكذلك إحداثياتها ومساحة المنطقة المراد الرسم عليها. نقوم بعدها بزيادة رقم الإطار ليكون جاهزا لعملية الرسم التالية (لحساب رقم الإطار نستخدم طريقة المعامل الرياضي فعدد الإطارات هو 6 فعندما يبلغ العداد ذلك الرقم يعود من جديد للعد من 0). في الأخير نقوم بفك القفل ورسم الإطار unlockCanvasAndPost. للتحكم بسرعة تحريك الإطارات نستخدم Thread.sleep() والتي تجعل عملية الخلفية تنام (أو تتوقف عن العمل) لمدة زمنية تحسب بأجزاء الثانية، فهذه القيمة تعتمد على عدد الإطارات وكذلك السرعة الحركة المناسبة. لرسم الإطار الذي يليه (رقم 1) نقوم بنفس الخطوات وإحداثيات الإطار تبدأ من نهاية الإطار السابق.

لاستخدام هذا الكلاس نهيئه أولا من الكلاس الرئيسي بالأمر التالي:

1
animGuy = new AnimGuy(this);

ويتم تشغيل وايقاف الحركة بالأمرين التاليين:

1
2
animGuy.resume();
animGuy.pause();

التطبيق الكامل (تجده هنا) فيه تنفيذ المثال المشروح هنا وكذلك تجد فيه كلاس لمشهد تحريك متكامل (كما في الفيديو بالأعلى) يشمل الشخصية السابقة وكذلك أرضية تتحرك بالاتجاه المعاكس وخلفية تتحرك كذلك بالاتجاه المعاكس لكن بسرعة اقل لتعطي إيحاء بالبعد. بالنسبة للأرضية فهي صورة لإطار واحد، نقوم أولا بتكراره إلى أن يملا عرض الشاشة ثم نقوم بتحريكه قليلا في الاتجاه المعاكس لحركة الولد إلى أن يصل الإطار الأول لطرف الشاشة ثم نعيده لموقعة الأول. أما بالنسبة للخلفية فنقوم أولا بتعديل حجمها ليناسب حجم سطح الرسم ثم نقوم بعمل مشابه لما قمنا به للأرضية.

للاستفسار عن هذا الشرح أو التطبيق يمكنك مراسلتي على تويتر

مصدر الصور: (الولد ) (الخلفية )

عند تنفيذ تطبيق الاندرويد يتم إنشاء عملية أساسية تسمى UI Thread وهي المسؤولة في تنفيذ أوامر التطبيق وعرض النتائج على الشاشة وكذلك الاستجابة لعمليات المستخدم مثل الضغط على الأزرار والكتابة …الخ. في التطبيقات البسيطة تكون تلك العملية قادرة على أداء المهمة بشكل جيد لكن توجد حالات كثيرة يحتاج فيها مطور التطبيق إلى إنشاء عمليات إضافية لكون العملية الأساسية UI Thread غير كافية.

لنفرض مثلا أن التطبيق يقوم بتحميل ملف ويعرض نسبة التحميل على الشاشة بشكل مباشر فهذا يعني أننا نحتاج إلى مراقبة حالة الملف وتعديل البيانات المعروضة على الشاشة بشكل مستمر، لو نفذنا هذه الخطوات باستخدام العملية الأساسية فستجد أن التطبيق سيصبح مشغول في حلقة برمجية (loop) لمراقبة عملية تحميل الملف وتعديل بيانات العرض ولن يكون هناك وقت للتعامل مع المستخدم أو بقية أجزاء التطبيق بمعنى أن التطبيق سيكون في حالة عدم استجابة إلى أن يكتمل الملف وتنتهي الحلقة البرمجية. وستلاحظ كذلك أن حالة تحميل الملف الظاهرة على الشاشة لن تتحدث وستكون صفر عند البداية وستبقى كذلك إلى أن يكتم التحميل وستقفز فجأة إلى 100% والسبب أن العملية الأساسية كما ذكرنا مشغولة بعملية التحميل ولا تستطيع تحديث شاشة التطبيق ليرى المستخدم نسبة تحميل الملف. نفس المشكلة لو كان البرنامج عبارة عن ساعة زمنية أو يقوم بتحريك رسومات أو لعبة.

الحل سهل، وهو بإنشاء عملية أخرى تعمل في الخلفية تقوم هي بمتابعة عملية تحميل الملف وترسل تحديثات عن حالة التحميل إلى العملية الأساسية وهذه العملية تسمى AsyncTask وتعني العملية غير المتزامنة لأنها تعمل بشكل مستقل عن العملية الأساسية.

عند إنشاء تلك العملية تحتاج أن تحدد لها أنواع القيم المستخدمة حسب الترتيب التالي:

  1. نوع القيم التي سترسل للعملية
  2. نوع القيم التي سترسلها العملية إلى العملية الأساسية
  3. نوع قيم النتيجة النهائية

تلك الأنواع ليست ضرورية بل حسب حاجة التطبيق وفي حال عدم الحاجة نكتب مكانها Void. للعملية التزامنية 4 دوال كالتالي:

  • onPreExecute() تعمل في العملية الأساسية قبل ابتداء العملية الخلفية وهي اختيارية
  • doInBackground(Params) هذه هي الدالة الأهم إذ هنا ننفذ النص الذي نريد أن يعمل في الخلفية ومنه يمكن تنفيذ الأمر publishProgress(Progress) لإرسال التحديثات للعملية الأساسية.
  • onProgressUpdate(Progress) هذه الدالة تعمل في العملية الأساسية وتستقبل ما يتم ارسالة من العملية التي تعمل في الخلفية وتستخدم لتحديث البيانات وعرضها للمستخدم وهي اختيارية.
  • onPostExecute(Result) دالة اختيارية تعمل في العملية الأساسية بعد انتهاء العملية الخلفية وتستخدم الاستقبال الناتج النهائي.

سأعرض مثال بسيط واشرحه، المثال عبارة عن دالة اسمها startAsync يمكن تنفيذها بضغطة زر مثلا. الدالة تتعامل مع ثلاث عناصر في واجهة التطبيق، عنصري (textView3 و textView4) و شريط تقدم (progressBar2).

قبل تنفيذ العملية الخلفية يقوم البرنامج بتغيير عنصر نص3 إلى كلمة “بدأ” ثم يتم إنشاء عملية غير تزامنية جديدة حيث تقوم في الخلفية بالعد من 1 إلى 50 كل 100 جزء من الثانية و وإرسال الرقم الحالي إلى العملية الأساسية عن طريق publishProgress والتي بدورها تستدعي onProgressUpdate لكتابة ذلك الرقم في عنصر نص4 وكذلك تحديث نسبة الشريط المتقدم بنفس قيمة الرقم. ثم بعد النص الخاص بالعملية الخلفية نقوم مرة أخرى بتغيير عنصر نص3 والذي كتبنا به كلمة “بدأ” إلى كلمة “خطوة 2”. هذا هو النص البرمجي واسفل منه سأذكر الناتج من تنفيذه. (رابط مباشر للنص)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public void startAsync(View view) {
final TextView textView3 = (TextView) findViewById(R.id.textView3);
final TextView textView4 = (TextView) findViewById(R.id.textView4);
final ProgressBar progressBar2 = (ProgressBar) findViewById(R.id.progressBar2);

textView3.setText("بدأ");
new AsyncTask<Void, Integer, Void>() {
@Override
protected Void doInBackground(Void...nothing) {
for (int i=1 ; i<51 ; i++) {
publishProgress(i);
SystemClock.sleep(100);
}
return null;
}
protected void onProgressUpdate(Integer... value) {
textView4.setText(value\[0\].toString());
progressBar2.setProgress(value\[0\]);
};
}.execute();

textView3.setText("خطوه 2");
}

عند تنفيذ هذه الدالة ستجد أن عنصر النص4 بدأ بالعد من 1 إلى 50 بشكل منتظم وكذلك شريط التقدم يتزايد إلى أن يصل لقيمته القصوى 50 وكل ذلك دون التأثير على أداء التطبيق العام حيث يمكنك في نفس الوقت التفاعل مع التطبيق وسيستجيب بشكل طبيعي كالضغط على أزرار أو الكتابة …الخ. لكن لو تابعت عنصر نص3 في واجهة التطبيق ففي الغالب أنك لن ترى كلمة “بدأ” بل سترى كلمة “خطوة 2” بمجرد أن تكبس على الزر والسبب هو أن التطبيق كتب كلمة “بدأ” ثم قام بتشغيل العملية الخلفية لكنه لم ينتظر إلى أن تنتهي فلا حاجة لذلك بل قام مباشرة بإكمال تنفيذ النص وكتب كلمة “خطوة 2” لذلك لن تستطيع رؤية كلمة “بدأ” لأنها استبدلت بسرعة.

التطبيق الكامل يحتوي على جزئين، الجزء الاول يقوم بالعد الى 50 لكن باستخدام العملية الأساسية (الواجهة) فتجد التطبيق يتجمد ولا يمكن ضغط اي زر فيه ولا يتم تحديث العداد ولا شريط التقدم. بينما الجزء الثاني من التطبيق يستخدم AsyncTask للعد في الخلفية وارسال حالة العداد الى الواجهة ليتم تحديثها فتجد البرنامج يعمل بشكل تفاعلي كما في الصورة المتحركة التالية:

AsyncTask

النص الكامل للبرنامج موجود هنا https://github.com/fduraibi/AsyncTask_Example

ويمكنك الحصول على البرنامج (ملف apk) للتجربة من هنا https://github.com/fduraibi/AsyncTask_Example/releases/latest

هل تكتب مقالات بلغات متعددة؟
هل ترغب في أن تتغير لغة المدونة لتطابق اللغة المستخدمة في المقالة؟

مع هذه الإضافة يمكنك تغيير لغة المدونة لتطابق اللغة التي تحددها لكل مقالة. ففي حال كانت مدونتك باللغة العربية فستكون الواجهة والقوائم كذلك بالعربي لكن لو كنت تكتب كذلك مقالات بلغة أخرى كالانجليزية مثلا فستظهر المقالة للزوار بالانجليزية لكن قوائم المدونة ستضل باللغة العربية، لكن مع هذه الإضافة يمكنك تغيير ذلك بحيث تتغير لغة المدونة حسب اللغة التي حددتها للمقالة. تغير اللغة كذلك يشمل تغير الاتجاه للقراءة فللغة العربية سيكون الاتجاه من اليمين لليسار وللغات الأجنبية سيكون من اليسار لليمين.
أما الترجمات فستكون من الترجمات المقدمة مع الواجهة المستخدمة والإضافات الأخرى.

  • الإضافة لا تقدم أي ترجمة، إنما فقط تقوم باختيار الترجمة المناسبة والمدرجة مع الواجهة.
  • اللغات المتوفرة هي اللغات التي تتعرف عليها برمجية الووردبريس وتدعمها.
  • الإضافة تمكن من تغيير لغات المقالات (posts) والصفحات (pages) اما لغة الصفحة الرئيسة فهي تتبع اللغة الإفتراضية للمدونة.

رابط تحميل الإضافة من موقع ووردبريس

هذه بعض الصور التي تبين صفحة الإعدادات ونتائج العرض حسب اللغة:



Do you write posts in different languages?
Would you like your blog theme language to be the same as the language in which you wrote your post or page?

With this plugin you can set the language of your blog per post and also per page, that is if your blog is in English and you wrote a post or a page in Spanish or Arabic you can set the language of your blog to match that post’s or page’s language, so when your visitors open that post or page they will see your blog in that language. You don’t have to translate your theme and plugins if they come with translations and even it will change the direction of the view to RTL (Right-to-Left) if your language is RTL based.

  • The plugin does not provide any translations, it only changes the themes and plugins translation language if they provide there own translations.
  • The available languages are only the languages that WordPress already recognizes and supports.
  • The plugin only works for posts and pages, the front page will show in the blog default language.

Download the plugin from Wordpress site

Here are some screenshots of the plugin settings and results:



في هذا الموضوع سأحاول أن اشرح برنامج git بشكل موجز، البرنامج ضخم وذو إمكانات كثيرة اجهل جلها لكن تعلمت بعض الأساسيات التي أود مشاركتكم بها. البرنامج كان فكرة وتطوير “لينوس تورفالدز” مخترع نواة اللينكس حيث كانت الأدوات البديلة المفتوحة وقتها لا تفي بمتطلبات مشروع ضخم مثل نواة اللينكس وكانو يستخدمون تطبيق مغلق وغير مجاني.

في البداية أريد أن أوضح أن git ليس github و github عبارة عن تطبيق ويب يعتمد على git ويوفر مساحة تخزينية للمشاريع. وتستطيع عمل مشاريعك وادارتها على خادمك الخاص او خادم الشركة باستخدام git دون الحاجة لgithub.

توجد عدد من الواجهات الرسومية للتعامل مع git إما تطبيقات مستقلة أو مدمجة في تطبيقات البرمجة IDE لكن من تجربتي لا يوجد تطبيق رسومي شامل وتحتاج بين الفينة والأخري لاستخدام الأمر git من سطر الأوامر لتنفيذ مهام معينة.

الفكرة الاساسية من git

ملفات التطبيق تكون محفوظة محليا على جهاز المطور (كل مطور) والتعديلات لا تعتبر نهائية إلى بعد أن تعمل لها commit، وتلك العملية تنفذ محليا كذلك ويحتفظ جهاز المطور على الإصدارات السابقة قبل عملية ال commit لكي يستطيع الرجوع لها.

إذا رغب المطور في رفع التعديلات للخادم لكي تحفظ بشكل نهائي او ليراها باقي المطورين فان يقوم بعملية الرفع او الدفع push. في تلك الحالة يتم رفع التغييرات ودمجها مع ملفات الخادم. في حال وجود تعارض كون احد المطورين قد قام برفع ملفات مسبقا فيها تغييرات تتعارض مع التغيرات الجديدة فان الخادم سيرفض عملية الرفع الجديدة وينبه المطور عن نقاط التعارض ويطلب منه إصلاحها ثم رفع الطلب مرة اخرى.

إذا أراد احد المطورين سحب التحديثات الأخيرة من الخادم إلى جهازه محليا فانه يقوم بعملية السحب pull حيث يرسل الخادم الملفات المعدلة منذ اخر عملية سحب قام بها هذا المطور. قد يحصل تعارض كذلك أثناء عملية السحب في حال أن المطور قد قام بعمل تعديلات محلية ولم يرفعها للخادم وكان احد الملفات المسحوبة هو نفس الملف المعدل محليا فهنا يطلب التطبيق من المطور أن يقوم بعملية الدمج merge بحيث يراجع المطور التغييرات ويعدلها بما بناسب (بعض التطبيقات الرسومية تجعل عملية الدمج سهلة جدا)

  • الشرح السابقة يخص المطوريين الذين لديهم صلاحيات التعديل على نفس المشروع، لكن من نقاط القوة في نظام git هي امكانية مساهمة الغير في تطوير المشاريع المفتوحة.
المساهمة في المشاريع المفتوحة

في المشاريع المفتوحة التي تستخدم نظام القت مثل المشاريع على موقع github او نواة اللينكس او KDE فإن الجميع لديهم صلاحيات القراءة وتستطيع نسخ المشروع لجهازك باستخدام امر الاستنساخ clone مع رابط المشروع

1
$ git clone <رابط_المشروع>

فيقوم بنسخ ملفات المشروع لجهازك في مجلد بالاسم الافتراضي (يمكنك تحديد اسم اخر إذا أردت)

  • رابط مشاريع القتهب تجده موجود على نفس صفحة المشروع

و إذا أردت لاحقا تحديث ملفات المشروع فكل ما عليك هو سحب الملفات الجديدة بالأمر pull، قم بالدخول لمجلد المشروع الأساسي (ليس المجلدات الفرعية) ثم نفذ

1
$ git pull

وتستطيع تعديل الملفات (لأنها محلية) لكن لا تستطيع رفعها للخادم لأنك لا تملك صلاحيات كتابة. فالحل هو أن تقوم بإنشاء نسخة خاصة بك على الخادم وتسمى تشعُّب fork بحيث تكون خاصة بك وتستطيع الكتابة عليها لكنها ليست مرتبطة بالنسخة الرئيسة وتحتاج أن تقوم بتحديثها بنفسك إذ هي مرتبطة بملفاتك المحلية. المشروع الرئيسي يسمى upstream و مشروعك على الخادم يسمى origin وكلاهما يعتبر remote وملفاتك المحلية local

فعندما تقوم بعمل fork على القتهب فهو يقوم بإنشاء مشروع جديد ونسخ ملفات المشروع الرئيسي له دون أن يتأثر المشروع الرئيسي والتعديلات والحذف التي تقوم بها كلها على مشروعك فقط. بعد عملية التشعب fork تقوم بنسخ الملفات محليا كما فعلنا في السابق لكن الآن المشروح موجود تحت حسابك وليس حساب المطور الأساسي:

1
$ git clone <رابط_نسختك>

لتحديث ملفات مشروعك لاحقا على الخادم ليطابق المشروع الأساسي في حال تم تحديثه تقوم بسحب التعديلات من المشروع الأساسي ثم رفعها لمشروعك على الخادم:

1
2
$ git pull <رابط_المشروع_الأساسي> master
$ git push origin master

كلمة master تدل على الفرع الرئيسي وبالإمكان استخدام فروع اخرى

الفروع

كل مشروع يحتوي على فرع واحد على الأقل وهو الفرع الرئيسي ويسمى غالبا master لكن الكثير من المشاريع تحتوي على عدة فروع مثلا فرع أساسي للكود المستقر وفرع للتطوير develop و فروع اخرى لتجارب المطورين أو اختبارات مؤقتة أو حالات خاصة. والتنقل بين الفروع محليا يكون باستخدام أمر checkout

1
2
3
$ git checkout master
$ git checkout develop
...

فتستطيع عمل تغييرات ثم دمجها في فرع التطوير ثم الانتقال لفرع الرئيس وستختفي التغييرات لان تلك التغييرات دمجت فقط في فرع التطوير.

طريقة تقديم تغييراتك للمشروع الرئيسي

لنفرض انك تريد المساهمة في مشروع تطبيق تعلم العربية للاندرويد:
https://github.com/fduraibi/FunWithArabic_Android
http://aosus.org/t/topic/275

  1. قم في البداية بعمل fork من خلال القيتهب وسينشيء نسخة بنفس اسم المشروع لكن تحت حسابك انت
  2. قم بعمل نسخة محلية clone لنسختك انت (ستجد الرابط في نفس صفحة نسختك باسم حسابك وليس حساب المشروع الرئيسي)
  3. ا ذا أردت التعديل فالأفضل إنشاء فرع جديد وليكن اسم الفرع يدل على التعديل أو الإضافة لتسهل عليك إدارتها لاحقا مثلا أردت إصلاح علة في فتح قاعدة البيانات فقم بإنشاء فرع محلي كالتالي:
1
$ git checkout -b patch_fix_db

هذا الامر سينشي فرع باسم patch_fix_db وسيتحول لذلك الفرع. لمعرفة الفروع الموجودة في المشروع المحلي وأي منها مفعل اكتب التالي

1
$ git branch

ستكون المخرجات كالتالي (في حال لا يوجد سوى فرعك الجديد مع الفرع الرئيسي)

1
2
 master
* patch_fix_db
  • علامة النجمة * تدل على ان هذا الفرع هو المفعل حاليا

للانتقال لفرع اخر موجود مسبقا قم بالتالي:

1
$ git checkout <اسم_الفرع>

لحذف فرع محلي:

1
$ git branch -d <اسم_الفرع>

لنفرض انك أنشأت فرع patch_fix_db وقمت بتعديل الملفات وتريد ان ترى حالة التغييرات فنفذ الامر التالي:

1
$ git status

صورة لخرج الامر (وتجد تعليمات من git توضح طريقة تنفيذ الأوامر الافتراضية):

git-status-1 الملفات باللون الاحمر تعني انها جديدة او معدلة ولم تدرج بعد. الملف في الاعلى ملف متابع وموجود من الاصل لكن تم تعديله ولم يدرج التعديل. الملفين في الأسفل (ملف ومجلد) ملفات جديدة وغير متابعة من الأساس أي أنها ليست موجودة في الأصل.

يتم إضافة الملفات بالأمر add، فانا أريد إضافة الملف المعدل لكن لا أريد إضافة الملفيين الاخريين (لانهما مؤقتين فقط او اي سبب اخر)

1
$ git add FunWithArabic_app/src/main/java/net/fadvisor/funwitharabic/DataBaseHelper.java
  • امر git ذكي ويمكن استخدام رز tab لاستكمال اسم الملف المعدل، ضغط رز tab سيقوم بعرض الملفات المعدلة فقط.

الناتج بعد اضافة الملف:

git-status-2 نجد ان الملف تحول للون الأخضر فنحتاج بعدها الى اعتماد التعديل بالامر commit

1
$ git commit

ذلك الامر سيطلب منك كتابة شرح او تعليل تبين فيه مالذي قمت به في هذا التعديل، الشرح سيظهر في القيتهب، اضغط حرف i ثم اكتب الشرح وبعد الانتهاء اضغط زر الهروب Esc ثم اكتب **wq:** للحفظ والخروج (مثل التعامل مع برنامج vi او vim)

الآن قم برفع التغييرات لمشروعك على خادم القتهب (سيتم إنشاء فرع بنفس الاسم المدخل إذا لم يكن موجودا على الخادم):

1
$ git push origin patch_fix_db
  • سيطلب منك ادخال اسم المستخدم وكلمة السر الخاصة بالقتهب

قم بزيارة مشروعك على القتهب وسترى التالي في الجزء العلوي من الصفحة:

github pull requestقم بالضغط على زر Compare & pull request وسيقوم بعرض الاختلاف بين تعديلاتك وبين الأصل وسيطلب منك كتابة شرح للتعديل (سيتم استخدام الشرح الذي كتبته في السابق لكن تستطيع تعديله والزيادة عليه إن أردت) عندما تنتهي من التعديل اضغط على زر Create pull request هنا انتهى دورك تقريبا حيث سيفتح طلب التعديل في المشروع الأساسي ويبقى دور من لهم صلاحيات في المشروع الأساسي في مراجعة عملك وقبوله أو رفضه أو أن يطلبو منك تبرير أو تعديل في حال التعارض مع تعديلات اخرى.

  • لو قمت بتعديلات تحت نفس الفرع لاحقا فإنها ستدرج مباشرة مع الطلب القائم لذلك إذا كانت التعديلات الجديدة ليس لها علاقة بالتعديل السابق بل تخص علة أو إضافة جديدة فقم بإنشاء فرع جديد لها.

في حال قمت بتعديل لملف معين ثم أردت إلغاء التعديلات والعودة للنسخة الأصلية قبل أن تقوم بعمل commit فقم بالتالي:

1
$ git checkout -- <اسم_الملف>

لإلغاء جميع التغييرات:

1
$ git checkout -- .

لحذف فرع من على الخادم:

1
$ git push origin :<اسم_الفرع>

Nexus 4 owners, and I am one of them, were disappointed to find out that it only support 1 button headset control, so no buttons for Vol+ and Vol-. When I bought the Nexus 6P I was hoping it will have support for 3 buttons control. After I got the phone I tested it with my Samsung headset, the play/pause button and the Volume Up button work, however, Volume Down didn’t!!! I was hoping it is a faulty headset since that I can replace easily, but if it was a design mistake in the Nexus then it might be a problem forever. Luckily and after a quick Google search I found a post on reddit from someone asking if the Nexus 6P has support for 3 buttons headset. The answer was yes, so that is a good news, but one of the replies was from a reddit user “buddhra” who was having a similar problem as mine and did a further test to find out that the Nexus 6P acceptable resistance range for the Vol- doesn’t stretch to the maximum range which the Android specs allows. Here is a snapshot for part of the post:
Reddit Nexus 6P 3 button headset support problem
So I tested mine and found the resistance of the third button (Vol-) to be 630 ohms, which is within the Android specs but seems out of what the Nexus 6P can recognize. Not sure if it is a software or a hardware problem in the Nexus 6P which I won’t be able to fix easily, but I know that I can instead fix the headset itself to give the readings that the Nexus 6P expects. So I opened up the headset control, it is very small and was glued together, but using a thin blade i managed to open it up:
Opening up Samsung headset control
Zooming into the circuit board and tracing the PCB wires I figured how the resistors were connected and managed to replace one of the resistors (R3 = 356 ohms) with one of a smaller value (200 ohms) and it now works. (The resistors used in the board are size 402, however, I had one with size 603 which is a little bigger but there was enough space to fit it without any problems):
Samsung Headset Fix for Nexus 6P
All Android headset controls follow a similar way to provide the needed resistance, so your control board might differ but it should be similar.

The sensor I am building is based on an Arduino Pro Mini (Atmega328p) with ESP8266 wifi module and a sensor. It will run on batteries with a sample rate of 1 sample per hour. With such low sampling rate it is very obvious that I need to make my microcontroller and the wifi module sleep to reduce power consumption. To wake up the Atmega328p MCU from power down sleep I have to use either the Watchdog Timer (WDT) or an external interrupt. The problem with the WDT on that MCU is that the maximum sleep time it supports is 8 seconds. And to make it sleep longer you need to put the sleep statement in a loop that puts it back into sleep until it reaches a certain count value then resume working.

This is an example of such solution:

1
2
3
for (int i = 1; i <= count ; i++) {
sleep_cpu ();
}

However, in 1 hour of needed sleep the MCU will wake up 450 times!

The solution!, in my case I was able to solve this problem with the help of the wifi module which I am using. The ESP8266 has its own deep sleep mode timer that can keep the module asleep for hours or maybe days (I am not sure what is the maximum value that it supports). The deep sleep is triggered with the AT command AT+GSLP and similat to the Arduino the values that it uses is in milliseconds, so AT+GSLP=60000 will make it sleep for one minute. The ESP8266 has a dedicated pin (XPD_DCDC or GPIO16) that is used to wake up the module by wiring it directly to the reset pin of the module. So when the sleep time is over that pin will pull the reset pin low causing the module to wake-up and restart. I thought about using that pin (XPD_DCDC) to act as an external interrupt (INT0 / Pin2) to wake up the arduino so I tried it and it works. And in order to wake up the wifi module itself which is still asleep I simply connected one of the arduino pins to its reset pin and a quick High-Low-High was enough to get it up and running again.

Here is a fritzing diagram of the connections:

Arduin & ESP8266 Deep Sleep
(Note, the ESP8266 ESP-01 has no exposed connection for the wake-up pin XPD_DCDC, put I soldered a wire directly to that pin on the chip which I have learned from this Blog while on other variants of the ESP8266 wifi module like ESP-07 and ESP-12 that pin would be the GPIO16)

ESP8266 wake-up pin

Here is a code to show how it is done:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
void sleepnow() {
  // Sent sleep command for 1 hour
  sendCommand("AT+GSLP=3600000");
 
  set\_sleep\_mode (SLEEP\_MODE\_PWR_DOWN);
  sleep_enable();

  // Set INT0 to trigger on Low Level (default)
  EICRA &= ~(\_BV(ISC01) | \_BV(ISC00));
  // Enable INT0 (Pin 2 on Arduino)
  EIMSK |= _BV(INT0);

  sei();

  sleep_cpu ();

  // After wakeing up disable sleep then
// reset ESP8266.
  sleep_disable();

  pinMode(ESP8266\_Reset\_pin, OUTPUT);
  digitalWrite(ESP8266\_Reset\_pin, LOW);
  delay(100);
  digitalWrite(ESP8266\_Reset\_pin, HIGH);
  delay(100);
  // Stop setting it high to save power since
// the wifi chip has its own pull-up.
  pinMode(ESP8266\_Reset\_pin, INPUT);
}

While working on a small arduino project that will run on batteries I needed to enable deep sleep mode to reduce the energy consumption when not needed until the arduino is awaken by an external interrupt. However, I am also using the Watchdog Timer (WDT) to make sure the system will not hang up or get into in infinite loop due to some bug or unknown situation. The maximum time that the WDT on the Atmega328p supports is 8 seconds, and if 8 seconds has passed before calling wdt_reset() the WDT will reset the microcontroller, however, my boards will sleep for way longer than 8 seconds so I have to disable the WDT before going to sleep and enable it back once waken up.

Disabling WDT should be an easy thing to do by simply calling wdt_disable(), however, calling this statement also caused the atmega328 to reset!

After looking into the content of the header file “avr/wdt.h” it seems like the Arduino IDE or AVR compiler (not sure who is responsible) is not defining the correct board/chip even though I set the correct board & processor in the Arduino IDE. And the way I solved the issue was to define the correct microcontroller before including the wdt.h:

1
2
#define \_\_AVR\_ATmega328P__
#include <avr/wdt.h>

Now the code works as intended without causing a reset.

Being a lucky Android user with the luxury of Wireless charging I thought about adding it to my car since I use it at home and love it. I have seen some charging pads for cars but that means you have to place your phone in a way which makes it unusable while I want it to charge while using the phone for navigation so the best place was the phone holder. So i bought one that allows me to place the phone near an A/C vent (so it will cool down the phone during long road trip when charging and using the navigation at the same time), I also bought a bare board Qi wireless charging board from eBay (~$3.6), you can also buy the cheaper round charging pads and take the internal parts, but the bare board uses better components which I though worth the extra dollar.

Phone holder and Qi wireless charging board
The board has two microUSB ports that can be used to power it, one is soldered on the board and the other one is connected through a relatively long wire which is useful in case I needed to have a hidden power cable running behind the phone holder (which I plan to implement in the future when time permits).

The next step was to spray the back of the PCB board and the inductance coil with a color that matches my phone holder.

Black paint the whole thing
I had to trim the PCB board a little to make it smaller, so I used my rotary tool to cut a little bit of both ends that has no traces on them. I also rerouted one of the inductance coil end to go through the middle hole instead of crossing over the other wire then with hot glue and double sided tape I put all parts together.
All glued now
I used hot glue to fix the board to the phone holder with the components facing the phone mount, and used double sided tape to attach the inductance coil to the smooth back of the PCB board.
Phone holder with wireless charging
Now I have a phone mount with Qi wireless charging capability.

تقدم شركة موزيلا في متصفحها فيرفوكس للحاسوب والاندرويد خاصية جديدة بحيث تقوم بحجب شركات التتبع، إما تتبع بغرض الإعلانات او تتبع للإحصاء، و بالإضافة لحماية خصوصيتك من تلك الشركات فان التصفح سيكون اسرع كذلك والسبب أن روابط التتبع تقوم بتحميل ملفات كبيرة الحجم وصور إعلانات ليس لها علاقة بمحتوى الموقع المُزار.

خطوات التفعيل سهلة إذ عليك زيارة صفحة إعدادات فيرفوكس المتقدمة وذلك عن طريق كتابة about:config في حقل عناوين الإنترنت والضغط على مفتاح الإدخال (قد تحتاج إلى ضغط زر “I’ll be careful, I promise!” إذا ظهرت صفحة التنبيه).

في صفحة الإعدادات ستجد شريط بحث في الأعلى يساعد على إيجاد الإعدادات بسهولة. فقم بكتابة “trackingprotection” في ذلك الشريط للبحث عن الإعدادات المتعلقة بذلك الترميز ثم قم بتفعيلها كما هو موجود في الصورة التالية للحواسيب:

Firefox Tracking Protection
والصورة التالية للاندرويد (حاليا متوفرة في Firefox Beta):

Firefox Beta Tracking Protection

فيدورا 21 والتي استغرق تطويرها ما يقارب السنة حملت في طيَّاتها تغيرات جذرية على راسها تقسيم التوزيعة الى 3 نكهات: 1- خادم 2- محطة عمل (مكتبي) 3- سحابي

فيدورا 22 والتي صدرت بعدها بعدة شهور استكملت هذه النقلة بتنقيحات وتحسينات وكذلك اضافات جديدة على راسها التالي:

  • اعتماد مدير الحزم DNF كبديل ل Yum بشكل كامل.
  • اعتماد نظام الملفات XFS كنظام افتراضي في نكهة الخادم.
  • تحسين لتطبيق “قمرة القيادة” cockpit والذي يمكنك من ادارة عدة خوادم من خلال المتصفح.
  • اعتماد اصدارة واجهة قينوم 3.16 حيث تاتي بنظام تنبيها جديد ورائع وكذلك تحسين في الشكل وايضا امكانية تشغيل تطبيقات واجهات اخرى مثل كدي بحيث تظهر بشكل منسجم مع واجهة قينوم.
  • اعتماد بلازما 5 (كدي 5) كواجهة اساسية لتدويرة (spin) “فيدورا كدي” مع كيوت 5 والتي تاتي بشكل جديد وتقنيات كثيرة.
  • تحديث تدويرة “فيدورا اكسفسي” الى 4.12 حيث تقدم دعم للشاشات ذات الدقة العالية.
  • نقل بعض التدويرات المتخصصة مثل تدويرة الالعاب و الرسم والاختراق الى صفحة “المختبرات” https://labs.fedoraproject.org
  • تخصيص صفحة لنكهات فيدورا مع تدويراتها والمبنية لمعالجات ارم (ARM) كالموجودة في الراسبيري باي 2 https://arm.fedoraproject.org مع انه لايوجد دعم مباشر للرازبري باي 2 بعد لكن هناك طرق لتشغلها عليها.
  • اعتماد GCC 5.1 كحزمة اساسية.
  • تحديثات للنكهة السحابية

الترقية لاصدار 22 من اي اصدار سابق تتم عن طريق استخدام برنامج fedup

1
sudo fedup --network 22

اذا تمت العملية السابقة بدون اخطاء فقم باعادة التشغيل لتتم عملية الترقية وتحديث الحزم (قد تستغرق العملية وقتا طويلا حسب سرعة الجهاز وعدد الحزم الموجودة سابقا. اما في حال وجود اخطاء فقم باصلاح المشاكل واعادة تشغيل الامر السابق.

عند اكتمال التحديث والاقلاع في النظام الجديد قم بتنفيذ الاوامر التالية:

1
2
3
4
sudo rpm --rebuilddb
sudo dnf distro-sync --setopt=deltarpm=0
sudo dnf install rpmconf
sudo rpmconf -a

الامر الاخير rpmconf -a سيقوم بالبحث عن ملفات الاعدادات الجديدة والتي تتعارض مع ملفات قديمة معدلة فبسبب التعديلات لايقوم النظام باستبدالها بل يبقي القديم ويحفظ الجديد بامتداد rpmnew فالامر هذا سيقوم بعرضها ويقدم لك عدة خيارات الاول ان تستخدم الجديد، الثاني ان تبقي القديم، الثالث ان يعرض لك الفروقات بينهما لكي تقرر، الرابع ان يدمج الملفان والخامس اعتقد يقوم بتاجيل القرار والاخير يتجاهل الملف. انا شخصيا اختار الخيار الاول للملفات التي لم اقم انا بتعديلها واما ما قمت بتعديله فاحاول عرض التغييرات ودمج ما احتاج من القديم مع الجديد.

* الخط الجديد المعتمد في الطرفية لايدعم المحرف العربي بعد، لذلك ستحتاج لتغيير الخط الى نوع اخر اذا كنت تحتاج العربية. الصفحة التالية تبين بعض التغييرات و المشاكل التي قد تواجهها اثناء الترقية او التحميل الجديد http://fedoraproject.org/wiki/Common_F22_bugs

في الفيديو التالي قمت بشرح عملي لطريقة تحويل الكاميرات إلى كاميرات قابلة للتصوير الليلي.
معظم الكاميرات بطبيعتها قادره على التصوير الليلي وهو الذي يعتمد على التقاط الإضاءة تحت الحمراء لكن ونظرا لكون تلك الإضاءة تؤثر على جودة ألوان الصور والتصوير في النهار فإن الشركات تقوم بوضع فلتر لحجب تلك الإشعاعات. بينما كاميرات التصوير المتخصصة فهي تحتوي على فلتر متحرك يتحكم فيه حساس قوة الإضاءة فيفعل في الليل ويعطل في النهار.

باختصار الفيديو يوضح طريقة رخيصة لتمكن تقريباً أي الكاميرة من التصوير في الليل، مشاهدة ممتعة:

التصوير الليلي

في بعض توزيعات اللينكس مثل فيدورا نجد أن بعض مشغلات أو مرمزات الفيديو معطلة بشكل افتراضي إما لكونها لا تزال في مراحل التطوير أو بسبب المخاوف من حقوق التسجيل وبراءات الاختراع. مهما كانت الأسباب فانك ستجد أن تشغيل مقاطع الفيديو التي تستخدم تلك التراميز في بعض المواقع غير ممكن حتى لو كنت قد جملت جميع حزم التراميز المطلوبة (مثل تراميز gstreamer وغيرها).

من اهم المواقع المختصة بالفيديو موقع يوتيوب حيث يوفر خاصية استخدام مشغل أفلام يعمل بتقنية HTML5 الحديثة بدلا من الفلاش إذ إنها اكثر أمنا واسرع واخف على المعالج من مشغلات الفلاش وحيث إن الفلاش يستخدم في الغالب من قبل شركات الإعلانات في تعقب تنقلاتك وعرض الإعلانات لك وكذلك من قبل الهاكرز في استغلال ثغراته. عند زيارة صفحة اليوتيوب https://www.youtube.com/html5 الخاصة بتفعيل مشغل HTML5 تقوم الصفحة بفحص المتصفح لمعرفة التراميز التي يدعمها وكانت الصفحة تظهر لي بالشكل التالي:

Firefox on Linux Youtube HTML5 Player

فالعناصر باللون الأحمر تعني أن تلك المرمزات غير متوفرة مما جعل مشغل HTML5 يعرض الفديوات بوضوح محدود في بعض الأحيان مثلا دقة 720HD كحد أقصى أو أن لا تكون الفديوات متوفرة بدون تلك التراميز.

الحل كان سهلا جدا فجميع حزم التراميز قد قمت بتثبيتها سابقا من مخازن RPM Fusion الخاصة بتوزيعة فيدورا وكنت في حاجة لتفعيلها في فيرفوكس فقط، خطوات التفعيل سهلة اذ عليك زيارة صفحة إعدادات فيرفوكس المتقدمة وذلك عن طريق كتابة about:config في حقل عناوين الإنترنت والضغط على مفتاح الإدخال (قد تحتاج إلى ضغط زر “I’ll be careful, I promise!” إذا ظهرت صفحة التنبيه).

في صفحة الإعدادات ستجد شريط بحث في الأعلى يساعد على إيجاد الإعدادات بسهولة. فقم بكتابة “h264” في ذلك الشريط للبحث عن الإعدادات المتعلقة بذلك الترميز ثم قم بتفعيلها كما هو موجود في الصورة التالية:

Firefox H264 decoder settings
قم بعد ذلك بالبحث عن الإعدادات المتعلقة ب “mp4” وفعلها كالصورة التالية:

firefox mediasource settings
أخيرا ابحث عن إعدادات “mediasource” وفعلها كالتالي:
firefox mp4 settings
بعد الانتهاء من الإعدادات قم بزيارة صفحة اليوتيوب الخاصة بمشغل فيدو HTML5 و إذا كانت التغييرات صحيحة مع توفر المرمزات المطلوبة ستكون بالشكل التالي:

firefox youtube html5

الآن يمكنك تفعيل المشغل بشكل افتراضي والاستمتاع بيوتيوب اسرع مع القدرة على تشغيل الفديوات بجميع التراميز.

In some Linux distributions such as Fedora the amazing browser Firefox will ship with some of the video decoders turned off by default, some of it is due to the decoder being in unstable stage or due to some copyrights/patents concerns. In either way trying to play videos that uses one of these formats won’t work even if you have all the packages installed (such as the good, the bad and the ugly gstreamer plugins).

I wanted to make youtube use the HTML5 player instead of the old flash player which is mostly used to track you, show ads and by hackers. Visiting the youtube html5 player page https://www.youtube.com/html5 used to be like this:

Firefox on Linux Youtube HTML5 Player
The items in red means they are missing which caused some youtube videos not be available in HTML5 player, or for the resolution to be limited mostly to a maximum of 720 or lower.

The solution is very simple after installing all needed packages, I got all my decoders for Fedora from RPM Fusion repos, and it is under the Firefox low level configuration page which you can get to by typing about:config in the URL box + Enter (click on the button “I’ll be careful, I promise!” if you see a warning page).

In the configuration page there is a search box at the top that makes it easy to find the settings which you need to change. So first type in “h264” and enable the disabled settings as you see in the picture below:

Firefox H264 decoder settings
Then type in “mp4” and do the same as the picture below:
firefox mediasource settings
Finally, search for “mediasource” and enable it as follows:
firefox mp4 settings
When you are done with the settings revisit the youtube html5 page and it should look like this:
firefox youtube html5
Now you can enable the HTML5 player as a default player and enjoy a faster youtube thanks to HTML5 and have the ability to play all videos in all formats.

When my son wanted me to buy him a toy robot I asked him if he would like to build one with me instead, he was so interested so I told him that it will be a car robot with two motorized wheels controlled from the phone over bluetooth and he needs to sketch the design then build it using Lego blocks.








And this is the android app that controls the robot/car, each slider controls the speed and direction of each wheel (the link to the app and its source code can be found at the end of this post):

While he was busy with the sketches I started looking for parts, so I went to eBay and found these wheels


They come in two speeds, I ordered the slower one since it has more torque. These wheel will need something to control them since the Arduino micro-controller is not strong enough to drive them with enough current so wanted to build an H-bridge using transistors (which I have already) but I found a module based on the L298 chip which is very cheap and has a voltage regulator too, awesome.


Next was the bluetooth module, and I went for the HC-06 which is easy to use and also cheap.

Bluetooth HC06-2
And finally is of course the Arduino board, I got the Arduino Pro Mini for its small size and low cost.

arduino_mini
Even though I actually used the Arduino Uno for the development since it is much easier to upload the code and fix mistakes.

I got them all from eBay with the cheapest price I can get so some took about a month to arrive and I wasn’t in a hurry:

2x Car Robot Wheels: $6.00
L298N Dual H Bridge: $3.00
HC-06 Bluetooth Module: $4.00
Arduino Pro Mini: $2.60
40pin Dupont Wires: $1.50
Total = about $17

You will also need an Android Phone or tablet, any with Android 3.0 and up should do. Lego blocks or anything to use for the car body.

Here is a video we made showing how to use the app and explaining the car we built and its main parts:


To get the Andriod app click on the Google play icon below:
Android-app-on-google-play
for the Android source code click here and for the Arduino code click here

I got myself on of those cheap Bluetooth OBDII dongles but it didn’t work in my car (2005 Dodge), it simply couldn’t detect the protocol which is SAE J1850 VPW used on most Chrysler/Dodge I believe before 2008. So I took it apart and as you can see in the picture it has two stacked circuit boards the one of top has a bluetooth chip (BEKEN BK3231Q) and a CAN protocol transceiver from NXP (TJA1040)

Fake ELM327
The flip side of the top board contains a CAN controller (MCP2515) from Microchip.
CAM controller MCP2515

However, and what is surprising is the bottom board which contains only voltage regulators for 5v and 3.3v and most of the OBD-II pins are not even connected!
OBD-II connections

Let’s compare the connected pins to the pinout of the OBD-II connector in the image below

OBD2_pinout

So the 12v VCC (pin 16 in red) is connected and the two ground pins (pin 4 & 5 in gray). How about the different OBD2 protocols? let’s see:

  • CAN (ISO15765) used pin 6 & 14 (green color) and they are connected.
  • ISO9141/14230 uses pin 7 & 15 (yellow color) and they are connected.
  • J1850 PWM uses pin 2 & 10 (blue color) and they are NOT connected.
  • J1850 VPW uses only pin 2 (blue color) and it is NOT connected.

So it is clear that this will not support any of the J1850 protocols which are used by most old American car makers (Chrysler/Dodge/Jeep, Ford, GM), luckily I think all new cars (2008+) are using the CAN protocol which is the newest among the others.


Update: Another fake OBD2 reader

I bought another Bluetooth OBD-2 reader that is slightly larger than the one I got before hoping it would have the parts needed to support all protocols and since the seller also claim it does. (Spoiler: I got a full refund).

obd2_01

Guess what? It is exactly the same as the other one, it didn’t work on both of my cars so I opened it up and unsurprisingly it has the same guts (same chips) in slightly different arrangement. obd2_02
obd2_03
obd2_04

I think having full support is a little too costly even for the Chinese manufacturer, also don’t be fooled by some sellers on Amazon who sell the same exact models for $15+, increasing the price won’t make it work. I also won’t recommend using these basic devices in your car since they don’t have Bluetooth authentication! and any nearby hacker can connect to them and have full access to your car CAN bus and do whatever your car manufacturer has allowed on that bus. You might have heard about the recent car hacks like disabling the breaks and such.

So if you are looking for something that works with all protocols and also safe to use I would go with trusted brands that have been tested by many users, e.g. “OBDLink LX Bluetooth“ which looks like the perfect solution, good quality build, support for all ODB2 protocols, sleep mode and has a security button that need to be pressed to allow Bluetooth pairing I have not used it though since it is a little expensive.

بعد مخالطة الكثير من اللينكساويين وجدت أن الأغلب متمسك بتوزيعة أو بأخرى لسبب ما، بعض الأسباب تقني وبعضها شخصي. لكني وجدت عند البعض نوع قد يكون فريد من القناعة بكون تلك التوزيعة التي يستخدمها تتفوق على غيرها وليس هناك ما هو أفضل منها. فعندما يبدأ حوار التوزيعات تجد احدهم يقاطع الجميع ويبدأ بالحديث عن مزايا توزيعته وكأن ما يتلوه هو قرآن لا يحتمل النقاش فيمجد مثلا ثباتها وسهولة استخدامها واستقرارها وأنها لا يعلوها احد ويذكر أمجادها حتى يضن السامع أن من يستخدم غيرها إنما هو ضال لم ير سبيل الرشاد بعد!. لحظة قد لا يكونون لهذه الدرجة من التعصب اللينكساوي لكن تجد فيهم نفحات منه.

النقاش أحيانا يكون صحي، فيساعد الآخرين على اكتشاف المميزات والعيوب لكن بشرط أن لا يكون نقاش تعصبي بحت وان يتم ذكر المميزات والعيوب بمنطقية وموضوعية ولنتذكر دائما أن ما قد تراه عيبا قد يراه غيرك ميزة. فالبعض يفضل توزيعات بطيئة التطور لأنها مستقرة بينما آخر قد يتغاضى عن مواجهة بعض العلل والمشاكل في سبيل الحصول على أحدث التقنيات حتى وإن لم تنضج بعد.

في بعض الأحيان قد يفشل نظام اللينكس في التعرف على بعض أنماط أو دقة شاشة العرض والأسباب قد تعود إلى مشاكل في معرفات كرت الشاشة أو مشاكل في الشاشة نفسها و أحيانا تكون بسبب كبل الشاشة خصوصا عند استخدام التقنيات التماثلية مثل VGA. التقنيات الرقمية مثل HDMI و DisplayPort اقل عرضة بكثير لمثل هذه المشاكل.

في هذا الموضوع سوف اشرح طريقة إضافة نمط مدعوم من قبل الشاشة لكن لم يستطع النظام التعرف عليه [* هذه الطريقة لن تسمح باستخدام دقة أعلى أو اقل مما تدعمه الشاشة لان تلك حدود مصنعية]. لنفرض أن شاشتك تدعم دقة عرض [1920x1080] وتسمى Full HD و FHD واحيانا 2K ولكن عند تشغيل النظام لم تعرف عليها واستخدم دقة اقل مثلا [1280x1024]. قم أولا بتنفيذ أمر xrandr لعرض الأنماط التي تعرف عليها:

1
2
3
4
5
6
7
8
9
$ xrandr
Screen 0: minimum 320 x 200, current 1280 x 1024, maximum 1280 x 1024
VGA1 connected 1280x1024+0+0 (normal left inverted right x axis y axis) 510mm x 287mm
   1280x1024     75.02    60.02*
   1024x768      75.08    60.00  
   800x600       75.00    60.32  
   640x480       75.00    60.00  
HDMI1 disconnected (normal left inverted right x axis y axis)
DP1 disconnected (normal left inverted right x axis y axis)

في الخرج السابق نجد انه لم يتعرف على النمط المطلوب مع أن الشاشة تدعمه وكذلك تعرفنا على أن الشاشة متصلة عن طريق منفذ VGA1 وان النمط الافتراضي (انظر إلى علامة النجمة *) هو [1280x1024].

نقوم بعدها بإضافة النمط المطلوب: أولا نقوم باستخراج إعدادات الشاشة المطابقة لذلك النمط باستخدام أمر cvt مع الدقة المطلوبة، نفذ التالي:

1
2
3
$ cvt 1920 1080
\# 1920x1080 59.96 Hz (CVT 2.07M9) hsync: 67.16 kHz; pclk: 173.00 MHz
Modeline "1920x1080_60.00" 173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync +vsync

السطر الثاني هو المهم و ما بين علامتي التنصيص “1920x1080_60.00” هو اسم النمط ويمكن تغييره (بل انصح بتغييره إلى “1920x1080” وذلك بحذف الجزء الأخير المتعلق بتردد الشاشة لكي لا يسبب مشكلة لاحقا)

بعد ذلك نقوم بإضافة النمط الجديد باستخدام الناتج من السطر الثاني أعلاه لكن بدون كلمة Modeline مع تغيير الاسم ثم ربطة مع منفذ الشاشة التي نستخدمها:

1
2
3
$ xrandr --newmode "1920x1080" 173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync +vsync

$ xrandr --addmode VGA1 "1920x1080"

لو ظهرت رسالة خطا فتأكد من صحت البيانات المدخلة وان الشاشة تدعم هذا النمط، أما إذا لم تظهر أي رسائل فالخطوة التالية هي تجربة النمط الجديد والتحقق من صلاحيته مع الشاشة بالأمر التالي:

1
$ xrandr --output VGA1 --mode "1920x1080"

بعد تنفيذ الأمر السابق هناك احتمالان، الأول هو أن تعمل الشاشة بشكل سليم مع النمط الجديد وتستطيع استكمال العمل أما الاحتمال الثاني فهو أن لا تكون الشاشة متوافقة مع النمط الجديد فتظهر الشاشة سوداء أو صورة غير مقروءة فهنا يلزم إعادة تشغيل الواجهة الرسومية أو إعادة تشغيل الجهاز. توجد طريقة أخرى لتجنب إعادة التشغيل وهي تجربة الأمر السابق ثم الانتظار لبعض الوقت ثم إعادة الشاشة لنمط معروف توافقه مسبقا كالتالي (ثلاث أوامر في سطر واحد):

1
$ xrandr --output VGA1 --mode "1920x1080" ; sleep 5 ; xrandr --output VGA1 --mode "1280x1024"

الأمر الأول ينفذ النمط الجديد التجريبي، والأمر الثاني ينتظر 5 ثواني خلالها تستطيع الحكم إذا كان النمط في الأمر الأول ناجحا أم لا والأمر الأخير يعيد النمط الافتراضي (راجع أول المقالة بخصوص النمط الافتراضي) لكي لا نضطر لإعادة التشغيل في حال كان النمط غير مناسب للشاشة.

في حال نجح الأمر السابق وعملت الشاشة مع النمط الجديد فيجب إضافته إلى إعدادات النظام لكي يعمل حتى بعد إعادة التشغيل، حيث إن الأمر السابق لا يحفظ الإعدادات الا في حال كان الاستخدام مؤقتا كربط الحاسوب مع جهاز عرض “بروجيتور”. في حال الرغبة في تثبيت الامر بالإمكان جمع الأوامر السابقة في ملف script وجعلها تنفذ بعد تشغيل الواجهة الرسومية لكن لا انصح بها او اتبعاع الطريقة الصحيحة وهي باضافة ملف يالنمط الجديد لمجلد اعدادات X11.

قم بانشاء ملف باسم “10-monitor.conf” تحت مجلد /etc/X11/xorg.conf.d/ (تحتاج صلاحيات روت للكتابة في ذلك المجلد) واكتب بداخل الملف التالي:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Section "Monitor"
    Identifier             "Monitor0"
    Modeline "1920x1080"  173.00  1920 2048 2248 2576  1080 1083 1088 1120 -hsync +vsync
EndSection

Section "Screen"
    Identifier             "Screen0"
    Device                 "VGA1"
    Monitor                "Monitor0"
    DefaultDepth           24
    SubSection             "Display"
        Depth              24
        Modes              "1920x1080"
    EndSubSection
EndSection

يجب مراعاة تغيير النمط “1920x1080” واسم منفذ الشاشة “VGA1” لما يناسبك ثم قم بإعادة التشغيل. في حال وجود مشكلة بعد إعادة التشغيل ادخل على النظام من الطرفية “Terminal” واحذف الملف السابق.