Tuesday, 15 November 2016

Zigbee Tutorial

IEEE802.15.4 defines the Physical and MAC layers, and ZigBee defines the network and application layers. Zigbee layers build on top of IEEE802.15.4.

Zigbee provides the features of low power consumption, low cost, small footprint, and mesh networking capabilities.

Two version: Zigbee 2006, Zigbee Pro (2007)
Zigbee Pro can scale up to thousands of devices.

Zigbee Architecture:

Application Profile is defined by Zigbee specification.
Eg. Home Automation (HA) and Smart Energy (SE).

Devices within an application profile communicate with each other by means of clusters, which may
be inputs to or outputs from the device.

Eg. In HA profile, cluster 0x0006 is the on/off cluster. Cluster 0x0702 is the zigbee power consumption report cluster. In HA profile, to use Zigbee on/off switch to control Zigbee power switch, we can bind the endpoint number of Zigbee on/off switch, with endpoint number Zigbee power switch, on the cluster 0x0006.

An endpoint defines a communication entity within a device. Zigbee Device Object (ZDO) is always endpoint zero. In all, 240 endpoints are available for use within ZigBee device, with endpoint zero dedicated to the ZigBee Device Object (ZDO), which provides control and management commands.

Joining a Zigbee network:

A ZigBee router or coordinator that wishes to allow other devices to join must issue a NLME-PERMIT-JOINING.request.  The joining device must issue a NLME-JOIN.request with the rejoin flag set to FALSE.


ZigBee Security:

It is based on the 128-bit AES algorithm.

Zigbee coordinator also functions as the trust center when security is enabled on the network.
  • Master key - used as an initial shared secret to generate Link key
  • Trust center master key - used to establish the Link key
  • Link Key - at the Application layer, two types: Trust center link key; application layer link key. Link key is used to encrypt the network key
  • Network Key - at the Network layer
Zigbee Concepts:

Three type of devices:
Zigbee end device, Zigbee router, Zigbee coordinator.

PAN ID - Personal Area Network Identifier. The Zigbee coordinator assigns a PAN ID to the network.

Binding - connecting endpoints
Device discovery - finding out other Zigbee devices, requires
  • IEEE address
  • NWK address
Service discovery - finding out services available on endpoints at the receiving device

IEEE802.15.4 Concepts:

IEE802.15.4 operating frequency is at 2.4GHz and 915MHz.
2.4GHz: channel 11-26
915MHz: channel 1-10

IEEE802.15.4 defines 4 types of MAC frame:
  • beacon frame
  • data frame
  • Ack frame
  • MAC command frame


IEEE802.15.4 data frame in action:

Zigbee Home Automation profile:

The Zigbee HA profile defines various device types that have various roles in the HA network. Device types such as Power Outlet(0x0009), On/Off Switch(0x0000), Combined Interface(0x0007), Pump(0x0303), Temperature sensor(0x0302), IAS devices; are frequently used.

Intruder Alarm Systems - IAS
  • IAS Zone(0x0402) - door sensor, smoke sensor
  • IAS Warning Device(0x0403) - siren
  • IAS ACE(0x0401) - remote control
  • IAS CIE(0x0400) - usually it is the Zigbee coordinator
To control zigbee devices. Firstly, zigbee devices must join the zigbee network. Then, Zigbee coordinator can send a data frame to the zigbee devices, to perform desired action. Zigbee devices can also report its status periodically to the zigbee coordinator.

On/Off switch can bind to power outlet, to control the power outlet directly. It is useful when the zigbee coordinator is down.

Zigbee Certification:

We can do testing in four modes:

Zigbee continuous TX
Zigbee continuous RX
Zigbee packet TX
Zigbee packet RX

For TX test, we can set TX channel, TX power, use range extender (an IC) to obtain higher TX power, send modulated or unmodulated signals.

To perform a Zigbee RX test, we need to setup a Zigbee end device and a Zigbee coordinator. The Zigbee end device can join the Zigbee coordinator, provided with the right key and PAN ID.

Wednesday, 14 October 2015

Device Tree in Linux

A device tree is the tree data structure that describes the physical devices in the system hardware. In Linux, the device tree source (DTS) files are located in arch/<xxx>/boot/dts

  •   dts for board level files
  •   dtsi for Soc level definitions

