Monday, September 2, 2013

UUID (Universally unique identifier) กับ Bluetooth Protocol

UUID เป็นกลุ่มตัวเลขขนาด 16-octet หรือ 128-bit หรือในรูปแบบ 32 hexadecimal charactor ที่กำหนดขึ้นมาเพื่อใช้ในงานทางซอฟต์แวร์  โดยจุดประสงค์ของ UUID คือการรับประกันว่าสิ่งของที่ถูกระบุด้วย UUID นี้จะไม่ซ้ำกับสิ่งอื่นๆ (เป็นเอกลักษณ์) เพราะโดยทางเทคนิคเป็นไปได้ยากที่จะซ้ำกัน  โดยมีการนำไปใช้งานที่หลากหลาย เช่น ระบุพาร์ติชั่นในระบบ Linux ระบุช่องทางการเชื่อมต่อ (RPC) เป็นต้น
ตัวเลข UUID แบ่งการใช้งานได้ออกเป็น 4 กลุ่มใหญ่ๆ คือ

Version 1 เป็นกลุ่มที่พบได้ในงานทางเครือข่ายทั่วไป โดยตัวเลขจะถูกสร้างขึ้นจาก MAC address รวมกับค่า timestamp ซึ่งเป็นตัวเลขในหน่วยนาโนวินาที (nanosecond) จำนวน 100 หลักเพื่อให้ได้ตัวเลขที่มีเอกลักษณ์ ส่วนใหญ่ถูกใช้ในการระบุ transaction

Version 3 และ 5 เป็นการใช้ UUID ในรูปแบบของการทำ hash function เช่น MD5 และ SHA-1

Version 4 ใช้เป็นเลขสุ่ม

แล้วมันเกี่ยวอะไรกับ Bluetooth Protocol
กลุ่ม Bluetooth ได้ให้มาตรฐานในการติดต่อบนเครือข่าย Bluetooth โดยใช้ UUID ในกระบวนการทำ Service Discovery Protocol (SDP) และการเชื่อมต่อ  โดยจองตัวเลขขนาด 32 bit แรกเอาไว้ แต่ที่ใช้ตอนนี้ใช้แค่เพียง 16 bit หลังสำหรับระบุโปรโตคอลก่อน  ซึ่งตัวเลขเหล่านี้ใช้ในการระบุมาตรฐานในการเชื่อมต่อ เช่น Protocol Identifiers,  profile ใน BluetoothProfileDescriptorList  เป็นต้น และต่อด้วยเลข UUID ฐานดังตารางที่ 1

ตารางที่ 1
UUID NameUUID
BASE_UUID0000XXXX-0000-1000-8000-00805F9B34FB

จากนั้นแทนค่า XXXX ด้วยค่า 16 bit ( 4 hexadecimal charactor) ดังยกตัวอย่างบางส่วนมาในตารางที่ 2

ตารางที่ 2
Service Class NameUUIDSpecificationAllowed Usage
ServiceDiscoveryServerServiceClassID0x1000Bluetooth Core SpecificationService Class
BrowseGroupDescriptorServiceClassID0x1001Bluetooth Core SpecificationService Class
SerialPort0x1101Serial Port Profile (SPP)
NOTE: The example SDP record in SPP v1.0 does not include a BluetoothProfileDescriptorList attribute, but some implementations may also use this UUID for the Profile Identifier.
Service Class/ Profile
LANAccessUsingPPP0x1102LAN Access Profile
[DEPRECATED]
NOTE: Used as both Service Class Identifier and Profile Identifier.
Service Class/ Profile
.............

link : https://www.bluetooth.org/en-us/specification/assigned-numbers/service-discoveryhttp://www.avetana-gmbh.de/avetana-gmbh/produkte/doc/javax/bluetooth/UUID.htmlhttp://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#createRfcommSocketToServiceRecord%28java.util.UUID%29

Saturday, August 24, 2013

รูปแบบการเขียนโค้ด (code)


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

  1. การตั้งชื่อตัวแปร
เนื่องด้วยกฏของการตั้งชื่อสิ่งต่างๆ ในโลกของการโปรแกรมไม่อนุญาตให้มีการเว้นวรรคระหว่างตัวอักษรทำให้ชื่อตัวแปรต้องเป็นกลุ่มตัวอักษรที่ติดกัน เช่น
int extrapayment;
int except_weightunit;
int multiple-string-number;

