AN03 Switching OFF a 230V power socket when current exceeds limit, email alerts | NETIO products: Networked power sockets
Tagy: 
Lua tutorials

This Application Note demonstrates how to create a Lua script to monitor the current flowing through individual sockets of a NETIO 4All smart power strip. When the current at a particular socket exceeds the limit for longer than the specified time period, the script turns the socket off and sends an email

Do you have any questions?

 

Supported devices: 

NETIO 4All, NETIO 4C, NETIO 4

 

The Lua script shown in NETIO AN03 monitors the current flowing through a selected output (or the sum of currents through all the outputs). If the current exceeds a specified limit, the script starts counting time. When the overcurrent condition lasts longer than the specified time period without interruption, the Lua script turns the socket off and sends an e-mail. 

 

 

For the example in the picture, the script can be configured in the following way. If the limit is exceeded for a short time only (situation A), the output remains on. If the limit is exceed for a longer time (situation B), the output is switched off.


 

NETIO AN03 also shows how to detect undercurrent in addition to overcurrent. For instance, this can be used to detect that during an extended period of time, an A/C unit has only been consuming power for ventilation but not for cooling, and send an e-mail alert.

 

The example demonstrates how to use global variables and how to measure current. 

 

Contents

  • Creating the rule
  • Creating the Lua script
  • Adding undercurrent monitoring
  • Setting up e-mail alerts

 

Creating the rule 

 

To create and run a Lua script, do the following:

1) In the Actions section of NETIO 4 web administration, click Create Rule to add a rule.

 

2) Fill in the following parameters:

  • Enabled: checked
  • Name: Watcher (user-defined)
  • Description: Current watcher (user-defined)
  • Trigger: System variables updated
  • Schedule: any (does not affect the function in this configuration)

 

3) Copy the following code and paste it into the field for the Lua script:

------------Section 1------------
local output = 1 -- choose number of outlet
local currentLimit = 100 -- choose ampere limit [mA]
local timeLimit = 1 -- choose time limit [seconds]
local recipient = "my.email@example.com"
local subject = "Output takes too much power"
local text = "Output " .. string.format(output) .. " on your NETIO exceeded limit " .. string.format(currentLimit) .. "mA!"
---------End of Section 1---------

-- Global variables: _G.timestamp

local current = 0

function shutDown()
  if output == 0 then
    for i=1,4,1 do
      devices.system.SetOut{output=i, value=false}
    end
  else
    devices.system.SetOut{output=output, value=false}
  end
end

function checkTime()
  local timeNow = os.time()
  if (_G.timestamp == 0 or _G.timestamp == nil) then
    _G.timestamp = timeNow
  end
  if (timeNow - _G.timestamp >= timeLimit) then
    return true
  end
  return false
end

function currentMeasurement()
  if output == 0 then
    for i=1,4,1 do	 
      current = current + devices.system["output" .. i .. "_current"]
    end
  else
    current = devices.system["output" .. output .. "_current"]
  end
  if current > currentLimit then
    if checkTime() then
      shutDown()
      mail(recipient, subject, text)
    end
  else
    _G.timestamp = 0
  end
end

currentMeasurement()

4) To finish the rule creation, click Create Rule at the bottom of the screen.

 

Creating the code

  • The script is run whenever a system variable (e.g. current or voltage at a particular output) changes. In most situations, the script is run once per second.
  • If the immediate current at a socket exceeds, without interruption, the specified limit for the specified time, the script automatically switches the socket off. It can also send an e-mail.
  • The script can also monitor the sum of currents through all outputs: simply set the number of the monitored output to 0.
  • In order to set the parameters, 6 variables are needed (socket number, current limit, time limit, e-mail address, e-mail subject, e-mail body).
  • The script contains a function that reads the current and compares it with the limit; if exceeded, it switches the socket off and sends an e-mail. This function is called currentMeasurement. The checkTime function checks if the specified time period has been exceeded. The shutDown function reacts to the overcurrent.

