TechTip: Using a Macro On a Weintek HMI to Generate a QR Code For The History Upload Address
Introduction This TechTip is about using a Macro to generate a QR code to scan with a phone to access via FTP* the HMI to upload history files etc from it. As usual, we’ll break it down so you can see what we’re doing here. *It’s worth noting that some browsers do not support parsing passwords etc in the address. As of today, Mozilla Firefox works ok. Using with Mozilla Firefox Scan the QR Code Generated by Macro to give the URL for FTP access to the HMI ftp://uploadhis:111111@192.168.16.43/ read from QR code…. Press “Go”… Access to the HMI to download logs etc. Macro The required string is in the following format: “ftp://uploadhis:password@IP1.IP2.IP3.IP4/“ Declare variables The first part, “ftp://uploadhis:” is fixed, so we’ll declare that in our macro: char Text1[16] = "ftp://uploadhis:" // first part of the string, this is fixed and 16 characters long Next is the ftp password, we are using the default of “111111” here. char Text2[10] ="111111" // 2nd part of the string - ftp password The other fixed characters (“@” “.” & “/”) are also defined. char Text3[1] ="@" // the "@" character char Dot[1] = "." // the "." dot character char Slash[1] = "/" // the "/" forward slash character The HMI IP address is stored in 4 consecutive LW registers, LW 9129-9132, 9129 is the first Octet, 9130, the second, etc. these are 16-bit numbers. So we’ll declare variables for each Octet as “short” data type. short IPfirstOctDEC // IP address 1st Octet short IPsecondOctDEC // IP address 2nd Octet short IPthirdOctDEC // IP address 3rd Octet short IPfourthOctDEC // IP address 4th Octet Since the IP Octets could be 1, 2 or 3 digits, we’ll declare some variables to store the length of them short IPfirstOctLength // Length of IP address 1st Octet short IPsecondOctLength // Length of IP address 2nd Octet short IPthirdOctLength // Length of IP address 3rd Octet short IPfourthOctLength // Length of IP address 4th Octet For concatenating our string, we’ll need to calculate the length of the new part we’re adding and use that as an offset, so we’ll need 2 variables for this short length1 // length1 used for offset calculations short length2 // length2 used for offset calculations Once we have our final string, we’ll measure the length of that too. short overalllength // Overall length of string Since our output will be an ASCII string, we’ll need some ASCII (char) variables as destinations for a Decimal to ASCII conversion char IPfirstOct[3] // IP address 1st Octet char char IPsecondOct[3] // IP address 2nd Octet char char IPthirdOct[3] // IP address 3rd Octet char char IPfourthOct[3] // IP address 4th Octet char Finally, a destination for the final string: char OutputString[64] // Result output string The Program Now to the program itself. Having set up our variables, first off, we’ll clear “OutputString” and put the result into our destination, LW100. FILL(OutputString[0], 0, 64) // clear OutputString SetData(OutputString[0], "Local HMI", LW, 100,64) // Clear LW100 Then get the IP address from the HMI, one Octet at a time. GetData(IPfirstOctDEC, "Local HMI", LW, 9129, 1) // Get IP address 1st Octet etc. Next, we’ll determine if the first Octet of the IP address is 1, 2 or 3 digits. if IPfirstOctDEC > 99 then // If 1st Octet of IP is>than 99 then IPfirstOctLength = 3 // 3 digits else if IPfirstOctDEC > 9 then // if it is greater than 9 then it is IPfirstOctLength = 2 // 2 digits else IPfirstOctLength = 1 // otherwise it's 1 digit end if As the IP address as read from the HMI LW is decimal, we’ll convert to ASCII and use the calculated length (IPfirstOctLength) to determine how many characters it will be. DEC2ASCII(IPfirstOctDEC, IPfirstOct[0], IPfirstOctLength) // // Convert the 1st Octet to ASCII for its calculated length of 1,2 or 3 We’ll repeat this for the other 3 Octets of the IP address. Next, we’ll start building the string… //"ftp://uploadhis:" StringCat(Text1[0], OutputString[0]) // concat Text1 - "ftp://uploadhis:" into OutputString length1 = StringLength(Text1[0]) // measure Text1 and put result into "length1" // //"ftp://uploadhis:password" StringCat(Text2[0], OutputString[length1]) // offset Text2 (password)into outputstring by length of Text1 (length1) length2 = StringLength(Text2[0]) + length1 // measure Text2 and add to length1 to give the next offset (length2) Using length1 and length2 alternately, we will offset the point at which the required variable or value is inserted into “OutputString“. And finally, we’ll measure “OutputString“, putting the result in “overalllength“. // Calculate the length of "ftp://uploadhis:password@IP1.IP2.IP3.IP4" overalllength = StringLength(OutputString[0]) And finally, putting in our ultimate destination, LW100. SetData(OutputString[0], "Local HMI", LW, 100, overalllength) // set LW100 with the value of OutputString The final, full macro is as follows: macro_command main() // // This Macro generates a string using the HMI IP address and the FTP password to generate: // // ftp://uploadhis:password@IP1.IP2.IP3.IP4/ // char Text1[16] = "ftp://uploadhis:" // first part of the string, this is fixed and 16 characters long char Text2[10] ="111111" // 2nd part of the string - ftp password char Text3[1] ="@" // the "@" character char Dot[1] = "." // the "." dot character char Slash[1] = "/" // the "/" forward slash character // the HMI IP address is in 16 bit registers, i.e. "decimal" short IPfirstOctDEC // IP address 1st Octet short IPsecondOctDEC // IP address 2nd Octet short IPthirdOctDEC // IP address 3rd Octet short IPfourthOctDEC // IP address 4th Octet // since each octet of the IP address can be 1,2 or 3 digits we will measure each Octet short IPfirstOctLength // Length of IP address 1st Octet short IPsecondOctLength // Length of IP address 2nd Octet short IPthirdOctLength // Length of IP address 3rd Octet short IPfourthOctLength // Length of IP address 4th Octet // when concatenating the strings for our final string we'll use 2 offsets short length1 // length1 used for offset calculations short length2 // length2 used for offset calculations // and calculate an overall length short overalllength // Overall length of string // char IPfirstOct[3] // IP address 1st Octet char char IPsecondOct[3] // IP address 2nd Octet char char IPthirdOct[3] // IP address 3rd Octet char char IPfourthOct[3] // IP address 4th Octet char char OutputString[64] // Result output string FILL(OutputString[0], 0, 64) // clear OutputString SetData(OutputString[0], "Local HMI", LW, 100,64) // Clear LW100 GetData(IPfirstOctDEC, "Local HMI", LW, 9129, 1) // Get IP address 1st Octet GetData(IPsecondOctDEC, "Local HMI", LW, 9130, 1) // Get IP address 2nd Octet GetData(IPthirdOctDEC, "Local HMI", LW, 9131, 1) // Get IP address 3rd Octet GetData(IPfourthOctDEC, "Local HMI", LW, 9132, 1) // Get IP address 4th Octet if IPfirstOctDEC > 99 then // If 1st Octet of IP is > than 99 then it is IPfirstOctLength = 3 // 3 digits else if IPfirstOctDEC > 9 then // if it is greater than 9 then it is IPfirstOctLength = 2 // 2 digits else IPfirstOctLength = 1 // otherwise it's 1 digit end if DEC2ASCII(IPfirstOctDEC, IPfirstOct[0], IPfirstOctLength) // Convert the 1st Octet to ASCII for its calculated length of 1,2 or 3 if IPsecondOctDEC > 99 then // If 2nd Octet of IP is > than 99 then it is IPsecondOctLength = 3 // 3 digits else if IPsecondOctDEC > 9 then // if it is greater than 9 then it is IPsecondOctLength = 2 // 2 digits else IPsecondOctLength = 1 // otherwise it's 1 digit end if DEC2ASCII(IPsecondOctDEC, IPsecondOct[0], IPsecondOctLength) // Convert the 2nd Octet to ASCII for its calculated length of 1,2 or 3 if IPthirdOctDEC > 99 then // If 3rd Octet of IP is > than 99 then it is IPthirdOctLength = 3 // 3 digits else if IPthirdOctDEC > 9 then // if it is greater than 9 then it is IPthirdOctLength = 2 else IPthirdOctLength = 1 // otherwise it's 1 digit end if DEC2ASCII(IPthirdOctDEC, IPthirdOct[0], IPthirdOctLength) // Convert the 3rd Octet to ASCII for its calculated length of 1,2 or 3 if IPfourthOctDEC > 99 then // If 4th Octet of IP is > than 99 then it is IPfourthOctLength = 3 // 3 digits else if IPfourthOctDEC > 9 then // if it is greater than 9 then it is IPfourthOctLength = 2 else IPfourthOctLength = 1 // otherwise it's 1 digit end if DEC2ASCII(IPfourthOctDEC, IPfourthOct[0], IPfourthOctLength) // Convert the 4th Octet to ASCII for its calculated length of 1,2 or 3 // Build the string // //"ftp://uploadhis:" StringCat(Text1[0], OutputString[0]) // concatenate Text1 - "ftp://uploadhis:" into OutputString length1 = StringLength(Text1[0]) // measure Text1 and put result into "length1" // //"ftp://uploadhis:password" StringCat(Text2[0], OutputString[length1]) // offset Text2 (password)into outputstring by length of Text1 (length1) length2 = StringLength(Text2[0]) + length1 // measure Text2 and add to length1 to give the next offset (length2) // //"ftp://uploadhis:password@" StringCat(Text3[0], OutputString[length2]) // offset Text3 (@)into outputstring by length of Text1 (length2) length1 = StringLength(Text3[0]) + length2 // measure Text3 and add to length2 to give the next offset (length1) // //"ftp://uploadhis:password@IP1" StringCat(IPfirstOct[0], OutputString[length1]) // Put 1st Octet of IP into our string length2 = StringLength(IPfirstOct[0]) + length1 // and calculate next offset // //"ftp://uploadhis:password@IP1." StringCat(Dot[0], OutputString[length2]) // Put "Dot" into our string length1 = StringLength(Dot[0]) + length2 // and calculate next offset // //"ftp://uploadhis:password@IP1.IP2" StringCat(IPsecondOct[0], OutputString[length1]) // Put 2nd Octet of IP into our string length2 = StringLength(IPsecondOct[0]) + length1 // and calculate next offset // //"ftp://uploadhis:password@IP1.IP2." StringCat(Dot[0], OutputString[length2]) // Put "Dot" into our string length1 = StringLength(Dot[0]) + length2 // and calculate next offset // //"ftp://uploadhis:password@IP1.IP2.IP3" StringCat(IPthirdOct[0], OutputString[length1]) // Put 3rd Octet of IP into our string length2 = StringLength(IPthirdOct[0]) + length1 // and calculate next offset // //"ftp://uploadhis:password@IP1.IP2.IP3." StringCat(Dot[0], OutputString[length2]) // Put "Dot" into our string length1 = StringLength(Dot[0]) + length2 // and calculate next offset // //"ftp://uploadhis:password@IP1.IP2.IP3.IP4" StringCat(IPfourthOct[0], OutputString[length1]) // Put 4th Octet of IP into our string length2 = StringLength(IPfourthOct[0]) + length1 // and calculate next offset // //"ftp://uploadhis:password@IP1.IP2.IP3.IP4/" StringCat(Slash[0], OutputString[length2]) // Put some slash on the end length1 = StringLength(Slash[0]) + length2 // and calculate next offset // // Calculate the length of "ftp://uploadhis:password@IP1.IP2.IP3.IP4" overalllength = StringLength(OutputString[0]) // Set LW100 to Value of OutputString // for length "overalllength" SetData(OutputString[0], "Local HMI", LW, 100, overalllength) // set LW100 with the value of OutputString end macro_command As usual, we have a demo program for you to download and try here.
For more information on TechTip: Using a Macro On a Weintek HMI to Generate a QR Code For The History Upload Address talk to Lamonde Automation Ltd