จากตัวอย่างในบรรทัดแรกจะเห็นได้ว่าหากเรานำคำต่างๆ มาเขียนติดกันเป็นชื่อตัวแปรทำให้เราอ่านแบ่งคำเพื่อเข้าใจชื่อของตัวแปรได้ยากขึ้นเพราะไม่มีสัญลักษณ์อะไรมาคั่นระหว่างคำ  ในบรรทัดที่ 2 และ 3 มีการใช้ '-' และ '_' มาช่วยในการแบ่งระหว่างคำ  สัญลักษณ์เหล่านี้สามารถนำมาใช้ช่วยให้อ่านได้ขึ้นได้แต่มีข้อเสียอยู่ที่สัญลักษณ์พิเศษเหล่านี้มักจะมีความยากในการพิมพ์เพิ่มขึ้น  ทำให้มีแนวคิดในการตั้งชื่อตัวแปรที่นิยมใช้กันเรียกว่า CamelCase (Wiki)
ผู้เขียนเข้าใจว่ามีที่มาจากลักษณะของอูฐที่มีขอที่ชูสูงโดยมีคอที่ยาวลงมายังลำและโหนกที่มีลักษณะสูงต่ำสลับกันไป  แนวคิดนี้ใช้วิธีในการแบ่งคำโดยให้ตัวอักษรแรกของคำหนึ่งคำจะต้องเป็นตัวพิมพ์ใหญ่และใช้ตัวอักษรที่เหลือของคำเป็นพิมพ์เล็กทั้งหมดทำให้เราได้ชื่อตัวแปรที่อ่านง่ายขึ้น ดังตัวอย่าง
int extraPayment;
int exceptWeightUnit;
int multipleStringNumber;
ซึ่งในภาษา Java ได้ให้แนวทางการใช้ CamelCase ไว้คือ
  • ชื่อตัวแปรและเมธทอดให้ใช้ lowerCamelCase เช่น variableName
  • ชื่อคลาสให้ใช้ UpperCamelCase เช่น ThisIsClassA
  • [ยกเว้น]ชื่อของค่าคงที่ให้ใช้ตัวพิมพ์ใหญ่ทั้งหมดและใช้ '_' เพื่อเว้นวรรคระหว่างคำ CONSTANT_VALUE

  1. การใช้วรรค/แท็บ
การเขียนโค้ดให้อ่านง่าย จุดหนึ่งที่ใช้ก็คือการวรรคและการแท็บ  รูปแบบของโค้ดโดยสากลนั้นใช้การวรรคอย่างน้อยหนึ่ง "เคาะ" เพื่อแบ่งรูปแบบของโค้ดต่างๆ เช่น ประเภทเมธทอด[วรรค]ชนิดของการคืนค่า[วรรค]ชื่อเมธทอด เป็นต้น หรืออนุญาตให้ไม่ต้องใช้วรรคระหว่าง ตัวกำหนดค่า เช่น 5+1 number<=3 เป็นต้น ซึ่งรูปแบบของโค้ดสามารถให้เราใช้วรรคมากกว่าหนึ่ง "เคาะ" ได้  พิจารณาตัวอย่างโค้ด
$search = array('a', 'b', 'c', 'd', 'e');
$replacement = array('foo', 'bar', 'baz', 'quux');
$value = 0;
$anothervalue = 1;
$yetanothervalue = 2;
$search      = array('a',   'b',   'c',   'd',   'e');
$replacement = array('foo', 'bar', 'baz', 'quux');
$value           = 0;
$anothervalue    = 1;
$yetanothervalue = 2;

เห็นได้ว่าตัวอย่างที่ 1 มีการใช้วรรคเพียงหนึ่ง "เคาะ" เพียงอย่างเดียวแต่ตัวอย่างที่ 2 มีการใช้วรรคและแท็บหลายครั้งเพื่อทำให้ผู้อ่านโค้ดสามารถอ่านและเปรียบเทียบจำนวนของตัวแปรได้ง่ายมากขึ้น  แต่ก็มีข้อเสียเกิดขึ้นเมื่อมีการเปลี่ยนค่าหรือชื่อตัวแปรเป็นชื่อที่มีตัวอักษรมากกว่าหรือน้อยกว่าทำให้การเว้นวรรค/แท็บที่วางไว้ผิดตำแหน่งไป  หรือผู้แก้ไขมีการตั้งค่าโปรแกรมที่ใช้เขียนโค้ดโดยมีจำนวน "เคาะ" ในการแท็บไม่เท่ากันก็อาจทำให้รูปแบบโค้ดดูผิดเพี้ยนได้
$search      = array('a',   'bbb',   'cc',   'd',   'e');
$r = array('foo', 'bar', 'baz', 'quux');
$value           = 0;
$a    = 1;
$yetanothervalue = 2;

  1. การใช้วงเล็บ