Variables

  • The variables for configuration parameters are called output, currentLimit, timeLimit, recipient, subject, text
  • The variables are declared using the local keyword (e.g. local output = 1)
  • Their meanings are as follows:

  • output             
    • Specifies the socket to monitor.
    • To monitor all sockets at once, specify 0.
    • For example, to monitor socket No. 3: output = 3

  • currentLimit
    • Specifies the current limit (in milliamps).
    • The maximum value is 8A = 8000mA (currentLimit = 8000).
    • The value must be an integer (NETIO Lua does not support decimal numbers).
    • For example, to set a current limit of 200mA: currentLimit = 200

 

  • timeLimit
    • Specifies the time (in seconds) for which the current through the output must exceed the limit for the socket to be switched off.
    • To switch the socket off as soon as the current exceeds the limit, specify 0.
    • For example, to switch off after 5 seconds of overcurrent: timeLimit = 5

  • recipient
    • E-mail address of the alert message recipient.
    • It is a text string, so it has to be enclosed in double quotes.
    • For example, to send the e-mail to john.smith@gmail.com: recipient = "john.smith@gmail.com"

  • subject
    • Specifies the subject of the alert e-mail message.
    • It is again a text string so it has to be enclosed in double quotes.
    • Example: subject = "Output takes too much power"

  • text
    • Specifies the body of the alert e-mail message.
    • It is again a text string so it has to be enclosed in double quotes.
    • Example: text = "Output " .. string.format(output) .. " on your NETIO exceeded limit " .. string.format(currentLimit) .. "mA!"
    • The script also includes a variable to keep the value of the current. It is named current and is initially set to zero (local current = 0).

 

checkTime function

function checkTime()
  local timeNow = os.time()
  if (_G.timestamp == 0 or _G.timestamp == nil) then
    _G.timestamp = timeNow
  end
  if (timeNow - _G.timestamp >= timeLimit) then
    return true
  end
  return false
end
  • The function contains 2 variables: the local variable timeNow that keeps the current time, and the global variable _G.timestamp that keeps the time when the limit was first exceeded. If the current limit has never been exceeded, it has the value of nil. When the current returns below the limit, the currentMeasurement function resets the value of this variable to 0.
  • A global variable is not declared using the local keyword and it can be accessed from all scripts. It is therefore very important not to use a global variable with the same name in other scripts. Most likely, both scripts would malfunction in such a case. In Lua, it is customary to prefix global variables with _G. for clarity.
  • First, the current time is read using the os.time() library function  and stored into the timeNow variable.
  • Then, it is checked whether the current limit has been exceeded anew (if (_G.timestamp == 0 or _G.timestamp == nil) then)*. If so, the current time is stored into the _G.timestamp variable (_G.timestamp = timeNow).
  • Finally the function checks whether the duration of the overcurrent condition has reached the specified time (if (timeNow - _G.timestamp >= timeLimit) then). If so, the function returns the value of true (return true). Otherwise, it returns the value of false (return false). 

currentMeasurement function

function currentMeasurement()
  if output == 0 then
    for i=1,4,1 do	 
      current = current + devices.system["output" .. i .. "_current"]
    end
  else
    current = devices.system["output" .. output .. "_current"]
  end
  if current > currentLimit then
    if checkTime() then
      shutDown()
      mail(recipient, subject, text)
    end
  else
    _G.timestamp = 0
  end
end
  • First, according to the output variable, the function stores the current flowing through one of the outputs (or the sum of currents through all the outputs) to the current variable. This value is then compared to the currentLimit variable.
  • The devices.system.outputN_current function, where N is the number of the output to measure, is used to read the value of the current.
  • The syntax to pass the parameters (output in this case) is as follows: devices.system["output" .. output .. "_current"]
  • Then, the function checks whether it should measure the total over all sockets (if output = 0 then), or just one socket (else).
function currentMeasurement()
  if output == 0 then
    ---- if section ----
  else
    ---- else section ----
  end
end
  • In case of all sockets (if section), the currents through all the sockets are added together.
    • This is done with a for loop that adds the currents through the individual sockets to the current variable one by one.
    • The loop declaration contains the initialization (variable name and the initial value), the condition (the value where the loop stops) and the increment** (the increase at each iteration).
    • This is the initialization: i=1, the condition: 4, the increment: 1
    • Then follows the do keyword, and the loop is terminated with the end keyword.
    • Inside the for loop, the currents flowing through the individual sockets are added to the current variable one by one: current = current + devices.system["output" .. i .. "_current"]
    • The entire loop looks like this:
for i=1,4,1 do	 
  current = current + devices.system["output" .. i .. "_current"]
