How to call M3 API with REST & JSON

With the Lawson Grid, M3 introduced a new REST endpoint for calling M3 API where the response is returned in XML or in JSON.

Background

Historically, software clients that called M3 API needed to use proprietary libraries, such as MvxSockJ.class for Java and MvxSockX_SVR.dll for Microsoft languages. Over the years, Intentia introduced Movex Web Services to call M3 API using the SOAP standard. Then, Lawson introduced the Grid for cloud computing. In the process, Lawson replaced IBM WebSphere Application Server by open source software, it also replaced the Core Web Services for Lawson Smart Office, and it added Jersey, an open source implementation of JAX-RS (JSR 311). The positive outcome is that now, software clients can call M3 API using REST/JSON.

Why does it matter?

REST is increasingly popular, and years ago it started supplanting SOAP for web services [1].

Also, JSON is becoming the de facto data-interchange format, nicknamed “The Fat-Free Alternative to XML” [2].

Most importantly, it’s now possible to call M3 API without needing the proprietary libraries, and without needing Lawson Web Services. Software clients can now make simple HTTP Requests to call M3 API. This makes it easier to call M3 API from third-party software (such as Tibco, Business Objects, Web Methods, etc.) and from previously unsupported or difficultly supported programming languages (such as JScript.NET, JavaScript, Ruby, PHP, etc.).

What about Lawson Web Services?

The new REST endpoint for M3 API doesn’t preclude using Lawson Web Services. Lawson Web Services is still necessary for calling M3 API with the SOAP protocol, and for using the unavoidable M3 Display Program adapter which cannot be found in any other Lawson product. Also, Lawson Web Services is still necessary for Lawson Smart Data Tool.

REST endpoint

To access the new REST endpoint for M3 API, open a Grid Information page, which is accessible from any participating Host in the Grid:

For example: http://ussplu123:20005/grid/info.html

At the bottom of the page is the Application Name M3-API-WS, and it has a Link to the Rest Service‘s WADL:

For example: http://ussplu123:20005/m3api-rest/application.wadl

This WADL gives us the resource path:

execute/{program}/{transaction}

Where {program} is the M3 API Program, like MNS150MI, CRS610MI, MMS200MI, etc. And where {transaction} is that API’s transaction, like GetBasicData, AddAddress, LstByNumber, etc.

Let’s try to call the API CRS610MI.LstByNumber. The URL in my example would be: http://ussplu123:20005/m3api-rest/execute/CRS610MI/LstByNumber

The server will challenge us for HTTP Basic Authentication, we need to provide a valid M3 userid and password:

And the result in XML is a collection of MIRecord elements with Name/Value pairs:

JSON

We can get the result in JSON by adding the HTTP Header field:

Accept: application/json

The result is:

REST GUI

RESTClient is a great REST graphical user interface which we can use to test M3 API; you can download it at http://code.google.com/p/rest-client/

Paste the URL, set the M3 userid and password in the Authentication tab, optionally set the Header to get the response in JSON, and click Go!

Conclusion

With the Lawson Grid, software clients can now natively call M3 API from third-party software, and from previously unsupported or difficultly supported programming languages, without the need for proprietary libraries, and without the need for Lawson Web Services.

Updates

Input parameters

UPDATE 2012-07-17: You can set input parameters in the URL, for example: http://hostname:port/m3api-rest/execute/MMS200MI/GetItmBasic?CONO=531&ITNO=ABCDEF . Also, you can hook RESTClient to use Fiddler as a proxy in Tools >;; Options.

Max number of records

UPDATE 2012-07-31: You can set the maximum number of records returned with the matrix parameter maxrecs, for example: http://hostname:port/m3api-rest/execute/CRS610MI/LstByNumber;maxrecs=20?CONO=1

Output fields

UPDATE 2012-08-02: You can set the output fields returned with the parameter returncols, for example: http://hostname:port/m3api-rest/execute/CRS610MI/LstByNumber;returncols=CUNO,CUNM,CUA1,STAT,PHNO

Related articles

Translate M3 with Google Translate API