เมื่อสมัยที่เราเรียนเขียนโค้ดถึงบทที่มีการใช้ if else  เรามักจะเจอตัวอย่างโค้ดที่ดูเข้าใจง่ายแบบนี้
if (you.hasAnswer())
{
    you.postAnswer();
}
else
{
    you.doSomething();
}
แต่เมื่อเรามีการใช้งานโปรแกรมเขียนโค้ดที่มีความสามารถสูงๆ ซึ่งมักจะมีระบบจัดวงเล็บให้อัตโนมัติเราก็จะได้ตัวอย่างโค้ด คือ
if (you.hasAnswer()) {
    you.postAnswer();
} else {
    you.doSomething();
}
ตัวอย่างที่ 1 จะมีข้อเสียเมื่อมีการใช้เงื่อนไขหรือการเรียกฟังก์ชันที่ซ้อนกันมากๆ ทำให้การขึ้นบรรทัดใหม่ของวงเล็บกินเนื้อที่บนหน้าจอทำให้เห็นโค้ดได้น้อยลงและจำนวนบรรทัดที่มากขึ้นนี้ทำให้การพิมพ์โค้ดลงในกระดาษจะต้องใช้กระดาษเพิ่มขึ้นหลายหน้า (หลายๆคนคงเคยชินกับข้อเสียนี้ดี) ในตัวอย่างที่ 2 อาจจะทำให้บางคนอ่านเส้นทางของเงื่อนไขยากขึ้นหรือไม่แน่ใจว่าในโค้ดนี้มีการปิดวงเล็บแล้วรึยังซึ่งโปรแกรมเขียนโค้ดในปัจจุบันมีตัวช่วยมากมายที่จะช่วยแสดงขอบเขตของวงเล็บหรือตรวจสอบและแก้ไขวงเล็บที่ขาดหายไปได้อีกด้วย
การใช้วงเล็บนี้ไม่มีจุดกำหนดที่ตายตัวนอกจากความชอบในการใช้งาน  ส่วนตัวผู้เขียนชอบที่จะผสมทั้งสองวิธีโดยขึ้นบรรทัดใหม่หรือเว้นบรรทัดวงเล็บให้กับเมธทอด คลาสหรือเงื่อนไขสำคัญๆ เพื่อให้อ่านง่ายขึ้นดังตัวอย่าง
public void onSensorChanged(SensorEvent event){
   
 if (samplingFilter(sampling, timeStamp)) {
   
  if(now != 0){
   temp++;
   if(temp == nbElement){
    time = timeStamp - now;
    freQ.setText("Current Frequency = " + nbElement * 1000000000 / time + "Hz");
    temp = 0;
   }
  }
  if(temp == 0){
   now = timeStamp;
   temp++;
  }
 }   
}

Tuesday, August 20, 2013

การใช้ bluetooth ใน android (ภาคแรก การตั้งค่า)

เริ่มแรกจะต้องตั้งตัวอแด็ปเตอร์ของ Bluetooth ก่อนโดยใช้คำสั่ง
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
  if (mBluetoothAdapter == null) {
   Toast.makeText(this, "Device does not support Bluetooth",
     Toast.LENGTH_LONG).show();
  }

จากนั้นให้โปรแกรมเรียกใช้งาน Bluetooth โดยใช้
if (!mBluetoothAdapter.isEnabled()) {
   Intent enableBtIntent = new Intent(
     BluetoothAdapter.ACTION_REQUEST_ENABLE);
   startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
  }

จะเห็นได้ว่ามีการสร้าง Intent เพื่อเรียกใช้งาน Blueotooth ด้วยคำสั่ง
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);

เมื่อมีการเรียกคำสั่งนี้ Android จะเปิดใช้งานอุปกรณ์ Bluetooth ซึ่งหาก Bluetooth ไม่ได้ถูกเปิด  ก็จะมีหน้าต่างมาถามผู้ใช้ให้ทำการเปิด Bluetooth ขึ้นมาเมื่อมีการกดตอบ (ตกลง, ยกเลิก) จะมีการส่งค่าผลลัพธ์กลับมาที่ onActivityResult ของระบบเพื่อตรวจสอบการตัดสินใจของผู้ใช้
protected void onActivityResult (int requestCode, int resultCode, Intent data)

