Skip to Content

SAP. Air Cannon. Together? (and we won!!)

12 months ago on our flight home from the 2012 Mastering SAP Technologies we were reflecting on the demo jam contest and wondered what we would need to in order to win the following year… We decided that the only think that we could win, in a room that we mostly full of men drinking beer, was to build an air cannon and then retrofit some technology…and so the concept began to take shape!

Fast forward to March 2013, and our concept was not only born but won!! Big thanks to my colleagues for all their work – John Schultz (Think180) and Abhinav Tayal.


Here’s the concept (I’ll cover the technology a bit later)….

  1. Audience register by SMS with their name
  2. SMS gets set straight back acknowledging the registration
  3. We select a respondent (one at a time), automatically send them an SMS with the link to our BSP to select their angle
  4. Person clicks on the link, goes to our HTML 5 BSP to select an angle for the cannon to fire. Our web page has a cannon on it, as the mobile devices moves, the canon moves and when satisfied they can hit fire.
  5. The air cannon moves the selected angle, fires the tennis ball across the room and hopefully goes in the net!!!
  6. Easy!

The whole premise for our concept was to demonstrate that you can do so much with what your already own as part of your SAP ERP system. You don’t need to go and buy other tools or take on additional licensing to do some pretty clever things.

Our solution was totally controlled by our cloud based ERP System. The system is not all that current is actually is a quite a few Enhancement Packs behind.

How we built it and all the pieces…

Step 1 & 2 – Sending & Receiving SMS

To send an receive SMS messages from SAP, we used a SOAP based web service from a large Australian SMS provider called Message Media ( who we’ve worked with in the past. We helped them a few years ago to setup their service to fully consumable from an ABAP system) We setup an acount which also included an incoming number that allowed messages to be routed to our account.

We consumed their WSDL in SE80 to create a client proxy – . Its that easy

The Message Media web service has a number of methods but we’re only interested in the send and receive methods.


Once we had the service consumed, we needed to put together a quick SMS Class that will allow us to perform the sending and receiving. We called the class ZCL_SMS. The outline of the class is below:


This method process all the responses from the audience.

method receive.

   datals_response like line of gt_response.

   data: lo_message type ref to zmmco_message_media_service_in .

   data: check_replies_response type zmmcheck_replies_response .

   data: check_replies_request type zmmcheck_replies_request .

   data: lv_message type string,

         lv_name    type string,

         lv_register type string,

         lt_recips   type stringtab,

         lv_recip   like line of lt_recips,

         lt_receipts type zmmconfirm_item_type_tab,

         ls_receipt like line of lt_receipts.

   field-symbols: <ls_response> like line of check_replies_responseparametersresultrepliesreply.


       create object lo_message.

     catch cx_ai_system_fault .                          “#EC NO_HANDLER


* Build authenticaion

   me->build_authentication( importing ev_password = check_replies_requestparametersauthenticationpassword

                                       ev_uname    = check_replies_requestparametersauthenticationuser_id ).


       call method lo_message->check_replies


           check_replies_request  = check_replies_request


           check_replies_response = check_replies_response.

       loop at check_replies_responseparametersresultrepliesreply assigning <ls_response>.

         ls_responsephoneno = <ls_response>origin.

         ls_responsename = <ls_response>content.

*       remove spaces

         condense ls_responsename.

*        TRANSLATE ls_response-response TO UPPER CASE.

         append ls_response to rt_response.


         ls_receiptreceipt_id = <ls_response>receipt_id.

         append ls_receipt to lt_receipts.


       if lt_receipts is not initial.

         call method me->confirm_response


             it_receipts = lt_receipts.


     catch cx_root .                                     “#EC NO_HANDLER



As we process the responses from the audience, we’ll store them in a database table with a unique GUID for processing. We send a message straight back advising that we’ve received their registration.

Method send.

   data: lx_error      type ref to cx_root,

         ls_message    type zmmmessage_type,

         lv_error      type string,

         ls_recipient  like line of ls_messagerecipientsrecipient.

   data: lo_message type ref to ZMMCO_MESSAGE_MEDIA_SERVICE_IN.

   data: send_messages_response type zmmsend_messages_response .

   data: send_messages_request type zmmsend_messages_request .

   field-symbols: <ls_recipient> like line of lt_recipients.


       create object lo_message.

     catch cx_ai_system_fault .                          “#EC NO_HANDLER


* Build authenticaion

   me->build_authentication( importing ev_password = send_messages_requestparametersauthenticationpassword

                                       ev_uname    = send_messages_requestparametersauthenticationuser_id ).

* Build Messages.

*  ls_message-scheduled = .

*  ls_message-delivery_report = abap_true.

   ls_messagevalidity_period = ‘169’.

   ls_messageformat = ‘SMS’.

   ls_messagecontent = iv_message.

*  Build recipients.

   loop at lt_recipients assigning <ls_recipient>.

     ls_recipientvalue = <ls_recipient>.

*    ls_recipient-uid = <ls_msg_itm>-networkuid.

     append ls_recipient to ls_messagerecipientsrecipient.

     clear ls_recipient.