A device tree compiler (DTC) compiles the source into binary files. The DTC source code is in scripts/dtc.c.

The device tree blob (DTB) is produced by the DTC compiler. It is loaded by the bootloader and parsed by kernel at boot time.

Let's look at an real example where a platform driver is using two clocks.

In xxx_probe(struct platform_device *pdev)
    my_port->aaclk = clk_get(&pdev->dev, "aa");
    my_port->bbclk = clk_get(&pdev->dev, "bb");

The corresponding device tree has to reflect the two clocks.

uart0: serial@3000 {
compatible = "xxx,uart";
reg = <0x3000 0x100>;
interrupt-parent = <&gic>;
interrupts = <11 12>;
clocks = <&oscclk 0>,<&oscclk 1>;
clock-names = "aa","bb";
};

The two clock-names needs to have two matching clocks source.

Let's look at at an advanced example of device tree usage:


This example shows an oscillator clock being fed to pll1, pll2 and pll3. The hw3_clk can be derived from either pll2, pll3 or osc clock. 

To model the hardware using device tree. We declare the following entries.

osc: oscillator {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <20000000>;
clock-output-names = "osc20M";
};

pll2: pll2 {
 #clock-cells = <0>;
compatible = "abc123,pll2-clock";
clock-frequency = <23000000>;
clocks = <&osc>;
reg = <0x05 0x10>;
};

pll3: pll3 {
 #clock-cells = <0>;
compatible = "abc123,pll3-clock";
clock-frequency = <23000000>;
clocks = <&osc>;
reg = <0x15 0x10>;
};

hw3_clk: hw3_clk { 
    #clock-cells = <0>; 
    compatible = "abc123,hw3-clk"; 
    clocks = <&pll2>,<&pll3>; 
    clock-output-names = "hw3_clk"; 
}; 

In the source code, to register hw_clk3 as a mux, and show the parent relationship of both pll2 and pll3, we declare the below.

of_property_read_string(node, "clock-output-names", &clk_name); 
parent_name[0] = of_clk_get_parent_name(node, 0); 
parent_name[1] = of_clk_get_parent_name(node, 1); 

clk = clk_register_mux(NULL, clk_name, parent_name, 
      ARRAY_SIZE(parent_name), 0, 
      regs_base , offset_bit, one_bit, 0, NULL);

Sunday, 8 March 2015

More USB stuff

Useful USB debug knowledge:

You can test the USB mass storage gadget's behavior with a Linux host.

To send a Set-Config request with value 0, to de-configure the gadget

        echo 0 >/sys/bus/usb/devices/.../bConfigurationValue

To send a Set-Config request with value 1, to re-configure the gadget

        echo 1 >/sys/bus/usb/devices/.../bConfigurationValue

where the "..." part is replaced with the gadget's device path.

Set-Config has only two stages, Setup and Status stage; there is no Data stage.

Host                        Device
----- Setup Packet --->         |
----- Data0 Packet --->         |== Setup stage
<---- Ack Packet ------         |

----- In Packet ------>         |
<---- Data1 Packet ----         |== Status stage
----- Ack Packet ----->         |


The Data1 packet above contains no data, as below.


      PID   !PID  CRC

USB software layering:

Client SW:

It decides what transfers are to be made with the USB device function.

USB Driver (USBD):

The software interface between the USB System SW and the Client SW. USBD provides the device drivers that the operating systems use to access USB devices.

USB System SW:

It is usually supplied with the operating systems. It can be seemed to include USBD and HCD.

Host Controller Driver (HCD):

The software interface between Host Controller and USB System SW. This interface allows a USBD to support different Host Controllers. HCD is an abstraction of the Host Controller hardware.

Host Controller:

It manages USB protocol level interface. It ensures USB bus access rules defined by the protocol are obeyed, such as inter packet timings, timeouts.
USB Host and Device Partitioning
Control Transfer:

It is started with setup transaction from Host to Device. The Setup transaction is followed by zero or more Data transactions. A Status Transaction completes the control transfer.

Setup Transaction consists of:
setup packet
data0 packet - the request
Ack packet

Data transaction
In packet
data1 packet - the data that is returned by device
Ack packet

