יום רביעי, 13 במרץ 2013

Webkit Guide




הדפדפנים נהפכים לחלק אינטגרלי כמעט בכול אפליקציה שמשתחררת באיזה שוק, האם פיתוח ב Native Code הולך לחלוף מהעולם ואת מקומו יחליפו דפי 5 Html ו Javascript? האמת שאין סיבה שלא, עדיין צריך לתת כבוד ל Native Code כי סביר שעדיין יהיה דברים שניתן לעשות רק איתו אבל הרעיון מעניין מאוד כי אחרי הכל Html ו Javascript שפות מאוד פופולריות ומאפשרות למפתחים שלא שולטים בשפת ה Native לכתוב אפליקציות על בסיס מנוע ה Webkit שקיים במערכות ההפעלה של הפלאפונים , הטאבלטים וכו', יש המון סביבות פיתוח שמאפשרות כתיבת אפליקציות שמוגדרת Cross Platfrom בעזרת שימוש ב Webkit ובכך לשמור על קוד אחיד עבור כל המערכות בשוק.

מאחורי כל דפדפן עומד מנוע שמפענח את הקוד למה שאנחנו רואים במסך, Webkit המנוע המפורסם ביותר וזה שעומד מאחורי ה Chrome וה Safari ,כנראה שזה המנוע הנפוץ בעולם וניתן להשתמש בו בלפטפורמות רבות במיוחד בתחום ה Mobile , לכן חשוב מאוד להכיר אותו,הוא יכול לחסוך לנו בדרך לאפליקציה המושלמת שתוכל לקפוץ בקלות ממערכת למערכת.

GTK

פלטפורמה ליצירת תוכניות מבוססות חלונות בדומה ל Windows Forms של Microsoft אבל הרבה יותר מגניבה, GTK היא פלטפורה שתומכת בהמון סביבות, שפות וכמובן קוד פתוח, שילוב של GTK עם Webkit נותן את הדפדפן המושלם שיכול לרוץ על מספר מערכות הפעלה שונות בניגוד ל Explorer עם .NET, ויכול לעבוד על מספר ארכיטקטורות מעבד שונות (Arm,x86,PPC), אז אם בא לכם להכניס דפדפן נוסף לשוק אל תוותרו על השילוב בינהם.

MYBROWSER

התוכנית היא דפדפן מבוסס Webkit ו Gtk ורצה בסביבת Linux - Fedora , על מנת להריץ את הקוד יש להוריד את הספריות של ה GTK ו Webkit.

#:yum install webkitgtk-devel webkitgtk gtk+ gtk+-devel



לאחר התקנת הספריות, נגדיר את ה Compiler וה Linker ב Eclipse



יש להשתמש בכלי Pkg-config שמגדיר הגדרות ל Compiler ניתן להוסיף תוסף ב Eclipse ב Help - > Eclipse Market Place.




#include <gtk/gtk.h>
#include <webkit/webkit.h>

//set gui items
static GtkWidget* main_window;

//url box
static GtkWidget* uri_entry;

//status bar
static GtkStatusbar* main_statusbar;

//the webkit view
static WebKitWebView* web_view;

//window title
static gchar* main_title;

//progress of the loading page
static gint load_progress;

//toolbar descriptor
static guint status_context_id;

//toolbar
static GtkWidget* toolbar;

//entire instance
static GtkWidget* vbox;

static void webkit_load (GtkWidget* entry, gpointer data)
 {
  //load url to webkit
  webkit_handle_switch(entry,data,1);
 }

 static void webkit_stop(GtkWidget* widget, gpointer data)
 {
//stop webkit
  webkit_handle_switch(widget,data,0);
 }

//finish load page signal
static void load_finished_handle(WebKitWebView *web_view, WebKitWebFrame *web_frame, gpointer data) {

webkit_handle_switch(web_view,data,0);

 }