*  add message

   append ls_message to send_messages_requestparametersrequest_bodymessagesmessage.


       call method lo_message->send_messages


           send_messages_request  = send_messages_request


           send_messages_response = send_messages_response.

     catch cx_root into lx_error.

          lv_error  = lx_error->get_text( ).

*        <ls_msg_itm>-msg_status = /etsa/cl_push_message=>gc_msg_error.




Step 3 – Processing Respondents

To give each person a chance to select their angle and fire the cannon (one at a time), we built a  Web Dynpro Screen (below). The phone number of the row selected was ‘active’. As soon as we selected a row (made the line active), we triggered an SMS message with the URL of the cannon BSP. We just re-used our SMS class with a different message.

web dynpro.png

The web dynpro above was just a simple table control that read the respondents from our database table and sorted them in order of received date and time. We also included a timer control to trigger automatic refreshes every 30 seconds. The SMS with the link to the BSP was triggered by the lead select event on the table control. The message we sent is below:


Step 4 – BSP Page

Once the respondent gets the SMS with the link on their phone they can click on the link to access our BSP page to select their preferred angle and fire. Our BSP page uses HTML5. The page contains a cannon image that can used move up and down depending on the phone’s orientation. Check out the page below:


We had a lot of trouble trying to get restrict the movement of cannon so that it would only move between 90 degree and 30 degree. We only allowed the web page to be viewed in landscape mode. The fire event on the BSP triggered a call to our cannon to move and fire through an ajax javascript call via an HTTP GET. We tried quite a few methods of executing the HTTP call to the cannon using approaches such as SM59, ajax etc and found SM59 was too slow and too slow to time-out if there was error.

Step 5 – The Cannon

We designed and built the air cannon from scratch using the following materials:

  • High pressure PVC pipe for compression chamber glued together with high pressure PVC glue.
  • Pressure Regulator
  • Stormwater pipe for the barrel
  • Irrigation solenoid for the firing mechanism
  • Sodastream bottles from the local super market (carbon dioxide) for the propellant
  • 12 volt stepper motor for moving the cannon up and down
  • Paralax Spinneret embedded Web Server (
  • Propeller chip that can run 8 parallel processes (cogs) to control the stepper motor and receive instructions from the web server (
  • Wireless router with USB wireless broadband


Once all the parts had been purchased, the mechanics of the cannon were put together one evening. Adding the electronics and the integration to SAP was far more complex!

To move the cannon we developed a REST service on our embedded web server. We basically needed the service to process 3 parameters:

  1. Firing Angle = 45 – angle selected by the users
  2. Fire = true or false
  3. Return Angle = angle that the cannon would return to once firing was complete.

The REST service executed the code that we’d developed using SPIN and deployed on the Propeller chip. The deployed SPIN code was responsible for telling the stepper motor how to move and in what increments. Additionally, the SPIN code also executed the fire command on the solenoid.

Our electronics and team member John Schultz was responsible for all the electronics and programming of the chip…nice work John!!


Our embedded web server was connected to our wireless router via Ethernet to form a small LAN. The REST service and associated electronics worked beautifully from our local cannon network (192.168.158.x) but the web server had to accessible from the internet as our SAP system is located outside of our cannon network (internet). In testing, all was working well in our Think180 office as we’d setup a port forward on our office based ADSL router to the embedded web server. However, demo jam was not going to be at our office and so we had to have a portable internet access…mobile broadband.

In hindsight the most complex component of the solution was getting our SAP system to be able to execute the REST service on our embedded web server using a mobile broadband internet connection. To be able to access the web server, we either needed a static IP on the mobile broadband or the ability to assign dynamic DNS. We now know that most mobile broadband provides in Australia (eg Telstra, Optus etc) NAT their mobile services meaning that they can’t be used for remote access. Problem solved when we found a local and very well respected ISP (Internode) that had cheap prepaid mobile broadband with static IPs…thank goodness and we thought we were sunk!

When it came togather, the cannon fired small runner tennis balls from the local pet shop (as you can see in the photo above).

Amazingly, all the pieces came together and worked beautifully on the day. Email me if you would like any more details on any of the pieces –

You must be Logged on to comment or reply to a post.
  • Hi Steve,

    thanks for blogging about your Demo Jam entry and sharing this fantastic idea with those that weren't privileged to see it for real.

    Congratulations to Abhinav , John and Yourself for putting this all together and then creating a great demo with lots of energy, fun and innovative audience participation. You guys have raised the bar to new levels.

    And for me it also reinforced my opinion that the best Demo Jam entries have no business case at all. They are done "just because you can". 😎


    Graham Robbo

  • It was totally awesome. What was the issue with sm59? (Didn't quite get that bit) did you need to connect phone directly to cannon to achieve a good response?

    • We found that if there was an issue calling the cannon's web service using an SM59 TCIP connection, it would take a lot longer to timeout that an javascript call.

      The cannon's web server was connected to our wireless broadband router and we actually got pretty good performance in the end. Every so often, we lost packets but it didn't make too much difference. The networking was almost harder than all the other technology!