--- /dev/null
+#include "antitheft.h"
+
+configuration AntiTheftAppC { }
+implementation
+{
+ components AntiTheftC, new TimerMilliC() as MyTimer, MainC, LedsC,
+ new PhotoC(), new AccelXStreamC(), SounderC,
+ ActiveMessageC, CollectionC, CC1000CsmaRadioC,
+ new DisseminatorC(settings_t, DIS_SETTINGS),
+ new CollectionSenderC(COL_ALERTS) as AlertSender,
+ new AMSenderC(AM_THEFT) as SendTheft,
+ new AMReceiverC(AM_THEFT) as ReceiveTheft;
+
+ AntiTheftC.Boot -> MainC.Boot;
+ AntiTheftC.Check -> MyTimer;
+ AntiTheftC.Read -> PhotoC;
+ AntiTheftC.ReadStream -> AccelXStreamC;
+ AntiTheftC.Leds -> LedsC;
+ AntiTheftC.Mts300Sounder -> SounderC;
+ AntiTheftC.SettingsValue -> DisseminatorC;
+ AntiTheftC.AlertRoot -> AlertSender;
+ AntiTheftC.CollectionControl -> CollectionC;
+ AntiTheftC.RadioControl -> ActiveMessageC;
+ AntiTheftC.LowPowerListening -> CC1000CsmaRadioC;
+ AntiTheftC.TheftSend -> SendTheft;
+ AntiTheftC.TheftReceive -> ReceiveTheft;
+}
--- /dev/null
+module AntiTheftC
+{
+ uses {
+ interface Timer<TMilli> as Check;
+ interface Read<uint16_t>;
+ interface ReadStream<uint16_t>;
+ interface Leds;
+ interface Boot;
+ interface Mts300Sounder;
+ interface DisseminationValue<settings_t> as SettingsValue;
+ interface Send as AlertRoot;
+ interface StdControl as CollectionControl;
+ interface SplitControl as RadioControl;
+ interface LowPowerListening;
+ interface AMSend as TheftSend;
+ interface Receive as TheftReceive;
+ }
+}
+implementation
+{
+ enum {
+ DARK_THRESHOLD = 200,
+ WARNING_TIME = 3,
+ ACCEL_SAMPLES = 10
+ };
+
+ settings_t settings;
+ message_t alertMsg, theftMsg;
+ uint16_t ledTime;
+ uint16_t accelSamples[ACCEL_SAMPLES];
+
+ void errorLed() {
+ ledTime = WARNING_TIME;
+ call Leds.led2On();
+ }
+
+ void settingsLed() {
+ ledTime = WARNING_TIME;
+ call Leds.led1On();
+ }
+
+ void theftLed() {
+ ledTime = WARNING_TIME;
+ call Leds.led0On();
+ }
+
+ void updateLeds() {
+ if (ledTime && !--ledTime)
+ {
+ call Leds.led0Off();
+ call Leds.led1Off();
+ call Leds.led2Off();
+ }
+ }
+
+ void check(error_t ok) {
+ if (ok != SUCCESS)
+ errorLed();
+ }
+
+ void theft() {
+ if (settings.alert & ALERT_LEDS)
+ theftLed();
+ if (settings.alert & ALERT_SOUND)
+ call Mts300Sounder.beep(100);
+ if (settings.alert & ALERT_RADIO)
+ 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));
+ }
+ }
+
+ event void AlertRoot.sendDone(message_t *msg, error_t ok) { }
+ event void TheftSend.sendDone(message_t *msg, error_t ok) { }
+
+ event message_t *TheftReceive.receive(message_t* msg, void* payload, uint8_t len) {
+ theftLed();
+ return msg;
+ }
+
+ void resetTimer() {
+ call Check.startPeriodic(settings.checkInterval);
+ }
+
+ event void Boot.booted() {
+ errorLed();
+ settings.alert = DEFAULT_ALERT;
+ settings.detect = DEFAULT_DETECT;
+
+ call Check.startPeriodic(DEFAULT_CHECK_INTERVAL);
+ call RadioControl.start();
+ }
+
+ event void RadioControl.startDone(error_t ok) {
+ if (ok == SUCCESS)
+ {
+ call CollectionControl.start();
+ call LowPowerListening.setLocalDutyCycle(200);
+ }
+ else
+ errorLed();
+ }
+
+ event void RadioControl.stopDone(error_t ok) { }
+
+ event void SettingsValue.changed() {
+ const settings_t *newSettings = call SettingsValue.get();
+
+ settingsLed();
+ settings = *newSettings;
+ call Check.startPeriodic(newSettings->checkInterval);
+ }
+
+ event void Check.fired() {
+ updateLeds();
+
+ if (settings.detect & DETECT_DARK)
+ call Read.read();
+ if (settings.detect & DETECT_ACCEL)
+ {
+ call ReadStream.postBuffer(accelSamples, ACCEL_SAMPLES);
+ call ReadStream.read(10000);
+ }
+ }
+
+ event void Read.readDone(error_t ok, uint16_t val) {
+ if (ok == SUCCESS && val < DARK_THRESHOLD)
+ theft();
+ }
+
+ task void checkAcceleration() {
+ uint8_t i;
+ uint16_t avg;
+ uint32_t var;
+
+ for (avg = 0, i = 0; i < ACCEL_SAMPLES; i++)
+ avg += accelSamples[i];
+ avg /= ACCEL_SAMPLES;
+
+ for (var = 0, i = 0; i < ACCEL_SAMPLES; i++)
+ {
+ int16_t diff = accelSamples[i] - avg;
+ var += diff * diff;
+ }
+
+ if (var > 4 * ACCEL_SAMPLES)
+ theft();
+ }
+
+ event void ReadStream.readDone(error_t ok, uint32_t usActualPeriod) {
+ if (ok == SUCCESS)
+ post checkAcceleration();
+ else
+ errorLed();
+ }
+
+ event void ReadStream.bufferDone(error_t ok, uint16_t *buf, uint16_t count) { }
+}
--- /dev/null
+SENSORBOARD=mts300
+PFLAGS += -I%T/lib/net/ctp -I%T/lib/net -I%T/lib/net/le
+COMPONENT=AntiTheftAppC
+include $(MAKERULES)
+
--- /dev/null
+#ifndef ANTITHEFT_H
+#define ANTITHEFT_H
+
+enum {
+ ALERT_LEDS = 1,
+ ALERT_SOUND = 2,
+ ALERT_RADIO = 4,
+ ALERT_ROOT = 8,
+
+ DETECT_DARK = 1,
+ DETECT_ACCEL = 2,
+
+ AM_SETTINGS = 54,
+ AM_THEFT = 99,
+ AM_ALERTS = 22,
+ DIS_SETTINGS = 42,
+ COL_ALERTS = 11,
+
+ DEFAULT_ALERT = ALERT_LEDS,
+ DEFAULT_DETECT = DETECT_DARK,
+ DEFAULT_CHECK_INTERVAL = 1000
+};
+
+typedef nx_struct {
+ nx_uint8_t alert, detect;
+ nx_uint16_t checkInterval;
+} settings_t;
+
+typedef nx_struct {
+ nx_uint16_t stolenId;
+} alert_t;
+
+#endif
--- /dev/null
+#include "../AntiTheft/antitheft.h"
+
+configuration AntiTheftRootAppC { }
+implementation
+{
+ components AntiTheftRootC, MainC, LedsC, CollectionC,
+ new DisseminatorC(settings_t, DIS_SETTINGS),
+ ActiveMessageC, SerialActiveMessageC, CC1000CsmaRadioC,
+ new SerialAMReceiverC(AM_SETTINGS) as SettingsReceiver,
+ new SerialAMSenderC(AM_ALERTS) as AlertsForwarder;
+
+ AntiTheftRootC.Boot -> MainC;
+ AntiTheftRootC.SerialControl -> SerialActiveMessageC;
+ AntiTheftRootC.RadioControl -> ActiveMessageC;
+ AntiTheftRootC.LowPowerListening -> CC1000CsmaRadioC;
+ AntiTheftRootC.CollectionControl -> CollectionC;
+
+ AntiTheftRootC.SettingsReceive -> SettingsReceiver;
+ AntiTheftRootC.SettingsUpdate -> DisseminatorC;
+
+ AntiTheftRootC.RootControl -> CollectionC;
+ AntiTheftRootC.AlertsReceive -> CollectionC.Receive[COL_ALERTS];
+ AntiTheftRootC.AlertsForward -> AlertsForwarder;
+
+ AntiTheftRootC.Leds -> LedsC;
+}
--- /dev/null
+module AntiTheftRootC
+{
+ uses
+ {
+ interface Boot;
+ interface SplitControl as SerialControl;
+ interface SplitControl as RadioControl;
+ interface LowPowerListening;
+
+ interface DisseminationUpdate<settings_t> as SettingsUpdate;
+ interface Receive as SettingsReceive;
+
+ interface StdControl as CollectionControl;
+ interface RootControl;
+ interface Receive as AlertsReceive;
+ interface AMSend as AlertsForward;
+
+ interface Leds;
+ }
+}
+implementation
+{
+ event void Boot.booted()
+ {
+ call SerialControl.start();
+ call RadioControl.start();
+ }
+
+ event void SerialControl.startDone(error_t error) { }
+ event void SerialControl.stopDone(error_t error) { }
+ event void RadioControl.startDone(error_t error) {
+ if (error == SUCCESS)
+ {
+ call LowPowerListening.setLocalDutyCycle(200);
+ call CollectionControl.start();
+ call RootControl.setRoot();
+ }
+ }
+ event void RadioControl.stopDone(error_t error) { }
+
+ event message_t *SettingsReceive.receive(message_t* msg, void* payload, uint8_t len)
+ {
+ settings_t *newSettings = payload;
+
+ if (len == sizeof(*newSettings))
+ {
+ call Leds.led2Toggle();
+ call SettingsUpdate.change(newSettings);
+ }
+ return msg;
+ }
+
+ message_t fwdMsg;
+ bool fwdBusy;
+
+ event message_t *AlertsReceive.receive(message_t* msg, void* payload, uint8_t len)
+ {
+ alert_t *newAlert = payload;
+
+ call Leds.led0Toggle();
+
+ if (len == sizeof(*newAlert) && !fwdBusy)
+ {
+ alert_t *fwdAlert = call AlertsForward.getPayload(&fwdMsg);
+
+ *fwdAlert = *newAlert;
+ if (call AlertsForward.send(AM_BROADCAST_ADDR, &fwdMsg, sizeof *fwdAlert) == SUCCESS)
+ fwdBusy = TRUE;
+ }
+ return msg;
+ }
+
+ event void AlertsForward.sendDone(message_t *msg, error_t error) {
+ if (msg == &fwdMsg)
+ fwdBusy = FALSE;
+ }
+
+}
--- /dev/null
+PFLAGS += -I%T/lib/net/ctp -I%T/lib/net -I%T/lib/net/le
+COMPONENT=AntiTheftRootAppC
+include $(MAKERULES)
+