//switch between signals
 void webkit_handle_switch(GtkWidget* entry, gpointer data,gint mode)
{
//load mode
if(mode == 1)
{

const gchar* uri = gtk_entry_get_text (GTK_ENTRY (entry));
//load url to webkit
   webkit_web_view_open (web_view, uri);

  //get and remove item[3] from toolbar container
  GtkToolItem* item = gtk_toolbar_get_nth_item(toolbar,3) ;
  gtk_container_remove(GTK_TOOLBAR (toolbar),item);

  //create new button from gtk theme pack
  item = gtk_tool_button_new_from_stock (GTK_STOCK_STOP);
  //attach to clicked signal
  g_signal_connect_swapped (G_OBJECT (item), "clicked", G_CALLBACK (webkit_stop), (gpointer)uri_entry);

  //insert new item to toolbar container positon 3
  gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, 3);
  //redraw toolbar
  gtk_widget_show_all(toolbar);
}
else
{
//stop webkit
webkit_web_view_stop_loading(web_view);

//get and remove item[3] from toolbar container
GtkToolItem* item = gtk_toolbar_get_nth_item(toolbar,3) ;
gtk_container_remove(GTK_TOOLBAR (toolbar),item);

//create new button from gtk theme pack
item = gtk_tool_button_new_from_stock (GTK_STOCK_OK);
//attach to clicked signal
g_signal_connect_swapped (G_OBJECT (item), "clicked", G_CALLBACK (webkit_load), (gpointer)uri_entry);

//insert new item to toolbar container positon 3
        gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, 3);
        //redraw toolbar
gtk_widget_show_all(toolbar);

}


}


static void update_title (GtkWindow* window)
{
    GString* string = g_string_new (main_title);
    g_string_append (string, " - MYBROWSER");
    if (load_progress < 100)
        g_string_append_printf (string, " (%d%%)", load_progress);
    gchar* title = g_string_free (string, FALSE);
    gtk_window_set_title (window, title);
    g_free (title);
}

static void link_hover_handle (WebKitWebView* page, const gchar* title, const gchar* link, gpointer data)
{
   //show link from webkit to status bar
    gtk_statusbar_pop (main_statusbar, status_context_id);
    if (link)
        gtk_statusbar_push (main_statusbar, status_context_id, link);
}

//webkit page title changed handle, change window title
static void title_change_handle (WebKitWebView* web_view, WebKitWebFrame* web_frame, const gchar* title, gpointer data)
{
    if (main_title)
         g_free (main_title);

     main_title = g_strdup (title);
     update_title (GTK_WINDOW (main_window));
}

//loading process webkit handle
static void progress_change_handle (WebKitWebView* page, gint progress, gpointer data)
{
   //update progress in the main window bar
    load_progress = progress;
    update_title (GTK_WINDOW (main_window));
}

//load event webkit handler
static void load_commit_handle (WebKitWebView* page, WebKitWebFrame* frame, gpointer data)
{
  //read the url ftom webkit
    const gchar* uri = webkit_web_frame_get_uri(frame);
    //update the textbox in the toolbar
     if (uri)
         gtk_entry_set_text (GTK_ENTRY (uri_entry), uri);
}

//kill the application
static void gtk_destory (GtkWidget* widget, gpointer data)
{
       gtk_main_quit ();
}

static void btn_backward_click(GtkWidget* widget, gpointer data)
{
//rise to webkit go back
webkit_web_view_go_back (web_view);
}

static void btn_forward_click (GtkWidget* widget, gpointer data)
{
//rise to webkit go forward
          webkit_web_view_go_forward (web_view);
}

static GtkWidget* init_browser ()
{
//create scroll bar object
         GtkWidget* scrolled_window = gtk_scrolled_window_new (NULL, NULL);
         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
         GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);

         //create webkit component
          web_view = WEBKIT_WEB_VIEW (webkit_web_view_new ());
          gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET (web_view));

         //attach to webkit events
         g_signal_connect (G_OBJECT (web_view), "title-changed", G_CALLBACK (title_change_handle),    web_view);
    g_signal_connect (G_OBJECT (web_view), "load-progress-changed", G_CALLBACK (progress_change_handle), web_view);
    g_signal_connect (G_OBJECT (web_view), "load-committed", G_CALLBACK (load_commit_handle), web_view);
    g_signal_connect (G_OBJECT (web_view), "hovering-over-link", G_CALLBACK (link_hover_handle), web_view);
    g_signal_connect (G_OBJECT (web_view), "load-finished", G_CALLBACK (load_finished_handle), web_view);

    return scrolled_window;
}