Status transaction
out packet
data1 packet - has no data
Ack packet

USB Device Request:

The USB host uses USB requests to get info from USB devices. These request are made using control transfer, from host to device default control pipe.The standard requests are:

  • Get Status
  • Clear Feature
  • Set Feature
  • Set Address
  • Get Descriptor
  • Set Descriptor
  • Get Configuration
  • Set Configuration
  • Get Interface
  • Set Interface
  • Synch Frame

An example of USB request sequence in USB Command Verifier test:

80 06 00 01 00 00 12 00  -  Get device descriptor

Data(12 01 00 02 00 00 00 40 25 05 A5 A4 33 03 01 02  00 01)  - Return device descriptor
80 06 00 02 00 00 09 00 – get config descriptor

Data(09 02 20 00 01 01 04 C0 01) – return config descriptor
00 09 01 00 00 00 00 00 – set configuration

0 byte data
80 06 00 02 00 00 09 00 – get config descriptor

09 02 20 00 01 01 04 C0 01 – return config desc
80 06 00 02 00 00 20 00 – get config desc

0 byte data
80 06 00 01 00 00 12 00 – get device desc

Data(12 01 00 02 00 00 00 40 25 05 A5 A4 33 03 01 02  00 01) – return device desc
80 06 00 06 00 00 0A 00 – get device qualifier

Data(0A 06 00 02 00 00 00 40 01 00) – return device qualifier
80 06 00 02 00 00 09 00 – get config desc

Data(09 02 20 00 01 01 04 C0 01) – return config desc
80 08 00 00 00 00 01 00 – get configuration

Data(01) – return

USB Descriptor:

USB devices report their attributes using descriptors. A descriptor is a defined data structure. Standard USB descriptors are:

  • Device descriptor
  • Device Qualifier descriptor
  • Configuration descriptor
  • Interface descriptor
  • Endpoint descriptor
  • String descriptor

Sunday, 4 January 2015

USB Mass Storage Device Enumeration, and usbmon

An usbmon text output dissection

Some quick commands to before running usbmon:

# mount -t debugfs none_debugs /sys/kernel/debug
# modprobe usbmon
# cat /proc/bus/usb/devices
/*to find out the usb devices number on the usb bus*/


# cat /sys/kernel/debug/usb/usbmon/2u > /tmp/mon.out
As an example, a control packet:

f4ae6f40 1217192721 S Co:2:018:0 s 21 ff 0000 0000 0000 0

f4ae6f40 - URB Tag

1217192721 - Timestamp in microseconds


S - Event Type, S is submission


Co:2:018:0 - "Address". It consists of four fields, separated by colons: URB type and direction, Bus number, Device address, and Endpoint number. 
Co is Control output.

s - URB Status. This is a letter, so 's' is Setup Tag of control packet. It can also be several numbers separated by colons.



21 ff 0000 0000 0000 - Setup packet, if present, consists of 5 words: one of each for bmRequestType, bRequest, wValue, wIndex, wLength

0 - Data Length. For submissions, this is the requested length. For callbacks,this is the actual length.


Now we will look at mass storage device enumeration within the USB gadget framework. The USB gadget framework is available in Linux and U-boot.

USB halt and wedge feature:


Two types of events may cause a USB halt condition.

1) The device did not receive a handshake packet from USB host after communication.
2) The device receive set halt request from the host

Set halt and set wedge are basically the same, with the difference that, the device will ignore clear halt request from the host if device is in set wedge condition.

USB mass storage gadget enumeration steps:

The USB code can be divided into two parts: Usb Mass storage gadget code and Usb device controller code.

Firstly, the host PC sends the setup data to get descriptors from Usb device. It is performed using control transfer.


.
So the Usb chip receives it and interrupt is triggered. In Usb device controller code,
myudc_isr(void) [the interrupt handler]

reads the IVECT register and gets 0x00 value. It passes control to gadget code
fsg_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)

The setup data is processed, the response is prepared. If there is data to send out to EP0, the device controller function
my_ep_queue(struct usb_ep *ep, struct usb_request *req, gfp_t gfp_flags)

is called to send out the data.