Here is a solution to automatically translate M3 and user-generated content in 52 languages.

For that, I will use the Google Translate API and a Personalized Script for Lawson Smart Office.

Business advantage

This solution is interesting to translate content that is generated by users, such as:

  • Bill of Materials
  • Work Orders
  • Service Orders
  • Customer Order Notes
  • etc.

Such content is entered in the user’s language and by design is not translated by Lawson Smart Office.

Also, this solution is interesting to translate M3 itself beyond the number of languages that Lawson makes available.

Lawson Smart Office

Lawson Smart Office supports 18 languages: Czech, Danish, German, Greek, English, Spanish, Finnish, French, Hungarian, Italian, Japanese, Dutch, Norwegian, Polish, Portuguese, Russian, Swedish, and Chinese:

It’s a high number of languages given that text is manually translated by professional translators which are probably paid by the word.

The quality is near perfect.

But by design, the user-generated content is not translated.

Google Translate

Google Translate supports 52 languages: Afrikaans, Albanian, Arabic, Belarusian, Bulgarian, Catalan, Chinese Simplified, Chinese Traditional, Croatian, Czech, Danish, Dutch, English, Estonian, Filipino, Finnish, French, Galician, German, Greek, Hebrew, Hindi, Hungarian, Icelandic, Indonesian, Irish, Italian, Japanese, Korean, Latvian, Lithuanian, Macedonian, Malay, Maltese, Norwegian, Persian, Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovenian, Spanish, Swahili, Swedish, Thai, Turkish, Ukrainian, Vietnamese, Welsh, and Yiddish.

It’s a very high number of languages because it uses machine learning and statistical analysis for automatic machine translation of millions of web pages and of official translations done by governments and by international organizations.

It is one of the best machine translations available, considered state of the art, and the quality is improving constantly. [1] [2] [3].

Google is even working on recognizing handwritten text, and text in images.

But even though the quality is good it’s not yet accurate.

It may not be accurate enough in a professional context to translate user-generated content in M3 with the Google Translate API.

But it still gives the user a general idea of the meaning of the text.

And as a pedagogical tool, it serves the purpose of illustrating how to write scripts for Smart Office, and how to integrate M3 to external systems.

Hello World!

To use the Google Translate API you need to register and obtain a key. It is a paid service that will translate one million characters of text for $20.

Once you obtain your key, you need to construct a URL with your API key, the text to translate, and the source and target languages.

Here is a sample URL that translates the text Hello World! from English (en) to French (fr):

https://www.googleapis.com/language/translate/v2?key=YOUR_API_KEY&q=Hello%20World!&source=en&target=fr

The result is a JSON object like this:

{
 "data": {
  "translations": [
   {
    "translatedText": "Bonjour tout le monde!"
   }
  ]
 }
}

First script

Then write a Personalized Script for Lawson Smart Office using the Script Tool.

The script will submit the HTTP GET Request to the Google Translate API over HTTPS and will parse the JSON response.

function translate(text: String, source, target) {
     var url = 'https://www.googleapis.com/language/translate/v2?key=YOUR_API_KEY&source=' + source + '&target=' + target + '&q=' + HttpUtility.UrlEncode(text);
     var request = HttpWebRequest(WebRequest.Create(url));
     var response = HttpWebResponse(request.GetResponse());
     var jsonText = (new StreamReader(response.GetResponseStream())).ReadToEnd();
     var o = eval('(' + jsonText + ')''unsafe');
     return o.data.translations[0].translatedText;
}

We can now use this function to translate any piece of user-generated content, for example the Customer Name in CRS610/E (WRCUNM):

var WRCUNM = ScriptUtil.FindChild(controller.RenderEngine.Content, 'WRCUNM');
WRCUNM.Text = translate(WRCUNM.Text, 'en''fr');

Also, we can translate several pieces of text at once by appending as many q parameters to the URL as pieces of text.

Beyond

With this technique, we can translate all the Controls of our Panel, including the user-generated content: Label, TextBox, Button, ListView, GridViewColumnHeader, ListRow, etc. That will cover Panels A, B, E, F, etc.

