The normal running of a script is sequential. Each instruction completes before the next one is started and we proceed down the file. However not all things you want to do are sequential. Often you need to make a decision based on a value. Later on we will discuss getting the status of a machine and, as the names of the states are user defined we do this with numbers.
If you have obtained the status and it is a variable called status it is a two digit number with where the tens digit represents the major status and the units digit the sub-status. Since we have 8 major status categories each with eight sub-categories this means we have numbers between 00 and 77. If maintenance is major category 2 then any code between 20 and 27 is a maintenance code. Hence if status divided by 10 is equal to 2, remember we do not do fractions, we are in maintenance. Try this code.
$machine = "Hicell1" |
// set the machine name |
$status = $dde("STATUS_AS_CODE", $machine) |
// machine status as text |
status = 0+$status |
// convert it to a number |
if(status/10==2){ |
// test for maint mode |
message($machine+" in maintenance mode") |
|
} |
|
OK that is complex unless you know programming so let us explain slowly.
$machine = "Hicell1"
This sets a string variable to the string Hicell1. This is the name of the machine and we are going to keep using it. If we keep it separate and in just one place we can save rewriting a script and, in fact we can later pass it in as a $1 value and just have one script that does all the machines.
$status = $dde("STATUS_AS_CODE", $machine)
This reads the machine status from the database. Notice that because the function has a $ at the front of its name it returns a string not a number and it takes two variables. The first is a name from the NMS manual and the second is the machine name (we could have put "Hicell1" here but I explained why not earlier). There are various items like this and, in fact, when you look into the hardware monitoring you can generate more data with names.
status = 0 + $status
The problem is that that returned a string like "23" and we want a number like 23. To swap strings and numbers we cheat and use the fact that adding strings and numbers changes the type to the first type. Beware however as 0+"hello" will return 0 and 0+" 72+6" will return 72 because, although the string to number converter will skip any leading spaces, it stops at the first non-number.
Actually I could have used status=dde("STATUS_AS_CODE", $machine) which combines these two operations but be warned all DDE values we read are strings so calling if we convert on something that is not a number you get zero as a result.
status/10==2
Now we have the status as a number so it might be 23 or 56 or 0 or something. We have lots of symbols to combine two numbers and give another number. The most obvious are things like +. In the line 2+2 two numbers are combined to give another number 4. This is the job of +. We have – for subtract and * for multiply and / for divide so status/10 combines the two numbers status and 10 and gives us a new number that is the current value of the variable status divided by 10.
This idea of combining numbers is a very powerful tool and restricting it to just these four operations is wasteful so programmers have long since defined lots of other useful ways of combining numbers. For example status>=20. Read that as status greater or equal to 20 and it has value of 1 if the current value of status is greater or equal to 20 and a value 0 if status is less than 20. There are all sorts of comparisons that give you 1 for true and 0 for false. > greater than, >= greater than or equal to, < less than, <= less than or equal to are reasonably easy to read while == equal to and != not equal to are a bit more obscure. (Naturally we could not have the equality test to be something like status=20 because that would set the value of status to 20).
The problem with all these operators is who goes first? We learned in our school algebra that multiply and divide go first so we just have a bigger table for the rest which is in the appendix. If you want to change the order use brackets.
So back to status/10==2 what does this do? Status/10 has the value of the current value in the variable called status divided by 10 with any remainder thrown away. Then this is compared with 2 and if it is 2 then the final value is 1 (ie: true) and if it is not 2 the value is 0 (ie: false). So if status is any number in the range 20 to 29 then this expression is 1 and if status has any other value the result is 0. You could just as easily write status>=20 && status<=29 using the && operator that combines two values such that if they are both true (not zero) the result is true (1).
if(status/10==2)
This is the decision-maker. If the expression within the brackets of the if is true (ie: not zero) then all the script commands within the following braces (curly brackets) are executed. If the expression is false (ie: zero) then they are ignored.
Naturally not all things are that easy so we have the choice construction
if(exp){ ……. } else { …… }
if exp is true then the first set of commands is executed but if it is false then the second set are executed. If you want to get more sophisticated we actually can supply the form
if(exp1){ ….. } elseif(exp2){ …. } else { …. }
for up to 50 elseifs. This only executes one of the braces but the expressions are evaluated in order until one is found that is true and the brace with that is executed. If no expression is true then the else brace is executed. eg:
if(fault==23) |
{ $f = "tool breakage" } |
elseif(fault==17) |
{ $f = "door open" } |
elseif(fault==0) |
{ $f = "no fault" } |
else |
{ $f = "unknown fault" } |
message($f) |
|
If you need more complex constructions, like loop back to the beginning, use the while( ) operator which keeps performing all the expressions in its brace while its value is true as in
n = 0 |
|
while(n<10){ |
|
do something with n |
|
n = n+1 |
// forget this line and it loops for all time |
} |
|
Alternatively use the goto instruction. For this you need a text label as a target which is marked by having a : after it. This is useful for extracting yourself from the middle of a deep nest of ifs and things eg: error in
if(…) {
while(…) {
if(…) {
if(it_has_all_blown_up){ goto error }
……
error:
message("I think we have a problem here")
Any text name will do provided it starts with a letter and contains letters, numbers or the _$@ characters.