After device, configuration, interface, endpoint, string descriptors are received by the host PC, the host PC detects the Usb device as a mass storage device (that is for a Usb mass storage device).

Device Descriptors:
As an example, the device descriptor is dissected here.

First Byte : bLength (the size of the descriptors in bytes) 0x12
Second Byte: bDescriptor (device descriptor)                 0x1
3rd-4th Byte: bcdUSB (USB spec number)                   0x0002
5th Byte: bDeviceClass (class code)                              0x00
6th Byte: bDeviceSubClass (subclass code)                   0x00
7th Byte: bDeviceProtocol (protocol code)                   0x00
8th Byte: bMaxPacketSize (max. packet size)                0x40
9-10 Byte: idVendor (vendor ID)                                  0x2505
11-12 Byte: idProduct (product ID)                               0xA5A4
13-14 Byte: bcdDevice (device release number)             0x0103
15th byte: iManufacturer (index of manufacturer string desc)      0x01
16th byte: iProduct (index of product string desc)                      0x02
17th byte: iSerialNumber (index of serial num. string desc)         0x03
18th byte: bNumConfigurations (number of possible config.)      0x01

Next step, the host PC will send SCSI commands to Usb device. The SCSI command is wrapped in CBW and sent using bulk transfer.


 So the Usb chip receives it and interrupt is triggered. In Usb device controller code,
myudc_isr(void) [the interrupt handler]

reads the IVECT register and gets 0x28 value for EP1 OUT IRQ. The data is read from FIFO, and sent to gadget function
bulk_out_complete(struct usb_ep *ep, struct usb_request *req)

