Category: Developer

งานพัฒนาระบบ, เขียนโปรแกรม

  • ตรวจสอบการสะกดคำด้วย NHunspell (.Net Framework Library)

    สำหรับแอปพลิเคชันที่มีส่วนค้นหาแล้วนั้น หนีไม่พ้นคำถามจากผู้ใช้ว่า ถ้าสะกดคำผิดจะค้นเจอมั้ย (ก็ไม่เจอซิครับ) พร้อมยกตัวอย่างความสามารถในการแก้คำผิดของ Google, Bing ให้ฟัง สำหรับนักพัฒนาตัวคนเดียว หรือทีมงานเล็กๆ ที่ไม่สามารถใช้แนวทาง API แบบต้องมีค่าใช้จ่าย หรือ Machine Learning ที่ต้องใช้ความรู้เฉพาะด้าน ผมก็มี Library ขนาดเล็กที่อาศัยวิธีการทางสถิติ และไฟล์คลังคำศัพท์ (Dictionary) มาใช้งานไปก่อนครับ โดยได้ทำการทดสอบประสิทธิภาพเปรียบเทียบกับ PyThaiNLP, WeCantSpell.Hunspell มาแล้วทั้งในด้านความเร็ว และความถูกต้อง พบว่าดีที่สุด นั้นคือ NHunspell

    ขั้นตอนการนำมาใช้งาน

    ในตัวอย่าง เป็นการนำมาใช้งานร่วมกับ Console Application

    1.เปิด Nuget Manager ด้วยการ คลิกขวาที่ชื่อโปรเจค เลือก Manage Nuget Packages

    2.ค้นหา NHunspell เลือก Install

    3.สร้างโฟลเดอร์สำหรับเก็บไฟล์ Dictionary โดยสามารถดาวส์โหลดได้จาก https://github.com/LibreOffice/dictionaries นำไปวางไว้ที่ [ProjectPath]/bin/Debug

    4.สร้างโฟลเดอร์สำหรับเก็บไฟล์คำตัวอย่าง sentense_list.txt โดยมีบรรทัดละ 1 คำ เพื่อทำการโหลดข้อมูลเข้ามาให้ Library ประมวลผล และเก็บไฟล์ผลลัพธ์ไว้ที่ suggest_result.txt นำไปวางไว้ที่ [ProjectPath]/bin/Debug

    5. จากนั้นก็เขียนโค้ดในไฟล์ Program.cs ดังนี้

    using System;
    using System.IO;
    using System.Collections.Generic;
    using System.Text.RegularExpressions;
    using NHunspell;
    
    namespace SpellCheckTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                try
                {
                    using (var sr = new StreamReader("example_data/sentense_list.txt"))
                    {
                        //อ่านรายการคำ
                        string searchterm = sr.ReadToEnd();
                        string[] searchtermArray = searchterm.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
    
                        Console.WriteLine("Processing...");
    
                        using (var sw = new StreamWriter("example_data/suggest_result.txt"))
                        {
                            foreach (string sentense in searchtermArray)
                            {
                                string result = string.Empty;
                                var startTime = System.DateTime.Now.Ticks;
    
                                //ส่งคำให้ NHunspell ประมวลผล
                                result = SuggestNHunSpell(sentense);
    
                                var endTime = System.DateTime.Now.Ticks - startTime;
                                TimeSpan elapsedSpan = new TimeSpan(endTime);
    
                                //เขียนผลการตรวจสอบ และเวลาที่ใช้ลงในไฟล์ผลลัพธ์
                                sw.WriteLine(result);
                                sw.WriteLine(string.Format("{0}", elapsedSpan.TotalSeconds));
                                sw.WriteLine();
                                sw.Flush();
                            }
                        }
    
                        Console.WriteLine("Process Complete.");
                        Console.ReadKey();
                    }
                }
                catch (IOException e)
                {
                    Console.WriteLine("The file could not be read:");
                    Console.WriteLine(e.Message);
                    Console.ReadKey();
                }
            }
    
            /// <summary>
            /// NHunSpell
            /// </summary>
            /// <param name="sentence"></param>
            /// <returns></returns>
            private static string SuggestNHunSpell(string sentence)
            {
                //ตรวจสอบว่าเป็นภาษาอังกฤษ หรือภาษาไทย
                bool IsEnglish = Regex.IsMatch(sentence.Replace(" ", string.Empty), "[a-zA-Z]");
    
                string dictPath = IsEnglish ? "dict/en_US.dic" : "dict/th_TH.dic";
                string affixPath = IsEnglish ? "dict/en_US.aff" : "dict/th_TH.aff";
                
                //โหลดไฟล์ Dict และ Affix 
                using (Hunspell hunspell = new Hunspell(affixPath, dictPath))
                {
                    //ตรวจสอบว่าสะกดถูกหรือไม่
                    if (!hunspell.Spell(sentence))
                    {
                        List<string> suggestions = hunspell.Suggest(sentence);
                        if (suggestions.Count > 0)
                        {
                            //คืนค่า รายการคำที่น่าจะเป็นคำสะกดที่ถูกต้อง
                            return sentence + " : " + string.Join(",", suggestions);
                        }
                    }
                }
    
                //หากตรวจสอบว่าสะกดถูกแล้ว บันทึกผลว่า Correct
                return sentence + ": Correct";
            }
        }
    }

    6.จากนั้นทำการ Run แบบ Debug จะปรากฎหน้าจอ Command Line แสดงข้อความ Processing… รอจนเห็นคำว่า Process Complete. แสดงว่าทำการประมวลผลเสร็จแล้ว

    7.ผลลัพธ์จะถูกบันทึกลงในไฟล์ suggest_list.txt ดังรูป

    ในตัวอย่างนี้ เป็นเพียงโปรเจคสำหรับทดสอบการเรียกใช้งาน และดูผลลัพธ์ของ Library เท่านั้น การนำไปใช้งานร่วมกับระบบยังต้องการ การประยุกต์ให้เหมาะสมกับแต่ละระบบ แต่ก็หวังว่าจะเป็นประโยชน์กับคนที่กำลังหาเครื่องมือที่ใช้ตรวจสอบการสะกดคำให้กับระบบของตัวเองอยู่ไม่มาก ก็น้อยครับ

  • เขียน code ส่ง Line Notify ด้วย C#

    เริ่มต้นต้องประกาศ Using ก่อน ดังนี้

    using System.Net;
    using System.IO;

    แล้วใส่ code ตามด้านล่างนี้

    private void LineNotify(string lineToken, string message)
    {
            try
            {
                string message = System.Web.HttpUtility.UrlEncode(message, Encoding.UTF8);
                var request = (HttpWebRequest)WebRequest.Create("https://notify-api.line.me/api/notify");
                var postData = string.Format("message={0}", message);            
                var data = Encoding.UTF8.GetBytes(postData);            
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded";
                request.ContentLength = data.Length;
                request.Headers.Add("Authorization", "Bearer " + lineToken);
                var stream = request.GetRequestStream();
                stream.Write(data, 0, data.Length);
                var response = (HttpWebResponse)request.GetResponse();
                var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

    พารามิเตอร์ที่ต้องส่งมีดังนี้

    lineToken วิธีการขอ Line Token ดูได้จากบทความ การส่ง Line Notify ด้วย Command Line

    message คือข้อความที่ต้องการจะส่งผ่าน Line Notify

    ในการทดสอบฟังก์ชันหรือใช้งานฟังก์ชันนี้เครื่องคอมพิวเตอร์ต้องทำการต่อ internet ด้วยถึงจะทำงานได้

    ตัวอย่างการเรียกใช้ฟังก์ชัน

    LineNotify(“DwNQ7NQxrG8wgEaoUKvjgWKh1n08rxxxxxx”,”Hello World” );

    ผลที่ได้

    ถ้าหากต้องการให้ส่ง sticker หรือ รูปภาพไปด้วยให้ใส่ code ตามด้านล่างนี้

    private void LineNotify(string lineToken, string message , int stickerPackageID, int stickerID, string pictureUrl)
    {
            try
            {
                string message = System.Web.HttpUtility.UrlEncode(message, Encoding.UTF8);
                var request = (HttpWebRequest)WebRequest.Create("https://notify-api.line.me/api/notify");
                var postData = string.Format("message={0}", message); 
                if (stickerPackageID > 0 && stickerID > 0)
                    {
                        var stickerPackageId = string.Format("stickerPackageId={0}", stickerPackageID);
                        var stickerId = string.Format("stickerId={0}", stickerID);
                        postData += "&" + stickerPackageId.ToString() + "&" + stickerId.ToString();
                    }
                if (pictureUrl != "")
                    {
                        var imageThumbnail = string.Format("imageThumbnail={0}", pictureUrl);
                        var imageFullsize = string.Format("imageFullsize={0}", pictureUrl);
                        postData += "&" + imageThumbnail.ToString() + "&" + imageFullsize.ToString();
                    }           
                var data = Encoding.UTF8.GetBytes(postData);            
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded";
                request.ContentLength = data.Length;
                request.Headers.Add("Authorization", "Bearer " + lineToken);
                var stream = request.GetRequestStream();
                stream.Write(data, 0, data.Length);
                var response = (HttpWebResponse)request.GetResponse();
                var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

    พารามิเตอร์ที่ต้องส่งมีดังนี้

    lineToken วิธีการขอ Line Token ดูได้จากบทความ การส่ง Line Notify ด้วย Command Line

    message คือข้อความที่ต้องการจะส่งผ่าน Line Notify

    stickerPackageID กับ stickerID ดูได้จาก sticker_list

    pictureUrl คือ url ของรูปภาพที่ต้องการจะส่งผ่าน Line Notify

    ตัวอย่างการเรียกใช้ฟังก์ชัน

    LineNotify(“DwNQ7NQxrG8wgEaoUKvjgWKh1n08rxxxxxx”,”สวัสดีชาวโลก” , 1 , 10 , “https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png”);

    ผลที่ได้

  • สร้าง Web API สำหรับส่ง iOS Push Notification ด้วย dotAPNS

    ความสามารถของแอปพลิเคชันในปัจจุบันที่จะขาดไม่ได้เลย อย่าง Push Notification นั้น สำหรับนักพัฒนาชาว .Net แน่นอนครับว่ามี Library มากมายให้เลือกใช้ ในบทความนี้ผมจะเล่าวิธีการหนึ่ง ที่ได้เลือกใช้เพื่อตอบโจทย์การเชื่อมต่อแอปพลิเคชันกับหลายๆฐานข้อมูล การที่เราจะไป Deploy ตัวส่ง (Sender) ไว้ทุกๆ Server นั้นในด้าน Compatibility, Configuration, Maintain นั้นมีปัญหาแน่นอน เพราะข้อกำหนดของ Apple นั้นมีหลายอย่างพอสมควร ก่อนที่ตัวส่งของเรา จะได้รับอนุญาตุให้ส่งข้อความไปหาผู้ใช้ได้ ดังนั้นการติดตั้ง Sender ในแบบ Web API ไว้เพียงที่เดียว แล้วให้ทุก Client ที่ต้องการส่งมาเรียกใช้งาน จึงเป็นการลดปัญหาข้างต้นได้

    สิ่งที่จะต้องมี

    1.KeyID, BundleID, TeamID ทั้งสามค่านี้สามารถดูได้จาก appstoreconnect ในรายละเอียดของแอปพลิเคชัน

    2.Push Notification Certification (.p8) ในบทความนี้จะใช้วิธีการส่งแบบ Token Based ซึ่งมีความยืดหยุ่นและบำรุงรักษาได้ง่ายกว่า แบบ Certification Based แต่อย่างไรก็ตามยังคงต้องมี Certificate สำหรับการยืนยันตัวตนประกอบการสร้าง Token อยู่ดี ซึ่งสามารถเข้าไปสร้างได้ที่ developer.apple.com > Account > Key เลือกสร้างแบบ
    Apple Push Notifications service (APNs)

    3. Web Server ที่สามารถเชื่อมต่อด้วย HTTPS, HTTP/2 ได้

    สร้างโปรเจค Web API

    ในบทความนี้ใช้ Visual Studio 2019 Version 16.8.0

    1.ไปที่ File > New > Project เลือกเทมเพลต ASP.NET Web Application (.Net Framework) กดปุ่ม Create

    2.เลือกรูปแบบโปรเจคเป็นแบบ Web API กดปุ่ม Create

    3.เมื่อสร้างโปรเจคสำเร็จจะได้ไฟล์ต่างๆดังรูป (Main.aspx, MainController.cs สร้างเองภายหลัง สามารถตั้งชื่ออื่นๆได้)

    4.ทำการเพิ่ม Library dotAPNS ด้วย Nuget Manager โดยการคลิกขวาที่โปรเจค เลือกเมนู Manage Nuget Packages ค้นหาด้วยคำว่า dotAPNS จากนั้นกดปุ่ม Install

    5. ในไฟล์ MainController.cs ทำการ using dotAPNS มาใช้งาน จากนั้นสร้าง Method ชื่อ SendPush (ไม่จำเป็นต้องชื่อนี้) โดยโค้ดการสร้าง Token และส่ง Push Notification ทั้งหมดมีดังนี้

    using System.Net.Http;
    using System.Web.Http;
    using System.Threading.Tasks;
    using System.Configuration;
    using dotAPNS;
    using System.Web;
    using System;
    
    namespace APNsService.Controllers
    {
        [RoutePrefix("api")]
        public class MainController : ApiController
        {
            [Route("SendPush")]
            [AcceptVerbs("GET", "POST")]
            public async Task<ApnsResponse> SendPush(string title, string body, string token, string category)
            {
                try
                {
                    //อ่านค่า CertContent หรือ CertFilePart, BundleID, KeyID,TeamID มาจาก ไฟล์ web.config
                    string certContent = ConfigurationManager.AppSettings["CertContent"];
                    string certFilePath = ConfigurationManager.AppSettings["CertFilePath"];
                    string bundleId = ConfigurationManager.AppSettings["BundleId"];
                    string keyId = ConfigurationManager.AppSettings["KeyId"];
                    string teamId = ConfigurationManager.AppSettings["TeamId"];
    
                    //สร้าง Option สำหรับ Token
                    var options = new ApnsJwtOptions()
                    {
                        CertContent = certContent,
                        BundleId = bundleId,
                        KeyId = keyId,
                        TeamId = teamId
                    };
    
                    //สร้าง Token
                    var apns = ApnsClient.CreateUsingJwt(new HttpClient(new WinHttpHandler()), options);
    
                    //สร้าง Push Object
                    var push = new ApplePush(ApplePushType.Alert)
                        .AddAlert(HttpUtility.UrlDecode(title), HttpUtility.UrlDecode(body))//ข้อความแจ้งเตือน
                        .AddBadge(0)//แสดงจำนวนแจ้งเตือนที่หน้าแอปพลิเคชัน
                        .AddCategory(category)//กำหนดกลุ่มของการแจ้งเตือน
                        .AddToken(token);//token
                    
                    //ส่ง Notification
                    return await apns.Send(push);
                }
                catch (Exception ex)
                {
                    return ApnsResponse.Error(ApnsResponseReason.Unknown, ex.Message + ex.StackTrace);
                }
            }
        }
    }

    จากโค้ดด้านบน สามารถทราบว่าส่วนไหนทำหน้าที่อะไรได้จาก Comment ครับ เพียงเท่านี้ก็สามารถ Publish และ Deploy Web API บน Server เพื่อทดสอบการใช้งานได้แล้ว อย่างไรก็แล้วแต่ Web API ดังกล่าวยังต้องการ การปรับแต่งให้เหมาะสมกับระบบของนักพัฒนาแต่ละท่าน แต่โดยขั้นตอนหลักๆก็มีเพียงเท่านี้ครับ

    6.หน้าฟอร์ม และตัวอย่างโค้ดเรียกใช้งาน (อยู่ในหน้า Main.aspx,Main.aspx.cs เพื่อใช้ทดสอบการส่ง)

    using System;
    using System.IO;
    using System.Configuration;
    using System.Net;
    using Newtonsoft.Json;
    
    namespace APNsService
    {
        public partial class Main : System.Web.UI.Page
        {
            string token = string.Empty;
            string baseUrl = string.Empty;
    
            protected void Page_Load(object sender, EventArgs e)
            {
                token = ConfigurationManager.AppSettings["apiToken"].ToString();
                baseUrl = string.Format("{0}://{1}{2}/", Request.Url.Scheme, Request.Url.Authority, Request.ApplicationPath.TrimEnd('/'));
            }
    
            protected void btnSend_Click(object sender, EventArgs e)
            {
                string url = string.Format("{0}api/SendPush?title={1}&body={2}&category={3}&token={4}", baseUrl, txtTitle.Text,txtBody.Text,txtCategory.Text,txtToken.Text);
    
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                request.Method = "GET";
                request.ContentType = "application/json";
                request.Headers.Add("token", token);
    
                try
                {
                    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                    using (Stream responseStream = response.GetResponseStream())
                    {
                        StreamReader reader = new StreamReader(responseStream, System.Text.Encoding.UTF8);
                        string resultJSON = reader.ReadToEnd();
                        var result = JsonConvert.DeserializeObject<APNsResult>(resultJSON);
                        txtResult.Text = resultJSON;
                        txtURL.Text = url;
                        btnSend.Focus();
                    }
                }
                catch (Exception ex) 
                {
                    txtResult.Text = ex.Message;
                }
            }
    
        }
    
        public class APNsResult
        {
            public bool IsSuccess { get; set; }
            public int Reason { get; set; }
            public string ReasonString { get; set; }
        }
    }

    สังเกตุว่าในส่วนของการส่งจาก Client อื่นๆผ่าน Web API นั้นต้องการเพียงแค่ HttpWebRequest, Newtonsoft.Json เท่านั้นทำให้มีขนาดเล็ก และลดปัญหาความเข้ากันได้ในการติดตั้ง Client ไปได้อย่างแน่นอนครับ

    ขั้นตอนที่มีความสำคัญแต่ยังไม่ได้กล่าวถึงในบทความนี้นั้นคือการขอ Token ระบุเครื่องเป้าหมายจากผู้ใช้ที่ติดตั้งแอปพลิเคชันของเราครับ เนื่องจากวิธีการจะจำเพาะกับเครื่องมือที่ใช้ในการพัฒนาแอปพลิเคชัน

  • การติดตั้งเว็บไซต์ ที่พัฒนาด้วย ASP.NET บน IIS

    สำหรับนักพัฒนาเว็บแอปพลิเคชัน ที่จะต้องทำหน้าที่ครบวงจร (Full Stack Programer) สิ่งที่ต้องทำหลังจากพัฒนาเว็บขึ้นมาเสร็จแล้ว คือการติดตั้งบนเซิร์ฟเวอร์ (Deploy) ในบทความนี้จะเล่าขั้นตอนหลักๆ ในการติดตั้งเว็บไซต์ ที่พัฒนาด้วย ASP.NET (ไม่ว่าจะพัฒนาด้วย .Net Framework เวอร์ชันไหนก็ขั้นตอนเดียวกัน เปลี่ยนแปลงแค่ .Net Runtime ที่ใช้งาน) บนวินโดวส์เซิร์ฟเวอร์ โดยใช้ IIS (Internet Information Services) ซึ่งหน้าตาอาจเปลี่ยนแปลงไปตามเวอร์ชันของ IIS แต่ขั้นตอนการตั้งค่ายังคงคล้ายคลึงกัน

    Publish เว็บไซต์ (กรณีใช้ Visual Studio)

    1.คลิกขวาที่ชื่อโปรเจ็ค เลือก Publish

    2.จะได้หน้าจอเลือกประเภทในบทความนี้เลือกเป็น Folder เพื่อใช้วิธีการ Deploy แบบนำไฟล์ไปวางที่ Server เอง ดังรูป

    3. เลือกที่ตั้งไฟล์ กด Finish

    4. ตั้งค่าการ Publish จากในรูปคือให้ลบไฟล์ที่มีอยู่ก่อน และใช้รูปแบบ Release ในการ Compile

    5. ตัวอย่างไฟล์ที่ทำการ Publish เสร็จแล้ว

    6. ทำการ Copy ไฟล์ทั้งหมดไปวางใน wwwroot บน Server

    ติดตั้ง Component ต่างๆ

    1.ในบทความนี้ใช้ Windows Server 2016 Datacenter เป็นตัวอย่าง ซึ่งการติดตั้ง Component ต่างๆ สามารถทำได้ผ่าน Server Manager > Manage > Add Roles and Features ได้เกือบทั้งหมด ยกเว้น Runtime อื่นๆที่เว็บไซต์มีการนำมาใช้งานเพิ่มเติม

    2. ติดตั้ง IIS , ASP.NET และ Component ที่เกี่ยวข้อง โดยไปที่ Server Role > Web Server (IIS) และทำการเลือก Component ต่างๆดังรูป จากนั้นกด Next

    3. ติดตั้ง .Net Framework เวอร์ชันที่เว็บไซต์ใช้งาน ในตัวอย่างใช้ .Net Framework 4.6 โดยสามารถเลือกจาก เมนู Features ดังรูป

    4. เท่านี้ก็จะมี Component ที่จำเป็นในการติดตั้งเว็บไซต์ที่พัฒนาด้วย ASP.NET แล้ว

    สร้าง และตั้งค่า Application Pool

    1.เปิดโปรแกรม IIS โดยไปที่ Start > Windows Administrative Tools > Internet information Services (IIS) จะได้หน้าจอดังรูป

    2. เลือกเมนู Application Pool จากนั้นคลิก Add Application Pool จะได้หน้าจอการตั้งค่าดังรูป โดยที่ .Net CLR Version จะแยกเป็น 2.0.xxx และ 4.0.xxx โดยหากต้องการใช้งาน .Net Runtime 3.5 – 4.x สามารถเลือกเป็น 4.0.x ได้ทั้งหมด

    3. เมื่อสร้างสำเร็จ จะมีรายการ Application Pool ที่เราสร้างดังรูป

    สร้าง และตั้งค่าเว็บไซต์ ทดสอบเรียกใช้งาน

    1.ในการสร้างไซต์นั้น หากบน Server นั้นยังไม่มีเว็บไซต์ใดๆ สามารถใช้ Default Web Site ได้เลย แต่ถ้ามีเว็บไซต์อื่นๆอยู่ก่อนแล้ว จะต้องพิจารณาว่าจะให้บริการในแบบใด เป็น Application ที่อยู่ภายใต้เว็บไซต์เดิม หรือแยกออกมาเป็นอีก URL ในส่วนนี้ บทความจะไม่ลงรายละเอียด โดยจะแสดงวิธีการเพิ่ม ไซต์ใหม่ภายใต้ URL เดิมที่มีอยู่แล้วโดยเลือกเมนู Add Website จะได้หน้าจอการตั้งค่าดังรูป

    2. จากนั้นทำการตั้งค่า Default Document โดยคลิกเลือกที่ชื่อเว็บไซต์ เลือกไฟล์ที่ต้องการกำหนดเป็นหน้าแรกของเว็บไซต์

    3. ตั้งค่าต่างๆของเว็บไซต์ ซึ่งขึ้นอยู่กับแต่ละเว็บไซต์ว่ามีการใช้งาน Feature ใดบ้าง ดังรูป (อีกช่องทางนึงคือการแก้ไขไฟล์ web.config โดยตรง)

    4. ทำการทดสอบเรียกใช้งาน โดยคลิกที่เมนู Browse เพื่อเรียกดูแบบ Localhost หรือหากมี URL อยู่แล้วสามารถเรียกดูผ่าน URL/ApplicationName ดังรูป

    ในขั้นตอนติดตั้งชิ้นงานจริง แน่นอนว่าอาจมีขั้นตอนเพิ่มเติมตามแต่ละเว็บไซต์ และอาจพบปัญหาต่างๆ แตกต่างกันไปตามเวอร์ชันของวินโดวส์, IIS, .Net Runtime แต่อย่างไรก็ดีหวังว่าบทความนี้จะเป็นไกด์ไลน์ ให้เห็นภาพขั้นตอนคร่าวๆในการติดตั้งเว็บไซต์หนึ่งๆ สำหรับผู้เริ่มต้นครับ

  • คลายข้อสงสัย “ทำไมสแกนบาร์โคดจากเครื่องอ่านแล้วไม่ enter หรือ tab ให้”

    ในการพัฒนาระบบที่ต้องมีการอ่านข้อมูลจากเครื่องสแกนบาร์โคดแบบสองมิติ (แบบแท่งหรือแบบเส้น) รูปแบบในการทำงานมักจะเป็นการอ่านข้อมูลจากตัวบาร์โคด จากนั้นตามด้วยอักขระ Enter หรือ Tab เพื่อเป็นการระบุว่าให้ส่งข้อมูลที่อ่านได้จากบาร์โคดให้กับฟังก์ชันใดฟังก์ชันหนึ่งเพื่อนำไปใช้งานต่อ แต่ในบางครั้งอาจจะเคยเจอปัญหาว่าทำไมเมื่อสแกนบาร์โคดแล้วไม่มีการ Enter หรือ Tab โดยอัตโนมัติ ทำให้ต้องกดปุ่ม Enter หรือ Tab เองทุกครั้งจากคีย์บอร์ด หรือต้องปรับแต่ง code เพื่อเพิ่มอักขระ Enter หรือ Tab ต่อหลังข้อมูลที่อ่านได้จากเครื่องสแกนบาร์โคด

    หนึ่งในแนวทางสำหรับการแก้ปัญหานี้อยู่ที่ตัวคู่มือสำหรับเครื่องสแกนบาร์โคดแต่ละรุ่นนั่นเอง โดยในที่นี้จะยกตัวอย่างกรณีที่เคยพบดังนี้

    ตัวอย่างการตั้งค่าเครื่องอ่านบาร์โคด Honeywell รุ่น Xenon Model 1900

    1. หาคู่มือการตั้งค่าตามรุ่น ซึ่งรุ่นนี้ คือ Xenon Model 1900 (ถ้าไม่มีคู่มือที่ให้มาพร้อมกับอุปกรณ์ อาจจะสามารถค้นหาคู่มือได้จากทาง internet โดยค้นตามรุ่น หรือตามบริษัทผู้ผลิต)
    2. ในคู่มือที่เกี่ยวกับการตั้งค่าเพื่อแก้ปัญหานี้ จะมีรหัสบาร์โคดที่ให้เราทำการสแกนเพื่อตั้งค่าอุปกรณ์ดังนี้

    กรณีต้องการให้ลงส่งอักขระ Enter หลังสแกนบาร์โคด สามารถทำได้โดยการสแกนบาร์โคดด้านล่าง

    กรณีต้องการให้ลงส่งอักขระ Tab หลังสแกนบาร์โคด สามารถทำได้โดยการสแกนบาร์โคดด้านล่าง

    สรุปควรแก้ปัญหาด้วยการเขียน Code หรือตั้งค่าอุปกรณ์

    จากการเปรียบเทียบจะเห็นว่าหากใช้วิธีการเขียน code น่าจะเป็นแนวทางที่ดีกว่าในการแก้ปัญหานี้ เพราะเป็นวิธีการที่ไม่ขึ้นกับเครื่องสแกนบาร์โคด ไม่ต้องลำบากหาคู่มือ แต่วิธีการตั้งค่าอุปกรณ์นั้น อาจจะเหมาะสมในกรณีที่ต้องการอ่านข้อมูลบาร์โคดจำนวนมากลงไฟล์ เช่น อ่านลง text file หรืออ่านลง excel เพื่อนำไฟล์นี้เตรียมไว้เป็นข้อมูลสำหรับทดสอบนำเข้าระบบใดระบบหนึ่งอีกที เป็นต้น

    ถือว่าเป็นสิ่งที่รู้ไว้เป็นแนวทางนำไปประยุกต์ใช้ให้เหมาะกับสถานการณ์ได้

  • Robot Framework Puppeteer

    Robot Framework Puppeteer คืออะไร

    เป็น Library ที่ทำมาครอบ Puppeteer เพื่อให้ Robot framework ใช้งานได้ง่าย โดย Keyword ต่างๆจะเหมือนกับการใช้งาน Selenium Library ทำให้ใครที่ใช้งาน Selenium Library อยู่แล้วสามารถปรับตัว รวมไปจนถึง การเปลี่ยนมาใช้ Puppeteer ทำได้ง่ายเลยค่ะ และหมดปัญหาการที่เราต้องมาคอยอัพเดต Web driver อยู่ตลอด ๆ

    การติดตั้งง่ายมาก ๆ ดูให้ทันหล่ะ 555

    รัน Command เดียวเลยจบ ไม่ต้องโหลด Chrome driver หรือ Setup Path เพิ่มเติมให้ปวดหัว เปิด Command line มาเลยค่ะ แล้วพิมพ์คำสั่ง

    pip install –upgrade robotframework-puppeteerlibrary

    การใช้งาน

    เราลองมารัน code เดิมที่เขียนไว้กันดูดีกว่า (selenium2library) อ้าวเฮ้ย!!! Error ซะงั้น Web driver ไม่ support ต้องอัพเดตอีกแล้ว

    งั้นขอไปอัพเดตแปปนึงนะ ไม่ขอเล่าถึงการอัพเดตแล้วนะ เคยเล่าไว้ตอนนึงแล้ว ไปลองหาอ่านกันดู อิอิ หลังจากอัพเดตแล้วมาลองรันอีกรอบ

    เปลี่ยนที่ Setting จาก Selenium2Library เป็น PuppeteerLibrary จากนั้นลองรันดู

    เปรียบเทียบความเร็วในการประมวลผลระหว่างใช้ Selenium2Library กับ PuppeteerLibrary
    รูปแรกจะเป็นการใช้ Selenium2Library รูปถัดไปจะเป็น PuppeteerLibrary

    จะเห็นได้ว่า PuppeteerLibrary ทำงานได้เร็วกว่า นี่ขนาดรันคำสั่งขนาดน้อย ๆ ไว้ลองกับคำสั่งที่ซับซ้อนแล้วจะมาเล่าให้ฟังค่ะ

  • Windows Terminal (3)

    • ติดตั้ง WSL2 ก็แล้ว แต่ใช้แค่ bash ดูไม่ว้าววววว เลย ให้ดูตัวอย่างก่อนที่

    https://github.com/ohmyzsh/ohmyzsh/wiki/Themes

    สวยงามอล่างฉ่าง
    • มาติดตั้ง zsh และ theme กัน
    • เริ่มจากติดตั้ง zsh
    sudo apt install zsh
    install zsh
    • ต่อด้วยคำสั่งต่อไปนี้เพื่อติดตั้ง ohmyzsh
    sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
    • จากภาพจะมีการเปลี่ยน default shell ด้วยเปลี่ยนจาก bash เป็น zsh ฉะนั้นเมื่อเปิด wsl terminal ครั้งใดก็จะได้เป็น zsh shell ทุกครั้ง
    • สิ่งที่เพิ่มมาและมีความสำคัญมากคือ .oh-my-zsh และ .zshrc
    • เสร็จละง่าย!! แต่ theme ตั้งต้นอาจจะไม่ฉูดฉาด
    • แก้ไขแฟ้ม .zshrc ด้วย editor ที่ชื่นชอบ!
    • ดูชื่อ theme ต่างๆ ได้ที่ https://github.com/ohmyzsh/ohmyzsh/wiki/Themes
    • มองหาคำว่า ZSH_THEME=”robbyrussell” สามารถเปลี่ยน robbyrussell เป็นอย่างอื่นได้เลย เช่น bira เปลี่ยนแล้ว save เมื่อออกมาอยู่ที่ prompt ให้พิมพ์
    . ./.zshrc
    • (อ่านว่า จุด-เว้นวรรค-จุด-สแลช-จุด-แซ่ด-เอส-เอช-อาร์-ซี)
    • หรือพิมพ์ว่า
    source .zshrc
    • ก็จะเปลี่ยนหน้าตาไปทันที ก่อนหน้านี้ต้องเคยติดตั้ง powerline font มาก่อนซึ่งในตอนที่ 1 ได้ให้ติดตั้งไปแล้ว จะได้ดังรูป
    • สวยแล้ว ทั้งนี้สวยแต่ละคนไม่เท่ากันก็อาจจะลองเปลี่ยนเป็นชื่ออื่นๆ ได้เลย หรือหากต้องการเขียนเองก็ทำได้ อ่านเอกสารเองนะจ๊ะ
    • เท่านี้ก่อนสำหรับ zsh shell
    • สำหรับ zsh สามาติดตั้งได้บน linux server แทบทุกดิสโทรเลยทีเดียว และโดยเฉพาะอย่างยิ่ง ubuntu หรือ debian ยังมี repository และ plugin เสริมต่างๆ ของ zsh อีกด้วย (ค่ายอื่นอาจจะมีแต่ไม่ได้ใช้งานมากเลยไม่ทราบนะครับ)
    • จบขอให้สนุก
    • ต้นฉบับ https://ohmyz.sh/
  • รู้จักเอแจ๊กซ์ (AJAX) และการใช้งาน

    AJAX ย่อมาจากคำว่า Asynchronous JavaScript and XML ซึ่งหมายถึงการพัฒนาเว็บแอพพลิเคชั่นที่ประมวลผลในเบื้องหลังเป็นเทคนิคในการพัฒนาเว็บแอปพลิเคชันเพื่อให้สามารถโต้ตอบกับผู้ใช้ได้ดีขึ้น ทำให้ความรู้สึกการใช้งานโปรแกรมเหมือนกับเดสก์ท็อปแอปพลิเคชัน

    ปกติแล้วในภาษาสคริปต์ที่ใช้งานกับเว็บไซต์จะมีการทำงานประมวลผลแบบเป็นลำดับ (synchronous) โดยที่คำสั่งแรกจะต้องประมวลผลให้เสร็จสิ้นก่อนแล้วถึงจะทำงานในคำสั่งถัดไป แต่กระบวนการทำงานแบบเอแจ๊กซ์เมื่อบราวเซอร์ (Browser) ร้องขอข้อมูลไปยังเซิร์ฟเวอร์ (Server) บราวเซอร์จะไปทำงานคำสั่งถัดไปทันที (asynchronous) โดยที่ไม่ต้องรอการตอบกลับจากเซิร์ฟเวอร์ก่อน

    ทำให้การตอบสนองต่อผู้ใช้งานดูรวดเร็วขึ้น และเมื่อเซิร์ฟเวอร์ประมวลผลเสร็จแล้วถึงจะส่งข้อมูลกลับมาที่เอแจ๊กซ์และให้เอแจ๊กซ์ทำงานกับข้อมูลที่ส่งกลับมาอีกทีซึ่งสามารถเขียนโค้คการทำงานดังนี้

    ตัวอย่างโค้คการทำงาน AJAX ของโดยใช้ jQuery

    $.ajax({
        	type: 'GET',
        	url: 'send-ajax-data.php',
        	dataType: "JSON", // data type expected from server
        	success: function (data) {
               	console.log(data);
        	},
        	error: function(error) {
               	console.log('Error: ' + error);
        	}
    });
    

    และปัจจุบันในการเขียน JavaScript เพื่อเรียกใช้งาน AJAX นั้นเราไม่จำเป็นต้องพึ่งพา jQuery อีกต่อไปแล้วซึ่งสามารถเขียนโค้ดการทำงานได้ดังนี้

    วิธีที่ 1  ใช้ XMLHttpRequest [1]

    var request = new XMLHttpRequest();
    request.open('GET','https://tutorialzine.com/misc/files/my_url.html', true);
    
    request.onload = function (e) {
        if (request.readyState === 4) {
    
            // Check if the get was successful
            if (request.status === 200) {
                console.log(request.responseText);
            } else {
                console.error(request.statusText);
            }
        }
    };
    
    // Catch errors:
    request.onerror = function (e) {
        console.error(request.statusText);
    };
    
    request.send(null);
    

    วิธีที่ 2 ใช้ Fetch API [2]

    fetch('./api/some.json')
      .then(
        function(response) {
          if (response.status !== 200) {
            console.log('Looks like there was a problem. Status Code:' +
     response.status);
            return;
          }
    
          // Examine the text in the response
          response.json().then(function(data) {
            console.log(data);
          });
        }
      )
      .catch(function(err) {
        console.log('Fetch Error :-S', err);
      });
    

    อ้างอิง:

    https://tutorialzine.com/2014/06/10-tips-for-writing-javascript-without-jquery [1]

    https://developers.google.com/web/updates/2015/03/introduction-to-fetch [2]

    https://www.javascripttutorial.net/javascript-fetch-api/  

    วิดีโอ: https://www.youtube.com/watch?v=F1TECaRf-uA&feature=youtu.be&t=2375

  • รู้จักการจัดการข้อมูล JSON และการใช้งาน

    รูปแบบข้อมูล JSON เป็นมาตรฐานในการแลกเปลี่ยนข้อมูลระหว่างเซิฟเวอร์และไคลเอนต์ที่ได้รับความนิยมในปัจจุบันซึ่งได้ถูกนำไปใช้งานอย่างแพร่หลายเช่นการเขียนโปรแกรมโดยใช้เทคนิค AJAX, RESTFul, เขียนคอนฟิกไฟล์ หรือการพัฒนา API เป็นต้น

    ด้วยคุณสมบัติของ JSON ที่เป็นไฟล์ประเภทข้อความ (Text based) ขนาดเล็กน้ำหนักเบา เป็นมาตรฐานกลางทุกภาษาสามารถใช้งานได้ง่ายทั้งการอ่านและเขียนที่มนุษย์สามารถอ่านเข้าใจได้ง่าย

    อักขระมาตารฐานของ JSON

    1. เครื่องหมาย “:” ใช้สำหรับแยกค่า name และ value
    2. เครื่องหมาย “,” ใช้สำหรับแยกข้อมุล name-value ในแต่ละคู่
    3. เครื่องหมาย “{” และ “}” ระบุว่าข้อมูลเป็นออบเจ็ค
    4. เครื่องหมาย “[” และ “]” ระบุว่าข้อมูลเป็นอาเรย์
    5. เครื่องหมาย “” (double quotes) ใช้เขียนค่า name-value ใน JSON

    ตัวอย่างการเขียนค่า Json

    – จำนวน 1 คู่

    "name" : "value"

    – หากมีมากกว่า 1 คู่ ให้ใช้เครื่องหมายคอมมา , (comma) ในการแยกเป็นคู่

    "name" : "value", "name" : "value", "name": "value"

    – ต้วอย่าง JSON object

    {
      "name" : "mama papa",
      "email" : "mama@email.com",
    };
    

    ชนิดข้อมูลของ JSON มี 6 ชนิด คือ

    1. strings
    2. numbers
    3. objects
    4. arrays
    5. booleans
    6. null or empty

    – ตัวอย่างการใช้งานชนิดข้อมูล

    {
       "text" : "This is Sting",
       "number" : 210,
       "object" :  {
                        "name" : "abc",
                        "popularity" : "immense"
                    },
       "arary" : ["1","2","3"], 
       "empty" : ,  	
       "booleans" : true
    }
    

    การใช้งาน JSON ร่วมกับภาษา JavaScript

    – ตัวอย่างการแสดงค่า JSON objects

    var user = {
       "name" : "mama papa",
       "email" : "mama@email.com",
    };
    
    console.log("The name is:  " +user.name);
    console.log("email is:  " +user.email);
    
    //output
     The name is: mama papa
     email is: mama@email.com

    – ตัวอย่างการแสดงค่า JSON objects ใน array

    var students = [{
       "name" : "สมชาย",
       "age" :  "29",
       "gender" : "ผู้ชาย"
    },
    {
       "name" : "สมหญิง",
       "age" : "27",
       "gender" : "ผู้หญิง"
    }];
    
    console.log(students[0].age);  //output: 29
    console.log(students[1].name); //output: สมหญิง

    – ตัวอย่างการแสดงค่า JSON objects ใน objects

    var cars = {
      "toyota" : {
         "type" : "vios",
         "year" :  "2018"
      },
      "honda" : {
         "type" : "city",
         "year" : "2015"
      }
    }
    
    console.log(cars.toyota.type); //output: vios
    console.log(cars.honda.year); //output: 2015

    ทริปเล็กๆน้อยๆ

    ในการใช้งาน JSON ในภาษา JavaScript มีฟังก์ชั่นที่เราใช้งานบ่อยๆ อยู่ 2 ฟังก์ชัน คือ

    1. JSON parser สำหรับแปลง JSON object เป็น javascript object ตัวอย่างเช่น
    var myJSObject = JSON.parse(students);

     2. JSON stringify สำหรับแปลง JavaScript object เป็น JSON text

    var jsonText= JSON.stringify(myJSObject);

    (*ข้อควรระวังอย่าสับสนระหว่าง JSON object กับ  javascript object เพราะมันเป็นคนละอย่างกันนะครับ [3])

    ทริปเพิ่มเติมสำหรับการใช้งานร่วมกับภาษา PHP จะมีฟังก์ชั่น json_encode เพื่อส่งข้อมูล json ไปให้ฝั่ง javascript ไปใช้งานต่ออีกที หากเราต้องการที่จะแปลงข้อมูลให้เป็น javascript object เพื่อจะให้เรานำข้อมูล json ไปทำงานต่อไปได้ง่ายขึ้นสามารถทำดังนี้

    var jsonText= JSON.stringify(myJsonFormPHP);
    var myJSObject = JSON.parse(jsonText);

    Reference:

    https://beginnersbook.com/2015/04/json-tutorial/

    https://restfulapi.net/json-data-types/

    Javascript Object VS JSON(JavaScript Object Notation) มันคนละเรื่องกัน ? [3]