+// $Id$
+/*
+ * Copyright (c) 2007 Intel Corporation
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached INTEL-LICENSE
+ * file. If you do not find these files, copies can be found by writing to
+ * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
+ * 94704. Attention: Intel License Inquiry.
+ */
+/**
+ * Main code for the anti theft demo application.
+ *
+ * @author David Gay
+ */
+#include "antitheft.h"
+
module AntiTheftC
{
uses {
interface DisseminationValue<settings_t> as SettingsValue;
interface Send as AlertRoot;
interface StdControl as CollectionControl;
+ interface StdControl as DisseminationControl;
interface SplitControl as RadioControl;
interface LowPowerListening;
interface AMSend as TheftSend;
implementation
{
enum {
- DARK_THRESHOLD = 200,
+ /* Threshold for considering mote in a dark place */
+ DARK_THRESHOLD = 600,
+
+ /* Amount of time warning leds should stay on (in checkInterval counts) */
WARNING_TIME = 3,
- ACCEL_SAMPLES = 10
+
+ /* Number of acceleration samples to collect */
+ ACCEL_SAMPLES = 10,
+
+ /* Interval between acceleration samples (us) */
+ ACCEL_INTERVAL = 10000
};
settings_t settings;
message_t alertMsg, theftMsg;
- uint16_t ledTime;
+ uint16_t ledTime; /* Time left until leds switched off */
uint16_t accelSamples[ACCEL_SAMPLES];
+ /********* LED handling **********/
+
+ /* Warn that some error occurred */
void errorLed() {
ledTime = WARNING_TIME;
call Leds.led2On();
}
+ /* Notify user that settings changed */
void settingsLed() {
ledTime = WARNING_TIME;
call Leds.led1On();
}
+ /* Turn on bright red light! (LED) */
void theftLed() {
ledTime = WARNING_TIME;
call Leds.led0On();
}
+ /* Time-out leds. Called every checkInterval */
void updateLeds() {
if (ledTime && !--ledTime)
{
}
}
+ /* Check result code and report error if a problem occurred */
void check(error_t ok) {
if (ok != SUCCESS)
errorLed();
}
+ /* Report theft, based on current settings */
void theft() {
if (settings.alert & ALERT_LEDS)
theftLed();
if (settings.alert & ALERT_SOUND)
call Mts300Sounder.beep(100);
if (settings.alert & ALERT_RADIO)
+ /* A local broadcast with no payload */
check(call TheftSend.send(AM_BROADCAST_ADDR, &theftMsg, 0));
if (settings.alert & ALERT_ROOT)
{
- alert_t *newAlert = call AlertRoot.getPayload(&alertMsg);
- newAlert->stolenId = TOS_NODE_ID;
- check(call AlertRoot.send(&alertMsg, sizeof *newAlert));
+ /* Report the identity of this node, using the collection protocol */
+
+ /* Get the payload part of alertMsg and fill in our data */
+ alert_t *newAlert = call AlertRoot.getPayload(&alertMsg, sizeof(alert_t));
+ if (newAlert != NULL) {
+ newAlert->stolenId = TOS_NODE_ID;
+ /* and send it... */
+ check(call AlertRoot.send(&alertMsg, sizeof *newAlert));
+ }
}
}
+ /* We have nothing to do after messages are sent */
event void AlertRoot.sendDone(message_t *msg, error_t ok) { }
event void TheftSend.sendDone(message_t *msg, error_t ok) { }
+ /* We've received a theft alert from a neighbour. Turn on the theft warning
+ light! */
event message_t *TheftReceive.receive(message_t* msg, void* payload, uint8_t len) {
theftLed();
+ /* We don't need to hold on to the message buffer, so just return the
+ received buffer */
return msg;
}
- void resetTimer() {
- call Check.startPeriodic(settings.checkInterval);
- }
-
+ /* At boot time, start the periodic timer and the radio */
event void Boot.booted() {
errorLed();
settings.alert = DEFAULT_ALERT;
call RadioControl.start();
}
+ /* Radio started. Now start the collection protocol and set the
+ wakeup interval for low-power-listening wakeup to half a second. */
event void RadioControl.startDone(error_t ok) {
if (ok == SUCCESS)
{
+ call DisseminationControl.start();
call CollectionControl.start();
- call LowPowerListening.setLocalDutyCycle(200);
+ call LowPowerListening.setLocalWakeupInterval(512);
}
else
errorLed();
event void RadioControl.stopDone(error_t ok) { }
+ /* New settings received, update our local copy */
event void SettingsValue.changed() {
const settings_t *newSettings = call SettingsValue.get();
settingsLed();
settings = *newSettings;
+ /* Switch to the new check interval */
call Check.startPeriodic(newSettings->checkInterval);
}
+ /* Every check interval: update leds, check for theft based on current
+ settings */
event void Check.fired() {
updateLeds();
if (settings.detect & DETECT_DARK)
- call Read.read();
+ call Read.read(); /* Initiate light sensor read */
if (settings.detect & DETECT_ACCEL)
{
+ /* To sample acceleration, we first register our buffer
+ (postBuffer). Then we trigger sampling at the desired
+ interval (read) */
call ReadStream.postBuffer(accelSamples, ACCEL_SAMPLES);
- call ReadStream.read(10000);
+ call ReadStream.read(ACCEL_INTERVAL);
}
}
+ /* Light sample completed. Check if it indicates theft */
event void Read.readDone(error_t ok, uint16_t val) {
if (ok == SUCCESS && val < DARK_THRESHOLD)
- theft();
+ theft(); /* ALERT! ALERT! */
}
+ /* A deferred task to check the acceleration data and detect theft. */
task void checkAcceleration() {
uint8_t i;
uint16_t avg;
uint32_t var;
+ /* We check for theft by checking whether the variance of the sample
+ (in mysterious acceleration units) is > 4 */
+
for (avg = 0, i = 0; i < ACCEL_SAMPLES; i++)
avg += accelSamples[i];
avg /= ACCEL_SAMPLES;
}
if (var > 4 * ACCEL_SAMPLES)
- theft();
+ theft(); /* ALERT! ALERT! */
}
+ /* The acceleration read completed. Post the task that will check for
+ theft. We defer this somewhat cpu-intensive computation to avoid
+ having the current task run for too long. */
event void ReadStream.readDone(error_t ok, uint32_t usActualPeriod) {
if (ok == SUCCESS)
post checkAcceleration();
errorLed();
}
+ /* The current sampling buffer is full. If we were using several buffers,
+ we would switch between them here. */
event void ReadStream.bufferDone(error_t ok, uint16_t *buf, uint16_t count) { }
}