in gadget code. This function will wake up thread in get_next_command((struct fsg_dev *fsg) and the thread will process the SCSI command. The get_next_command() is waiting for a buffer, which must be the same as the buffer returned by interrupt handler.

Again, if there is data to be replied to host PC, the device controller function
my_ep_queue(struct usb_ep *ep,  struct usb_request *req, gfp_t gfp_flags)
is called to send data to EP1 IN using bulk transfer.

After that, for every SCSI command, the gadget code will call gadget function
send_status(struct fsg_dev *fsg)

to prepare the CSW, and CSW is sent to the host PC using device controller function
my_ep_queue(struct usb_ep *ep,  struct usb_request *req, gfp_t gfp_flags)

 via EP1 IN.

The Transfer Protocol:

The Bulk Only Transport (BOT) is defined by Usb mass storage specification. It defines how Usb host can use bulk transfer to send commands and receives response from Usb device.

In the first transfer, the host sends a command in a structure called a Command Block Wrapper (CBW). The CBW is 31 byte in length. Many CBWs are followed by a transfer that contains data sent to the host or device.
For example, the CBW structure of a SCSI Inquiry command:

dCBWSignature  0x55 0x53 0x42 0x43
dCBWTag
dCBWDataTransferLength   0x24
bmCBWFlags
bCBWLUN
bCBWCBLength             0x06 (The valid length of CBWCB in bytes)
Operation Code               0x12
enableVitalProductData    false
commandSupportData       0x0
page or opcode                  0x0
allocation length                0x24
control                              0x0

In the final transfer, the device returns status in a structure called a Command Status Wrapper (CSW).

CSW structure:

dCSWSignature    0x55 0x53 0x42 0x43
dCSWTag
dCSWDataResidue    0x0
bCSWStatus               0x0

The SCSI Commands:

The SCSI commands used by the Usb mass storage device are from SCSI Primary Commands (SPC-2) and SCSI Block Commands (SBC-2).

Some of the commonly used commands, together with the command codes, are listed below.

SCSI Inquiry                0x12
SCSI Request Sense    0x3
SCSI Read Capacity    0x25
SCSI Read 10             0x28
SCSI Mode Sense 6    0x1A
SCSI Mode Select 6    0x15
SCSI Test Unit Ready  0x00

SD Card Partition Table:

The SD card will try to mimic a hard disk.

The MBR is located at offset 0x0, size is 512 bytes.

                      boot code (first 446 bytes)
                      partition #1  0x1BE (each partition is 16 bytes)
   MBR           partition #2
                       partition #3
                       partition #4
                       0xaa55   0x1FE  (signature)

Partition table info: (from offset 0x1BE)

0x00  0x80 if bootable, else 0x0
0x01  start of partition in CHS
0x04  type of partition
0x05  end of partition
0x08  relative offset to the partition in LBA (Partition LBA begin)
0x0C  size of the partition

For example, if the relative offset in LBA is 0x2000, it means the start of the boot sector is 0x2000.

At 0x2000, it is the FAT boot record (if formatted in FAT file system).

For example, FAT32 boot record:

0x00  3 bytes    0xeb0090       jump instruction
0x03  8 bytes    MSDOS5.0    OEM name
0x0B  2 bytes    0x0200           bytes per sector
0x0D  1 byte      0x08               sectors per cluster
0x0E   2 bytes     0x20               number of reserved sector (usually 0x20)
0x10   1 byte      0x2                 number of FATs
0x11   2 bytes                           N/A
0x13   2 bytes                            N/A
0x15   1 byte    0xF8                 media descriptors(F8 for hard disk)
0x16   2 bytes                            N/A
0x18   2 bytes                           sectors per track
0x1A  2 bytes                             number of heads
0x24   4 bytes                         sectors per FAT
0x2C   4 bytes                          root directory first cluster
0x5A  420 bytes                      bootstrap code
0x1fe  2 bytes    0x55aa           end of boot sector mark

Important info that are needed for accessing the FAT32 filesystem:


(unsigned long)fat_begin_lba = Partition_LBA_Begin + Number_of_Reserved_Sectors;
(unsigned long)cluster_begin_lba = Partition_LBA_Begin + Number_of_Reserved_Sectors + (Number_of_FATs * Sectors_Per_FAT);
(unsigned char)sectors_per_cluster = sectors_per_cluster;
(unsigned long)root_dir_first_cluster = root_directory_first_cluster;

Wednesday, 19 November 2014

[iOS App] 'NSInvalidArgumentException', reason : unrecognized selector sent to Instance

I am going through iOS App development recently. I use modal segue to move from parent ViewController to child ViewController, as shown in the picture below.


When i return from child ViewController to parent ViewController.  There is an error.


2014-11-20 09:00:48.229 Heritage[64395:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[XYZContinentTableViewController topViewController]: unrecognized selector sent to instance 0x8c60050'

The error shows up when i have 3 level of ViewController, and specifically, from second level ViewController to root ViewController.

I found out the root cause. It is because the unwind segue

- (IBAction)unwindToRegion:(UIStoryboardSegue *)segue
{  }

is mixed up with prepareForSegue.

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    ....
}
   
To fix the error, in prepareForSegue, add the segue identifier checking. Make sure prepareForSegue is only processing the forward segue (In our case, the UserShowSegueCountry).

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    
    if ([[segue identifier] isEqualToString:@"UserShowSegueCountry"])
    {
    UINavigationController *nav = segue.destinationViewController;
    XYZCountryTableViewController *vcToPushTo = (XYZCountryTableViewController *)nav.topViewController;
        
    }
    

}


Wednesday, 15 October 2014

IP address conflict and its detection

We have an IP network, with devices getting their IP address from DHCP server. A problem could arise when a device is off the network, then reconnect to the network, and its IP address is the same as other device which has just joined the network. This could be due to DHCP server thinks that the DHCP lease has expired, but the device doesn't. This is a problem of IP address conflict.

To detect IP address conflict, we can use two methods

1) ARP probe: It is an ARP request. The sending device fills the source MAC address with the hardware address of its interface, and the source IP address must be all ZEROes. The destination MAC address should be all ZEROes. The destination IP address is the address being probe. If the sending device receives any ARP on the interface where probe is being performed, where the packet's source IP is the IP being probed for, then this IP is used by other host. So it is an IP conflict.

2) Gratuitous ARP: It could mean both gratuitous ARP request or gratuitous ARP reply. Gratuitous in this case means a request/reply is not required, but could be used in some cases. In a gratuitous ARP request,  the source and destination IP are both set to the IP of the device issuing the packet, and the destination MAC is the broadcast address ff:ff:ff:ff:ff:ff. Ordinarily, no reply packet will occur. A gratuitous ARP reply is a reply to which no request has been made. When a device receives an ARP request containing a source IP that matches its own, then it knows there is an IP conflict.

