Archive for the ‘Java & OSGi Development’ Category
How to learn XML, HTML or for that matter anything in Programming
OSGi Bundle Management Code [Part 4, ROM]
In the part 4 of my series I am going to describe the OSGi/Java code on the Plug Computer that implements the bundle manager in the ROM (Remote OSGi Manager) project…. and one of the best parts of doing this particular portion was that I started getting a much better understanding of the XML fundamentals. Notionally I always understood XML, but this was my first time programming with it.
At the simplest level – there is an OSGi bundle that receives network command over a Sockets Interface from the IOS app or a Java Test app, and then performs the appropriate action. These commands are all listed in the overview post. And I did get some good help from my Java programming friends to implement the entire interface along with the Java test application that I used to test the interface and responses. First step to start a TCP server, here is the code snippet to accept a incoming connection and spin it on a new thread:
try {
ServerSocket ss = new ServerSocket(port);
ss.setSoTimeout(soTimeout);
System.out.println("\nSocket Server listening on port "+port);
while (stopFlag == false) {
try {
Socket s = ss.accept();
clients.addElement(new Worker(s,bc));
System.out.println("Worker Thread Created");
} catch (Exception ignore) {
System.out.println(ignore.getMessage());
} }
One challenge, that I faced later, was the decision to use UTF8 functions in Java to avoid network ordering issues. This did create problems during the IOS app but it was a good learning experience that was overcome using Google Search and Stack Overflow. The spawned worker thread handles the commands using Switch/Case flow:
public void run() {
String message = null;
String content = null;
int option = -1;
int BId = -1;
String file = "";
try {
message = dis.readUTF();
System.out.println(message);
if (message != null)
option = Integer.parseInt((message.split(","))[0]);
BId = Integer.parseInt((message.split(","))[1]);
file = message.split(",",3)[2];
System.out.println("Recd packet from client Option:"+option+" BID:"+BId + " file:"+file);
} catch (IOException e1) {
System.out.println(e1.getMessage());
}
//System.out.print("message: "+message+"\n");
DoOps getb = new DoOps();
switch (option){
case LIST_BUNDLES:
content = getb.getBundleList(bc);
break;
case GET_BUNDLE_INFO:
content = getb.getBundleInfo(BId, bc);
break;
case STOP_BUNDLE:
content = getb.stopBundle(BId, bc);
break;
case START_BUNDLE:
content = getb.startBundle(BId, bc);
break;
case UPDATE_BUNDLE:
content = getb.updateBundle(BId, bc,file);
break;
case SYS_INFO:
content = getb.getControllerInfo(bc);
break;
case INSTALL_BUNDLE:
content = getb.installBundle(bc, file);
break; } try {
dos.writeUTF(content);
dos.flush();
dos.writeBoolean(true);
this.stopWorker();
s.close();
return;
} catch (IOException e) {
System.out.println(e.getMessage());
} }
All the commands are implemented in the Class DoOps, which perform the command and return the result. The first two commands above in the Switch/Case statements are returning XML schemas. The List of All Bundles returns all the bundles as XML content and the Get Bundle Info returns details of the requested bundle using an XML schema as well. Here is the XML schema/format for the List of Bundles:
<?xml version="1.0" encoding="UTF-8"?> <bundles> <bundle id="0"> <name>name of bundle</name> <status>ACTIVE</status> </bundle> </bundles>
SSDP Service using Java/OSGi [Part 3, ROM]
The SSDP service runs as a thread when the OSGi bundle is installed and started – “AdvertiseServiceSSDP()”. [The call before that – SocksServer is the class that implements the network interface between the IOS app & the Plug Computer as explained in the project overview.
public void start(BundleContext bc) throws Exception {
this.bc = bc;
nServer = new SocksServer(bc);
advtROMService = new AdvertiseServiceSSDP(bc);
}
Here is the SSDP code:
public void run() {
String msg = "LISTEN-FOR=THIS MESSAGE";
String chkResponse = "RESPOND-WITH-THIS-MESSAGE";
try {
int port = 1900;
InetAddress listenSSDP = InetAddress.getByName("239.255.255.250");
MulticastSocket ms = new MulticastSocket(port); // Create socket
ms.joinGroup(listenSSDP);
System.out.println("\n Rcvr started, Ready to Receive... \n");
boolean match = false;
do {
byte[] response = new byte[256];
DatagramPacket rspPkt = new DatagramPacket(response, response.length);
ms.receive(rspPkt);
//System.out.println("\n Done Receiving!\n");
String getResponse;
getResponse = new String(rspPkt.getData());
match = getResponse.regionMatches(0, msg, 0, msg.length());
if (match)
{
System.out.println("Controller found\n");
// Send Response
InetAddress IPAddress = rspPkt.getAddress();
byte[] sendData = new byte[1024];
String sendResponse = chkResponse;
sendResponse += IPAddress.getHostName();
sendResponse += "/:portAddr";
System.out.println(sendResponse);
sendData = sendResponse.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, 1900);
ms.send(sendPacket);
System.out.println("Response Sent");
match = false;
}
} while(match==false);
} catch(Exception ignore) {
System.out.println(ignore.getMessage());
}
}
The above code when running on the Plug Computer(s) allows the IOS app to discover them. Of course the beauty is that this will work for all devices that support OSGi/JVM and have multicast networking support.
SSDP Service/Device Discovery [Part 2, ROM]
//// serviceSSDP.h// SimpleSSDPDiscovery//// Created by Ashu Joshi on 3/1/12.// Copyright (c) 2012 Movinture, LLC. All rights reserved.//
#import <Foundation/Foundation.h>#import “AsyncUdpSocket.h”#import “connectedLifeController.h”
@interface serviceSSDP : NSObject
// This is the string that is Multicast to Discover the Controller@property (strong, nonatomic) NSString *discoverControllerString;// The Controller would respond with the string below upon discovery being received@property (strong, nonatomic) NSString *responseStringFromController;// The list of discovered controllers@property (strong, nonatomic) NSMutableArray *controllerList;
@property (strong, nonatomic) connectedLifeController *currentController;
@property (strong, nonatomic) AsyncUdpSocket *ssdpSocket;
– (BOOL)startControllerDiscoveryProcess;
– (BOOL)startControllerDiscoveryProcess:(NSMutableArray *)listOfControllers;@end
Getting Started: IOS-based OSGi Application Manager
I am going to provide more details on the project that I have in of the earlier posts. The objective of the project is to build a network interface between an iOS application & a device running OSGi (it could be any device running OSGi since that lends to portability but I am going to start with a Plug Computer). And using that network interface/protocol the IOS/iPad application would function as a “Remote Manager” to the Plug Computer. Obviously all code on the Plug that interacts with the iOS/iPad app would be developed in OSGi/JVM.
I had started doing some preliminary design work and thinking through in late January, and to prepare spent last two weeks of December (2011) getting my coding skills comfortable with both Java & iOS/Objective-C. The approach was to build the project incrementally, baby steps at a time. The key was to define the network protocol/interface between the iOS App & Plug. The interface by itself was very simple but I had to decide what it would do and more importantly in the first iteration what it won’t do.
Here is a simple diagram illustrating the protocol/interface, and I had decided to use a Sockets Interface between the iOS and Plug. The Plug and the iPad are both on the same network/subnet.
Using sockets was my first decision – in my next iteration I would move to a REST API between the two. I can comfortably say 3 months into it that the design & implementation is flexible enough where my “network interface” code on both sides is separate from the actual command processing. The next couple of decisions were also what not to take on in the first round of implementation – no TLS/SSL sockets and no authentication. I would take that on once I have the entire interface working. In addition there is no authentication or provisioning for the iPad/iOS app – that is – I have not built in any authorization check before the iOS/iPad app would be allowed to access the OSGi information on the Plug computers.