Also, we will need to submit the HTTP Request in a background thread to avoid blocking the user interface.

Complete Script

Here is the complete source code of my script that translates all the content of any M3 program, any panel.

Installation

Replace the constant YOUR_API_KEY of the source code with your own Google Translate API key.

The script has a limit GOOGLE_MAX_TEXT_SEGMENTS which was applicable when I wrote the script back in March 2010, but Google has since removed the limit so you can remove it from the script as well.

Then deploy the script on each program and each panel that you’d like to translate. The deployment can probably be automated with some custom XML and XSLT.

Result

Here is an animation of the M3 program Work Order – MOS100/B1 with buttons for seven languages. Click on the image to see the animation. Note how the user-generated content in the rightmost column of the list is also being translated.

Future Work

A future implementation should also translate menus, drop down lists, and text panels (T). I still haven’t been able to execute scripts in a T panel.

That’s it!

 

Updates

UPDATE 2012-08-02: Just fixed the line breaks at line 280 which the copy/paste had corrupted + fixed GetType().ToString() + fixed Exception handling in BackgroundWorker.

UPDATE 2012-08-03, Martin Trydal Torp & Thibaud: Adapted listView for newer LSO (new: listView.ItemsSource; old: listView.Items) + change sourceLanguage dynamically

Send SMS from PFI with Twilio

Here I propose a solution to send SMS text messages from M3.

The desired solution is an exchange of SMS text messages between M3 and the user.

Scenario

For example, let’s suppose we have a scenario where approvers need to review new Customers before setting the Customer’s status to 20-Definite in CRS610. Also, let’s suppose that the approvals are done by SMS text messages. In such a scenario, M3 would send an SMS text message to the user’s mobile phone saying “Please review and approve this new customer XYZ”. The user would respond with an SMS text message saying “APPROVE”. M3 would acknowledge receipt of the approval and would call the API CRS610MI.ChgBasicData to set the Customer’s Status to 20-Definite.

Here is a screenshot of such an exchange between M3 and the approver:

Alternate solutions

The current solutions for such approval scenarios is to use the Smart Office Inbasket, the Mailbox Inbasket, and the Mobile Inbasket of ProcessFlow Integrator (PFI). But those solutions do not support SMS text messaging.

Why it matters

SMS text messaging is a market of 6 trillion SMS text messages sent in 2010 [1], generating $114.6 billion in 2010 [2].

We want M3 to also benefit from the potential of using SMS text messages.

Background

In a previous post, I had posted a solution to Send SMS from Smart Office with Skype. That was a solution for the client-side.

This time, I post a solution using Twilio. And this time the solution is for the server-side.

How it works

I propose a solution that uses PFI and the REST API of Twilio cloud communications.

Twilio is a service that allows developers to programmatically make and receive phone calls, and to send and receive text messages. Twilio’s REST API is XML or JSON over HTTP.

Technically speaking, we want PFI to send an HTTP request to Twilio. The HTTP Request must be over HTTPS, using a POST method, using Basic Authentication, and the Body of the request will contain as parameters the source phone number, the target phone number, and the desired message. We’ll use the WebRun activity node in PFI for that. And when Twilio will receive that HTTP Request it will send the SMS text message on our behalf using its PSTN gateway.

Pre-requisites

Make sure your Twilio account works:

  1. Open an account with Twilio
  2. Add funds
  3. Make sure to get a valid Twilio phone number
  4. Test it with the Twilio Sandbox
  5. Test it with the API Explorer
  6. Write down the Account SID and the Authorization Token, they will be needed for authentication later:

Sample HTTP Request

A sample HTTP Request to send an SMS text message looks like:

POST https://api.twilio.com/2010-04-01/Accounts/ACec246b17f76e0f336a6........../SMS/Messages.xml HTTP/1.1
Authorization: Basic QUNlYzI0NmIxN2Y3NmUwZjMzNmE2NTYzMjI2ZmNmMTUyYzo1ZjA2MDA4NDI0ZGQ1OGFmNWZkMThiYW.........==
Content-Type: application/x-www-form-urlencoded
Host: api.twilio.com
Content-Length: 64