Tuesday, 2 September 2014

Java Serializer

In Computer Science, serialisation is a process of translating data structures or objects into a byte stream that can be stored (in a file or memory buffer), or can be transmitted across a network link, and the byte stream can be re-read and re-constructed into the same clone.  Serialisation is a way to prevent the byte ordering (endianness), memory layout problem.

In Java, the java.io.serializable implement the serialisation. You can write a Java class to implement the Serializable interface.

class IsSerializable implements Serializable  
{  
    private String plug = "Plugin to Java!";  
    public IsSerializable()  
    {  
        try  
        {  
            FileOutputStream out = new FileOutputStream("/mnt/sdcard/yes-out.txt");  
            ObjectOutputStream oos = new ObjectOutputStream(out);  
            oos.writeObject(this);  
        }  
        catch (Exception e)  
        {  
            e.printStackTrace();  
        }  
    }  

}  

@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        IsSerializable is = new IsSerializable();  
        ...
}

If you run this code, there is an error message:

java.io.NotSerializableException: com.example.xxxxx.MainActivity.

The reason is that you can't get the whole class to be serialised.

Solution:
If we replace oos.writeObject(this); with oos.writeObject(plug);  the problem is fixed.

Monday, 25 November 2013

View the Android App database contents

So you created your Android App with SQLite database, and you are interested to view the database offline. You can do it with the adb command.

1) in command line, issue "adb shell" command, and then you will go to android prompt:
root@android:/ #

2) cd data/data, then ls, and you will see a lot of the App package:
com.android.bluetooth
com.android.browser
com.android.calculator2
com.android.calendar
com.android.certinstaller
com.android.contacts
com.android.defcontainer
....

3) cd  to your App package, say for example "com.victor.example"

4) cd databases, and ls to find out the databases name

5) run the command "sqlite3 mydb.s3db"
root@android:/data/data/com.victor.example/databases # sqlite3 mydb.s3db
sqlite3 mydb.s3db
SQLite version 3.7.11 2012-03-20 11:35:50
Enter ".help" for instructions
Enter SQL statements terminated with a ";"

6) check the table name
sqlite> .tables
.tables
android_metadata  employees
sqlite> select * from employees;
select * from employees;
1|mitt|01234567|01234567|20
2|mitt|01234567|01234567|20
3|mitt|01234567|01234567|20
4|mitt|01234567|01234567|20
5|mitt|01234567|01234567|20
sqlite>

7) That's it. You successfully view the App database content using the adb shell command.

Sunday, 24 November 2013

Export Excel data to MySQL database


We will show you how to export Excel data to MySQL db.

The steps are:

1) saved the excel data to csv format, such as below
BK001,Introduction to science,976,85.0
BK002,Human Anatomy,985,200.0
BK003,Concepts in Health,765,100.5

2) create a db table that matches the csv format
mysql> create table book_info
    -> (book_id varchar(20), book_name varchar(40), isbn_no int(11), book_price, int(10));

3) run the mysql command
mysql> load data infile 'c:\\Book1.csv' into table book_info fields terminated by ',' lines terminated by '\n';
Query OK, 3 rows affected (0.07 sec)
Records: 3  Deleted: 0  Skipped: 0  Warnings: 0

After that, the db contains the Excel data, To verify, issue the command:

mysql> select * from book_info;
+---------+-------------------------+---------+------------+
| book_id | book_name               | isbn_no | book_price |
+---------+-------------------------+---------+------------+
| BK001   | Introduction to science |     976 |         85 |
| BK002   | Human Anatomy           |     985 |        200 |
| BK003   | Concepts in Health      |     765 |        101 |
+---------+-------------------------+---------+------------+
3 rows in set (0.00 sec)

Friday, 25 October 2013

Facebook App Development on Android

On Facebook
Firstly, we talk about the tasks and tools available on Facebook developers.

Now, login to your FB account, go to "Manage Apps"

Choose "Edit App" or "Create New App".

Here are the basic settings of the App:

Then, choose "Use Graph API Explorer".
Enter the POST action path: "me/victory-test-now:gin"

victory-test-now is the namespace, gin is the Action. You may have to add the Action in the "Open Graph" section beforehand.