static GtkWidget* init_statusbar ()
{
    main_statusbar = GTK_STATUSBAR (gtk_statusbar_new ());
    status_context_id = gtk_statusbar_get_context_id (main_statusbar, "Link Hover");

    return (GtkWidget*)main_statusbar;
}

//create toolbar inside window
static GtkWidget* init_toolbar ()
{
  toolbar = gtk_toolbar_new ();

  //position the toolbar
    gtk_toolbar_set_orientation (GTK_TOOLBAR (toolbar), GTK_ORIENTATION_HORIZONTAL);
    gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_BOTH_HORIZ);

    GtkToolItem* item;

    //back button -> get image from GTK stock, connect to signal of clicked
    item = gtk_tool_button_new_from_stock (GTK_STOCK_GO_BACK);
    g_signal_connect (G_OBJECT (item), "clicked", G_CALLBACK (btn_backward_click), NULL);
    gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);

    //forward button -> get image from GTK stock, connect to signal of clicked
    item = gtk_tool_button_new_from_stock (GTK_STOCK_GO_FORWARD);
    g_signal_connect (G_OBJECT (item), "clicked", G_CALLBACK (btn_forward_click), NULL);
    gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);

    //url text box
    item = gtk_tool_item_new ();
    gtk_tool_item_set_expand (item, TRUE);
    uri_entry = gtk_entry_new ();
    gtk_entry_set_text(uri_entry,"https://www.google.co.il");
    gtk_container_add (GTK_CONTAINER (item), uri_entry);
    g_signal_connect (G_OBJECT (uri_entry), "activate", G_CALLBACK (webkit_load), NULL);
    gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);

    //load button -> get image from GTK stock, connect to signal of clicked
    item = gtk_tool_button_new_from_stock (GTK_STOCK_OK);
    g_signal_connect_swapped (G_OBJECT (item), "clicked", G_CALLBACK (webkit_load), (gpointer)uri_entry);
    gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);

    return toolbar;
}

static GtkWidget* init_window ()
{
  //create main window
    GtkWidget* window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_window_set_default_size (GTK_WINDOW (window), 800, 600);
    gtk_widget_set_name (window, "Webkit");

    //connect to destroy signal
    g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (gtk_destory), NULL);

    return window;
}

 int main (int argc, char *argv[])
 {

gtk_init (&argc, &argv);

vbox = gtk_vbox_new (FALSE, 0);

//set containers in instance
gtk_box_pack_start (GTK_BOX (vbox), init_toolbar (), FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (vbox), init_browser (), TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (vbox), init_statusbar (), FALSE, FALSE, 0);

//create main window add as container to instance
main_window = init_window ();
gtk_container_add (GTK_CONTAINER (main_window), vbox);

gchar* uri = "http://";

webkit_web_view_open (web_view, uri);

gtk_widget_grab_focus (GTK_WIDGET (web_view));

//show window
gtk_widget_show_all (main_window);
gtk_main ();

    return 0;
 }




בפיתוח ב .Net אפשר להשתמש ב Webkit . NET שמאוד חברותי, וב Android ניתן לכתוב אפליקציות שלמות על בסיס ה Webkit שמגיע במערכת ההפעלה כמו שהסברתי באחד המאמרים בבלוג.

סיכום:

פרוייקט ה Webkit בהחלט הצליח והיכולת לעבוד על כל פלטפורמה הפכה אותו לנפוץ ופופולרי, הרבה אפליקציות נעזרות בו והוא עשה סוג של מהפכה בעולם ה Gui שמאפשר להשתמש ב Webkit כשכבה עיצובית בפרויקטים שלנו.