From=%2B14156250342&To=%2B18472874945&Body=Hi%2C+this+is+Thibaud!

Solution

Perform the following steps to implement the solution:

  1. Open PF Designer
  2. Create a new flow
  3. Add a WebRun activity node:
  4. Open the Properties of the WebRun activity node.
  5. Set the WebRun to Use external host
  6. Set the hostname to api.twilio.com
  7. Set the userid to your Twilio’s AccountSid as shown on your Twilio’s account Dashboard.
  8. Set the password to your Twilio’s AuthToken as shown on your Twilio’s account Dashboard.
  9. Check the box SSL enabled
  10. Set the Web program to:
    /2010-04-01/Accounts/{AccountSid}/SMS/Messages.{format}

    Where {AccountSid} is your AccountSid, and where {format} is either XML or JSON.

  11. Set the Post string with a From, To, and Body parameters.
  12. Set the source From phone number to your Twilio’s number, and URL-encode it. For example, the phone number +14156250342 becomes:
    From=%2B14156250342
  13. Set the destination To phone number to any number you want, and URL-encode it. For example, the phone number +18472874945 becomes:
    To=%2B18472874945
  14. Set the Body of the SMS text message to any text you want, and URL-encode it. For example, the message “Hi, this is PF Designer!” becomes:
    Body=Hi%2C+this+is+PF+Designer!
  15. Separate the From, To, and Body parameters with ampersands &
  16. Set the Content-type to application/x-www-form-urlencoded.
    But because PF Designer doesn’t have that specific content-type in the available list of options, you will have to add it manually in the XML file of the flow with a text editor like Notepad, and URL-encode it. The new value should be application%2Fx-www-form-urlencoded. The result should look like:

    <activity activityType="WEBRN" ...>
      <prop className="java.lang.String" name="contentType" propType="SIMPLE">
        <anyData><![CDATA[application%2Fx-www-form-urlencoded]]></anyData>
      </prop>
      ...
    </activity>
  17. Save the flow
  18. The Properties of the WebRun should look like this:
  19. Run the flow:
  20. Now your mobile phone should receive the SMS text message and beep. Here is a screenshot from the SMS text message received on my iPhone:
     
  21. You can check the logs in Twilio:

Note: The WebRun activity node was meant for another purpose, to be used in conjunction with S3; we’re sort of deviating the WebRun activity node from its original purpose. So it will submit two more HTTP Requests to PFI – which are unnecessary to our solution – before submitting the HTTP Request to Twilio. It’s inefficient but that’s the only activity node of PFI that can natively submit HTTP Requests. UPDATE: I think I’m wrong here because I was testing from PFI Designer and that may have caused the two extra requests. When deployed the flow will probably not send them. To be verified.

Applications

Here are a few possible applications of sending and receiving SMS text messages from M3:

  • Support for users that do not have smartphones
  • Support for regions that are covered by GSM only and that lack coverage for 3G/4G/Wifi
  • Approve/Reject Customers (CRS610) by text messages
  • Approve/Reject Purchase Orders (PPS180) by text messages
  • Send driving directions to truck drivers
  • Send pick-up reminders
  • Place a Customer Order via text messages
  • Send notifications by text message when an order changes status.
  • Monitoring and alert. To help with the scheduled jobs, such as CAS950, OIS180, PPS600, POs, Invoicing, Stock Transactions, etc. If there is an issue, if the jobs fail or do not complete within the expected time, M3 could alert a maintenance staff via SMS text message to its mobile phone.

Future work

Here are future implementations:
  • In addition to sending text messages, we can receive text messages via Twilio, so as to have two-way SMS text messaging with the user.
  • As an alternative to PFI, we could use Twilio’s helper libraries in Java to send SMS text messages directly from M3 Business Engine with an MAK modification, i.e. without having to go thru PFI.
  • In addition to PFI and M3, we could send SMS text messages from Lawson Smart Office scripts with the Twilio’s helper libraries for .NET.