The food url is from "Open Graph->Types":

After clicking submit button in the Graph API Explorer, go to the Activity Log of the user. You can see the Action in the Activity Log.

You can add a place field to the POST Action.

The place id can be obtained using the following method.

Click on the profile picture, right click, choose "Copy link address"

For example, the link address is below.
https://www.facebook.com/photo.php?fbid=10150753663333147&set=a.438257763146.238406.145768288146&type=1&source=11

The place id is "145768288146".

The Action can be seen in the Activity Log again.

On Android
Secondly, we highlight how the Android App is able to access the data in Facebook through the Facebook App.

Preparation steps:

  • Download the Facebook SDK for Android
  • Import the SDK into Eclipse
  • Compile and build it

After that, you can start to create an Android App in Eclipse. The good tutorial from FB is listed below:
https://developers.facebook.com/docs/android/getting-started/facebook-sdk-for-android/

After you have created the Android App, we go back to the App Dashboard on Facebook Developers, and register the Android package and activity name in the "Native Android App" settings. As an example, the detail info is shown below.

To get the Key Hash, add the code to the OnCreate() method of the MainActivity class.
    // Add code to print out the key hash
    try {
        PackageInfo info = getPackageManager().getPackageInfo(
                "com.facebook.samples.hellofacebook", 
                PackageManager.GET_SIGNATURES);
        for (Signature signature : info.signatures) {
            MessageDigest md = MessageDigest.getInstance("SHA");
            md.update(signature.toByteArray());
            Log.d("KeyHash:", Base64.encodeToString(md.digest(), Base64.DEFAULT));
            }
    } catch (NameNotFoundException e) {

    } catch (NoSuchAlgorithmException e) {

    }
Publish to Facebook Feed

In the Facebook tutorial below,
https://developers.facebook.com/docs/android/scrumptious/publish-open-graph-story/
it talks about publishing to Open Graph story.

You could modify the code to make it publish to Facebook Feed. Sounds interesting, isn't it? The essential changes are:

1) populate the Bundle with the description, link, name, caption
2) change the post action path to "me/feed"

The obvious changes are not difficult. However, you may have to retrieve the user info from List<GraphUser>.

                        public String announceString;
                        ...
                        private List<GraphUser> selectedUsers;
                        ...
                     for (GraphUser user : selectedUsers) {
                         announceString += user.getName();
                     }

The changes to AsyncTask:

AsyncTask<Void, Void, Response> task =
    new AsyncTask<Void, Void, Response>() {

    @Override
    protected Response doInBackground(Void... voids) {
        // Create an eat action
        EatAction eatAction =
        GraphObject.Factory.create(EatAction.class);
        // Populate the action with the POST parameters:
        // the meal, friends, and place info
        for (BaseListElement element : listElements) {
            element.populateOGAction(eatAction);
        }
        // Set up a request with the active session, set up
        // an HTTP POST to the eat action endpoint
         // Request request = new Request(Session.getActiveSession(),
         //         POST_ACTION_PATH, null, HttpMethod.POST);
        Bundle postParams = new Bundle();
        postParams.putString("name", "Gin food");
        postParams.putString("caption", "Gin food");
        postParams.putString("description", announceString);
        postParams.putString("link", announceUrl);
        Request request = new Request(Session.getActiveSession(),
        "me/feed", postParams, HttpMethod.POST);
       
        // Add the post parameter, the eat action
        request.setGraphObject(eatAction);
        // Execute the request synchronously in the background
        // and return the response.
        return request.executeAndWait();
    }

    @Override
    protected void onPostExecute(Response response) {
        // When the task completes, process
        // the response on the main thread
        onPostActionResponse(response);
     }
};

Tuesday, 22 October 2013

Factory Design Pattern

The factory design pattern is a pattern that has some methods that create objects for you. You don't use new method directly to create the objects. 

When you want to change the types of objects created, you just change the factory. All other codes that use the factory change automatically.

For example, in PHP:

<?php

class ClassModelC {
  private $ModelC;  
  public function __construct($c)
  {
    $this->ModelC = $c;
  }
  public function getModel()
  {  return $this->ModelC; }
}
class ClassModelB {
  private $ModelB;
  public function __construct($b)
  {
    $this->ModelB = $b;
  }  
  public function getModel()
  {  return $this->ModelB; }
}