קישורים:
GTK project

WebKit

תמשיכו לדפדף.

יום שישי, 1 במרץ 2013

Arduino Relay Shield Guide


את המאמר הזה אני רוצה לכתוב כבר המון זמן , הוא חשוב מאוד והוא מראה לנו צד נוסף ב Arduino  ,עד עכשיו חיברנו חיישנים, דיברנו עם המחשב  ועשינו כמה טריקים אבל עכשיו העסק נהפך ליצירתי יותר,  תארו לכם שבעזרת ה Arduino אתם מדליקים מנוע חשמלי או את האור בסלון?

שימו לב - סכנת התחשמלות! - עבודה עם חשמל שמעבר ל 5 V של ה USB שאנחנו רגילים אליו עד כה,  לכן יש לקחת את הנושא ברצינות ולהשתמש בספקי כח של עד 12 V ראו הוזהרתם!

דרישות:
  • Arduino Uno
  • Relay Shield
  • ספק כוח 12 V.
  • מאוורר מחשב ישן 12 V. 


Relay Shield




את שלי קניתי מחברת iteadstudio.com והוא עולה בסביבות 16 דולר, יש עליו 2 Relay ו 2 MOS switch שמאפשרים להעביר זרם מקסימלי של עד 20 V , אפשר לקבוע זרם של 5 V עבור כל ערוץ בעזרת שינוי של ה Jumpers שעל גבי הכרטיס, בנוסף יש עוד מספר חיבורים שמאפשרים לנו לחבר חיישנים ותושבת Xbee Module עבור RF וגם אפשרות לחבר מקור כוח חיצוני.

Relay - מתג מכני שמנתב את הזרם החשמלי בעזרת מגנטים.

MOS switch - מתג אלקטרוני שמשנה את המיתוג בעזרת Transistor, אבל מוגבל בזרם שיכול לעבור דרכו עד ל 60 V.

ל Arduino כניסת חשמל ע"ג הלוח שמאפשרת לנו לחבר ספקי כוח עד ל 20 V ובעזרת ה Shield ניתן לחבר מוצרים שצריכת החשמל שלהם גדולה מ 5 V , ניתן להפעיל סוגים שונים של מנועים , מנורות, מאווררים וכו' מומלץ לעבוד עם Multimeter שנוכל לבדוק את רמת הזרם של הערוצים לפני שאתם מחברים משהו.


קוד:

פינים 4 -7 מאפשרים להפעיל או לכבות את ה Relays שעל הלוח.


void setup()
{
  //set pins as output
  pinMode(4,OUTPUT);
  pinMode(5,OUTPUT);
  pinMode(6,OUTPUT);
  pinMode(7,OUTPUT);
}

void loop()
{
  //set all pins to high, active relays
  digitalWrite(4,HIGH);
  digitalWrite(5,HIGH);
  digitalWrite(6,HIGH);
  digitalWrite(7,HIGH);
  delay(1000);
  
  //set 2 pins to low just for fun
  digitalWrite(4,LOW);
 digitalWrite(5,LOW);
  digitalWrite(6,HIGH);
  digitalWrite(7,HIGH);
  delay(1000);
  
  //set all pins to low
  digitalWrite(4,LOW);
  digitalWrite(5,LOW);
  digitalWrite(6,LOW);
  digitalWrite(7,LOW);
  delay(1000);  
}



מבנה סופי:




סיכום:

עבודה עם Relay Shield מאפשרת לנו לחבר רכיבים שצריכת החשמל שלהם גבוהה ולהרחיב את התחומים בהם ניתן להשתמש ב Arduino חשוב לי להדגיש ש Relay Shield לא מאפשר לנו לשלוט על טווח הזרם שעובר בו וניתן לשחק רק בין 5 V ובין הזרם שמגיע מהספק לכן הוא לא מתאים למנועים שנדרשת שליטה על מהירות, עבור פרויקטים מהסוג הזה נשתמש ב Motor Shield שעליו אכתוב בהמשך.