I will publish such solutions in future posts.

Conclusion

That was an easy solution to send SMS text messages from PFI. By extension, since M3 Business Engine can trigger PFI flows, we can consider this a solution too for M3 BE to send SMS text messages.

That’s it!

Mailbox Inbasket for corporate mobile phones

Here is a video that illustrates we can use the mailbox of mobile phones to take action in the Inbasket of ProcessFlow Integrator (PFI). The video is a working demo for the BlackBerry and dates from September 2009, but the concept is still valid today and could apply to iPhones and Android devices as well.

The scenario is the following. We have a workflow where approvers need to review certain information and take action, for example Approve or Reject. In this particular scenario the buttons to approve and reject are embedded in the email such that approvers can take action directly from their mailbox, i.e. we are not discussing the scenario of the Inbasket in Lawson Smart Office (LSO).

The reason to use emails instead of the Inbasket is that taking action from the mailbox works from mobile phones that have network access to the PFI server, such as corporate mobile phones.

An alternative to the mailbox for corporate mobile phones would to use the Mobile Inbasket.

Finally, the demo in the video challenges the user for authentication, but there is also a solution with single sign-on to skip the user/password part.

If you are interested in the solution, contact me for details.

Here is a screenshot for an iPhone:

Warehouse 3D demo

I implemented a Warehouse 3D demo that demonstrates the integration capabilities of M3 with cool stuff from the software industry.

The Warehouse 3D demo displays racks and boxes with live data coming from Stock Location – MMS010, and Balance Identity – MMS060. The Location Aisle, Rack, and Level of MMS010 is written dynamically on each box. The Status Balance ID of MMS060 is rendered as the color of the box: 1=yellow, 2=green, 3=red, else brown. And the Item Number is generated dynamically as a real bar code that can be scanned on the front face of the box.

Here is a screenshot:

The demo uses the Google Earth plugin to render a 3D model that was modeled with Google SketchUp, Ruby scripts to geocode the boxes and identify the front faces of the boxes, PHP to make the 3D Collada model dynamic, SOAP-based Lawson Web Services that calls M3 API, and the PEAR and NuSOAP open source PHP libraries.

The result is useful for sales demos, and as a seed for customers interested in implementing such a solution.

Try for yourself

http://ibrix.info/warehouse3d/

You can try the demo for yourself with your own M3 environment. For that, you will need several things. You will need to install the Google Earth plugin in your browser. You will also need to deploy the Lawson Web Service for MMS060MI provided here; note that your LWS server must be in a DMZ so that the http://www.ibrix.info web server can make the SOAP call over HTTP. Also, you will need to follow the Settings wizard to setup your own M3 environment, user, password, CONO, WHLO, etc. The result is a long URL that is specific to your settings.

Constructing the 3D model

I built a 3D model with Google SketchUp.

Here is the video of the 3D model being built in Google SketchUp:

You can download my resulting SketchUp model here.

Identifying Aisles, Racks, Levels

Then, I set the Aisle, Rack, and Level of each box as in MMS010 using a custom Ruby script for Google SketchUp.

Here is a video that shows the script in action:

You can download this Ruby script here.

You can download the resulting SketchUp model here.

Identifying front faces

Then, I identified each front face of each box so as to dynamically overlay information, such as the Item Number, Item Name, etc. For that, I implemented another Ruby script.

Here is a video of that process:

You can also download this Ruby script here.

Exporting the Collada model

The original model is a SKP filetype, which is binary. I exported the model to a Collada DAE filetype, which is XML. The file is very big, 30.000 lines of XML.

The Collada file contains this:

  • Components (racks, boxes, walls, etc.)
  • Homogenous coordinates (X, Y, Z, H) relative to the model
  • Absolute coordinates (latitude, longitude)
  • Orientation (azimut, etc.)
  • Scale
  • Effects (surface, diffusion, textures, etc.)
  • Colors in RGBA

From the top of my head, the Collada hierarchy in XML is something like this:

