QR Codes can hold URLs. Therefore, they are a great binder between the outside world and your information system.
Imagine a standard QR-code-reading-app on anyone’s phone being the entry point deep into your information, showing the user's current state of something and asking them how to proceed.
That was the basic pitch Lars gave me. This article is about how to leverage this ability in the current MDriven Turnkey release.
It turns out that there were a few things I needed to get straight to get the implementation the way I wanted it. I wanted the functionality to produce a QR Code that is easily accessible. I did not want it to be a new operator in OCL/EAL, since that would clutter the language - if we add every good extension we come to think of in that way.
I wanted to make it available as a static method on a class so that you could go like SomeClass.QRImage(theUrlToEncode):Image
.
Static methods were not supported, however, so we needed to add that and fix it. You can now have methods in your model with OperationKind=static
. They will show up on the Class in EAL and OCL if you mark the method as IsQuery (then you promise to not change the state on model objects so that the method is safe to include in OCL queries).
I could now go on to add a good QR-code library – and add it as an extension as described in this article, but I wanted it to be accessible for everyone running Turnkey since I think it is such a crucial interaction widget. Instead, I added a pattern you can use in your model - when you use it, we will provide the logic behind it. This is the pattern:
Add a class ZXing (this is the open-source QR-code library we use, credit goes to everyone involved in that). Add a static method with this signature QRImage(width:Integer; height:Integer; value:String):Image
– and then you have access. In the application (a returns and reclamation system) where this was first used, we added a derived attribute like so:
QRCode: Blob , DerivationOcl = ZXing.QRImage(300,300,’https://reklamation.azurewebsites.net/MDriven/DisplayWithVariables?view=TestQRCodeFromVariable&id=$null$&vLopnummer=’+self.Lopnummer.asstring)
Let me explain the OCl a bit:
ZXing.QRImage(300,300, theUrl)
– this calls the static method QRImage on class ZXing, stating that the QR Code should be 300×300 pixels. For this to be acceptable in OCL, we must have the QRImage method marked as IsQuery.
Note! The Method QRImage must have a tagged value: Eco.ExternalLateBound = True
The URL we send in is a string made up of the URL of our application: ‘https://reklamation.azurewebsites.net’ - the path to the MDriven controller and then a new Verb: DisplayWithVariables. What this new verb does is the same as the usual Display verb – namely takes a view name and a root id for that view. For now, I use “view=TestQRCodeFromVariable&id=$null$
”. What the new verb DisplayWithVariables offers beyond “Display” is a way to send in variable values that should be set in the view once. In this case, I want it to set a variable called vLopnummer in the TestQRCodeFromVariable view – and I want the QR Code to set the variable to the value of the attribute called Lopnummer of the reclamation that the QR Code belongs to: ‘vLopnummer=’+self.Lopnummer.asstring
.
This means I now have a way to produce a QR code that points to my app – a specific view in that app – and sets a specific variable when entering that view.
I can then define this view:
It is a simple search view. The search button action has however been given an Interval=100 – this means it will execute repeatedly every 100 milliseconds – as long as the action is visible. Since the Visible expression is “vSearchIsPerformedOn<>vLopnummer
”, the repetition will only go on as long as the vSearchIsPerformedOn differs from the vLopnummer. Once they are equal, the search button will be hidden and the repetition will stop. If we examine the search button’s execute expression, we see that it first executes the search with selfVM.Search – then sets the variable vSearchIsPerformedOn:=vLopnummer
– thus stopping further action. This is a pattern that is useable when you need to react with an action on data that changes. Use a periodic action that only runs when some variables differ and make the action set the variables so that they do not differ. It effectively becomes a trigger that executes once when some watched data has changed.
I can now have a view that produces the QR-Code – and email or print it or leave it somewhere in another form. Any person, with a smart-phone, that has an app that reads QR Codes, can point and click to end up on my target page for the specific object I set:
I make this view accessible to everyone – leaving it out of any AccessGroups. Then, it is up to me to decide what actions to allow from this view. Is the “Lopnummer” considered hard to guess so that I can trust the holder of it to be the intended person? Maybe not – but what if it was a generated Guid instead? In a sea of billions of possibilities, it will be hard to guess.
As the QR Code is treated as any kind of image (a blob with BlobType=Image), you can present it in grids or reports, etc. Since the QR Code needs to be a certain size to be readable, new stylerefs on images have been added; small, medium, or large (changeable through CSS).