Managing Power Distribution Unit via SMS

From MikroTik Wiki
Jump to: navigation, search

Below a script to manage Aviosys 9258S, 9258HP, 9258DS, ... PDU via /tool sms

Warning : needs Routeros >= 6.2, see comments in the script.

Original page (in French): Gestion des alimentations électriques via SMS

Titre LndkSmsPower.png

Testing

Getting state of outlets of default device and device named pwr004 :

/system script run LndkSmsPower
:global DV "pwr004"; /system script run LndkSmsPower

Switching outlet 2 of default device :

:global PR 2; /system script run LndkSmsPower

Cycling outlet 1 of default device :

:global PR 1; :global OP "RE"; /system script run LndkSmsPower

Sending SMS

SMS to send to request state of pwr099 device, and then to switch outlet 3 of default device pwr015 :

:cmd password script LndkSmsPower DV=pwr099

:cmd password script LndkSmsPower PR=3

Android phone screenshot :

Screenshot 20150215.png

Cycling outlet 3 of default device :

:cmd password script LndkSmsPower OP=re PR=3

The LndkSmsPower script

Downloadable file LndkSmsPower.rsc (/tool fetch url=http://blog.lekermeur.net/wp-content/uploads/2015/02/LndkSmsPower.rsc) :

#######################################################################################
# Script RouterOS LndkSmsPower                                                        #
# Managing outlets of  Aviosys PDU 9258S, 9258HP and 9258DS via SMS                   #
# Send state of outlets of the device, switch or reinit outlet                        #
# Web page : http://blog.lekermeur.net/?p=2531                                        #
# Marc Dilasser, Le Net du Kermeur, Fevrier 2015                                      #
#######################################################################################

:global DV
:global PR
:global OP
:local  ADRIP     ""
:local  HPORT
:local  NETWORK   "MyNet"
:local  DEVNAME   ""
:local  MODEL     ""
:local  PRISE     -1
:local  NBJOB
:local  NBSMS
:local  VER
:local  NBOPER
:local  URL
:local  ERR
:local  OUTFILE   "LndkPowerState"
:local  IDF
:local  CONTENT
:local  MSG
:local  HHMMSS
:local  IJ
:local  IK
:local  IL
:local  ISTAT
:local  IOSTATE
:local  ITEM
:local  PORT
:local  NUMTEL
:local  DEBUG  0
:local  ADMIN
:local  PASSWORD
:local  OPER
:local  AROPERS
:local  ONOFF   [:toarray ("OFF,ON ")]
:local  HEXA    [:toarray ("0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f")]
:local  LANG
:local  ARLANGS [:toarray ("en,fr")]
:local  AAR  {
              "address"={ en="address";                fr="adresse"   };
              "outlet"={  en="outlet";                 fr="prise"     };
              "device"={  en="device";                 fr="equipement"};
              "model"={   en="model";                  fr="modele"    };
              "state"={   en=" state of ";             fr=" etat de " };
              "at"={      en=" at ";                   fr=" a "       };
              "err200"={  en="sending sms error";      fr="erreur envoi SMS"     };
              "err220"={  en="http error";             fr="erreur acces http"    };
              "err230"={  en="Url non defined";        fr="Url non definie"      };
              "err240"={  en="script already running"; fr="script deja en cours" };
             }

:global ChangeToMajOrMinCase do={
                     :local S1
                     :local S2 ""
                     :local CH ""
                     :local I1
                     :local I2
                     :local I3
                     :local MINMAJ {
                        "min"="abcdefghijklmnopqrstuvwxyz";
                        "maj"="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
                     }
                     :local SOURCE "min"
                     :local TARGET "maj"
                     :set S1 $1
                     :set I2 [:len $S1]
                     :if ($2 = 0) do={
                         :set SOURCE "maj"; set TARGET "min";
                     }
                     :if ($I2 > 0) do={
                        for I1 from=0 to=($I2 - 1)  do={
                           :set CH [:pick $S1 $I1 ($I1 + 1)]
                           :set I3 [:find ($MINMAJ->$SOURCE) $CH]
                           :if ($I3 >= 0) do={
                              :set CH [:pick ($MINMAJ->$TARGET) $I3 ($I3 + 1)]  
                           }    
                           :set S2 ($S2 . $CH)
                        }
                     }
                     :return $S2
                  }
:local ToUpper    do={
                     :global ChangeToMajOrMinCase
                     :return [$ChangeToMajOrMinCase $1]
                  }
:local ToLower    do={
                     :global ChangeToMajOrMinCase
                     :return [$ChangeToMajOrMinCase $1 0]
                  }
# if ($VER >= 6.2)
:local  DoHttp    do={
                     :local LERR 0
                     :do {
                        /tool fetch url="$1" dst-path="$2"
                     } on-error={ 
                        :set LERR 1 
                     }
                     :return $LERR
                  }
:local  DoSendSms do={
                     :local LERR 0
                     :local MESS
                     :set MESS [:pick $3 0 158]
                     :do {
                        /tool sms send "$1" "$2" message="$MESS"
                     } on-error={ 
                        :set LERR 1 
                     }
                     :return $LERR
                  }
#endif
#######################################################################################
# Valeurs a configurer suivant exploitation :                                         #
#    - user et mot de passe Aviosys                                                   #
#    - adresse ip                                                                     #
#    - nom de device                                                                  #
#    - modele                                                                         #
#    - numero telephone destinataire du SMS, par defaut allowed-number de /tool sms   #
#    - le device par defaut                                                           #
# La variable DV du SMS, si presente, donne le device                                 #
# La variable PR du SMS, si presente, donne la prise a basculer                       #
# La variable OP du SMS, si presente, donne le type d'operation                       #
#######################################################################################
:if ([:len $DV] = 0) do={:set DV "pwr001"; }

:set  ADMIN     "admin"
:set  PASSWORD  "password"

# Default lang is en
# :set LANG "fr"

:if ($DV = "pwr001") do={
   :set ADRIP     "10.6.7.8"
   :set DEVNAME   "pwr001"
   :set MODEL     "9258S"
}

:if ($DV = "pwr009") do={
   :set ADRIP     "10.6.2.9"
   :set DEVNAME   "pwr009"
   :set MODEL     "9258DSv1"
   :set PASSWORD  "motdepasse"
}

:if ($DV = "pwr028") do={
   :set ADRIP     "192.168.1.100"
   :set DEVNAME   "pwr028"
   :set MODEL     "9258DSv4"
   :set DEBUG     1
}

:if ($DV = "pwr029") do={
   :set ADRIP     "192.168.1.100"
   :set HPORT     "8084"
   :set DEVNAME   "pwr029"
   :set MODEL     "9258HP"
   :set PASSWORD  "motdepasse"
   :set DEBUG     1
}
#######################################################################################
# END OF CONFIG                                                                       #
#######################################################################################

#######################################################################################
# CGI commands examples on different Aviosys models and responses                     #
# 9258S    :                                                                          #
#  > /tool fetch url="http://admin:password@192.168.1.100/Set.cmd\?CMD=GetPower"      #
#  < <html>p61=0,p62=1,p63=0,p64=0</html>                                             #
# 9258DSv1 : (firmware version 1.x)                                                   #
#  > wget -qO- http://192.168.1.100/Set.cmd?user=admin+pass=password+CMD=GetSysIO     #
#  <  IOVALUE:fb                                                                      #
# 9258DSv4 : (firmware version 4.x)                                                   #
#  > wget -qO- http://192.168.8.100/set.cmd?user=admin+pass=password+cmd=GetPower     #
#  <  P61=0,P62=1,P63=1,P64=0,P65=1,P66=1,P67=1,P68=1                                 #
# 9258HP   :                                                                          #
#  > wget -qO- http://admin:password@192.168.1.100/SetPower.cgi?p4=1                  #
#  < <TITLE>Set Power Control</TITLE><BODY>Power Control = P4:1,P3:0,P2:1,P1:1;<p>... #
#######################################################################################
:set NBJOB [/system script job print count-only where script=LndkSmsPower]
if ($NBJOB > 1) do={
   :log error ($AAR->"err240"->$LANG)
   return 240
}

#######################################################################################
# List of operations                                                                  #
# Default operation is ST, only send STATE                                            #
# If PR (outlet) is set, defaut OP is SW, to switch this outlet                       #
# If OP is RE (reinit) and PR is set, operations are STATE,SWITCH,DELAY,SWITCH,STATE  #
# If OP is LI (list names of outlets), operation is LIST (not implemented yet)        #
#######################################################################################

:if (([:len [:find $ARLANGS $LANG]]) = 0) do={ :set LANG "en"; }

:if ([:len $OP] = 0) do={
   :set OP "ST";
   :if ([:len $PR] = 1) do={ :set OP "SW"; }
} else={
   :set OP [$ToUpper $OP]
}

:set AROPERS [:toarray ("STATE")]
:if ($OP = "SW") do={
   :if ([:len $PR] = 1) do={
      :set AROPERS [:toarray ("STATE,SWITCH,STATE")]
   }
}
:if ($OP = "RE") do={
   :if ([:len $PR] = 1) do={
      :set AROPERS [:toarray ("STATE,SWITCH,STATE,DELAY20,SWITCH,STATE")]
   } 
}
:if ($OP = "LI") do={
   :set AROPERS [:toarray ("LIST")]
}
:if ([:len $PR] > 0) do={ 
   :set PRISE ([:tonum $PR] - 1); 
} 
:if ([:len $OP] = 0) do={ :set OP ""; }
:set VER [/system resource get version]
:set MSG (($AAR->"device"->$LANG) . " " . $DEVNAME . ", ")
:set MSG ($MSG . ($AAR->"model"->$LANG) . " " . $MODEL . ", ")
:set MSG ($MSG . ($AAR->"address"->$LANG) . " " . $ADRIP)
:log info $MSG

#######################################################################################
# Do while some operation to do                                                       #
#######################################################################################
foreach OPER in ($AROPERS) do={
   :if ($OPER = "STATE") do={
      :set URL ""       
      :if ($MODEL = "9258S") do={
         :set URL ("http://" . $ADMIN . ":" . $PASSWORD . "@" . $ADRIP )
         :if ([:len $HPORT] > 0) do={ :set URL ($URL . ":" . $HPORT); }
         :set URL ($URL . "/Set.cmd\?CMD=GetPower")
      }
      :if ($MODEL = "9258DSv1") do={
         :set URL ("http://" . $ADRIP);
         :if ([:len $HPORT] > 0) do={ :set URL ($URL . ":" . $HPORT); }
         :set URL ($URL . "/Set.cmd\?user=" . $ADMIN )
         :set URL ($URL . "+pass=" . $PASSWORD . "+CMD=GetSysIO")
      }
      :if ($MODEL = "9258DSv4") do={
         :set URL ("http://" . $ADRIP)
         :if ([:len $HPORT] > 0) do={ :set URL ($URL . ":" . $HPORT); }
         :set URL ($URL . "/set.cmd\?user=" . $ADMIN )
         :set URL ($URL . "+pass=" . $PASSWORD . "+cmd=GetPower")
      }
      :if ($MODEL = "9258HP") do={
         :set URL ("http://" . $ADRIP)
         :if ([:len $HPORT] > 0) do={ :set URL ($URL . ":" . $HPORT); }
         :set URL ($URL . "/GetPower.cgi")
      }
      :if ([:len $URL] = 0) do={
         :return 250
      } else={  
         :if ($DEBUG > 0) do={ :put "Url : $URL";  }
      }
      :set ERR 0
# if ($VER >= 6.2) 
      :set ERR [$DoHttp $URL $OUTFILE]
# else
# :set ERR 0
# /tool fetch url=$URL dst-path=$OUTFILE
# endif
      :if ($ERR < 1) do={
         :set IDF [/file find where name=$OUTFILE]
         :set CONTENT [ /file get $IDF contents]
         :if ($DEBUG > 0) do={ :put $CONTENT; }
         :set HHMMSS [/system clock get time]
         :set MSG ($NETWORK . " :" . ($AAR->"state"->$LANG))
         :set MSG ($MSG . $DEVNAME . ($AAR->"at"->$LANG) . $HHMMSS . "\n")

         :if ($MODEL = "9258DSv1") do={
            :set ISTAT [:tonum ("0x" . [:pick $CONTENT 9 11])]
            :set IOSTATE $ISTAT
            :set IJ 0
            while ($IJ < 8) do={
               :set IK ($ISTAT % 2)
               :set MSG ($MSG . ($AAR->"outlet"->$LANG) . " " . [:tostr ($IJ + 1)] )
               :set MSG ($MSG . ": " . [:pick $ONOFF $IK] . " ")
               :if (($IJ % 2) = 1) do={ :set MSG ($MSG . "\n"); }
               :set ISTAT ($ISTAT / 2)
               :set IJ ($IJ + 1)
            }
         }
         :if (($MODEL = "9258S") || ($MODEL = "9258DSv4")) do={
            :if ($MODEL = "9258S") do={ 
                :set IJ 10;
                :set IK 4;
             } else={ 
                :set IJ 5;
                :set IK 8;
             } 
            :if (([:pick $CONTENT 0 6] = "<html>") || ([:pick $CONTENT 0 5] = " P61=")) do={
               :for IL from=1 to=$IK do={
                  :set MSG ($MSG . "   " . ($AAR->"outlet"->$LANG) . " " . ([:tostr $IL]) . ": ")
                  :set MSG ($MSG . ([:pick $ONOFF [:pick $CONTENT ($IJ + (($IL - 1) * 6)) ]]))
                  :if ((($IL % 2) = 0) && ($IL < $IK)) do={
                     :set MSG ($MSG . "\n")
                  }
               }
               :if ( $PRISE > -1 ) do={
                  :set IOSTATE [:pick $CONTENT ($IJ + (6 * $PRISE))]
                  :log info (($AAR->"outlet"->$LANG) . " " . ($PRISE + 1) . ", iostate : $IOSTATE")
               }
            }
         }
         :if ($MODEL = "9258HP") do={
            :set IJ [:find $CONTENT "Control = P4"]
            :if ([:len $IJ] > 0) do={
               :set IJ ($IJ + 13)
               :set MSG ($MSG . "   " . ($AAR->"outlet"->$LANG) . " 1: ")
               :set MSG ($MSG . ([:pick $ONOFF [:pick $CONTENT ($IJ + 15) ]]))
               :set MSG ($MSG . ", " . ($AAR->"outlet"->$LANG) . " 2: ")
               :set MSG ($MSG . ([:pick $ONOFF [:pick $CONTENT ($IJ + 10) ]]) . "\n")
               :set MSG ($MSG . "   " . ($AAR->"outlet"->$LANG) . " 3: ")
               :set MSG ($MSG . ([:pick $ONOFF [:pick $CONTENT ($IJ + 5) ]]))
               :set MSG ($MSG . ", " . ($AAR->"outlet"->$LANG) . " 4: ")
               :set MSG ($MSG . ([:pick $ONOFF [:pick $CONTENT $IJ ]]))
               :if ( $PRISE > -1 ) do={
                  :set IOSTATE [:pick $CONTENT ($IJ + (5 * $PRISE))]
                  :log info (($AAR->"outlet"->$LANG) . " " . ($PRISE + 1) . ", iostate : $IOSTATE")
               }
            }
         }
         :if ([:len $MSG] > 60) do={
            :if ($DEBUG = 0) do={
               :set PORT [/tool sms get port]
               :if ([:len $NUMTEL] = 0) do={
                  :set NUMTEL [/tool sms get allowed-number]
               }
# if ($VER >= 6.2)
               :set ERR [$DoSendSms $PORT $NUMTEL $MSG]
               :if ($ERR > 0) do={
                  :log error ($AAR->"err200"->$LANG) 
                  return 200
               }
# else
# /tool sms send ...
# endif
            } else={
               :put ($MSG)
               :log info ($MSG)
            }
         }
         /file remove $IDF
      } else={
         :log error ($AAR->"err220"->$LANG) 
         return 220; 
      }
   }

   :if ($OPER = "SWITCH") do={
      :if (([:len $PRISE] = 1) && ([:len $IOSTATE] > 0)) do={
         :set URL ""       
         :if ($MODEL = "9258S") do={
            :set URL ("http://" . $ADMIN . ":" . $PASSWORD . "@")
            :set URL ($URL . $ADRIP)
            :if ([:len $HPORT] > 0) do={ :set URL ($URL . ":" . $HPORT); }
            :set URL ($URL . "/Set.cmd\?CMD=SetPower")
            :set URL ($URL . "+P6" . [:tostr ($PRISE + 1)] . "=")
            :set URL ($URL . [:tostr (($IOSTATE + 1) % 2)])
         }
         :if ($MODEL = "9258DSv4") do={
            :set URL ("http://" . $ADMIN . ":" . $PASSWORD . "@")
            :set URL ($URL . $ADRIP)
            :if ([:len $HPORT] > 0) do={ :set URL ($URL . ":" . $HPORT); }
            :set URL ($URL . "/set.cmd\?cmd=setpower")
            :set URL ($URL . "+p6" . [:tostr ($PRISE + 1)] . "=")
            :set URL ($URL . [:tostr (($IOSTATE + 1) % 2)])
         }
         :if ($MODEL = "9258DSv1") do={
            :set URL ("http://" . $ADRIP)
            :if ([:len $HPORT] > 0) do={ :set URL ($URL . ":" . $HPORT); }
            :set URL ($URL . "/Set.cmd\?user=" . $ADMIN )
            :set URL ($URL . "+pass=" . $PASSWORD . "+CMD=SetSysIO+IO=")
            :set IJ 8
            :set IK 0
            while ($IJ > 0) do={
               :set IK ($IK * 2)
               :if ($IJ = ($PRISE + 1)) do={ :set IK ($IK + 1); }
               :set IJ ($IJ - 1)
            }
            :set IJ ( $IOSTATE ^ $IK)
            :set URL ($URL . [:pick $HEXA ($IJ / 16)])
            :set URL ($URL . [:pick $HEXA ($IJ % 16)])
            :set URL ($URL . "+Delay=1")
         }
         :if ($MODEL = "9258HP") do={
            :set URL ("http://" . $ADMIN . ":" . $PASSWORD . "@")
            :set URL ($URL . $ADRIP)
            :if ([:len $HPORT] > 0) do={ :set URL ($URL . ":" . $HPORT); }
            :set URL ($URL . "/SetPower.cgi\?p")
            :set URL ($URL . [:tostr ($PRISE + 1)] . "=")
            :set URL ($URL . [:tostr (($IOSTATE + 1) % 2)])
         }
         :if ([:len $URL] = 0) do={
            :log error ($AAR->"err230"->$LANG)
            :return 230
         } 
         :if ($DEBUG > 0) do={
            :put "Url : $URL"
            :log info "Url : $URL"
         } else={
            :log info "Url : $URL"
# if ($VER >= 6.2) 
            :set ERR [$DoHttp $URL $OUTFILE]
# else
# :set ERR 0
# /tool fetch url=$URL dst-path=$OUTFILE
# endif
            :if ($ERR < 1) do={
               :set IDF [/file find where name=$OUTFILE]
               /file remove $IDF
            }
         } 
      } else={
         :log error ($AAR->"err220"->$LANG)
         :return 220
      }
   }

   :if ($OPER = "DELAY20") do={
      :delay 20
   }

   :if ($OPER = "LIST") do={
      :delay 1
   }
}

#######################################################################################
# Some cleanings                                                                      #
#######################################################################################
:foreach ITEM in ("DV", "OP", "PR") do={
   /system script environment remove [find where name=$ITEM]
}

:set NBSMS [/tool sms inbox print count-only]
:if ($NBSMS >= 30) do={
   /tool sms inbox remove 0,1,2,3,4,5,6,7,8,9
}
###########   End of LndkSmsPower   ###########   That's All, Folks   ###########

See also

Manual:USB Features

Manual:Tools/Sms