class ClassModelA {
  private $ModelA;
  public function __construct($b, $c)
  {
    $this->ModelA = $b->getModel().' '.$c->getModel();
  }
  public function getModel()
  {
    return $this->ModelA;
  }
}

class Factory{
    public function build($b, $c)
    {
        $classc = $this->buildC($c);
        $classb = $this->buildB($b);
        return $this->buildA($classb, $classc);
    }

    public function buildA($classb, $classc)
    {
        return new ClassModelA($classb, $classc);
    }

    public function buildB($b)
    {
        return new ClassModelB($b);
    }

    public function buildC($c)
    {
        return new ClassModelC($c);
    }
}

$factory = new Factory;
$obj     = $factory->build('Thunderbird','Jaguar');
print_r($obj->getModel());
print("\n");
?>

If in future, you want to change the object type, you can just change the factory method, as below.

class Factory_New extends Factory{
    public function build($b, $c)
    {
        return DatabaseObject($b, $c);
    }
}

Wednesday, 9 October 2013

Getting Started with the Amazon Web Services

The Amazon Web Services (AWS) is a set of virtual computing and storage services. It is scalable, flexible, and has low start-up cost.

AWS application can be programmed through PHP, Python, Java, and Ruby, etc. Mobile apps can also access AWS through SDK for Android and iOS.


Sign up for AWS products
A credit card is required in order to sign up for AWS. You can use EntroPay, a virtual credit card provider, as the credit card.

Get the Security Credentials from your AWS account
Create a group and user in AWS IAM. The purpose is to get the access key ID and the secret key.

Using AWS SDK for PHP
  • install PHP
  in Windows, copy the following dll files to Windows/System32 folder
    libeay32.dll
    ssleay32.dll
  and also, modify php.ini, and enable the curl extension.
  • install the SDK for PHP
git clone git://github.com/amazonwebservices/aws-sdk-for-php.git AWSSDKforPHP
cd ./AWSSDKforPHP
  • configure the security credentials
  copy the config-sample.inc.php file in the SDK folder, and rename it to config.inc.php, and change the access key ID and secret key
  • run the sample php file 
  in the samples folder, run
    php cli-s3_get_urls_for_uploads.php

EXAMPLE
one example of access the bucket using non composer way, it is heavily commented.

<?php

//non-composer way, you need to download aws.phar separately
require 'aws.phar';

use Aws\S3\S3Client;

// Instantiate the S3 client with your AWS credentials and desired AWS region, 
// you must create a user in AWS IAM console
$client = S3Client::factory(array(
    'key'    => 'AKIAILBKCPBE6I2GEKOA',
    'secret' => '2Nbn7LJl/sDz40kviPCFBaOHxZItDelQ1pZzhPyq',
));

//The requested bucket name is not available. 
//The bucket namespace is shared by all users of the system. 
//Please select a different name and try again.
//If you see this error, it means the bucket name is already used by other people. 
//Please choose a bucket name which is not common
$bucket = 'my-bupket1'; 
$array_bucket = array('Bucket' => $bucket);

//check for existence of bucket
if (($client->doesBucketExist($bucket, true, $array_bucket)) == false)
{
  $result = $client->createBucket($array_bucket);

  // Wait until the bucket is created
  $client->waitUntil('BucketExists', array('Bucket' => $bucket));
  echo "bucket created";
}
else
{
  echo "bucket exist";
}

// Key is the identifier of the object
// Body is the content of the object
$client->putObject(array(
    'Bucket' => $bucket,
    'Key'    => 'README.md',
    'Body'   => fopen('README.md', 'r')));

$result = $client->getObject(array(
    'Bucket' => $bucket,
    'Key'    => 'README.md'
));

//the Body value can be cast to a string
echo $result['Body'] . "\n";
?>

Using AWS SDK for Android
  • install Eclipse for Android
  This is necessary to build an Android application.
  • install the SDK for Android
  After that, go to download the SDK from http://aws.amazon.com/developers/getting-started/android/
  • import the sample Android project
   From the samples folder, choose S3_Uploader, change the security credentials, and build the project, and run the application.