Uno tra le principali library che permette di generare e decodificare anche il QR Code è ZXing.NET.
Poichè nel crittogramma possiamo codificare informazioni, possiamo inventarci innumerevoli funzionalità da trasmettere agli smartphone: da semplici url con parametri nel querystring ad informazioni gestite opportunamente dalle app installate sugli smartphone.
In questo esempio la mappa sul tablet è sincronizzata agli spostamenti della mappa a monitor perchè il QR Code è generato dinamicamente ad ogni cambio extent e nel QR Code è memorizzato il corrente extent della mappa; la fotocamera decodifica il QR Code ed applica il nuovo extent alla mappa sul tablet. In questo caso è stata applicata una compressione all'informazione per semplificare il crittogramma e rendere ancora più veloce la decodifica.
Ma vediamo una semplice Proof of concept che codifica un indirizzo di mappa. In questo caso potremmo utilizzare l'indirizzo del Map Viewer arcgis.com che accetta parametri via url. Nel caso specifico passeremo l'extent (parametro extent) e la web map da visualizzare (parametro webmap) e restituiremo un url abbreviato appoggiandoci ad un servizio di URL shortening (Goo.gl, bit.ly ecc.) o creandoci il nostro utilizzando ad esempio URL Rewrite Module di IIS così da avere un crittogramma semplificato.
/// <summary> /// handle qr Code /// </summary> /// <param name="boundVariables">bound Variables</param> /// <param name="operationInput">object operationInput</param> /// <param name="outputFormat">object outputFormat</param> /// <param name="requestProperties">object requestProperties</param> /// <param name="responseProperties">object responseProperties</param> /// <returns>return handle rest request</returns> private byte[] QrCodeOperatorHandler(NameValueCollection boundVariables, JsonObject operationInput, string outputFormat, string requestProperties, out string responseProperties) { responseProperties = "{\"Content-Type\" : \"application/json\"}"; string textValue; bool found = operationInput.TryGetString("text", out textValue); if (!found || string.IsNullOrEmpty(textValue)) { throw new ArgumentNullException("text"); } bool useShortenerUrl = true; bool? useShortenerUrlValue; found = operationInput.TryGetAsBoolean("useShortenerUrl", out useShortenerUrlValue); if (found && useShortenerUrlValue.HasValue) { useShortenerUrl = useShortenerUrlValue.Value; } try { if ((outputFormat == "json") || (outputFormat == "image")) { if (useShortenerUrl) { if (!ShortenerUrl.CheckUrl(textValue)) { throw new QRCoderException("url wrong!"); } ShortUrl shortUrl = new ShortUrl(); shortUrl.OriginalUrl = textValue; shortUrl.CodeShortUrl = ShortenerUrl.UniqueShortUrl(shortUrl.PrefixShortUrl); shortUrl.Expire = true; shortUrl.ShortenedUrl = null; ShortenerUrl.AddUrlToDatabase(ref shortUrl); textValue = ShortenerUrl.PublicShortUrl(this.shortenerUrl, shortUrl.ShortenedUrl); } QRCodeGenerator qrGenerator = new QRCodeGenerator(); QRCodeGenerator.QRCode qrCode = qrGenerator.CreateQrCode(textValue, QRCodeGenerator.ECCLevel.Q); using (System.Drawing.Bitmap image = qrCode.GetGraphic(20)) { if (outputFormat == "json") { responseProperties = "{\"Content-Type\" : \"application/json\"}"; string fileName = System.IO.Path.ChangeExtension(string.Format("_ags_{0}", Guid.NewGuid().ToString()), "png"); string pathfileName = System.IO.Path.Combine(this.pathOutputAGS, fileName); image.Save(pathfileName, System.Drawing.Imaging.ImageFormat.Png); JsonObject jsonObject = new JsonObject(); jsonObject.AddString("url", string.Format("{0}/{1}", this.pathOutputVirtualAGS, fileName)); jsonObject.AddLong("status_code", 200); jsonObject.AddString("status_txt", "OK"); jsonObject.AddString("text", textValue); return Encoding.UTF8.GetBytes(jsonObject.ToJson()); } else if (outputFormat == "image") { responseProperties = "{\"Content-Type\" : \"image/png\"}"; return Helper.ImageToByte(image, System.Drawing.Imaging.ImageFormat.Png); } else { throw new QRCoderException("Format output not found!"); } } } else { throw new QRCoderException("Format output not found!"); } } catch { JsonObject jsonObject = new JsonObject(); jsonObject.AddLong("status_code", 503); jsonObject.AddString("status_txt", "UNKNOWN_ERROR"); return Encoding.UTF8.GetBytes(jsonObject.ToJson()); } }Qui possiamo vedere la soe online.
Richiamiamo la soe per generare qr code dinamici da un template js arcgis:
require(["esri/lang", "esri/request"], lang.hitch(this, function (esriLang, esriRequest) { this.map.on("extent-change", lang.hitch(this, function () { extent = this.map.geographicExtent; var params = { f: "json", text: esriLang.substitute({host: this.config.sharinghost, webmap: this.config.webmap, xmin: extent.xmin, ymin: extent.ymin, xmax: extent.xmax, ymax: extent.ymax }, "${host}/home/webmap/viewer.html?webmap=${webmap}&extent=${xmin},${ymin},${xmax},${ymax}"), useShortenerUrl: true }; var requestHandle = esriRequest({ url: this.config.qrcodeSOE, content: params, callbackParamName: "callback" }, { useProxy: false }); requestHandle.then( function (response) { var qrcodeImg = dom.byId("qrcodeImg"); var qrcodeAnchor = dom.byId("qrcodeAnchor"); if (response.status_code === 200) { qrcodeImg.src = response.url; qrcodeAnchor.href = response.text; } else { console.log("Error: ", response.status_txt); } }, function (error) { console.log("Error: ", error.message); }); })); }));
Qui vediamo l'esempio online.