เมื่อทำการสร้างและเปิดใช้งาน BluetoothAdapter แล้วลำดับต่อไปเป็นการค้นหาอุปกรณ์ Bluetooth ใกล้เคียงเพื่อทำการเชื่อมต่อโดยใช้คำสั่ง
mBluetoothAdapter.startDiscovery();

เมื่อเริ่มคำสั่งทุกครั้งที่เจออุปกรณ์ Bluetooth ระบบจะส่ง Broadcast Intent ที่ชื่อว่า ACTION_FOUND ออกมาซึ่งใน Intent นี้บรรจุข้อมูลใน extra filed คือ EXTRA_DEVICE กับ EXTRA_CLASS หรืออาจมี EXTRA_NAME กับ EXTRA_RSSI ด้วยถ้ามี เราสามารถรับโดยตั้ง BroadcastReceiver เพื่อรับและดึงข้อมูลจาก Intent เช่น ชื่ออุปกรณ์ หมายเลขแอดเดรส ดังตัวอย่าง
// Create a BroadcastReceiver for ACTION_FOUND
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        // When discovery finds a device
        if (BluetoothDevice.ACTION_FOUND.equals(action)) {
            // Get the BluetoothDevice object from the Intent
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            // Add the name and address to an array adapter to show in a ListView
            mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
        }
    }
};
// Register the BroadcastReceiver
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy

ข้อควรระวังเมื่อทำการสั่งค้นหาอุปกรณ์ด้วยคำสั่ง startDiscovery() เสร็จสิ้นแล้วควรทำการยกเลิกการค้นหาก่อนที่จะสร้างการเชื่อมต่อกับอุปกรณ์ที่ต้องการ  เนื่องจากการกลไกในการค้นหาอุปกรณ์ Bluetooth นั้นใช้ทรัพยากรต่างๆ มากและอาจทำให้ความเร็วในการส่งข้อมูลระหว่างอุปกรณ์ช้าลงได้

การตั้งค่าให้อุปกรณ์อยู่ในสถานะ "ถูกค้นหาได้" ด้วยการสร้าง Intent โดยใช้ ACTION_REQUEST_DISCOVERABLE เพื่อขอการเปลี่ยนสถานะถูกค้นหาได้จากระบบ  ค่าตั้งต้นของระบบจะเปิดให้ถูกค้นหาได้เป็นเวลา 120 วินาที  เราสามารถแก้ไขค่านี้ได้โดยเพิ่มค่า EXTRA_DISCOVERABLE_DURATION พร้อมกับค่าเวลาที่ต้องการ (ค่าสูงสุดไม่เกิน 3600) หรือตั้งค่าเป็น 0 เพื่อเปิดให้ถูกค้นหาได้ตลอด ดังตัวอย่างโค้ด
Intent discoverableIntent = new
Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);

Wednesday, May 15, 2013

เขียน blog การเขียนโปรแกรมด้วย CodeSnippet plugin

ในบางครั้งเมื่อเราต้องการแสดงโค้ดให้อ่านง่ายด้วย format ต่างๆตามที่แสดงใน code editor ที่เราใช้ แต่การ copy + paste โดยปกติแล้วจะได้มาแค่ข้อความ เราสามารถใช้ plugin CodeSnippet เพื่อคัดลอกข้อความให้มี format ติดมาด้วยในรูปแบบของโค้ด html ทำให้เราสามารถวางลงใน blog ได้โดยง่าย การติดตั้งทำได้โดยนำโฟลเดอร์ภายในไฟล์ zip ลงใน folder plugin ของ Eclipse จากนั้นปิดแล้วเปิดใหม่ได้เลย

Tuesday, May 14, 2013

การตั้งค่า filter ด้วยเงื่อนไข AND OR ใน Gmail

สร้าง filter ให้มี address เป็นหรือให้ใช้ OR คั่น  แล้วจะได้ผลลัพธ์ดังนี้
from:(email@domain OR email2@domain)
แต่ถ้าใช้กับ word จะใช้ ',' คั่นแทน
-{Call, SMS, Chat}

Thursday, April 25, 2013

ปัญหา error [Emulator] PANIC: Could not open: avd

สร้าง environment parameter ใน system ไปยัง path ที่มีโฟลเดอร์ ".Android" เช่น
ANDROID_SDK_HOME = C:\users\my.username

จากนั้นเปิดโปรแกรม Eclipse เข้าเมนู Window > Preferences > Run/Debug and String Substitution สร้างตัวแปรใหม่ ดังนี้
user.home = C:\Users\Administrator