end
  • If only one socket is monitored (else section), the current is read directly: current = devices.system["output" .. output .. "_current"]
  • The current is compared to the specified limit.
    • This is done with a simple condition: if current > currentLimit
    • If the condition is true, that is the current is higher than the limit, the checkTime function checks whether the time limit has been exceeded (if checkTime() then). If so, the shutDown() function is called to switch off the socket (or sockets) and send the e-mail alert.
    • The mail function is used to send the e-mail. Its parameters are: recipient, subject, body. In this case, the variables recipient, subject and text are passed as the parameters.
    • The statement is: mail(recipient, subject, text)
    • The limit for sending e-mails is one per 5 minutes. This limit can be changed by passing a 4th parameter to the mail function. This parameter is a number in seconds. To be able to send a mail every 30 seconds, the command would look like: mail(recipient, subject, text,30)
    • If the current limit is not exceeded, the _G.timestamp global variable needs to be reset to zero (_G.timestamp = 0).

shutDown function

function shutDown()
  if output == 0 then
    for i=1,4,1 do
      devices.system.SetOut{output=i, value=false}
    end
  else
    devices.system.SetOut{output=output, value=false}
  end
end
  • The function switches off the output (or all the outputs).
  • To switch off all outputs, the same condition (output = 0) as in the currentMeasurement function is used.
    • The condition and the loop are the same as in the currentMeasurement function, except that the adding of currents is replaced by the switching off of the given socket. This command is used:
      devices.system.SetOut{output=i, value=false}
  • If only one socket is monitored, the following command is used: devices.system.SetOut{output=output, value=false}

Starting the script

  • The script is started by calling the currentMeasurement function. The script ends with the following command: currentMeasurement().
  • After checking Enabled and saving changes, the script is activated.

*Every unitialized variable has the value of nil.

**The default increment is 1. So, in this case, it was not necessary to specify it.


 

Adding undercurrent monitoring

To monitor whether the current through a socket lies within a certain range, make the following changes.

1) In Section 1, add a new currentLowerLimit variable and set it to the minimum allowed value of the current. Example for 100mA: local currentLowerLimit = 100

2) Replace the currentMeasurement function with the following:

 

function currentMeasurement()
  if output == 0 then
    for i=1,4,1 do         
      current = current + devices.system["output" .. i .. "_current"]
    end
  else
    current = devices.system["output" .. output .. "_current"]
  end
  if (current > currentLimit or current < currentLowerLimit) then
    if checkTime() then
      shutDown()
      mail(recipient, subject, text)
    end
  else
    _G.timestamp = 0
  end
end

 

  • The script will now check for current above as well as below the limits. The time limit specified in the timeLimit variable applies to both situations – the output must be outside of the allowed range for longer than the specified time.

 

 

Setting up e-mail alerts

  • In order to send e-mails from your NETIO device, it is necessary to configure the settings in the Settings – E-mail section of the web interface.
  • For details, see NETIO AN07

 


Supported FW versions:

3.0.0 and higher


Keywords: 

Current monitoring, current measurement, current, Overload control, Lua, e-mail, SMTP, ampere, email when limit was exceeded, Lua tutorial, current SafeRange

 

FAQ

Expand all

Is it possible to monitor several outputs (e.g. 1 and 2) of the same NETIO device?

Yes. Simply create a new rule, give it a new name (e.g. Watcher2), change the value of the output variable to 2 and set the required limit. Remember to rename the _G.timestamp global variable, e.g. to _G.timestamp2, in the whole script. The two rules will run in parallel.

I don't want to receive e-mails, what should I do?

In the currentMeasurement function, delete (or comment out) the line with the mail command.

I want to power-cycle the output instead of turning it off, is it possible?

Yes. In the shutDown function, replace the command to switch off the output with a command to reset it. Here is the modified function:


function shutDown()
  if output == 0 then
    for i=1,4,1 do
      devices.system.ResetOut{output=i}
    end
  else
    devices.system.ResetOut{output=output}
  end
end

If you need a delay between the successive power off and power on, add a delay parameter to the ResetOut command to specify the delay. The statement is: devices.system.ResetOut{output=i, delay=12} or devices.system.ResetOut{output=output, delay=12} (replace 12 with the required delay).

 

Is it possible to switch on another output when the current at the monitored output is over the limit?

Yes. Add the following command to the shutDown function, just above the last line with the end statement: devices.system.SetOut{output=X, value=true}. Replace X with the number of the output to switch on.

Is it possible to send an e-mail only but leave the socket turned on?

Yes. In the currentMeasurement function, delete the shutDown() function call.

Is it possible to combine this script with other scripts?

Yes. However, keep in mind that if the limit is exceeded, the socket turns off, and this may disrupt other simultaneous actions. Also pay attention to the _G.timestamp global variable.

Ask for a price or technical parameters

For device testing use name/password demo/demo