Newbie question (not sure if agent/device code issue) - server call doesn't work after awhile

Hi all,

Just got my board and led tail set up and demo code working (yay!). So I’m trying to get it to work as a connected alarm for our CI system (yeah! hooking it up to Jenkins).

Problem I have is that the code works for maybe 2 - 3 times that I hit the URLs for the different led alerts but then it stops working. Any idea what’s going on? I do not get any exceptions so I am really clueless about how to troubleshoot it. (Thanks!!)

So here’s the agent code which is similar to the demo code:

`// Agent Code

// Log the URLs we need
server.log("Red Alert: " + http.agenturl() + “?alrt=0”);
server.log("Amber Alert: " + http.agenturl() + “?alrt=1”);
server.log("All Clear: " + http.agenturl() + “?alrt=2”);

function requestHandler(request, response) {
try {
// check if the user sent led as a query parameter
if (“alrt” in request.query) {

  // if they did, and led=1.. set our variable to 1
  if (request.query.alrt == "0" || request.query.alrt == "1" || request.query.alrt == "2") {
    // convert the led query parameter to an integer
    local alertState = request.query.alrt.tointeger();

    // send "led" message to device, and send ledState as the data
    device.send("setAlert", alertState); 
    server.log("Alert state is " + alertState);
  }
}
// send a response back saying everything was OK.
response.send(200, "OK");

} catch (ex) {
response.send(500, "Internal Server Error: " + ex);
}
}

// Reqister the handler to deal with incoming requests
http.onrequest(requestHandler);`

Here is the device code (ignore the extra global variables - not cleaned up yet):

`// Device Code

#require “WS2812.class.nut:1.0.0”

// CONSTANTS

const NUMPIXELS = 5
const DELAY = 0.1

// Instantiate the WS2812s

local spi = hardware.spi257
spi.configure(MSB_FIRST, 7500)
local pixels = WS2812(spi, NUMPIXELS)

local redVal = 0
local greenVal = 0
local blueVal = 0

local redDelta = 1
local greenDelta = 1
local blueDelta = 1

local redOn = true
local greenOn = false
local blueOn = false

local timer = null
local pixel = 0
local pDelta = 1

local blinkState = 0

function redAlert(dummy)
{
blink()
}

function blink()
{
for (local i = 0 ; i < NUMPIXELS ; i++)
{
if (blinkState == 1)
{
pixels.writePixel(i, [255, 0, 0])
} else {
pixels.writePixel(i, [0, 0, 0])
}
}

pixels.writeFrame()

blinkState = 1 - blinkState

imp.wakeup(DELAY,blink)

}

function amberAlert(dummy)
{
for (local i = 0 ; i < NUMPIXELS ; i++)
{
pixels.writePixel(i, [100, 50, 0])
}

pixels.writeFrame()

}

function allClear(dummy)
{
for (local i = 0 ; i < NUMPIXELS ; i++)
{
pixels.writePixel(i, [0, 50, 0])
}

pixels.writeFrame()

}

function setAlert(alrt)
{
switch (alrt)
{
case 0:
redAlert(true)
break

    case 1:
        amberAlert(true)
        break
    
    case 2:
        allClear(true)
        break
    
}
agent.on("setAlert", setAlert)

}

// START OF PROGRAM

// Register handlers for messages from the agent
agent.on(“setAlert”, setAlert)`

The issue is that you’re never stopping the Blink function. In other words, as soon as you call agentUrl?alrt=0 you’re LEDs will start blinking forever. If you call it again, you’ll have two Blink loops going.

If you call alrt=1 or alrt=2 after you’ve called alrt=0, the blinking from alrt=0 will write over the pixels you just set with alrt=1 and alrt=2

To fix this, you can store the imp.wakeup reference from the blink function in a variable, and use imp.cancelwakeup to cancel it when something else happens. You would modify your device code to look like this:

`// Device Code

#require “WS2812.class.nut:1.0.0”

// CONSTANTS

const NUMPIXELS = 5
const DELAY = 0.1

// Instantiate the WS2812s

local spi = hardware.spi257
spi.configure(MSB_FIRST, 7500)
local pixels = WS2812(spi, NUMPIXELS)

local redVal = 0
local greenVal = 0
local blueVal = 0

local redDelta = 1
local greenDelta = 1
local blueDelta = 1

local redOn = true
local greenOn = false
local blueOn = false

local timer = null
local pixel = 0
local pDelta = 1

local blinkState = 0
local blinkWakeup = null;

function redAlert(dummy)
{
blink()
}

function blink()
{
if (blinkWakeup != null) {
imp.cancelwakeup(blinkWakeup);
}

for (local i = 0 ; i < NUMPIXELS ; i++)
{
    if (blinkState == 1)
    {
        pixels.writePixel(i, [255, 0, 0])
    } else {
        pixels.writePixel(i, [0, 0, 0])
    }
}

pixels.writeFrame()

blinkState = 1 - blinkState

blinkWakeup = imp.wakeup(DELAY,blink)

}

function amberAlert(dummy)
{
if (blinkWakeup != null) {
imp.cancelwakeup(blinkWakeup);
}

for (local i = 0 ; i < NUMPIXELS ; i++)
{
    pixels.writePixel(i, [100, 50, 0])
}

pixels.writeFrame()

}

function allClear(dummy)
{
if (blinkWakeup != null) {
imp.cancelwakeup(blinkWakeup);
}

for (local i = 0 ; i < NUMPIXELS ; i++)
{
    pixels.writePixel(i, [0, 50, 0])
}

pixels.writeFrame()

}

function setAlert(alrt)
{
switch (alrt)
{
case 0:
redAlert(true)
break

    case 1:
        amberAlert(true)
        break
    
    case 2:
        allClear(true)
        break
    
}

}

// START OF PROGRAM

// Register handlers for messages from the agent
agent.on(“setAlert”, setAlert)`

I also removed the agent.on(“setAlert”, setAlert) from inside the setAlert function, as you only need to call that once.

You could probably simplify the code I wrote by putting the wakeup check inside setAlert, instead of the handlers for each alert…

Cool! Thanks dude! I can’t wait to try it out.

Ok works! I refactored the code a little by putting the

if (blinkWakeup != null) {
    imp.cancelwakeup(blinkWakeup);
}

in setAlerts instead … a little cleaner.

Thanks!!