จากนั้นปิดเปิด Eclipse ใหม่ และทดสอบรัน ADT อีกครั้ง

Wednesday, April 24, 2013

การตั้งค่า auto complete ใน eclipse

มีหลายวิธีรวมๆกัน ยังไม่แน่ใจเหมือนกันว่าอันไหนดีสุดแต่ที่ลองไปคือ

1. เข้าไปที่ Window > Perference > Java > Editor > Content Assist > Advanced ติ๊กเลือกรายการตามรูป


2.  เข้าไปที่ Window > Perference > Java > Editor > Content Assist เลือก Insert best guessed arguments


3. เข้าไปที่ Window > Perference > Java > Editor > Content Assist แล้วเพิ่ม .abcdefghijklmnopqrstuvwxyz ในช่อง "Auto activation triggers for Java"

ปัญหา error Problems occurred when invoking code from plug-in: "org.eclipse.jface".

น่าจะเป็นปัญหาจากการ crash ระหว่างใช้งานโปรแกรมทำให้เกิด error นี้ขึ้นมา  ให้เปิดโปรแกรมใหม่จาก commandline โดยใช้คำสั่ง eclipse.exe -clean

สร้าง android application project ไม่ได้

ปัญหา เมื่อเข้าโปรแกรมเข้ามาโปรแกรมแจ้งให้อัพเดทจาก 21.0.1 ส่วนที่พอสร้าง android application project ตรงช่อง compile with ดันเป็นช่องว่าง  ทำให้กดปุ่ม next ต่อไปไม่ได้



วิธีแก้ เข้าไปเพิ่ม Link update ใน eclipse > help > Install new software เลือก add แล้วใส่ url : https://dl-ssl.google.com/android/eclipse/ จากนั้นโปรแกรมจะแสดงรายการอัพเดทที่มีให้  ก็ให้เลือก Install ทั้งหมด

Friday, January 4, 2013

OPNET fresh install complie error

OPNET install instruction for windows 7 (64-bit)

Requirement



  • Visual studio 2008
  • OPNET 1.6 PL 4

Instuction


  1. Install visual studio 2008
  2. Insert system variable path
    Framework35Version =  v3.5
    FrameworkDir =  C:\WINDOWS\Microsoft.NET\Framework64
    FrameworkVersion =  v2.0.50727
    INCLUDE =  C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\ATLMFC\INCLUDE;C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\INCLUDE;C:\Program Files\Microsoft SDKs\Windows\v6.0A\include;
    LIB =  C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\ATLMFC\LIB\amd64;C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\LIB\amd64;C:\Program Files\Microsoft SDKs\Windows\v6.0A\lib\x64;
    LIBPATH =  C:\WINDOWS\Microsoft.NET\Framework64\v3.5;C:\WINDOWS\Microsoft.NET\Framework64\v2.0.50727;C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\ATLMFC\LIB\amd64;C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\LIB\amd64;
    Path =  C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\BIN\amd64;C:\WINDOWS\Microsoft.NET\Framework64\v3.5;C:\WINDOWS\Microsoft.NET\Framework64\v2.0.50727;C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\VCPackages;C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE;C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\Tools;C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\x64;C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin;
    VCINSTALLDIR = C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC
    VS90COMNTOOLS = C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\Tools\
    VSINSTALLDIR = C:\Program Files (x86)\Microsoft Visual Studio 9.0
    WindowsSdkDir = C:\Program Files\Microsoft SDKs\Windows\v6.0A\
    

    for some device amd64 path is not exist. you have to delete those on LIB, LIBPATH and PATH.
  3. To ensure that the MSVS 2008 is installed correctly, open a Command Prompt and type "cl" to invoke the compiler. Then type "link" to invoke the linker/binder. Confirm that each of these commands returns the correct information for the .NET installation.
  4. Restart your computer.
  5. Install OPNET 1.6 PL4
  6. Start OPNET Modeler
  7. Set repository by go to edit menu select Preferences ( or use the shortcut Alt+Ctrl+P). Type repositories in the Find field and click Find bottom. Then make sure the value of "Network Simulation Repositories" is set to stdmod. If not click on the value column and press the Insert bottom. Enter stdmod and press Ok.
  8. If the Network Simulation Repositories is not set OPNET will give you an error like the following:
    Object repository construction failed
    due to errors encountered by the binder program (bind_so_msvc)
    T (0), EV (-), MOD (NONE), PROC (sim_load_repos_rebuild)