Node Instance
	Node Definition
		Instance Geometry
			Instance Material
				Material
					Instance Effect
						Color
						Surface
							Image

Making the model dynamic

The goal is to set the color of each box dynamically, based on the Location of the box, and based on the Inventory Status in MMS060.

Unfortunately, Google Earth doesn’t have an API to change the color of a component dynamically. So, I decided to change the XML dynamically on the server. There are certainly better solutions but that’s the one I chose at the time. And I chose PHP because that’s what I had available on my server ibrix.info; otherwise any dynamic web language (ASP, JSP, etc.) would have been suitable.

In the XML, I found the mapping between the box (nodeDefinition) and its color (material). So, I changed the mapping from hard-coded to dynamic with a PHP function getColor() that determines the color based on the Location and based on the result of the web service call.

The color is determined by the Balance ID: 1=yellow, 2=green, 3=red, else brown. The Balance ID is stored in the SOAP Response of the web service.

Lawson Web Service

I created a SOAP-based Lawson Web Service for MMS060MI. I invoke the SOAP Web Service at the top of the PHP script, and store the Response in a global variable. To call SOAP Web Services, I use NuSOAP, an open source PHP library.

Generating front faces

I dynamically generate a texture for each each front face as a PNG image with the Item Number, Item Description, Quantity, and the bar code. I set the True Type Font, the size, the XY coordinates, and the background color.

Bar code

I generate an image of the bar code based on the Item Number using PEAR, an open source PHP library.

Settings wizard

I made a Settings wizard to assist the user in setting up a demo with their own M3 environment, user, password, CONO, WHLO, etc.

Applications

This Warehouse 3D demo illustrates possible applications such as:

  • Monitoring a warehouse
  • Locating a box for item picking
  • Implementing Augmented Reality to overlay relevant data on top of the boxes

Demo

Finally, I made a demo video using the back projection screen at the Lawson Schaumburg office, and using Johny Lee’s Low-Cost Multi-point Interactive Whiteboards Using the Wiimote and my home made IR pens to convert the back projection screen into a big touch screen. The 3D model in the demo has 10 Aisles, 6 Racks per Aisle (except the first aisle which only has 4 racks), and 4 Levels per Rack. That’s 224 boxes. There is also a floor plan that illustrates that structure.

Limitations

The main limitation of this demo is performance. When programming with Google Earth we do not have the capability of dynamically changing a 3D model. I would have liked to dynamically set the color of a box, and dynamically overlay text on the face of a box. Because that capability is lacking – there’s no such API in the Google Earth API – I chose to generate the XML of the 3D model dynamically on the server. As a result, the server has to send 30k lines of XML to the web browser over HTTP, it has to generate 224 PNG images and transfer them over the network, and the Google Earth plugin has to render it all. As a consequence, it takes between one and four minutes to fully download and render the demo. This design turns out to be inadequate for this type of application. Worse, it is not scalable nor improvable. I would have to re-think the design from scratch to get a more performant result.

Future Work

If I had to continue working on this project (which is not planned), I would implement the following:

  • Ideally, we would generate boxes, colors, and text dynamically on the client-side, with JavaScript and WebGL for example. Google Earth doesn’t support that, and generating the model on the server-side turns out to be a bad design. So we need a different technique.
  • Also, we could use a better 3D client, like O3D.
  • Also, we would need to implement easy keyboard navigation, like the First Person Camera demo, and like the Monster Milktruck demo.
  • Also, we would need to implement hit detection, so as to click on a box and display more M3 data in a pop-up for example. Google Earth supports even listeners but doesn’t yet support hit detection.
  • Finally, we would need to improve performance by an order of magnitude.

Thanks

Special thanks to Gunilla A for sponsoring this project and making it possible.

Resources

  • Download Ruby script to set the Aisle, Rack, and Level of each box as in MMS010
  • Download Ruby script to identify each front face of each box so as to dynamically overlay information
  • Download SketchUp model with floor plan, geo-location, racks, and walls
  • Download SketchUp model of boxes identified by Stock Location
  • Watch video of the 3D model being built in Google SketchUp
  • Watch video of the process of setting the Aisle, Rack, and Level of each box as in MMS010
  • Watch video of the process of identifying each front face of each box
  • Watch video of the demo on the large touch screen
  • Download Lawson Web Service for MMS060MI

