Skip to Content
(link to part one (How to take on Four SAP Mentors and win, or how I did Demo Jam Aussie Rules Style. (Part One))) h2. The story so far… I had managed to con Neil (aka @TonkaPome) into teaming up with me to build an utterly mad SAP augmented reality application that reads barcodes …and to make it more fun it does it whilst flying. We’d just been told that we had actually been successful in our bid to compete against the crème-de-la-crème of the DemoJam world, and were suddenly realising that this meant we ought to do some work. Oh and we’re 900km apart (thankfully same timezone.) h2. Lights, Camera, Action! Have awesome Wifi controlled video streaming quadracopter.  AR Drone Check. Have any means to control it… hmmm, says on box that it can be controlled by iPhone or iPad (this was before the iPad2 days).  I have this –little– “thing” though, about Apple’s closed development environment and have sort of rabidly boycotted any of their products. So no iOS devices in my house. But fortunately a quick trip to the AR Drone Developer Site (https://projects.ardrone.org/) and I have the Drone SDK – which includes a Linux (yeah) example of some code to control the Drone using a Play Station USB controller. Excellent – so, now one minor problem I don’t have a Linux install anywhere in the house. Next stop Ubuntu (http://www.ubuntu.com/) for an easy to install, easy to administer Linux system. Several + hours later (it was at least two nights of frustration) and a change in PC’s BIOS to change how my hard disks thought they were being controlled and I had a nice dual booting Ubuntu/Win7 on my PC. (I still have no idea what I really changed, just that it all works now). Cool!… But I only have an XBox 360 wireless remote  (I don’t actually have an XBox 360 by the way – I just use this remote to play games on my HTPC very, very occasionally.) So hacked the code to control the drone to recognise the Xbox360 remote instead (my first playing with C since university a long time ago).  Xbox360 Wireless Remotejstest running in Ubuntu  A little bit of playing with the jstest testing tool and I had figured out which buttons should be mapped to what. Compared to installing the OS this was a breeze, and soon I had my first taste of –flying– attempting to fly the helicopter around my front room. Only a few crashes. h2. Collaboration and Integration, Sticky tape and string +(it’s what holds it all together).+ Having proved that I could –control– get the drone into the air, the next stage was to figure out how to get any data out of it and integrate it into SAP. This was going to need a little help and a little organisation. I managed to get Neil on Skype (took about a week because we both have families that come first and I have a very unreliable internet connection.) Had a great chat and decided we ought to have some way of collaborating. So whilst we were both online, we both signed into SAP StreamWork (http://www.sapstreamwork.com/) (having first visited that nice Streamworks (http://www.streamworks.com/) fly-fishing site, I bet they wonder why they get so many random hits from all around the world). The ability to use my Google account to validate my user was a really nice touch,. We created an “Activity”, spent about 10 minutes trying to figure out how to let each other both see it, and then we had our first Streamwork “work item”. Weren’t we proud.  Streamwork Decision  We continued to use StreamWork all through the project – after all the point of the project was to get us familiar with SAP technologies and it (SAP StreamWork) was quite good. I was/am quite a big fan of the Google Wave – the instant feedback was something that I really liked. This flexibility and instant collaboration was something I find lacking in StreamWork – texts only appear after you’ve finished typing them. Many people I speak to like this feature. Personally, I’m still a fan of immediate distribution of info – it’s more like you’re in the room with the person you are working with, rather than working at a distance. But, StreamWork never crashed on me and even recovered gracefully when my internet connection starting doing its yo-yo thing. Sometimes I was a little frustrated by the lack of available ways to collaborate – no whiteboard for example, which for me is almost a requirement. But all in all was quite happy – 3.5 stars. It’s a grown up version of the Wave. I think for the next remote collaboration (unless I can use the cool SAP Research Gravity tool, (http://www.youtube.com/watch?v=FaNhXPSCQWo&rel=0) old Demo (http://www.sdn.sap.com/irj/scn/elearn?rid=/library/uuid/f0be4b4d-9202-2d10-4d95-e6cf6a091819)) – Hmm seems the Beta is open for people to use (How to get access to the new SAP StreamWork tool for modeling process flows) , I might be convinced,  and I’d almost buy an iPhone to use Holodeck (http://twitpic.com/4bzyaj)) I’ll probably try out the new Google Docs collaboration tools (http://www.youtube.com/watch?v=7zmOYziFKZw&feature=player_embedded&rel=0) – just a little more freeform.   h2. “And the Australian Grand Prix is GO GO GO” +Murray Walker+ The next step was for Neil to give me a little bit of a beginners course in starting an SAP NW7.02 ABAP system. Turns out it’s exactly the same as starting a SAP NW7.0 Java system (which I’ve done lots of). The fun part here of course was that the system was running in the Amazon EC2 cloud. I was blown away by how simple it was to start up the system, and then remote desktop into it. Even whilst I was running Ubuntu, I could use a simple client to access the Windows server in EC2 and start and stop it. So easy and so powerful. Step 1) – Start your engines  Starting an EC2 instance Step 2) Go Go Go!  Linux remote desktop cloent  Starting SAP h2. “I have (http://en.wikiquote.org/wiki/Blackadder) a cunning plan” +Blackadder+ Ok, back to the checklist : ** Means of remote collaborationtick ** SAP System (in cloud)tick ** Ubuntu system to control Helicoptertick ** Xbox360 wireless controller working with Linuxtick ** Any kind of interaction between systems …red cross It was clear, we needed to get some sort of interaction between the helicopter and the SAP system. But before we could get integration/interaction we had to figure out how and what. I had wanted to control the helicopter from the phone and talk to SAP at the same time. However, I found that the ability of my phone to use two separate wireless networks simultaneously  is, understandably, quite limited. So I couldn’t connect to the wireless access point generated by the AR Drone and at the same time connect to the Internet. (I could if I wanted to use my mobile data plan to do the Internet bit (http://developer.android.com/reference/android/net/ConnectivityManager.html) , but at that point I wasn’t on a particularly healthy data plan, and I didn’t trust my coding skills not to accidentally balls it up and end up with an enormous phone bill (not to mention this functionality isn’t really part of the standard Android SDK but a bit deeper into the guts of the OS.) So the wonderful idea of using the phone to control the Drone was put on ice. 🙁 However, the same multiple wireless networks issue did not cause any difficulty for my Ubuntu PC. 🙂   h2. Seems barcode scanners and not only custom ABAP start with “Z”. The next bit to be worked out was how to scan the barcode. I’d seen a pretty cool implementation of a barcode scanner in Android called ZXing (http://code.google.com/p/zxing/) (apparently it’s supposed to be pronounced “Zebra Crossing”, but if you’re like the rest of the uneducated world and learnt to read phonetically, then you’re blatantly going to say Z-Zing or something similar.) Small problem, Toto, I have a feeling we’re not in Android anymore (http://www.youtube.com/watch?v=EPWenQxryr4&rel=0). Given that all the control code for the AR Drone for Linux was written in C, I thought perhaps it might be sensible to find some code that worked with C for the barcode scanning rather than Java. After a little searching I stumbled upon ZBar (http://zbar.sourceforge.net/), the logo’s not as fancy as ZXing, but it offers a pretty good library for doing barcode scans – and what was more – there was even a package compatible with version of Ubuntu (http://packages.ubuntu.com/lucid/libzbar-dev) I was using.  Next step was to figure out what it would output so I could let Neil get busy with the RESTful interface in SAP. The version of Ubuntu I was on didn’t have the libraries needed to support the latest version of ZBar (https://launchpad.net/ubuntu/maverick/+package/libzbar-dev), but I could scan a simple 13 digit barcode – so that became the starting point. h2. RESTful SAP ICF Sometime after that (and whilst I was trying to figure out how to connect to SAP from just using HTTP), I decided it would be a good idea to mock up a test frame to allow me to try communications with an SAP system. So I did just that – the code below is pretty appalling but it was thrown together in one evening and was never meant to be productive. Hopefully, therefore, it’s simple enough to  understand, it implements its own version of interface IF_HTTP_EXTENSION (http://help.sap.com/saphelp_nw70/helpdata/en/78/9852abc06b11d4ad310000e83539c3/frameset.htm), etc. method if_http_extension~handle_request. * test framework for DemoJam   data: l_verb type string,         l_path_info type string,         l_query_string type string,         lo_json_document type ref to zcl_json_document,         l_time_output(19) type c,         lt_fields type tihttpnvp,         l_timestamp type timestampl,         lt_values type tihttpnvp,         ls_values type ihttpnvp,         l_json type string,         l_script_name type string,         l_server type string,         l_port type string,         l_scheme type string,         l_uri_start type string.   data: ls_barcode_detail type zdemojam_barcode_detail,         ls_barcode_location_main type zdemojam_barcode_location_main,         lt_barcode_location type zdemojam_barcode_location_t,         ls_barcode_location type zdemojam_barcode_location,         ls_barcode_status_main type zdemojam_barcode_status_main,         lt_barcode_status type zdemojam_barcode_status_t,         ls_barcode_status type zdemojam_barcode_status.   l_verb = server->request->get_header_field( name = ‘~request_method’ ). * Abort if not GET or PUT   if not ( l_verb = ‘GET’ or l_verb = ‘PUT’ ).     server->response->set_header_field(    name = ‘Allow’    value = ‘GET, PUT’ ).     server->response->set_status(    code = ‘405’    reason = ‘Method not allowed’ ).     return.   endif.   l_path_info = server->request->get_header_field( name = ‘~path_info’ ).   l_query_string = server->request->get_header_field( name = ‘~query_string’ ).   server->request->get_header_fields( changing fields = lt_fields ).   if l_verb = ‘GET’.     if l_path_info is not initial.       shift l_path_info left by 1 places.       l_script_name = server->request->get_header_field( name = ‘~script_name’ ).       l_server = server->request->get_header_field( name = ‘~server_name_expanded’ ).       l_port = server->request->get_header_field( name = ‘~server_port_expanded’ ).       l_scheme = server->request->get_header_field( name = ‘~uri_scheme_expanded’ ).       concatenate l_scheme ‘://’ l_server ‘:’ l_port l_script_name        into l_uri_start. * get details of barcode       case l_path_info.         when          ‘This_is_M.A.D.S.H.I.T’.           ls_barcode_detail-barcode = l_path_info.           ls_barcode_detail-description = ‘A very cool box graciously gifted by Sophie’.           concatenate l_uri_start ‘/This_is_M.A.D.S.H.I.T/location’             into ls_barcode_detail-location_uri.           concatenate l_uri_start ‘/This_is_M.A.D.S.H.I.T/status’ into ls_barcode_detail-status_uri.           get time stamp field l_timestamp.           l_timestamp = l_timestamp – 100.           write l_timestamp to l_time_output time zone sy-zonlo.           ls_barcode_detail-last_updated = l_time_output.           ls_barcode_detail-last_updated_by = ‘Chris Paine’.           lo_json_document = zcl_json_document=>create_with_data( ls_barcode_detail ).         when           ‘This_is_M.A.D.S.H.I.T/location’.           ls_barcode_location_main-location = ‘Somewhere in Sydney’.           ls_barcode_location_main-lat_long = ‘-33.877, 151.177’.           get time stamp field l_timestamp.           l_timestamp = l_timestamp – 100.           write l_timestamp to l_time_output time zone sy-zonlo.           ls_barcode_location_main-last_updated = l_time_output.           ls_barcode_location_main-last_updated_by = ‘Chris Paine’.           concatenate l_uri_start ‘/This_is_M.A.D.S.H.I.T/location_history’             into  ls_barcode_location_main-location_history_uri.           lo_json_document = zcl_json_document=>create_with_data( ls_barcode_location_main ).         when           ‘This_is_M.A.D.S.H.I.T/location_history’.           ls_barcode_location-location = ‘Somewhere in Sydney’.           ls_barcode_location_main-lat_long = ‘-33.877, 151.177’.           get time stamp field l_timestamp.           l_timestamp = l_timestamp – 100.           write l_timestamp to l_time_output time zone sy-zonlo.           ls_barcode_location-last_updated = l_time_output.           ls_barcode_location-last_updated_by = ‘Chris Paine’.           append ls_barcode_location to lt_barcode_location.           ls_barcode_location-location = ‘Buggered if I know’.           ls_barcode_location_main-lat_long = ‘0, 0’.           get time stamp field l_timestamp.           l_timestamp = l_timestamp – 2000.           write l_timestamp to l_time_output time zone sy-zonlo.           ls_barcode_location-last_updated = l_time_output.           ls_barcode_location-last_updated_by = ‘Chris Paine’.           append ls_barcode_location to lt_barcode_location.           lo_json_document = zcl_json_document=>create_with_data( lt_barcode_location ).         when           ‘This_is_M.A.D.S.H.I.T/status’.           ls_barcode_status_main-status = ‘Requested’..           get time stamp field l_timestamp.           l_timestamp = l_timestamp – 100.           write l_timestamp to l_time_output time zone sy-zonlo.           ls_barcode_status_main-last_updated = l_time_output.           ls_barcode_status_main-last_updated_by = ‘Chris Paine’.           concatenate l_uri_start ‘/This_is_M.A.D.S.H.I.T/status_history’             into ls_barcode_status_main-status_history_uri.           lo_json_document = zcl_json_document=>create_with_data( ls_barcode_status_main ).         when           ‘This_is_M.A.D.S.H.I.T/status_history’.           ls_barcode_status-status = ‘Requested’.           get time stamp field l_timestamp.           l_timestamp = l_timestamp – 100.           write l_timestamp to l_time_output time zone sy-zonlo.           ls_barcode_status-last_updated = l_time_output.           ls_barcode_status-last_updated_by = ‘Chris Paine’.           append ls_barcode_status to lt_barcode_status.           ls_barcode_status-status = ‘Entered into system’.           get time stamp field l_timestamp.           l_timestamp = l_timestamp – 2000.           write l_timestamp to l_time_output time zone sy-zonlo.           ls_barcode_status-last_updated = l_time_output.           ls_barcode_status-last_updated_by = ‘Chris Paine’.           append ls_barcode_status to lt_barcode_status.           lo_json_document = zcl_json_document=>create_with_data( lt_barcode_status ).         when others.           server->response->set_status(         code = ‘404’         reason = ‘Details not found for barcode’ ).           return.       endcase.       l_json = lo_json_document->get_json( ).       server->response->set_header_field(      name = ‘Content-Type’      value = ‘application/json; charset=utf-8’ ).       server->response->set_cdata( data = l_json ).     endif.   else. * verb better be PUT or we have a problem! * Not going to check anything here – Neil can do some code! * Update status – tell em we have successfully updated       server->response->set_status(        code = ‘200’        reason = ‘OK’ ).   endif. endmethod. +(If you’re observant, you’ll notice that the code for the resource that I’m passing to the handler is a reasonably long alpha text string not just a short 13 char numeric – You’re getting ahead of me there, hold on, it will be explained.)+ The final version of the code which Neil –fixed– refactored from this is similar, but obviously less hardcoded and a darn bit neater! I promised Neil I wouldn’t put our final code online for others to marvel at – even if the least marvellous code was mine.  (BTW you can’t just subtract seconds from a timestamp – it doesn’t work.) (Also because Neil actual did such a good job of refactoring, there’s plenty of nice small methods, which doesn’t make for such easy reading).  If you’re interested in better examples (than my test framework) of simple HTTP accessible (some might say RESTful, some might not, but if SAP gets away with calling OData RESTful, I’m sure gonna claim my code was) interfaces using the SAP ICF, then I suggest you look up DJ Adams (http://www.sdn.sap.com/irj/scn/index?rid=/library/uuid/ea8db790-0201-0010-af98-de15b6c1ee1a) (a man clearly ahead of his time, and probably why he’s an SAP Mentor! If any of my mock-up looks like his code, there’s possibly a reason for that). Also check out Uwe Fetzer (aka @se38) (VCD #16 – The REST Bot: Behind the scenes)  or more recently John Moy (Deliver dynamic search of SAP data into a website using RESTful services) from Australia Post, who has recently done some stuff with JQuery and mobile devices using simple HTTP access to SAP.

h2. Big shout out I have to say a double thank-you to Uwe, as not only is he an inspiration (and a SAP Mentor again :), but he also is the father of the innocuous, yet extremely powerful  zcl_json_document class, used in the code above to transform the SAP data into (and in the final version out of) JSON notation. Thank you, Sir! Another SAP Mentor (who shall remain nameless) when I asked him about his code that used JSON and if he’d used the new Gateway code to do the transformations, said “No, I used Uwe’s code, it’s much better!” , ’nuff said.

h2. HTTP – for real – in C With a working SAP connection, well working test-frame anyway, I set about trying to connect to it. I’d had some fun in the past building a Javascript Yahoo Widget that connected to SAP to get data about statuses of interfaces, so I knew a little bit about the challenges of authenticating to an SAP system using an HTTP connection. Of course, JavaScript and C are two completely different languages, as I was learning very quickly. One thing that became very apparent, very quickly, especially when I put a few breakpoints in my ABAP code, was that despite me thinking otherwise, my code to control the Drone was actually single threaded. So synchronous communication to SAP was not going to be possible (or I was going to crash the Drone even more than normal). After a little lot of research I came across a library called {code:html}LibSoup{code}. (How one is supposed to guess that searching for “soup” will lead to the easiest way to do HTTP communication from C in Linux, is beyond me, yet I ended up there eventually.) A snapshot of some of the code I used to GET and PUT details (Yes, *real*, REST not just reading data!) from/to SAP follows:  (Obviously, in a better implementation I wouldn’t hardcode the username/password into the code 😉 I used the glib JSON library (http://live.gnome.org/JsonGlib) to convert to and from JSON. It’s very simple and if you have occasion to use it, I can recommend it.   /*  * comms.c
 */ h2. Almost at the final fence Around the same time I was implementing the comms code, I implemented some of the{code:html} libzbar{code} code that allowed me to scan each frame that was taken from the video feed of the helicopter and check if there was a barcode in it. After surprisingly little tweeking (I think I only spent 2 nights cursing my dodgy internet connection whilst searching for any kind of online doco) I was intercepting the Drone’s video feed and passing it through the scanner code and actually getting a result. 🙂 h2. Time to relax? Nah! The end was nearing, it was stilla few weeks until the DemoJam, things were looking good! But that would hardly be fitting with the general pattern of any true geek and their attempt to out-geek their fellow egHeads (http://enterprisegeeks.com/). As George Mallory (http://en.wikipedia.org/wiki/George_Mallory) famously said when asked why climb Everest ,8 “Because it’s there.” It was in that spirit that I decided that simple vertical line barcodes were boring and cool QR Codes (http://en.wikipedia.org/wiki/QR_code) would be much more fun.  Normal barcodes are boring

To report this post you need to login first.

4 Comments

You must be Logged on to comment or reply to a post.

  1. Chris Paine
    Didn’t know that there was such a thing as size limit for blogs. but I hit it with this one! – please read the text as strikethroughs – as markup to actually do the strikethrough didn’t seem to work…

    Anyway – have been sitting on this since before Easter, so I thought I’d give up on getting the formatting perfect and just release it!

    Hope you all enjoy it!

    Cheers,

    Chris

    (0) 
  2. John Moy
    Hi Chris,

    OMG, I don’t think I’ve ever seen someone undertake so many challenges all rolled up into a single demo!  Of course I saw the actual demo, but to get a glimpse of what you had to do under the covers is really unbelievable.  If only other developers were as ambitious and tenacious as you and Neil.  Well done!  Look forward to the next instalment.

    Cheers

    John

    (0) 
    1. Chris Paine
      Thanks John,

      it certainly was a learning experience. But that’s the whole point of being part of it I think. No point just demoing tech that you’re comfortable with. If you don’t challenge yourself, you’ll end up being the worst kind of “grey haired ABAPer” 😉 As you know I don’t have to worry about that so much (due to one of my most striking similarities with Prince William – hair most likely to go completely before it goes grey.)

      I’ll try to get the next bit with the Android code out soon (must hold back and not buy Portal 2).

      Cheers,

      Chris

      (0) 

Leave a Reply