// Examples ------------------------------------------------------------------------------------------------------------------------------
?-
/spy(append,sensors,device)
spy : observing sensors
spy : observing device
log : set temp for sensor 0 as increasing
spy : S sensors(0, 101.683965) := 1.00 (15.000000)
log : sensor 2 selected
spy : S sensors(0, 101.576752) := 1.00 (15.000000)
spy : S sensors(0, 100.967118) := 1.00 (15.000000)
log : set temp for sensor 2 as stable
spy : S sensors(0, 101.308985) := 1.00 (15.000000)
spy : S sensors(0, 102.084105) := 1.00 (15.000000)
spy : S sensors(0, 104.742469) := 1.00 (15.000000)
spy : S sensors(0, 106.598127) := 1.00 (15.000000)
spy : S sensors(0, 109.148667) := 1.00 (15.000000)
spy : S sensors(0, 112.191178) := 1.00 (15.000000)
spy : S sensors(0, 114.372971) := 1.00 (15.000000)
log : sensor 0 selected
spy : S sensors(0, 115.681879) := 1.00 (15.000000)
log : sensor 0 temp = 115.681879
spy : S sensors(0, 116.144503) := 1.00 (15.000000)
spy : S sensors(0, 116.797341) := 1.00 (15.000000)
spy : S sensors(0, 117.044270) := 1.00 (15.000000)
spy : S sensors(0, 119.253259) := 1.00 (15.000000)
spy : S sensors(0, 118.034160) := 1.00 (15.000000)
spy : S sensors(0, 119.317154) := 1.00 (15.000000)
spy : S sensors(0, 120.669959) := 1.00 (15.000000)
spy : S device(0, warn) := 1.00 (15.000000)
spy : S sensors(0, 121.018383) := 1.00 (15.000000)
spy : S sensors(0, 121.877841) := 1.00 (15.000000)
spy : S sensors(0, 123.226638) := 1.00 (15.000000)
spy : S sensors(0, 124.075093) := 1.00 (15.000000)
spy : S sensors(0, 125.312428) := 1.00 (15.000000)
spy : S sensors(0, 125.987162) := 1.00 (15.000000)
spy : S sensors(0, 127.267860) := 1.00 (15.000000)
spy : S sensors(0, 129.789043) := 1.00 (15.000000)
log : sensor 2 selected
spy : S sensors(0, 131.107867) := 1.00 (15.000000)
spy : S device(0, halt) := 1.00 (15.000000)
log : you can stop the trend on the sensor(s)
spy : S sensors(0, 133.214001) := 1.00 (15.000000)
log : set temp for sensor 2 as decreasing
spy : S sensors(0, 135.027244) := 1.00 (15.000000)
spy : S sensors(2, 99.234608) := 1.00 (15.000000)
spy : S sensors(0, 136.436559) := 1.00 (15.000000)
spy : S sensors(2, 99.228892) := 1.00 (15.000000)
spy : S sensors(0, 135.505916) := 1.00 (15.000000)
spy : S sensors(2, 98.995847) := 1.00 (15.000000)
log : sensor 2 temp = 98.995847
spy : S sensors(0, 136.399544) := 1.00 (15.000000)
spy : S sensors(2, 97.911749) := 1.00 (15.000000)
...
spy : S sensors(0, 139.408460) := 1.00 (15.000000)
spy : S sensors(2, 69.827354) := 1.00 (15.000000)
spy : S device(1, warn) := 1.00 (15.000000)
spy : S sensors(0, 139.867773) := 1.00 (15.000000)
spy : S sensors(2, 68.121973) := 1.00 (15.000000)
...
spy : S sensors(0, 139.282944) := 1.00 (15.000000)
spy : S sensors(2, 59.997318) := 1.00 (15.000000)
spy : S device(1, halt) := 1.00 (15.000000)
log : you can stop the trend on the sensor(s)
spy : S sensors(0, 138.947859) := 1.00 (15.000000)
spy : S sensors(2, 59.620651) := 1.00 (15.000000)
spy : S sensors(0, 138.158339) := 1.00 (15.000000)
spy : S sensors(2, 58.211917) := 1.00 (15.000000)
spy : S sensors(0, 137.390321) := 1.00 (15.000000)
spy : S sensors(2, 56.604156) := 1.00 (15.000000)
spy : S sensors(0, 136.252418) := 1.00 (15.000000)
spy : S sensors(2, 55.810378) := 1.00 (15.000000)
spy : S sensors(0, 138.436355) := 1.00 (15.000000)
spy : S sensors(2, 55.129705) := 1.00 (15.000000)
log : sensor 0 selected
spy : S sensors(0, 140) := 1.00 (15.000000)
spy : S sensors(2, 55.157148) := 1.00 (15.000000)
spy : S sensors(0, 140) := 1.00 (15.000000)
spy : S sensors(2, 54.185301) := 1.00 (15.000000)
spy : S sensors(0, 139.433864) := 1.00 (15.000000)
spy : S sensors(2, 53.325331) := 1.00 (15.000000)
log : set temp for sensor 0 as decreasing
spy : S sensors(0, 140) := 1.00 (15.000000)
spy : S sensors(2, 52.710033) := 1.00 (15.000000)
spy : S sensors(0, 138.757596) := 1.00 (15.000000)
spy : S sensors(2, 53.300451) := 1.00 (15.000000)
log : sensor 1 selected
spy : S sensors(0, 137.109581) := 1.00 (15.000000)
spy : S sensors(2, 51.592981) := 1.00 (15.000000)
log : sensor 2 selected
spy : S sensors(0, 135.982156) := 1.00 (15.000000)
spy : S sensors(2, 50) := 1.00 (15.000000)
log : set temp for sensor 2 as increasing
spy : S sensors(0, 135.879557) := 1.00 (15.000000)
spy : S sensors(2, 50.108183) := 1.00 (15.000000)
...
spy : S sensors(0, 127.966440) := 1.00 (15.000000)
spy : S sensors(2, 55.312917) := 1.00 (15.000000)
spy : S device(0, warn) := 1.00 (15.000000)
spy : S sensors(0, 126.445741) := 1.00 (15.000000)
spy : S sensors(2, 57.264923) := 1.00 (15.000000)
...
spy : S sensors(0, 120.240757) := 1.00 (15.000000)
spy : S sensors(2, 61.589817) := 1.00 (15.000000)
spy : S device(1, warn) := 1.00 (15.000000)
spy : S sensors(0, 118.443330) := 1.00 (15.000000)
spy : S sensors(2, 62.733532) := 1.00 (15.000000)
spy : S device(0, okay) := 1.00 (15.000000)
spy : S sensors(0, 116.731061) := 1.00 (15.000000)
spy : S sensors(2, 62.904042) := 1.00 (15.000000)
spy : S sensors(0, 116.126724) := 1.00 (15.000000)
spy : S sensors(2, 63.294547) := 1.00 (15.000000)
spy : S sensors(0, 113.932571) := 1.00 (15.000000)
spy : S sensors(2, 62.398282) := 1.00 (15.000000)
spy : S sensors(0, 113.319822) := 1.00 (15.000000)
spy : S sensors(2, 62.717602) := 1.00 (15.000000)
log : sensor 0 selected
spy : S sensors(0, 113.375384) := 1.00 (15.000000)
spy : S sensors(2, 63.854610) := 1.00 (15.000000)
spy : S sensors(0, 112.923171) := 1.00 (15.000000)
spy : S sensors(2, 64.299641) := 1.00 (15.000000)
log : set temp for sensor 0 as stable
spy : S sensors(2, 63.444886) := 1.00 (15.000000)
spy : S sensors(2, 64.319511) := 1.00 (15.000000)
spy : S sensors(2, 65.880719) := 1.00 (15.000000)
log : sensor 2 selected
spy : S sensors(2, 68.037126) := 1.00 (15.000000)
spy : S sensors(2, 67.985082) := 1.00 (15.000000)
spy : S sensors(2, 67.805207) := 1.00 (15.000000)
spy : S sensors(2, 69.026185) := 1.00 (15.000000)
spy : S sensors(2, 69.770006) := 1.00 (15.000000)
spy : S sensors(2, 71.996552) := 1.00 (15.000000)
spy : S device(1, okay) := 1.00 (15.000000)
spy : S sensors(2, 71.989145) := 1.00 (15.000000)
spy : S sensors(2, 72.840229) := 1.00 (15.000000)
log : set temp for sensor 2 as stable
// Code ----------------------------------------------------------------------------------------------------------------------------------
cycle {class = FZZCTicker, mod = 4} { // used to trigger sensor reporting
}
trend { // compute a new trend value based on some random variation of the previous reading plus the trend
(:v,:s,:w) :- add(:v,:s,:v2), rnd.rsnd(1,:w,:v2,:s);
}
trend.step { // define the trend step for each sensors
(0,1.0);
(1,0.4);
(2,0.8);
(3,0.6);
(4,0.3);
(5,0.1);
}
range { // specifies the temperature range for each sensors
(0,<40|140>);
(1,<15|200>);
(2,<50|140>);
(3,<50|140>);
(4,<50|140>);
(5,<100|140>);
}
line { // specifies the line for each sensors
//(sensor,redline,guardline)
(0,<60|130>,<70|120>);
(1,<20|180>,<40|160>);
(2,<60|130>,<70|120>);
(3,<60|130>,<70|120>);
(4,<65|125>,<70|120>);
(5,<110|130>,<115|125>);
}
line.check { // match a sensor reading to the 'guardline' & 'readline' lines
(:v,:rl,:gl,okay) :- rng.inc(:rl,:v), rng.inc(:gl,:v);
(:v,:rl,:gl,warn) :- !rng.inc(:gl,:v), rng.inc(:rl,:v);
(:v,:rl,:gl,halt) :- !rng.inc(:rl,:v);
}
sensors { // keeps track of the sensors readings and handle the console inputs
readings = [100,100,100,100,100,100], // last temperature reading for all the 5 sensors
trending = [0,0,0,0,0,0], // trending for each of the 5 sensors
selected = 0 // currently selected sensor
} {
// select a sensor
() :- @console.keypress(:k?[<49|54>]), hush, sub(:k,49,:s), !peek(selected,:s), poke(selected,:s),
&console.puts("log : sensor ",:s," selected");
// stable temp
() :- @console.keypress(_?[lst.member([48,42])]), hush, peek(selected,:s), peek(trending,:l), lst.swap(:l,:s,0,:l2),
poke(trending,:l2), console.puts("log : set temp for sensor ",:s," as stable");
// lower temp
() :- @console.keypress(45), hush, peek(selected,:s), peek(trending,:l), #trend.step(:s,:t), mul(:t,-1,:t2),
lst.swap(:l,:s,:t2,:l2), poke(trending,:l2), console.puts("log : set temp for sensor ",:s," as decreasing");
// higher temp
() :- @console.keypress(_?[lst.member([61,43])]), hush, peek(selected,:s), peek(trending,:l), #trend.step(:s,:t),
lst.swap(:l,:s,:t,:l2), poke(trending,:l2), console.puts("log : set temp for sensor ",:s," as increasing");
// debug print the reading for the selected sensor
() :- @console.keypress(114), hush, peek(selected,:s), peek(readings,:l), lst.item(:l,:s,:v),
console.puts("log : sensor ",:s," temp = ",:v);
// debug print the trend for the selected sensor
() :- @console.keypress(116), hush, peek(selected,:s), peek(trending,:l), lst.item(:l,:s,:v),
console.puts("log : sensor ",:s," trend = ",:v);
// this prototype get going cyclically and compute a new reading for each of the sensors and fire-up a statement for each
// we need to peek a second time at the 'reading' property as its value may get modified by a concurrent inference during
// the call to #trend
() :- @cycle(:c,:t), hush, peek(readings,:lr), peek(trending,:lt), lst.item(:lr,:s,:v), lst.item(:lt,:s,:step?[neq(0)]),
#trend(:v,:step,:w), #range(:s,:rng), rng.clamp(:rng,:w,:w2), peek(readings,:lr2), lst.swap(:lr2,:s,:w2,:lr3),
poke(readings,:lr3), declare(sensors(:s,:w2));
// when a device is halted, we just put out an hint for the user
() :- @device(:i,halt), hush, console.puts("log : you can stop the trend on the sensor(s)");
// handle a reading query
(:s?[<0|5>],:r) :- peek(readings,:l), lst.item(:l,:s,:r);
}
device { // represents a single sensor
id = 0, // id of the device
sensors = [0,1], // list of sensors connected to that device
state = okay // current state (okay, warn, halt)
} {
// when a sensor reading is available, we check if the reading is within the accepted range. If not we adjust the state
() :- @sensors(:s,:v), hush, peek(sensors,:l), lst.item(:l,_,:s), #line(:s,:rl,:gl), #line.check(:v,:rl,:gl,:o),
peek(state,:state), neq(:o,:state), poke(state,:o), peek(id,:i), declare(device(:i,:o));
// handle state query
(:i,:s) :- peek(id,:id?[eq(:i)]), peek(state,:s);
}
device { // represents a single sensor
id = 1, // id of the device
sensors = [2], // list of sensors connected to that device
state = okay // current state (okay, warn, halt)
} {
// when a sensor reading is available, we check if the reading is within the accepted range. If not we adjust the state
() :- @sensors(:s,:v), hush, peek(sensors,:l), lst.item(:l,_,:s), #line(:s,:rl,:gl), #line.check(:v,:rl,:gl,:o),
peek(state,:state), neq(:o,:state), poke(state,:o), peek(id,:i), declare(device(:i,:o));
// handle state query
(:i,:s) :- peek(id,:id?[eq(:i)]), peek(state,:s);
}
device { // represents a single sensor
id = 2, // id of the device
sensors = [3], // list of sensors connected to that device
state = okay // current state (okay, warn, halt)
} {
// when a sensor reading is available, we check if the reading is within the accepted range. If not we adjust the state
() :- @sensors(:s,:v), hush, peek(sensors,:l), lst.item(:l,_,:s), #line(:s,:rl,:gl), #line.check(:v,:rl,:gl,:o),
peek(state,:state), neq(:o,:state), poke(state,:o), peek(id,:i), declare(device(:i,:o));
// handle state query
(:i,:s) :- peek(id,:id?[eq(:i)]), peek(state,:s);
}
device { // represents a single sensor
id = 3, // id of the device
sensors = [4,5], // list of sensors connected to that device
state = okay // current state (okay, warn, halt)
} {
// when a sensor reading is available, we check if the reading is within the accepted range. If not we adjust the state
() :- @sensors(:s,:v), hush, peek(sensors,:l), lst.item(:l,_,:s), #line(:s,:rl,:gl), #line.check(:v,:rl,:gl,:o),
peek(state,:state), neq(:o,:state), poke(state,:o), peek(id,:i), declare(device(:i,:o));
// handle state query
(:i,:s) :- peek(id,:id?[eq(:i)]), peek(state,:s);
}