Related articles

UPDATE

2012-09-27: I added the SketchUp models and Ruby scripts for download.

Cash drawer integration with Smart Office Script

Here is a demo video of the integration I implemented for one of our customers between a cash drawer and Lawson Smart Office using a Script. (If you want to skip the talk, jump to time stamp 3:31 in the video to see the cash drawer open.)

The result is a single cash drawer controlled by multiple Points of Sales throughout the showroom. Each Point of Sales runs Smart Office. The solution requires authorization (who can access the cash drawer) and auditing (who opened the cash drawer when) for security purposes. For the user its just a click on a new button Open Register.

I implemented the solution as client/server: the clients are Personalized Scripts in JScript.NET for Smart Office, the server is a custom Java program connected to the cash drawer with JavaPOS and a Serial cable, a custom bridge between .NET and Java made with a tiny HTTP server, and Properties file.

Send SMS from Smart Office with Skype

To send an SMS text message to a mobile phone from a Personalized Script in Lawson Smart Office using Skype do:

skype.SendSms("+18472874945", "Hello World", null)

Script

A simple script that sends an SMS would be:

import System;
import System.Reflection;

package MForms.JScript {
    class SendSms {
         public function Init(element: Object, args: Object, controller : Object, debug : Object) {
             try {
                 var assembly: Object = Assembly.LoadFrom('C:\\Program Files\\Skype\\SEHE\\Interop.SKYPE4COMLib.dll');
                 var skype = assembly.CreateInstance('SKYPE4COMLib.SkypeClass');
                 skype.Attach(8, false);
                 skype.SendSms('+18472874945', 'Hello World!', null);
             } catch (ex: Exception) {
                 debug.WriteLine(ex);
             }
         }
    }
}

Note: The programming language for scripts in Smart Office is JScript.NET.

Installation

Follow these steps to run the script above:

  1. Download and install Skype on the computer that is running Smart Office (the script must communicate with Skype locally). Then sign in to Skype (the script will not work if you are not signed in). Also, your Skype account must have credit (USD, EUR, etc.) to be able to send SMS.
  2. Download and unzip Skype4COMsomewhere in your computer, for example C:\Program Files\Skype\skype4com-1.0.36\ . Skype4COM is the API used to send/receive Skype commands. Then register the DLL Skype4COM.dll with the following command:
    regsvr32 Skype4COM.dll

  3. Download and install SEHE and place the file Interop.SKYPE4COMLib.dll somewhere in your computer or somewhere on the network so that it is accessible by the Smart Office computer, for example C:\Program Files\Skype\SEHE\Interop.SKYPE4COMLib.dll or http://host/path/Interop.SKYPE4COMLib.dll . That DLL contains the Interop code to be able to call Skype4COM from the .NET framework.
  4. Launch Smart Office, and log in.
  5. For the Script Tool it is necessary to have an M3 program open, so open for example Customer. Open – CRS610.
  6. Open the Script Tool with the following command:
    mforms://jscript
  7. Copy/paste the sample script above into the Script Tool
  8. Change the path to the DLL. In my example I used C:\\Program Files\\Skype\\SEHE\\Interop.SKYPE4COMLib.dll . Make sure to escape the backslashes in the String with double backslashes.
  9. Change the phone number. It must be in international notation. In my example I used +18472874945.
  10. Click Compile
  11. Click Run
  12. Skype will show the message “LawsonClient.exe wants to use Skype”. Click Allow access; Skype will only ask once.
  13. Skype will now send the SMS. Check in your mobile phone that you received it. That’s it!

Note: I tested this on Windows XP and on Windows 7 32-bit with success. It doesn’t seem to work on Windows 64-bit. Also, I tested this in Smart Office 9.x.

More advanced script

A more elaborated script with an editable SMS text message in a pop-up looks like: