The QR code of QR data logger contains a simple web link. It's easy to integrate the reading of QR codes and data uploading operation to third party softwares.
To integrate QR reading and data uploading into your own software you must implement following steps:
- Get a QR code scanner if you don't already have one. For mobile we suggest using https://github.com/zxing/zxing library. For desktop applications we suggest using laser 2D scanner.
- Once QR scanner is up and running and you have scanned QR data logger it's good practice to validate that the scanned data is valid. At the bottom of this page you can find example code how to validate our data links.
- When you have valid QR link just make a HTTP GET request to that URL. Server responds with HTTP 301 forwarding the normal user to our web interface. From forward URL you can validate whether the data upload was successful or if there was an error. If response looks like this the data was uploaded successfully:
HTTP Code: 301
Headers: Location: <https://web.logmore.com/scan/><scan secret id>
If it looks like this there was an error:
HTTP Code: 301
Headers: Location: <https://web.logmore.com/scan-error>
Probable cause for this is that link was read incorrectly, there is bug somewhere, system is having problems, the tag is broken or tag is no longer in the system.
Link format and available data
<HTTPS://RT.AG/><protocol version><tag serial><encrypted and compressed payload>
As per format above the protocol version and tag serial are available in the link without encryption thus being available offline. Version protocol is simply the first character of url path. Data logger serial is next 6 characters. To decode this into tag serial integer following python or javascript code can be used:
Python
#!/usr/bin/python3 -tt
# -*- coding: utf-8 -*-
"""Parse serial number from URL"""
import sys
URLMAP = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+-.$:'
def decode(triplet):
"""Decode single triplet to u16"""
return (URLMAP.find(triplet[0]) +
URLMAP.find(triplet[1]) * 41 +
URLMAP.find(triplet[2]) * 1681)
def main():
"""Main Program"""
if len(sys.argv) != 2:
print('Usage:')
print(' python3 get_serial.py url')
sys.exit(1)
# Get url from parameters
url = sys.argv[1]
if url.startswith(('http', 'HTTP')):
url = url.split('/', 3)[-1]
url = url.replace('/', '$')
# Decode and print serial
print(decode(url[1:4]) + decode(url[4:7]) * 65536)
if __name__ == '__main__':
main()
Javascript
getSerial: function(url) {
const URLMAP = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+-.$:';
var res = JSON.stringify(url).split("/")
var triplet = res[3].substring(1, 4);
var triplet2 = res[3].substring(4, 7);
var first = URLMAP.indexOf(triplet[0]) + URLMAP.indexOf(triplet[1]) * 41 + URLMAP.indexOf(triplet[2]) * 1681;
var last = URLMAP.indexOf(triplet2[0]) + URLMAP.indexOf(triplet2[1]) * 41 + URLMAP.indexOf(triplet2[2]) * 1681
var tagId = first + last * 65536;
return tagId;
}
Validation of RT.AG links
Javascript example
validateUrl: function(url) {
// Validate url start
if(url.substr(0,14).toLowerCase() != "<https://rt.ag/>") {
console.log('Not a valid Logmore url: no valid <https://rt.ag/> start');
return false;
}
// Validate payload first char
var validFirstChars = ["0","1","2","3","4"];
if(validFirstChars.indexOf(url.substr(14,1)) == -1) {
console.log('Not a valid Logmore url: invalid first char - should be '+validFirstChars.join());
return false;
}
// Validate payload len
if((url.length - 14 - 2) % 3 != 0) {
console.log('Not a valid Logmore url: (url len-2)%3 is not 0');
return false;
}
// Validate payload end
if(url.slice(-1) != "B") {
console.log('Not a valid Logmore url: last char is not B');
return false;
}
// Validate payload chars
var strippedUrl = url.slice(14).replace(/[A-Za-z0-9\\+:\\.\\/\\-\\$]/g, "");
if(strippedUrl != "") {
console.log('Not a valid Logmore url: invalid chars ('+strippedUrl+') in url data payload (allowed: A-Za-z0-9+:./-$)');
return false;
}
return true;
}