Program that uses the QuickStart Library to interface a SmartMesh IP mote: Connects to the default network and starts publishing a random walk value every 5 seconds.

Dependencies:   mbed millis

Fork of QSL_SimplePublish by Jon-Håkon Bøe Røli

QSL SimplePublish

SmartMesh IP QuickStart Library

Committer:
jhbr
Date:
Thu Sep 01 14:53:55 2016 +0000
Revision:
0:d3f5fdf2e6da
Initial commit of working example

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jhbr 0:d3f5fdf2e6da 1 /*
jhbr 0:d3f5fdf2e6da 2 Copyright (c) 2016, Dust Networks. All rights reserved.
jhbr 0:d3f5fdf2e6da 3
jhbr 0:d3f5fdf2e6da 4 Finite State Machine for the QuickStart Library.
jhbr 0:d3f5fdf2e6da 5
jhbr 0:d3f5fdf2e6da 6 \license See attached DN_LICENSE.txt.
jhbr 0:d3f5fdf2e6da 7 */
jhbr 0:d3f5fdf2e6da 8
jhbr 0:d3f5fdf2e6da 9 #include "dn_fsm.h"
jhbr 0:d3f5fdf2e6da 10 #include "dn_ipmt.h"
jhbr 0:d3f5fdf2e6da 11 #include "dn_time.h"
jhbr 0:d3f5fdf2e6da 12 #include "dn_watchdog.h"
jhbr 0:d3f5fdf2e6da 13 #include "dn_qsl_api.h"
jhbr 0:d3f5fdf2e6da 14 #include "dn_debug.h"
jhbr 0:d3f5fdf2e6da 15
jhbr 0:d3f5fdf2e6da 16 //=========================== variables =======================================
jhbr 0:d3f5fdf2e6da 17
jhbr 0:d3f5fdf2e6da 18 typedef struct
jhbr 0:d3f5fdf2e6da 19 {
jhbr 0:d3f5fdf2e6da 20 // FSM
jhbr 0:d3f5fdf2e6da 21 uint32_t fsmEventScheduled_ms;
jhbr 0:d3f5fdf2e6da 22 uint16_t fsmDelay_ms;
jhbr 0:d3f5fdf2e6da 23 bool fsmArmed;
jhbr 0:d3f5fdf2e6da 24 uint8_t state;
jhbr 0:d3f5fdf2e6da 25 // C Library API
jhbr 0:d3f5fdf2e6da 26 dn_fsm_reply_cbt replyCb;
jhbr 0:d3f5fdf2e6da 27 dn_fsm_timer_cbt fsmCb;
jhbr 0:d3f5fdf2e6da 28 uint8_t replyBuf[MAX_FRAME_LENGTH];
jhbr 0:d3f5fdf2e6da 29 uint8_t notifBuf[MAX_FRAME_LENGTH];
jhbr 0:d3f5fdf2e6da 30 // Connection
jhbr 0:d3f5fdf2e6da 31 uint8_t socketId;
jhbr 0:d3f5fdf2e6da 32 uint16_t networkId;
jhbr 0:d3f5fdf2e6da 33 uint8_t joinKey[DN_JOIN_KEY_LEN];
jhbr 0:d3f5fdf2e6da 34 uint16_t srcPort;
jhbr 0:d3f5fdf2e6da 35 uint32_t service_ms;
jhbr 0:d3f5fdf2e6da 36 uint8_t payloadBuf[DN_DEFAULT_PAYLOAD_SIZE_LIMIT];
jhbr 0:d3f5fdf2e6da 37 uint8_t payloadSize;
jhbr 0:d3f5fdf2e6da 38 uint8_t destIPv6[DN_IPv6ADDR_LEN];
jhbr 0:d3f5fdf2e6da 39 uint16_t destPort;
jhbr 0:d3f5fdf2e6da 40 dn_inbox_t inbox;
jhbr 0:d3f5fdf2e6da 41 } dn_fsm_vars_t;
jhbr 0:d3f5fdf2e6da 42
jhbr 0:d3f5fdf2e6da 43 static dn_fsm_vars_t dn_fsm_vars;
jhbr 0:d3f5fdf2e6da 44
jhbr 0:d3f5fdf2e6da 45
jhbr 0:d3f5fdf2e6da 46 //=========================== prototypes ======================================
jhbr 0:d3f5fdf2e6da 47 // FSM
jhbr 0:d3f5fdf2e6da 48 static void dn_fsm_run(void);
jhbr 0:d3f5fdf2e6da 49 static void dn_fsm_scheduleEvent(uint16_t delay, dn_fsm_timer_cbt cb);
jhbr 0:d3f5fdf2e6da 50 static void dn_fsm_cancelEvent(void);
jhbr 0:d3f5fdf2e6da 51 static void dn_fsm_setReplyCallback(dn_fsm_reply_cbt cb);
jhbr 0:d3f5fdf2e6da 52 static void dn_fsm_enterState(uint8_t newState, uint16_t spesificDelay);
jhbr 0:d3f5fdf2e6da 53 static bool dn_fsm_cmd_timeout(uint32_t cmdStart_ms, uint32_t cmdTimeout_ms);
jhbr 0:d3f5fdf2e6da 54 // C Library API
jhbr 0:d3f5fdf2e6da 55 static void dn_ipmt_notif_cb(uint8_t cmdId, uint8_t subCmdId);
jhbr 0:d3f5fdf2e6da 56 static void dn_ipmt_reply_cb(uint8_t cmdId);
jhbr 0:d3f5fdf2e6da 57 static void dn_event_responseTimeout(void);
jhbr 0:d3f5fdf2e6da 58 static void dn_event_reset(void);
jhbr 0:d3f5fdf2e6da 59 static void dn_reply_reset(void);
jhbr 0:d3f5fdf2e6da 60 static void dn_event_disconnect(void);
jhbr 0:d3f5fdf2e6da 61 static void dn_reply_disconnect(void);
jhbr 0:d3f5fdf2e6da 62 static void dn_event_getMoteStatus(void);
jhbr 0:d3f5fdf2e6da 63 static void dn_reply_getMoteStatus(void);
jhbr 0:d3f5fdf2e6da 64 static void dn_event_openSocket(void);
jhbr 0:d3f5fdf2e6da 65 static void dn_reply_openSocket(void);
jhbr 0:d3f5fdf2e6da 66 static void dn_event_bindSocket(void);
jhbr 0:d3f5fdf2e6da 67 static void dn_reply_bindSocket(void);
jhbr 0:d3f5fdf2e6da 68 static void dn_event_setJoinKey(void);
jhbr 0:d3f5fdf2e6da 69 static void dn_reply_setJoinKey(void);
jhbr 0:d3f5fdf2e6da 70 static void dn_event_setNetworkId(void);
jhbr 0:d3f5fdf2e6da 71 static void dn_reply_setNetworkId(void);
jhbr 0:d3f5fdf2e6da 72 static void dn_event_search(void);
jhbr 0:d3f5fdf2e6da 73 static void dn_reply_search(void);
jhbr 0:d3f5fdf2e6da 74 static void dn_event_join(void);
jhbr 0:d3f5fdf2e6da 75 static void dn_reply_join(void);
jhbr 0:d3f5fdf2e6da 76 static void dn_event_requestService(void);
jhbr 0:d3f5fdf2e6da 77 static void dn_reply_requestService(void);
jhbr 0:d3f5fdf2e6da 78 static void dn_event_getServiceInfo(void);
jhbr 0:d3f5fdf2e6da 79 static void dn_reply_getServiceInfo(void);
jhbr 0:d3f5fdf2e6da 80 static void dn_event_sendTo(void);
jhbr 0:d3f5fdf2e6da 81 static void dn_reply_sendTo(void);
jhbr 0:d3f5fdf2e6da 82 // helpers
jhbr 0:d3f5fdf2e6da 83 static dn_err_t checkAndSaveNetConfig(uint16_t netID, const uint8_t* joinKey, uint16_t srcPort, uint32_t req_service_ms);
jhbr 0:d3f5fdf2e6da 84 static uint8_t getPayloadLimit(uint16_t destPort);
jhbr 0:d3f5fdf2e6da 85
jhbr 0:d3f5fdf2e6da 86 //=========================== public ==========================================
jhbr 0:d3f5fdf2e6da 87
jhbr 0:d3f5fdf2e6da 88 //========== QSL API
jhbr 0:d3f5fdf2e6da 89
jhbr 0:d3f5fdf2e6da 90 bool dn_qsl_init(void)
jhbr 0:d3f5fdf2e6da 91 {
jhbr 0:d3f5fdf2e6da 92 debug("QSL: Init");
jhbr 0:d3f5fdf2e6da 93 // Reset local variables
jhbr 0:d3f5fdf2e6da 94 memset(&dn_fsm_vars, 0, sizeof (dn_fsm_vars));
jhbr 0:d3f5fdf2e6da 95
jhbr 0:d3f5fdf2e6da 96 // Initialize the ipmt module
jhbr 0:d3f5fdf2e6da 97 dn_ipmt_init // Should be augmented with return value to know if successful...
jhbr 0:d3f5fdf2e6da 98 (
jhbr 0:d3f5fdf2e6da 99 dn_ipmt_notif_cb,
jhbr 0:d3f5fdf2e6da 100 dn_fsm_vars.notifBuf,
jhbr 0:d3f5fdf2e6da 101 sizeof (dn_fsm_vars.notifBuf),
jhbr 0:d3f5fdf2e6da 102 dn_ipmt_reply_cb
jhbr 0:d3f5fdf2e6da 103 );
jhbr 0:d3f5fdf2e6da 104
jhbr 0:d3f5fdf2e6da 105 dn_fsm_enterState(DN_FSM_STATE_DISCONNECTED, 0);
jhbr 0:d3f5fdf2e6da 106 return TRUE;
jhbr 0:d3f5fdf2e6da 107 }
jhbr 0:d3f5fdf2e6da 108
jhbr 0:d3f5fdf2e6da 109 bool dn_qsl_isConnected(void)
jhbr 0:d3f5fdf2e6da 110 {
jhbr 0:d3f5fdf2e6da 111 debug("QSL: isConnected");
jhbr 0:d3f5fdf2e6da 112 return dn_fsm_vars.state == DN_FSM_STATE_CONNECTED;
jhbr 0:d3f5fdf2e6da 113 }
jhbr 0:d3f5fdf2e6da 114
jhbr 0:d3f5fdf2e6da 115 bool dn_qsl_connect(uint16_t netID, const uint8_t* joinKey, uint16_t srcPort, uint32_t req_service_ms)
jhbr 0:d3f5fdf2e6da 116 {
jhbr 0:d3f5fdf2e6da 117 uint32_t cmdStart_ms = dn_time_ms();
jhbr 0:d3f5fdf2e6da 118 dn_err_t err;
jhbr 0:d3f5fdf2e6da 119 debug("QSL: Connect");
jhbr 0:d3f5fdf2e6da 120 switch (dn_fsm_vars.state)
jhbr 0:d3f5fdf2e6da 121 {
jhbr 0:d3f5fdf2e6da 122 case DN_FSM_STATE_NOT_INITIALIZED:
jhbr 0:d3f5fdf2e6da 123 log_warn("Can't connect; not initialized");
jhbr 0:d3f5fdf2e6da 124 return FALSE;
jhbr 0:d3f5fdf2e6da 125 case DN_FSM_STATE_DISCONNECTED:
jhbr 0:d3f5fdf2e6da 126 err = checkAndSaveNetConfig(netID, joinKey, srcPort, req_service_ms);
jhbr 0:d3f5fdf2e6da 127 if (err != DN_ERR_NONE)
jhbr 0:d3f5fdf2e6da 128 {
jhbr 0:d3f5fdf2e6da 129 return FALSE;
jhbr 0:d3f5fdf2e6da 130 }
jhbr 0:d3f5fdf2e6da 131 debug("Starting connect process...");
jhbr 0:d3f5fdf2e6da 132 dn_fsm_enterState(DN_FSM_STATE_PRE_JOIN, 0);
jhbr 0:d3f5fdf2e6da 133 break;
jhbr 0:d3f5fdf2e6da 134 case DN_FSM_STATE_CONNECTED:
jhbr 0:d3f5fdf2e6da 135 if ((netID > 0 && netID != dn_fsm_vars.networkId)
jhbr 0:d3f5fdf2e6da 136 || (joinKey != NULL && memcmp(joinKey, dn_fsm_vars.joinKey, DN_JOIN_KEY_LEN) != 0)
jhbr 0:d3f5fdf2e6da 137 || (srcPort > 0 && srcPort != dn_fsm_vars.srcPort))
jhbr 0:d3f5fdf2e6da 138 {
jhbr 0:d3f5fdf2e6da 139 err = checkAndSaveNetConfig(netID, joinKey, srcPort, req_service_ms);
jhbr 0:d3f5fdf2e6da 140 if (err != DN_ERR_NONE)
jhbr 0:d3f5fdf2e6da 141 {
jhbr 0:d3f5fdf2e6da 142 return FALSE;
jhbr 0:d3f5fdf2e6da 143 }
jhbr 0:d3f5fdf2e6da 144 debug("New network ID, join key and/or source port; reconnecting...");
jhbr 0:d3f5fdf2e6da 145 dn_fsm_enterState(DN_FSM_STATE_RESETTING, 0);
jhbr 0:d3f5fdf2e6da 146 } else if (req_service_ms > 0 && req_service_ms != dn_fsm_vars.service_ms)
jhbr 0:d3f5fdf2e6da 147 {
jhbr 0:d3f5fdf2e6da 148 debug("New service request");
jhbr 0:d3f5fdf2e6da 149 dn_fsm_vars.service_ms = req_service_ms;
jhbr 0:d3f5fdf2e6da 150 dn_fsm_enterState(DN_FSM_STATE_REQ_SERVICE, 0);
jhbr 0:d3f5fdf2e6da 151 } else
jhbr 0:d3f5fdf2e6da 152 {
jhbr 0:d3f5fdf2e6da 153 debug("Already connected");
jhbr 0:d3f5fdf2e6da 154 // Nothing to do
jhbr 0:d3f5fdf2e6da 155 }
jhbr 0:d3f5fdf2e6da 156 break;
jhbr 0:d3f5fdf2e6da 157 default:
jhbr 0:d3f5fdf2e6da 158 log_err("Unexpected state");
jhbr 0:d3f5fdf2e6da 159 dn_fsm_enterState(DN_FSM_STATE_DISCONNECTED, 0);
jhbr 0:d3f5fdf2e6da 160 return FALSE;
jhbr 0:d3f5fdf2e6da 161 }
jhbr 0:d3f5fdf2e6da 162
jhbr 0:d3f5fdf2e6da 163 // Drive FSM until connect success/failure or timeout
jhbr 0:d3f5fdf2e6da 164 while (dn_fsm_vars.state != DN_FSM_STATE_CONNECTED
jhbr 0:d3f5fdf2e6da 165 && dn_fsm_vars.state != DN_FSM_STATE_DISCONNECTED
jhbr 0:d3f5fdf2e6da 166 && !dn_fsm_cmd_timeout(cmdStart_ms, DN_CONNECT_TIMEOUT_S * 1000))
jhbr 0:d3f5fdf2e6da 167 {
jhbr 0:d3f5fdf2e6da 168 dn_watchdog_feed();
jhbr 0:d3f5fdf2e6da 169 dn_fsm_run();
jhbr 0:d3f5fdf2e6da 170 }
jhbr 0:d3f5fdf2e6da 171
jhbr 0:d3f5fdf2e6da 172 return dn_fsm_vars.state == DN_FSM_STATE_CONNECTED;
jhbr 0:d3f5fdf2e6da 173 }
jhbr 0:d3f5fdf2e6da 174
jhbr 0:d3f5fdf2e6da 175 bool dn_qsl_send(const uint8_t* payload, uint8_t payloadSize_B, uint16_t destPort)
jhbr 0:d3f5fdf2e6da 176 {
jhbr 0:d3f5fdf2e6da 177 uint32_t cmdStart_ms = dn_time_ms();
jhbr 0:d3f5fdf2e6da 178 uint8_t maxPayloadSize;
jhbr 0:d3f5fdf2e6da 179 debug("QSL: Send");
jhbr 0:d3f5fdf2e6da 180 switch (dn_fsm_vars.state)
jhbr 0:d3f5fdf2e6da 181 {
jhbr 0:d3f5fdf2e6da 182 case DN_FSM_STATE_CONNECTED:
jhbr 0:d3f5fdf2e6da 183 maxPayloadSize = getPayloadLimit(destPort);
jhbr 0:d3f5fdf2e6da 184
jhbr 0:d3f5fdf2e6da 185 if (payloadSize_B > maxPayloadSize)
jhbr 0:d3f5fdf2e6da 186 {
jhbr 0:d3f5fdf2e6da 187 log_warn("Payload size (%u) exceeds limit (%u)", payloadSize_B, maxPayloadSize);
jhbr 0:d3f5fdf2e6da 188 return FALSE;
jhbr 0:d3f5fdf2e6da 189 }
jhbr 0:d3f5fdf2e6da 190 // Store outbound payload and parameters
jhbr 0:d3f5fdf2e6da 191 memcpy(dn_fsm_vars.payloadBuf, payload, payloadSize_B);
jhbr 0:d3f5fdf2e6da 192 dn_fsm_vars.payloadSize = payloadSize_B;
jhbr 0:d3f5fdf2e6da 193 memcpy(dn_fsm_vars.destIPv6, DN_DEST_IP, DN_IPv6ADDR_LEN);
jhbr 0:d3f5fdf2e6da 194 dn_fsm_vars.destPort = (destPort > 0) ? destPort : DN_DEFAULT_DEST_PORT;
jhbr 0:d3f5fdf2e6da 195 // Start send process
jhbr 0:d3f5fdf2e6da 196 dn_fsm_enterState(DN_FSM_STATE_SENDING, 0);
jhbr 0:d3f5fdf2e6da 197 break;
jhbr 0:d3f5fdf2e6da 198 default:
jhbr 0:d3f5fdf2e6da 199 log_warn("Can't send; not connected");
jhbr 0:d3f5fdf2e6da 200 return FALSE;
jhbr 0:d3f5fdf2e6da 201 }
jhbr 0:d3f5fdf2e6da 202
jhbr 0:d3f5fdf2e6da 203 // Drive FSM until send success/failure or timeout
jhbr 0:d3f5fdf2e6da 204 while (dn_fsm_vars.state == DN_FSM_STATE_SENDING
jhbr 0:d3f5fdf2e6da 205 && !dn_fsm_cmd_timeout(cmdStart_ms, DN_SEND_TIMEOUT_MS))
jhbr 0:d3f5fdf2e6da 206 {
jhbr 0:d3f5fdf2e6da 207 dn_watchdog_feed();
jhbr 0:d3f5fdf2e6da 208 dn_fsm_run();
jhbr 0:d3f5fdf2e6da 209 }
jhbr 0:d3f5fdf2e6da 210
jhbr 0:d3f5fdf2e6da 211 // Catch send failure
jhbr 0:d3f5fdf2e6da 212 if (dn_fsm_vars.state == DN_FSM_STATE_SEND_FAILED)
jhbr 0:d3f5fdf2e6da 213 {
jhbr 0:d3f5fdf2e6da 214 debug("Send failed");
jhbr 0:d3f5fdf2e6da 215 dn_fsm_enterState(DN_FSM_STATE_CONNECTED, 0);
jhbr 0:d3f5fdf2e6da 216 return FALSE;
jhbr 0:d3f5fdf2e6da 217 }
jhbr 0:d3f5fdf2e6da 218
jhbr 0:d3f5fdf2e6da 219 return dn_fsm_vars.state == DN_FSM_STATE_CONNECTED;
jhbr 0:d3f5fdf2e6da 220 }
jhbr 0:d3f5fdf2e6da 221
jhbr 0:d3f5fdf2e6da 222 uint8_t dn_qsl_read(uint8_t* readBuffer)
jhbr 0:d3f5fdf2e6da 223 {
jhbr 0:d3f5fdf2e6da 224 uint8_t bytesRead = 0;
jhbr 0:d3f5fdf2e6da 225 debug("QSL: Read");
jhbr 0:d3f5fdf2e6da 226 if (dn_fsm_vars.inbox.unreadPackets > 0)
jhbr 0:d3f5fdf2e6da 227 {
jhbr 0:d3f5fdf2e6da 228 // Pop payload at head of inbox
jhbr 0:d3f5fdf2e6da 229 memcpy
jhbr 0:d3f5fdf2e6da 230 (
jhbr 0:d3f5fdf2e6da 231 readBuffer,
jhbr 0:d3f5fdf2e6da 232 dn_fsm_vars.inbox.pktBuf[dn_fsm_vars.inbox.head],
jhbr 0:d3f5fdf2e6da 233 dn_fsm_vars.inbox.pktSize[dn_fsm_vars.inbox.head]
jhbr 0:d3f5fdf2e6da 234 );
jhbr 0:d3f5fdf2e6da 235 bytesRead = dn_fsm_vars.inbox.pktSize[dn_fsm_vars.inbox.head];
jhbr 0:d3f5fdf2e6da 236 dn_fsm_vars.inbox.head = (dn_fsm_vars.inbox.head + 1) % DN_INBOX_SIZE;
jhbr 0:d3f5fdf2e6da 237 dn_fsm_vars.inbox.unreadPackets--;
jhbr 0:d3f5fdf2e6da 238 debug("Read %u bytes from inbox", bytesRead);
jhbr 0:d3f5fdf2e6da 239 } else
jhbr 0:d3f5fdf2e6da 240 {
jhbr 0:d3f5fdf2e6da 241 debug("Inbox empty");
jhbr 0:d3f5fdf2e6da 242 }
jhbr 0:d3f5fdf2e6da 243 return bytesRead;
jhbr 0:d3f5fdf2e6da 244 }
jhbr 0:d3f5fdf2e6da 245
jhbr 0:d3f5fdf2e6da 246 //=========================== private =========================================
jhbr 0:d3f5fdf2e6da 247
jhbr 0:d3f5fdf2e6da 248 //========== FSM
jhbr 0:d3f5fdf2e6da 249
jhbr 0:d3f5fdf2e6da 250 //===== run
jhbr 0:d3f5fdf2e6da 251
jhbr 0:d3f5fdf2e6da 252 /**
jhbr 0:d3f5fdf2e6da 253 Check if an event is scheduled and run it if due.
jhbr 0:d3f5fdf2e6da 254 */
jhbr 0:d3f5fdf2e6da 255 static void dn_fsm_run(void)
jhbr 0:d3f5fdf2e6da 256 {
jhbr 0:d3f5fdf2e6da 257 if (dn_fsm_vars.fsmArmed && (dn_time_ms() - dn_fsm_vars.fsmEventScheduled_ms > dn_fsm_vars.fsmDelay_ms))
jhbr 0:d3f5fdf2e6da 258 {
jhbr 0:d3f5fdf2e6da 259 // Scheduled event is due; execute it
jhbr 0:d3f5fdf2e6da 260 dn_fsm_vars.fsmArmed = FALSE;
jhbr 0:d3f5fdf2e6da 261 if (dn_fsm_vars.fsmCb != NULL)
jhbr 0:d3f5fdf2e6da 262 {
jhbr 0:d3f5fdf2e6da 263 dn_fsm_vars.fsmCb();
jhbr 0:d3f5fdf2e6da 264 }
jhbr 0:d3f5fdf2e6da 265 } else
jhbr 0:d3f5fdf2e6da 266 {
jhbr 0:d3f5fdf2e6da 267 // Sleep to save CPU power
jhbr 0:d3f5fdf2e6da 268 dn_sleep_ms(DN_FSM_RUN_INTERVAL_MS);
jhbr 0:d3f5fdf2e6da 269 }
jhbr 0:d3f5fdf2e6da 270 }
jhbr 0:d3f5fdf2e6da 271
jhbr 0:d3f5fdf2e6da 272 //===== scheduleEvent
jhbr 0:d3f5fdf2e6da 273
jhbr 0:d3f5fdf2e6da 274 /**
jhbr 0:d3f5fdf2e6da 275 Schedule function to be called after a given delay.
jhbr 0:d3f5fdf2e6da 276 */
jhbr 0:d3f5fdf2e6da 277 static void dn_fsm_scheduleEvent(uint16_t delay_ms, dn_fsm_timer_cbt cb)
jhbr 0:d3f5fdf2e6da 278 {
jhbr 0:d3f5fdf2e6da 279 dn_fsm_vars.fsmEventScheduled_ms = dn_time_ms();
jhbr 0:d3f5fdf2e6da 280 dn_fsm_vars.fsmDelay_ms = delay_ms;
jhbr 0:d3f5fdf2e6da 281 dn_fsm_vars.fsmCb = cb;
jhbr 0:d3f5fdf2e6da 282 dn_fsm_vars.fsmArmed = TRUE;
jhbr 0:d3f5fdf2e6da 283 }
jhbr 0:d3f5fdf2e6da 284
jhbr 0:d3f5fdf2e6da 285 //===== cancelEvent
jhbr 0:d3f5fdf2e6da 286
jhbr 0:d3f5fdf2e6da 287 /**
jhbr 0:d3f5fdf2e6da 288 Cancel currently scheduled event.
jhbr 0:d3f5fdf2e6da 289 */
jhbr 0:d3f5fdf2e6da 290 static void dn_fsm_cancelEvent(void)
jhbr 0:d3f5fdf2e6da 291 {
jhbr 0:d3f5fdf2e6da 292 dn_fsm_vars.fsmDelay_ms = 0;
jhbr 0:d3f5fdf2e6da 293 dn_fsm_vars.fsmCb = NULL;
jhbr 0:d3f5fdf2e6da 294 dn_fsm_vars.fsmArmed = FALSE;
jhbr 0:d3f5fdf2e6da 295 }
jhbr 0:d3f5fdf2e6da 296
jhbr 0:d3f5fdf2e6da 297 //===== setReplyCallback
jhbr 0:d3f5fdf2e6da 298
jhbr 0:d3f5fdf2e6da 299 /**
jhbr 0:d3f5fdf2e6da 300 Set the callback function that the C Library will execute when the next reply
jhbr 0:d3f5fdf2e6da 301 is received and the reply buffer is ready to be parsed.
jhbr 0:d3f5fdf2e6da 302 */
jhbr 0:d3f5fdf2e6da 303 static void dn_fsm_setReplyCallback(dn_fsm_reply_cbt cb)
jhbr 0:d3f5fdf2e6da 304 {
jhbr 0:d3f5fdf2e6da 305 dn_fsm_vars.replyCb = cb;
jhbr 0:d3f5fdf2e6da 306 }
jhbr 0:d3f5fdf2e6da 307
jhbr 0:d3f5fdf2e6da 308 //===== setReplyCallback
jhbr 0:d3f5fdf2e6da 309
jhbr 0:d3f5fdf2e6da 310 /**
jhbr 0:d3f5fdf2e6da 311 Transition FSM to new state and schedule any default entry events.
jhbr 0:d3f5fdf2e6da 312 */
jhbr 0:d3f5fdf2e6da 313 static void dn_fsm_enterState(uint8_t newState, uint16_t spesificDelay)
jhbr 0:d3f5fdf2e6da 314 {
jhbr 0:d3f5fdf2e6da 315 uint32_t now = dn_time_ms();
jhbr 0:d3f5fdf2e6da 316 uint16_t delay = DN_CMD_PERIOD_MS;
jhbr 0:d3f5fdf2e6da 317 static uint32_t lastTransition = 0;
jhbr 0:d3f5fdf2e6da 318 if (lastTransition == 0)
jhbr 0:d3f5fdf2e6da 319 lastTransition = dn_time_ms();
jhbr 0:d3f5fdf2e6da 320
jhbr 0:d3f5fdf2e6da 321 // Use default delay if none given
jhbr 0:d3f5fdf2e6da 322 if (spesificDelay > 0)
jhbr 0:d3f5fdf2e6da 323 delay = spesificDelay;
jhbr 0:d3f5fdf2e6da 324
jhbr 0:d3f5fdf2e6da 325 // Schedule default events for transition into states
jhbr 0:d3f5fdf2e6da 326 switch (newState)
jhbr 0:d3f5fdf2e6da 327 {
jhbr 0:d3f5fdf2e6da 328 case DN_FSM_STATE_PRE_JOIN:
jhbr 0:d3f5fdf2e6da 329 dn_fsm_scheduleEvent(delay, dn_event_getMoteStatus);
jhbr 0:d3f5fdf2e6da 330 break;
jhbr 0:d3f5fdf2e6da 331 case DN_FSM_STATE_PROMISCUOUS:
jhbr 0:d3f5fdf2e6da 332 dn_fsm_scheduleEvent(delay, dn_event_search);
jhbr 0:d3f5fdf2e6da 333 break;
jhbr 0:d3f5fdf2e6da 334 case DN_FSM_STATE_JOINING:
jhbr 0:d3f5fdf2e6da 335 dn_fsm_scheduleEvent(delay, dn_event_join);
jhbr 0:d3f5fdf2e6da 336 break;
jhbr 0:d3f5fdf2e6da 337 case DN_FSM_STATE_REQ_SERVICE:
jhbr 0:d3f5fdf2e6da 338 dn_fsm_scheduleEvent(delay, dn_event_requestService);
jhbr 0:d3f5fdf2e6da 339 break;
jhbr 0:d3f5fdf2e6da 340 case DN_FSM_STATE_RESETTING:
jhbr 0:d3f5fdf2e6da 341 if (DN_MOTE_DISCONNECT_BEFORE_RESET)
jhbr 0:d3f5fdf2e6da 342 dn_fsm_scheduleEvent(delay, dn_event_disconnect); // More graceful
jhbr 0:d3f5fdf2e6da 343 else
jhbr 0:d3f5fdf2e6da 344 dn_fsm_scheduleEvent(delay, dn_event_reset); // Faster
jhbr 0:d3f5fdf2e6da 345 break;
jhbr 0:d3f5fdf2e6da 346 case DN_FSM_STATE_SENDING:
jhbr 0:d3f5fdf2e6da 347 /*
jhbr 0:d3f5fdf2e6da 348 Send is scheduled immediately because it is the users responsibility
jhbr 0:d3f5fdf2e6da 349 to implement the necessary backoff and not exceed the granted bandwidth.
jhbr 0:d3f5fdf2e6da 350 */
jhbr 0:d3f5fdf2e6da 351 dn_fsm_scheduleEvent(0, dn_event_sendTo);
jhbr 0:d3f5fdf2e6da 352 break;
jhbr 0:d3f5fdf2e6da 353 case DN_FSM_STATE_SEND_FAILED:
jhbr 0:d3f5fdf2e6da 354 case DN_FSM_STATE_DISCONNECTED:
jhbr 0:d3f5fdf2e6da 355 case DN_FSM_STATE_CONNECTED:
jhbr 0:d3f5fdf2e6da 356 // These states have no default entry events
jhbr 0:d3f5fdf2e6da 357 break;
jhbr 0:d3f5fdf2e6da 358 default:
jhbr 0:d3f5fdf2e6da 359 log_warn("Attempt at entering unexpected state %#.2x", newState);
jhbr 0:d3f5fdf2e6da 360 return;
jhbr 0:d3f5fdf2e6da 361 }
jhbr 0:d3f5fdf2e6da 362
jhbr 0:d3f5fdf2e6da 363 debug("FSM state transition: %#.2x --> %#.2x (%u ms)",
jhbr 0:d3f5fdf2e6da 364 dn_fsm_vars.state, newState, now - lastTransition);
jhbr 0:d3f5fdf2e6da 365 lastTransition = now;
jhbr 0:d3f5fdf2e6da 366 dn_fsm_vars.state = newState;
jhbr 0:d3f5fdf2e6da 367 }
jhbr 0:d3f5fdf2e6da 368
jhbr 0:d3f5fdf2e6da 369 //===== cmdTimeout
jhbr 0:d3f5fdf2e6da 370
jhbr 0:d3f5fdf2e6da 371 /**
jhbr 0:d3f5fdf2e6da 372 Correctly abort the current API command if time passed since the given start
jhbr 0:d3f5fdf2e6da 373 has exceeded the given timeout.
jhbr 0:d3f5fdf2e6da 374 */
jhbr 0:d3f5fdf2e6da 375 static bool dn_fsm_cmd_timeout(uint32_t cmdStart_ms, uint32_t cmdTimeout_ms)
jhbr 0:d3f5fdf2e6da 376 {
jhbr 0:d3f5fdf2e6da 377 bool timeout = (dn_time_ms() - cmdStart_ms) > cmdTimeout_ms;
jhbr 0:d3f5fdf2e6da 378 if (timeout)
jhbr 0:d3f5fdf2e6da 379 {
jhbr 0:d3f5fdf2e6da 380 // Cancel any ongoing transmission or scheduled event and reset reply cb
jhbr 0:d3f5fdf2e6da 381 dn_ipmt_cancelTx();
jhbr 0:d3f5fdf2e6da 382 dn_fsm_vars.replyCb = NULL;
jhbr 0:d3f5fdf2e6da 383 dn_fsm_cancelEvent();
jhbr 0:d3f5fdf2e6da 384
jhbr 0:d3f5fdf2e6da 385 // Default timeout state is different while connecting vs sending
jhbr 0:d3f5fdf2e6da 386 switch (dn_fsm_vars.state)
jhbr 0:d3f5fdf2e6da 387 {
jhbr 0:d3f5fdf2e6da 388 case DN_FSM_STATE_PRE_JOIN:
jhbr 0:d3f5fdf2e6da 389 case DN_FSM_STATE_JOINING:
jhbr 0:d3f5fdf2e6da 390 case DN_FSM_STATE_REQ_SERVICE:
jhbr 0:d3f5fdf2e6da 391 case DN_FSM_STATE_RESETTING:
jhbr 0:d3f5fdf2e6da 392 debug("Connect timeout");
jhbr 0:d3f5fdf2e6da 393 dn_fsm_enterState(DN_FSM_STATE_DISCONNECTED, 0);
jhbr 0:d3f5fdf2e6da 394 break;
jhbr 0:d3f5fdf2e6da 395 case DN_FSM_STATE_SENDING:
jhbr 0:d3f5fdf2e6da 396 debug("Send timeout");
jhbr 0:d3f5fdf2e6da 397 dn_fsm_enterState(DN_FSM_STATE_SEND_FAILED, 0);
jhbr 0:d3f5fdf2e6da 398 break;
jhbr 0:d3f5fdf2e6da 399 default:
jhbr 0:d3f5fdf2e6da 400 log_err("Command timeout in unexpected state: %#x", dn_fsm_vars.state);
jhbr 0:d3f5fdf2e6da 401 break;
jhbr 0:d3f5fdf2e6da 402 }
jhbr 0:d3f5fdf2e6da 403 }
jhbr 0:d3f5fdf2e6da 404 return timeout;
jhbr 0:d3f5fdf2e6da 405 }
jhbr 0:d3f5fdf2e6da 406
jhbr 0:d3f5fdf2e6da 407 //========== C Library API
jhbr 0:d3f5fdf2e6da 408
jhbr 0:d3f5fdf2e6da 409 //===== notif_cb
jhbr 0:d3f5fdf2e6da 410
jhbr 0:d3f5fdf2e6da 411 /**
jhbr 0:d3f5fdf2e6da 412 This function is called whenever a notification is received through the
jhbr 0:d3f5fdf2e6da 413 SmartMesh C Library. The notification variables are than available through
jhbr 0:d3f5fdf2e6da 414 the notification buffer that can be cast to the correct type based on the
jhbr 0:d3f5fdf2e6da 415 given command ID (notification type).
jhbr 0:d3f5fdf2e6da 416 */
jhbr 0:d3f5fdf2e6da 417 static void dn_ipmt_notif_cb(uint8_t cmdId, uint8_t subCmdId)
jhbr 0:d3f5fdf2e6da 418 {
jhbr 0:d3f5fdf2e6da 419 //dn_ipmt_timeIndication_nt* notif_timeIndication;
jhbr 0:d3f5fdf2e6da 420 dn_ipmt_events_nt* notif_events;
jhbr 0:d3f5fdf2e6da 421 dn_ipmt_receive_nt* notif_receive;
jhbr 0:d3f5fdf2e6da 422 //dn_ipmt_macRx_nt* notif_macRx;
jhbr 0:d3f5fdf2e6da 423 //dn_ipmt_txDone_nt* notif_txDone;
jhbr 0:d3f5fdf2e6da 424 dn_ipmt_advReceived_nt* notif_advReceived;
jhbr 0:d3f5fdf2e6da 425
jhbr 0:d3f5fdf2e6da 426 debug("Got notification: cmdId; %#.2x (%u), subCmdId; %#.2x (%u)",
jhbr 0:d3f5fdf2e6da 427 cmdId, cmdId, subCmdId, subCmdId);
jhbr 0:d3f5fdf2e6da 428
jhbr 0:d3f5fdf2e6da 429 switch (cmdId)
jhbr 0:d3f5fdf2e6da 430 {
jhbr 0:d3f5fdf2e6da 431 case CMDID_TIMEINDICATION:
jhbr 0:d3f5fdf2e6da 432 // Not implemented
jhbr 0:d3f5fdf2e6da 433 break;
jhbr 0:d3f5fdf2e6da 434 case CMDID_EVENTS:
jhbr 0:d3f5fdf2e6da 435 notif_events = (dn_ipmt_events_nt*)dn_fsm_vars.notifBuf;
jhbr 0:d3f5fdf2e6da 436 debug("State: %#.2x | Events: %#.4x", notif_events->state, notif_events->events);
jhbr 0:d3f5fdf2e6da 437
jhbr 0:d3f5fdf2e6da 438 // Check if in fsm state where we expect a certain mote event
jhbr 0:d3f5fdf2e6da 439 switch (dn_fsm_vars.state)
jhbr 0:d3f5fdf2e6da 440 {
jhbr 0:d3f5fdf2e6da 441 case DN_FSM_STATE_JOINING:
jhbr 0:d3f5fdf2e6da 442 if (notif_events->events & DN_MOTE_EVENT_MASK_OPERATIONAL)
jhbr 0:d3f5fdf2e6da 443 {
jhbr 0:d3f5fdf2e6da 444 // Join complete
jhbr 0:d3f5fdf2e6da 445 if (dn_fsm_vars.service_ms > 0)
jhbr 0:d3f5fdf2e6da 446 {
jhbr 0:d3f5fdf2e6da 447 dn_fsm_enterState(DN_FSM_STATE_REQ_SERVICE, 0);
jhbr 0:d3f5fdf2e6da 448 } else
jhbr 0:d3f5fdf2e6da 449 {
jhbr 0:d3f5fdf2e6da 450 dn_fsm_enterState(DN_FSM_STATE_CONNECTED, 0);
jhbr 0:d3f5fdf2e6da 451 }
jhbr 0:d3f5fdf2e6da 452 return;
jhbr 0:d3f5fdf2e6da 453 }
jhbr 0:d3f5fdf2e6da 454 break;
jhbr 0:d3f5fdf2e6da 455 case DN_FSM_STATE_REQ_SERVICE:
jhbr 0:d3f5fdf2e6da 456 if (notif_events->events & DN_MOTE_EVENT_MASK_SVC_CHANGE)
jhbr 0:d3f5fdf2e6da 457 {
jhbr 0:d3f5fdf2e6da 458 // Service request complete; check what we were granted
jhbr 0:d3f5fdf2e6da 459 dn_fsm_scheduleEvent(DN_CMD_PERIOD_MS, dn_event_getServiceInfo);
jhbr 0:d3f5fdf2e6da 460 return;
jhbr 0:d3f5fdf2e6da 461 }
jhbr 0:d3f5fdf2e6da 462 break;
jhbr 0:d3f5fdf2e6da 463 }
jhbr 0:d3f5fdf2e6da 464
jhbr 0:d3f5fdf2e6da 465 // Check if reported mote state should trigger fsm state transition
jhbr 0:d3f5fdf2e6da 466 switch (notif_events->state)
jhbr 0:d3f5fdf2e6da 467 {
jhbr 0:d3f5fdf2e6da 468 case DN_MOTE_STATE_IDLE:
jhbr 0:d3f5fdf2e6da 469 switch (dn_fsm_vars.state)
jhbr 0:d3f5fdf2e6da 470 {
jhbr 0:d3f5fdf2e6da 471 case DN_FSM_STATE_PRE_JOIN:
jhbr 0:d3f5fdf2e6da 472 case DN_FSM_STATE_JOINING:
jhbr 0:d3f5fdf2e6da 473 case DN_FSM_STATE_REQ_SERVICE:
jhbr 0:d3f5fdf2e6da 474 case DN_FSM_STATE_RESETTING:
jhbr 0:d3f5fdf2e6da 475 case DN_FSM_STATE_PROMISCUOUS:
jhbr 0:d3f5fdf2e6da 476 // Restart during connect; retry
jhbr 0:d3f5fdf2e6da 477 dn_fsm_enterState(DN_FSM_STATE_PRE_JOIN, 0);
jhbr 0:d3f5fdf2e6da 478 break;
jhbr 0:d3f5fdf2e6da 479 case DN_FSM_STATE_CONNECTED:
jhbr 0:d3f5fdf2e6da 480 case DN_FSM_STATE_SENDING:
jhbr 0:d3f5fdf2e6da 481 case DN_FSM_STATE_SEND_FAILED:
jhbr 0:d3f5fdf2e6da 482 // Disconnect/reset; set state accordingly
jhbr 0:d3f5fdf2e6da 483 dn_fsm_enterState(DN_FSM_STATE_DISCONNECTED, 0);
jhbr 0:d3f5fdf2e6da 484 break;
jhbr 0:d3f5fdf2e6da 485 }
jhbr 0:d3f5fdf2e6da 486 break;
jhbr 0:d3f5fdf2e6da 487 case DN_MOTE_STATE_OPERATIONAL:
jhbr 0:d3f5fdf2e6da 488 switch (dn_fsm_vars.state)
jhbr 0:d3f5fdf2e6da 489 {
jhbr 0:d3f5fdf2e6da 490 case DN_FSM_STATE_PRE_JOIN:
jhbr 0:d3f5fdf2e6da 491 case DN_FSM_STATE_PROMISCUOUS:
jhbr 0:d3f5fdf2e6da 492 /*
jhbr 0:d3f5fdf2e6da 493 Early (and unexpected) operational (connected to network)
jhbr 0:d3f5fdf2e6da 494 during connect; reset and retry
jhbr 0:d3f5fdf2e6da 495 */
jhbr 0:d3f5fdf2e6da 496 dn_fsm_enterState(DN_FSM_STATE_RESETTING, 0);
jhbr 0:d3f5fdf2e6da 497 break;
jhbr 0:d3f5fdf2e6da 498 }
jhbr 0:d3f5fdf2e6da 499 break;
jhbr 0:d3f5fdf2e6da 500 }
jhbr 0:d3f5fdf2e6da 501 break;
jhbr 0:d3f5fdf2e6da 502 case CMDID_RECEIVE:
jhbr 0:d3f5fdf2e6da 503 notif_receive = (dn_ipmt_receive_nt*)dn_fsm_vars.notifBuf;
jhbr 0:d3f5fdf2e6da 504 debug("Received downstream data");
jhbr 0:d3f5fdf2e6da 505
jhbr 0:d3f5fdf2e6da 506 // Push payload at tail of inbox
jhbr 0:d3f5fdf2e6da 507 memcpy
jhbr 0:d3f5fdf2e6da 508 (
jhbr 0:d3f5fdf2e6da 509 dn_fsm_vars.inbox.pktBuf[dn_fsm_vars.inbox.tail],
jhbr 0:d3f5fdf2e6da 510 notif_receive->payload,
jhbr 0:d3f5fdf2e6da 511 notif_receive->payloadLen
jhbr 0:d3f5fdf2e6da 512 );
jhbr 0:d3f5fdf2e6da 513 dn_fsm_vars.inbox.pktSize[dn_fsm_vars.inbox.tail] = notif_receive->payloadLen;
jhbr 0:d3f5fdf2e6da 514 dn_fsm_vars.inbox.tail = (dn_fsm_vars.inbox.tail + 1) % DN_INBOX_SIZE;
jhbr 0:d3f5fdf2e6da 515 if(dn_fsm_vars.inbox.unreadPackets == DN_INBOX_SIZE)
jhbr 0:d3f5fdf2e6da 516 {
jhbr 0:d3f5fdf2e6da 517 log_warn("Inbox overflow; oldest packet dropped");
jhbr 0:d3f5fdf2e6da 518 } else
jhbr 0:d3f5fdf2e6da 519 {
jhbr 0:d3f5fdf2e6da 520 dn_fsm_vars.inbox.unreadPackets++;
jhbr 0:d3f5fdf2e6da 521 }
jhbr 0:d3f5fdf2e6da 522 debug("Inbox capacity at %u / %u", dn_fsm_vars.inbox.unreadPackets, DN_INBOX_SIZE);
jhbr 0:d3f5fdf2e6da 523
jhbr 0:d3f5fdf2e6da 524 break;
jhbr 0:d3f5fdf2e6da 525 case CMDID_MACRX:
jhbr 0:d3f5fdf2e6da 526 // Not implemented
jhbr 0:d3f5fdf2e6da 527 break;
jhbr 0:d3f5fdf2e6da 528 case CMDID_TXDONE:
jhbr 0:d3f5fdf2e6da 529 // Not implemented
jhbr 0:d3f5fdf2e6da 530 break;
jhbr 0:d3f5fdf2e6da 531 case CMDID_ADVRECEIVED:
jhbr 0:d3f5fdf2e6da 532 notif_advReceived = (dn_ipmt_advReceived_nt*)dn_fsm_vars.notifBuf;
jhbr 0:d3f5fdf2e6da 533 debug("Received network advertisement");
jhbr 0:d3f5fdf2e6da 534
jhbr 0:d3f5fdf2e6da 535 if (dn_fsm_vars.state == DN_FSM_STATE_PROMISCUOUS
jhbr 0:d3f5fdf2e6da 536 && dn_fsm_vars.networkId == DN_PROMISCUOUS_NET_ID)
jhbr 0:d3f5fdf2e6da 537 {
jhbr 0:d3f5fdf2e6da 538 debug("Saving network ID: %#.4x (%u)",
jhbr 0:d3f5fdf2e6da 539 notif_advReceived->netId, notif_advReceived->netId);
jhbr 0:d3f5fdf2e6da 540 dn_fsm_vars.networkId = notif_advReceived->netId;
jhbr 0:d3f5fdf2e6da 541 dn_fsm_scheduleEvent(DN_CMD_PERIOD_MS, dn_event_setNetworkId);
jhbr 0:d3f5fdf2e6da 542 }
jhbr 0:d3f5fdf2e6da 543
jhbr 0:d3f5fdf2e6da 544 break;
jhbr 0:d3f5fdf2e6da 545 default:
jhbr 0:d3f5fdf2e6da 546 log_warn("Unknown notification ID");
jhbr 0:d3f5fdf2e6da 547 break;
jhbr 0:d3f5fdf2e6da 548 }
jhbr 0:d3f5fdf2e6da 549 }
jhbr 0:d3f5fdf2e6da 550
jhbr 0:d3f5fdf2e6da 551 //===== reply_cb
jhbr 0:d3f5fdf2e6da 552
jhbr 0:d3f5fdf2e6da 553 /**
jhbr 0:d3f5fdf2e6da 554 This function is called whenever a reply is received through the SmartMesh.
jhbr 0:d3f5fdf2e6da 555 C Library. It calls the reply function that was armed at the start of the
jhbr 0:d3f5fdf2e6da 556 current event.
jhbr 0:d3f5fdf2e6da 557 */
jhbr 0:d3f5fdf2e6da 558 static void dn_ipmt_reply_cb(uint8_t cmdId)
jhbr 0:d3f5fdf2e6da 559 {
jhbr 0:d3f5fdf2e6da 560 debug("Got reply: cmdId; %#.2x (%u)", cmdId, cmdId);
jhbr 0:d3f5fdf2e6da 561 if (dn_fsm_vars.replyCb == NULL)
jhbr 0:d3f5fdf2e6da 562 {
jhbr 0:d3f5fdf2e6da 563 debug("Reply callback empty");
jhbr 0:d3f5fdf2e6da 564 return;
jhbr 0:d3f5fdf2e6da 565 }
jhbr 0:d3f5fdf2e6da 566 dn_fsm_vars.replyCb();
jhbr 0:d3f5fdf2e6da 567 }
jhbr 0:d3f5fdf2e6da 568
jhbr 0:d3f5fdf2e6da 569 //===== response_timeout
jhbr 0:d3f5fdf2e6da 570
jhbr 0:d3f5fdf2e6da 571 /**
jhbr 0:d3f5fdf2e6da 572 This event is scheduled after each mote API command is sent, effectively
jhbr 0:d3f5fdf2e6da 573 placing a timeout for the mote to reply.
jhbr 0:d3f5fdf2e6da 574 */
jhbr 0:d3f5fdf2e6da 575 static void dn_event_responseTimeout(void)
jhbr 0:d3f5fdf2e6da 576 {
jhbr 0:d3f5fdf2e6da 577 debug("Response timeout");
jhbr 0:d3f5fdf2e6da 578
jhbr 0:d3f5fdf2e6da 579 // Cancel any ongoing transmission and reset reply cb
jhbr 0:d3f5fdf2e6da 580 dn_ipmt_cancelTx();
jhbr 0:d3f5fdf2e6da 581 dn_fsm_vars.replyCb = NULL;
jhbr 0:d3f5fdf2e6da 582
jhbr 0:d3f5fdf2e6da 583 switch (dn_fsm_vars.state)
jhbr 0:d3f5fdf2e6da 584 {
jhbr 0:d3f5fdf2e6da 585 case DN_FSM_STATE_PRE_JOIN:
jhbr 0:d3f5fdf2e6da 586 case DN_FSM_STATE_JOINING:
jhbr 0:d3f5fdf2e6da 587 case DN_FSM_STATE_REQ_SERVICE:
jhbr 0:d3f5fdf2e6da 588 case DN_FSM_STATE_RESETTING:
jhbr 0:d3f5fdf2e6da 589 case DN_FSM_STATE_PROMISCUOUS:
jhbr 0:d3f5fdf2e6da 590 // Response timeout during connect; retry
jhbr 0:d3f5fdf2e6da 591 dn_fsm_enterState(DN_FSM_STATE_PRE_JOIN, 0);
jhbr 0:d3f5fdf2e6da 592 break;
jhbr 0:d3f5fdf2e6da 593 case DN_FSM_STATE_SENDING:
jhbr 0:d3f5fdf2e6da 594 // Response timeout during send; fail
jhbr 0:d3f5fdf2e6da 595 dn_fsm_enterState(DN_FSM_STATE_SEND_FAILED, 0);
jhbr 0:d3f5fdf2e6da 596 break;
jhbr 0:d3f5fdf2e6da 597 default:
jhbr 0:d3f5fdf2e6da 598 log_err("Response timeout in unexpected state: %#x", dn_fsm_vars.state);
jhbr 0:d3f5fdf2e6da 599 break;
jhbr 0:d3f5fdf2e6da 600 }
jhbr 0:d3f5fdf2e6da 601 }
jhbr 0:d3f5fdf2e6da 602
jhbr 0:d3f5fdf2e6da 603 //===== reset
jhbr 0:d3f5fdf2e6da 604
jhbr 0:d3f5fdf2e6da 605 /**
jhbr 0:d3f5fdf2e6da 606 Initiates a soft-reset of the mote. Its reply simply checks that
jhbr 0:d3f5fdf2e6da 607 the command was accepted, as the FSM will wait for the ensuing boot event.
jhbr 0:d3f5fdf2e6da 608 */
jhbr 0:d3f5fdf2e6da 609 static void dn_event_reset(void)
jhbr 0:d3f5fdf2e6da 610 {
jhbr 0:d3f5fdf2e6da 611 debug("Reset");
jhbr 0:d3f5fdf2e6da 612 // Arm reply callback
jhbr 0:d3f5fdf2e6da 613 dn_fsm_setReplyCallback(dn_reply_reset);
jhbr 0:d3f5fdf2e6da 614
jhbr 0:d3f5fdf2e6da 615 // Issue mote API command
jhbr 0:d3f5fdf2e6da 616 dn_ipmt_reset
jhbr 0:d3f5fdf2e6da 617 (
jhbr 0:d3f5fdf2e6da 618 (dn_ipmt_reset_rpt*)dn_fsm_vars.replyBuf
jhbr 0:d3f5fdf2e6da 619 );
jhbr 0:d3f5fdf2e6da 620
jhbr 0:d3f5fdf2e6da 621 // Schedule timeout for reply
jhbr 0:d3f5fdf2e6da 622 dn_fsm_scheduleEvent(DN_SERIAL_RESPONSE_TIMEOUT_MS, dn_event_responseTimeout);
jhbr 0:d3f5fdf2e6da 623 }
jhbr 0:d3f5fdf2e6da 624
jhbr 0:d3f5fdf2e6da 625 static void dn_reply_reset(void)
jhbr 0:d3f5fdf2e6da 626 {
jhbr 0:d3f5fdf2e6da 627 dn_ipmt_reset_rpt* reply;
jhbr 0:d3f5fdf2e6da 628 debug("Reset reply");
jhbr 0:d3f5fdf2e6da 629
jhbr 0:d3f5fdf2e6da 630 // Cancel reply timeout
jhbr 0:d3f5fdf2e6da 631 dn_fsm_cancelEvent();
jhbr 0:d3f5fdf2e6da 632
jhbr 0:d3f5fdf2e6da 633 // Parse reply
jhbr 0:d3f5fdf2e6da 634 reply = (dn_ipmt_reset_rpt*)dn_fsm_vars.replyBuf;
jhbr 0:d3f5fdf2e6da 635
jhbr 0:d3f5fdf2e6da 636 // Choose next event or state transition
jhbr 0:d3f5fdf2e6da 637 switch (reply->RC)
jhbr 0:d3f5fdf2e6da 638 {
jhbr 0:d3f5fdf2e6da 639 case DN_RC_OK:
jhbr 0:d3f5fdf2e6da 640 debug("Mote soft-reset initiated");
jhbr 0:d3f5fdf2e6da 641 // Will wait for notification of reboot
jhbr 0:d3f5fdf2e6da 642 break;
jhbr 0:d3f5fdf2e6da 643 default:
jhbr 0:d3f5fdf2e6da 644 log_warn("Unexpected response code: %#x", reply->RC);
jhbr 0:d3f5fdf2e6da 645 dn_fsm_enterState(DN_FSM_STATE_DISCONNECTED, 0);
jhbr 0:d3f5fdf2e6da 646 break;
jhbr 0:d3f5fdf2e6da 647 }
jhbr 0:d3f5fdf2e6da 648 }
jhbr 0:d3f5fdf2e6da 649
jhbr 0:d3f5fdf2e6da 650 //===== disconnect
jhbr 0:d3f5fdf2e6da 651
jhbr 0:d3f5fdf2e6da 652 /**
jhbr 0:d3f5fdf2e6da 653 This event does much the same as reset, however it uses the disconnect command
jhbr 0:d3f5fdf2e6da 654 instead, where the mote first spends a couple of seconds notifying its
jhbr 0:d3f5fdf2e6da 655 neighbors of its imminent soft-reset. If the reply is anything but success,
jhbr 0:d3f5fdf2e6da 656 it will schedule a simple reset event instead.
jhbr 0:d3f5fdf2e6da 657 */
jhbr 0:d3f5fdf2e6da 658 static void dn_event_disconnect(void)
jhbr 0:d3f5fdf2e6da 659 {
jhbr 0:d3f5fdf2e6da 660 debug("Disconnect");
jhbr 0:d3f5fdf2e6da 661
jhbr 0:d3f5fdf2e6da 662 // Arm reply callback
jhbr 0:d3f5fdf2e6da 663 dn_fsm_setReplyCallback(dn_reply_disconnect);
jhbr 0:d3f5fdf2e6da 664
jhbr 0:d3f5fdf2e6da 665 // Issue mote API command
jhbr 0:d3f5fdf2e6da 666 dn_ipmt_disconnect
jhbr 0:d3f5fdf2e6da 667 (
jhbr 0:d3f5fdf2e6da 668 (dn_ipmt_disconnect_rpt*)dn_fsm_vars.replyBuf
jhbr 0:d3f5fdf2e6da 669 );
jhbr 0:d3f5fdf2e6da 670
jhbr 0:d3f5fdf2e6da 671 // Schedule timeout for reply
jhbr 0:d3f5fdf2e6da 672 dn_fsm_scheduleEvent(DN_SERIAL_RESPONSE_TIMEOUT_MS, dn_event_responseTimeout);
jhbr 0:d3f5fdf2e6da 673 }
jhbr 0:d3f5fdf2e6da 674
jhbr 0:d3f5fdf2e6da 675 static void dn_reply_disconnect(void)
jhbr 0:d3f5fdf2e6da 676 {
jhbr 0:d3f5fdf2e6da 677 dn_ipmt_disconnect_rpt* reply;
jhbr 0:d3f5fdf2e6da 678 debug("Disconnect reply");
jhbr 0:d3f5fdf2e6da 679
jhbr 0:d3f5fdf2e6da 680 // Cancel reply timeout
jhbr 0:d3f5fdf2e6da 681 dn_fsm_cancelEvent();
jhbr 0:d3f5fdf2e6da 682
jhbr 0:d3f5fdf2e6da 683 // Parse reply
jhbr 0:d3f5fdf2e6da 684 reply = (dn_ipmt_disconnect_rpt*)dn_fsm_vars.replyBuf;
jhbr 0:d3f5fdf2e6da 685
jhbr 0:d3f5fdf2e6da 686 // Choose next event or state transition
jhbr 0:d3f5fdf2e6da 687 switch (reply->RC)
jhbr 0:d3f5fdf2e6da 688 {
jhbr 0:d3f5fdf2e6da 689 case DN_RC_OK:
jhbr 0:d3f5fdf2e6da 690 debug("Mote disconnect initiated");
jhbr 0:d3f5fdf2e6da 691 // Will wait for notification of reboot
jhbr 0:d3f5fdf2e6da 692 break;
jhbr 0:d3f5fdf2e6da 693 case DN_RC_INVALID_STATE:
jhbr 0:d3f5fdf2e6da 694 debug("The mote is in an invalid state to disconnect; resetting");
jhbr 0:d3f5fdf2e6da 695 dn_fsm_scheduleEvent(DN_CMD_PERIOD_MS, dn_event_reset);
jhbr 0:d3f5fdf2e6da 696 break;
jhbr 0:d3f5fdf2e6da 697 default:
jhbr 0:d3f5fdf2e6da 698 log_warn("Unexpected response code: %#x", reply->RC);
jhbr 0:d3f5fdf2e6da 699 dn_fsm_scheduleEvent(DN_CMD_PERIOD_MS, dn_event_reset);
jhbr 0:d3f5fdf2e6da 700 break;
jhbr 0:d3f5fdf2e6da 701 }
jhbr 0:d3f5fdf2e6da 702 }
jhbr 0:d3f5fdf2e6da 703
jhbr 0:d3f5fdf2e6da 704 //===== getMoteStatus
jhbr 0:d3f5fdf2e6da 705
jhbr 0:d3f5fdf2e6da 706 /**
jhbr 0:d3f5fdf2e6da 707 Asks the mote for its status, and the reply will use the reported
jhbr 0:d3f5fdf2e6da 708 mote state to decide whether or not it is ready to proceed with pre-join
jhbr 0:d3f5fdf2e6da 709 configurations or if a reset is needed first.
jhbr 0:d3f5fdf2e6da 710 */
jhbr 0:d3f5fdf2e6da 711 static void dn_event_getMoteStatus(void)
jhbr 0:d3f5fdf2e6da 712 {
jhbr 0:d3f5fdf2e6da 713 debug("Mote status");
jhbr 0:d3f5fdf2e6da 714
jhbr 0:d3f5fdf2e6da 715 // Arm reply callback
jhbr 0:d3f5fdf2e6da 716 dn_fsm_setReplyCallback(dn_reply_getMoteStatus);
jhbr 0:d3f5fdf2e6da 717
jhbr 0:d3f5fdf2e6da 718 // Issue mote API command
jhbr 0:d3f5fdf2e6da 719 dn_ipmt_getParameter_moteStatus
jhbr 0:d3f5fdf2e6da 720 (
jhbr 0:d3f5fdf2e6da 721 (dn_ipmt_getParameter_moteStatus_rpt*)dn_fsm_vars.replyBuf
jhbr 0:d3f5fdf2e6da 722 );
jhbr 0:d3f5fdf2e6da 723
jhbr 0:d3f5fdf2e6da 724 // Schedule timeout for reply
jhbr 0:d3f5fdf2e6da 725 dn_fsm_scheduleEvent(DN_SERIAL_RESPONSE_TIMEOUT_MS, dn_event_responseTimeout);
jhbr 0:d3f5fdf2e6da 726 }
jhbr 0:d3f5fdf2e6da 727
jhbr 0:d3f5fdf2e6da 728 static void dn_reply_getMoteStatus(void)
jhbr 0:d3f5fdf2e6da 729 {
jhbr 0:d3f5fdf2e6da 730 dn_ipmt_getParameter_moteStatus_rpt* reply;
jhbr 0:d3f5fdf2e6da 731 debug("Mote status reply");
jhbr 0:d3f5fdf2e6da 732
jhbr 0:d3f5fdf2e6da 733 // Cancel reply timeout
jhbr 0:d3f5fdf2e6da 734 dn_fsm_cancelEvent();
jhbr 0:d3f5fdf2e6da 735
jhbr 0:d3f5fdf2e6da 736 // Parse reply
jhbr 0:d3f5fdf2e6da 737 reply = (dn_ipmt_getParameter_moteStatus_rpt*)dn_fsm_vars.replyBuf;
jhbr 0:d3f5fdf2e6da 738 debug("Mote state: %#.2x", reply->state);
jhbr 0:d3f5fdf2e6da 739
jhbr 0:d3f5fdf2e6da 740 // Choose next event or state transition
jhbr 0:d3f5fdf2e6da 741 switch (reply->state)
jhbr 0:d3f5fdf2e6da 742 {
jhbr 0:d3f5fdf2e6da 743 case DN_MOTE_STATE_IDLE:
jhbr 0:d3f5fdf2e6da 744 dn_fsm_scheduleEvent(DN_CMD_PERIOD_MS, dn_event_openSocket);
jhbr 0:d3f5fdf2e6da 745 break;
jhbr 0:d3f5fdf2e6da 746 case DN_MOTE_STATE_OPERATIONAL:
jhbr 0:d3f5fdf2e6da 747 dn_fsm_enterState(DN_FSM_STATE_RESETTING, 0);
jhbr 0:d3f5fdf2e6da 748 break;
jhbr 0:d3f5fdf2e6da 749 default:
jhbr 0:d3f5fdf2e6da 750 dn_fsm_enterState(DN_FSM_STATE_RESETTING, 0);
jhbr 0:d3f5fdf2e6da 751 break;
jhbr 0:d3f5fdf2e6da 752 }
jhbr 0:d3f5fdf2e6da 753 }
jhbr 0:d3f5fdf2e6da 754
jhbr 0:d3f5fdf2e6da 755 //===== openSocket
jhbr 0:d3f5fdf2e6da 756
jhbr 0:d3f5fdf2e6da 757 /**
jhbr 0:d3f5fdf2e6da 758 Tells the mote to open a socket, and the reply saves the reported
jhbr 0:d3f5fdf2e6da 759 socket ID before scheduling its binding. If no sockets are available, a mote
jhbr 0:d3f5fdf2e6da 760 reset is scheduled and the connect process starts over.
jhbr 0:d3f5fdf2e6da 761 */
jhbr 0:d3f5fdf2e6da 762 static void dn_event_openSocket(void)
jhbr 0:d3f5fdf2e6da 763 {
jhbr 0:d3f5fdf2e6da 764 debug("Open socket");
jhbr 0:d3f5fdf2e6da 765
jhbr 0:d3f5fdf2e6da 766 // Arm reply callback
jhbr 0:d3f5fdf2e6da 767 dn_fsm_setReplyCallback(dn_reply_openSocket);
jhbr 0:d3f5fdf2e6da 768
jhbr 0:d3f5fdf2e6da 769 // Issue mote API command
jhbr 0:d3f5fdf2e6da 770 dn_ipmt_openSocket
jhbr 0:d3f5fdf2e6da 771 (
jhbr 0:d3f5fdf2e6da 772 DN_PROTOCOL_TYPE_UDP,
jhbr 0:d3f5fdf2e6da 773 (dn_ipmt_openSocket_rpt*)dn_fsm_vars.replyBuf
jhbr 0:d3f5fdf2e6da 774 );
jhbr 0:d3f5fdf2e6da 775
jhbr 0:d3f5fdf2e6da 776 // Schedule timeout for reply
jhbr 0:d3f5fdf2e6da 777 dn_fsm_scheduleEvent(DN_SERIAL_RESPONSE_TIMEOUT_MS, dn_event_responseTimeout);
jhbr 0:d3f5fdf2e6da 778 }
jhbr 0:d3f5fdf2e6da 779
jhbr 0:d3f5fdf2e6da 780 static void dn_reply_openSocket(void)
jhbr 0:d3f5fdf2e6da 781 {
jhbr 0:d3f5fdf2e6da 782 dn_ipmt_openSocket_rpt* reply;
jhbr 0:d3f5fdf2e6da 783 debug("Open socket reply");
jhbr 0:d3f5fdf2e6da 784
jhbr 0:d3f5fdf2e6da 785 // Cancel reply timeout
jhbr 0:d3f5fdf2e6da 786 dn_fsm_cancelEvent();
jhbr 0:d3f5fdf2e6da 787
jhbr 0:d3f5fdf2e6da 788 // Parse reply
jhbr 0:d3f5fdf2e6da 789 reply = (dn_ipmt_openSocket_rpt*)dn_fsm_vars.replyBuf;
jhbr 0:d3f5fdf2e6da 790
jhbr 0:d3f5fdf2e6da 791 // Choose next event or state transition
jhbr 0:d3f5fdf2e6da 792 switch (reply->RC)
jhbr 0:d3f5fdf2e6da 793 {
jhbr 0:d3f5fdf2e6da 794 case DN_RC_OK:
jhbr 0:d3f5fdf2e6da 795 debug("Socket %d opened successfully", reply->socketId);
jhbr 0:d3f5fdf2e6da 796 dn_fsm_vars.socketId = reply->socketId;
jhbr 0:d3f5fdf2e6da 797 dn_fsm_scheduleEvent(DN_CMD_PERIOD_MS, dn_event_bindSocket);
jhbr 0:d3f5fdf2e6da 798 break;
jhbr 0:d3f5fdf2e6da 799 case DN_RC_NO_RESOURCES:
jhbr 0:d3f5fdf2e6da 800 debug("Couldn't create socket due to resource availability");
jhbr 0:d3f5fdf2e6da 801 dn_fsm_enterState(DN_FSM_STATE_RESETTING, 0);
jhbr 0:d3f5fdf2e6da 802 break;
jhbr 0:d3f5fdf2e6da 803 default:
jhbr 0:d3f5fdf2e6da 804 log_warn("Unexpected response code: %#x", reply->RC);
jhbr 0:d3f5fdf2e6da 805 dn_fsm_enterState(DN_FSM_STATE_DISCONNECTED, 0);
jhbr 0:d3f5fdf2e6da 806 break;
jhbr 0:d3f5fdf2e6da 807 }
jhbr 0:d3f5fdf2e6da 808 }
jhbr 0:d3f5fdf2e6da 809
jhbr 0:d3f5fdf2e6da 810 //===== bindSocket
jhbr 0:d3f5fdf2e6da 811
jhbr 0:d3f5fdf2e6da 812 /**
jhbr 0:d3f5fdf2e6da 813 Binds the previously opened socket to a port. If said port is already bound,
jhbr 0:d3f5fdf2e6da 814 a mote reset is scheduled and the connect process starts over.
jhbr 0:d3f5fdf2e6da 815 */
jhbr 0:d3f5fdf2e6da 816 static void dn_event_bindSocket(void)
jhbr 0:d3f5fdf2e6da 817 {
jhbr 0:d3f5fdf2e6da 818 debug("Bind socket");
jhbr 0:d3f5fdf2e6da 819
jhbr 0:d3f5fdf2e6da 820 // Arm reply callback
jhbr 0:d3f5fdf2e6da 821 dn_fsm_setReplyCallback(dn_reply_bindSocket);
jhbr 0:d3f5fdf2e6da 822
jhbr 0:d3f5fdf2e6da 823 // Issue mote API command
jhbr 0:d3f5fdf2e6da 824 dn_ipmt_bindSocket
jhbr 0:d3f5fdf2e6da 825 (
jhbr 0:d3f5fdf2e6da 826 dn_fsm_vars.socketId,
jhbr 0:d3f5fdf2e6da 827 dn_fsm_vars.srcPort,
jhbr 0:d3f5fdf2e6da 828 (dn_ipmt_bindSocket_rpt*)dn_fsm_vars.replyBuf
jhbr 0:d3f5fdf2e6da 829 );
jhbr 0:d3f5fdf2e6da 830
jhbr 0:d3f5fdf2e6da 831 // Schedule timeout for reply
jhbr 0:d3f5fdf2e6da 832 dn_fsm_scheduleEvent(DN_SERIAL_RESPONSE_TIMEOUT_MS, dn_event_responseTimeout);
jhbr 0:d3f5fdf2e6da 833 }
jhbr 0:d3f5fdf2e6da 834
jhbr 0:d3f5fdf2e6da 835 static void dn_reply_bindSocket(void)
jhbr 0:d3f5fdf2e6da 836 {
jhbr 0:d3f5fdf2e6da 837 dn_ipmt_bindSocket_rpt* reply;
jhbr 0:d3f5fdf2e6da 838 debug("Bind socket reply");
jhbr 0:d3f5fdf2e6da 839
jhbr 0:d3f5fdf2e6da 840 // Cancel reply timeout
jhbr 0:d3f5fdf2e6da 841 dn_fsm_cancelEvent();
jhbr 0:d3f5fdf2e6da 842
jhbr 0:d3f5fdf2e6da 843 // Parse reply
jhbr 0:d3f5fdf2e6da 844 reply = (dn_ipmt_bindSocket_rpt*)dn_fsm_vars.replyBuf;
jhbr 0:d3f5fdf2e6da 845
jhbr 0:d3f5fdf2e6da 846 // Choose next event or state transition
jhbr 0:d3f5fdf2e6da 847 switch (reply->RC)
jhbr 0:d3f5fdf2e6da 848 {
jhbr 0:d3f5fdf2e6da 849 case DN_RC_OK:
jhbr 0:d3f5fdf2e6da 850 debug("Socket bound successfully");
jhbr 0:d3f5fdf2e6da 851 dn_fsm_scheduleEvent(DN_CMD_PERIOD_MS, dn_event_setJoinKey);
jhbr 0:d3f5fdf2e6da 852 break;
jhbr 0:d3f5fdf2e6da 853 case DN_RC_BUSY:
jhbr 0:d3f5fdf2e6da 854 debug("Port already bound");
jhbr 0:d3f5fdf2e6da 855 dn_fsm_enterState(DN_FSM_STATE_RESETTING, 0);
jhbr 0:d3f5fdf2e6da 856 break;
jhbr 0:d3f5fdf2e6da 857 case DN_RC_NOT_FOUND:
jhbr 0:d3f5fdf2e6da 858 debug("Invalid socket ID");
jhbr 0:d3f5fdf2e6da 859 dn_fsm_enterState(DN_FSM_STATE_DISCONNECTED, 0);
jhbr 0:d3f5fdf2e6da 860 break;
jhbr 0:d3f5fdf2e6da 861 default:
jhbr 0:d3f5fdf2e6da 862 log_warn("Unexpected response code: %#x", reply->RC);
jhbr 0:d3f5fdf2e6da 863 dn_fsm_enterState(DN_FSM_STATE_DISCONNECTED, 0);
jhbr 0:d3f5fdf2e6da 864 break;
jhbr 0:d3f5fdf2e6da 865 }
jhbr 0:d3f5fdf2e6da 866 }
jhbr 0:d3f5fdf2e6da 867
jhbr 0:d3f5fdf2e6da 868 //===== setJoinKey
jhbr 0:d3f5fdf2e6da 869
jhbr 0:d3f5fdf2e6da 870 /**
jhbr 0:d3f5fdf2e6da 871 Configures the join key that the mote should use when attempting to join a
jhbr 0:d3f5fdf2e6da 872 network.
jhbr 0:d3f5fdf2e6da 873 */
jhbr 0:d3f5fdf2e6da 874 static void dn_event_setJoinKey(void)
jhbr 0:d3f5fdf2e6da 875 {
jhbr 0:d3f5fdf2e6da 876 debug("Set join key");
jhbr 0:d3f5fdf2e6da 877
jhbr 0:d3f5fdf2e6da 878 // Arm reply callback
jhbr 0:d3f5fdf2e6da 879 dn_fsm_setReplyCallback(dn_reply_setJoinKey);
jhbr 0:d3f5fdf2e6da 880
jhbr 0:d3f5fdf2e6da 881 // Issue mote API command
jhbr 0:d3f5fdf2e6da 882 dn_ipmt_setParameter_joinKey
jhbr 0:d3f5fdf2e6da 883 (
jhbr 0:d3f5fdf2e6da 884 dn_fsm_vars.joinKey,
jhbr 0:d3f5fdf2e6da 885 (dn_ipmt_setParameter_joinKey_rpt*)dn_fsm_vars.replyBuf
jhbr 0:d3f5fdf2e6da 886 );
jhbr 0:d3f5fdf2e6da 887
jhbr 0:d3f5fdf2e6da 888 // Schedule timeout for reply
jhbr 0:d3f5fdf2e6da 889 dn_fsm_scheduleEvent(DN_SERIAL_RESPONSE_TIMEOUT_MS, dn_event_responseTimeout);
jhbr 0:d3f5fdf2e6da 890 }
jhbr 0:d3f5fdf2e6da 891
jhbr 0:d3f5fdf2e6da 892 static void dn_reply_setJoinKey(void)
jhbr 0:d3f5fdf2e6da 893 {
jhbr 0:d3f5fdf2e6da 894 dn_ipmt_setParameter_joinKey_rpt* reply;
jhbr 0:d3f5fdf2e6da 895 debug("Set join key reply");
jhbr 0:d3f5fdf2e6da 896
jhbr 0:d3f5fdf2e6da 897 // Cancel reply timeout
jhbr 0:d3f5fdf2e6da 898 dn_fsm_cancelEvent();
jhbr 0:d3f5fdf2e6da 899
jhbr 0:d3f5fdf2e6da 900 // Parse reply
jhbr 0:d3f5fdf2e6da 901 reply = (dn_ipmt_setParameter_joinKey_rpt*)dn_fsm_vars.replyBuf;
jhbr 0:d3f5fdf2e6da 902
jhbr 0:d3f5fdf2e6da 903 // Choose next event or state transition
jhbr 0:d3f5fdf2e6da 904 switch (reply->RC)
jhbr 0:d3f5fdf2e6da 905 {
jhbr 0:d3f5fdf2e6da 906 case DN_RC_OK:
jhbr 0:d3f5fdf2e6da 907 debug("Join key set");
jhbr 0:d3f5fdf2e6da 908 if (dn_fsm_vars.networkId == DN_PROMISCUOUS_NET_ID)
jhbr 0:d3f5fdf2e6da 909 {
jhbr 0:d3f5fdf2e6da 910 // Promiscuous netID set; search for new first
jhbr 0:d3f5fdf2e6da 911 dn_fsm_enterState(DN_FSM_STATE_PROMISCUOUS, 0);
jhbr 0:d3f5fdf2e6da 912 /*
jhbr 0:d3f5fdf2e6da 913 As of version 1.4.x, a network ID of 0xFFFF can be used to indicate
jhbr 0:d3f5fdf2e6da 914 that the mote should join the first network heard. Thus, searching
jhbr 0:d3f5fdf2e6da 915 before joining will not be necessary.
jhbr 0:d3f5fdf2e6da 916 */
jhbr 0:d3f5fdf2e6da 917 } else
jhbr 0:d3f5fdf2e6da 918 {
jhbr 0:d3f5fdf2e6da 919 dn_fsm_scheduleEvent(DN_CMD_PERIOD_MS, dn_event_setNetworkId);
jhbr 0:d3f5fdf2e6da 920 }
jhbr 0:d3f5fdf2e6da 921 break;
jhbr 0:d3f5fdf2e6da 922 case DN_RC_WRITE_FAIL:
jhbr 0:d3f5fdf2e6da 923 debug("Could not write the key to storage");
jhbr 0:d3f5fdf2e6da 924 dn_fsm_enterState(DN_FSM_STATE_DISCONNECTED, 0);
jhbr 0:d3f5fdf2e6da 925 break;
jhbr 0:d3f5fdf2e6da 926 default:
jhbr 0:d3f5fdf2e6da 927 log_warn("Unexpected response code: %#x", reply->RC);
jhbr 0:d3f5fdf2e6da 928 dn_fsm_enterState(DN_FSM_STATE_DISCONNECTED, 0);
jhbr 0:d3f5fdf2e6da 929 break;
jhbr 0:d3f5fdf2e6da 930 }
jhbr 0:d3f5fdf2e6da 931 }
jhbr 0:d3f5fdf2e6da 932
jhbr 0:d3f5fdf2e6da 933 //===== setNetworkId
jhbr 0:d3f5fdf2e6da 934
jhbr 0:d3f5fdf2e6da 935 /**
jhbr 0:d3f5fdf2e6da 936 Configures the ID of the network that the mote should should try to join.
jhbr 0:d3f5fdf2e6da 937 */
jhbr 0:d3f5fdf2e6da 938 static void dn_event_setNetworkId(void)
jhbr 0:d3f5fdf2e6da 939 {
jhbr 0:d3f5fdf2e6da 940 debug("Set network ID");
jhbr 0:d3f5fdf2e6da 941
jhbr 0:d3f5fdf2e6da 942 // Arm reply callback
jhbr 0:d3f5fdf2e6da 943 dn_fsm_setReplyCallback(dn_reply_setNetworkId);
jhbr 0:d3f5fdf2e6da 944
jhbr 0:d3f5fdf2e6da 945 // Issue mote API command
jhbr 0:d3f5fdf2e6da 946 dn_ipmt_setParameter_networkId
jhbr 0:d3f5fdf2e6da 947 (
jhbr 0:d3f5fdf2e6da 948 dn_fsm_vars.networkId,
jhbr 0:d3f5fdf2e6da 949 (dn_ipmt_setParameter_networkId_rpt*)dn_fsm_vars.replyBuf
jhbr 0:d3f5fdf2e6da 950 );
jhbr 0:d3f5fdf2e6da 951
jhbr 0:d3f5fdf2e6da 952 // Schedule timeout for reply
jhbr 0:d3f5fdf2e6da 953 dn_fsm_scheduleEvent(DN_SERIAL_RESPONSE_TIMEOUT_MS, dn_event_responseTimeout);
jhbr 0:d3f5fdf2e6da 954 }
jhbr 0:d3f5fdf2e6da 955
jhbr 0:d3f5fdf2e6da 956 static void dn_reply_setNetworkId(void)
jhbr 0:d3f5fdf2e6da 957 {
jhbr 0:d3f5fdf2e6da 958 dn_ipmt_setParameter_networkId_rpt* reply;
jhbr 0:d3f5fdf2e6da 959 debug("Set network ID reply");
jhbr 0:d3f5fdf2e6da 960
jhbr 0:d3f5fdf2e6da 961 // Cancel reply timeout
jhbr 0:d3f5fdf2e6da 962 dn_fsm_cancelEvent();
jhbr 0:d3f5fdf2e6da 963
jhbr 0:d3f5fdf2e6da 964 // Parse reply
jhbr 0:d3f5fdf2e6da 965 reply = (dn_ipmt_setParameter_networkId_rpt*)dn_fsm_vars.replyBuf;
jhbr 0:d3f5fdf2e6da 966
jhbr 0:d3f5fdf2e6da 967 // Choose next event or state transition
jhbr 0:d3f5fdf2e6da 968 switch (reply->RC)
jhbr 0:d3f5fdf2e6da 969 {
jhbr 0:d3f5fdf2e6da 970 case DN_RC_OK:
jhbr 0:d3f5fdf2e6da 971 debug("Network ID set");
jhbr 0:d3f5fdf2e6da 972 dn_fsm_enterState(DN_FSM_STATE_JOINING, 0);
jhbr 0:d3f5fdf2e6da 973 break;
jhbr 0:d3f5fdf2e6da 974 case DN_RC_WRITE_FAIL:
jhbr 0:d3f5fdf2e6da 975 debug("Could not write the network ID to storage");
jhbr 0:d3f5fdf2e6da 976 dn_fsm_enterState(DN_FSM_STATE_DISCONNECTED, 0);
jhbr 0:d3f5fdf2e6da 977 break;
jhbr 0:d3f5fdf2e6da 978 default:
jhbr 0:d3f5fdf2e6da 979 log_warn("Unexpected response code: %#x", reply->RC);
jhbr 0:d3f5fdf2e6da 980 dn_fsm_enterState(DN_FSM_STATE_DISCONNECTED, 0);
jhbr 0:d3f5fdf2e6da 981 break;
jhbr 0:d3f5fdf2e6da 982 }
jhbr 0:d3f5fdf2e6da 983 }
jhbr 0:d3f5fdf2e6da 984
jhbr 0:d3f5fdf2e6da 985 //===== search
jhbr 0:d3f5fdf2e6da 986
jhbr 0:d3f5fdf2e6da 987 /**
jhbr 0:d3f5fdf2e6da 988 Tells the mote to start listening for network advertisements. The mote will
jhbr 0:d3f5fdf2e6da 989 then report the network ID (among other things) of any advertisements heard.
jhbr 0:d3f5fdf2e6da 990 Upon a successful reply, the FSM will wait for an advReceived notification,
jhbr 0:d3f5fdf2e6da 991 before attempting to join the reported network.
jhbr 0:d3f5fdf2e6da 992 */
jhbr 0:d3f5fdf2e6da 993 static void dn_event_search(void)
jhbr 0:d3f5fdf2e6da 994 {
jhbr 0:d3f5fdf2e6da 995 debug("Search");
jhbr 0:d3f5fdf2e6da 996
jhbr 0:d3f5fdf2e6da 997 // Arm reply callback
jhbr 0:d3f5fdf2e6da 998 dn_fsm_setReplyCallback(dn_reply_search);
jhbr 0:d3f5fdf2e6da 999
jhbr 0:d3f5fdf2e6da 1000 // Issue mote API command
jhbr 0:d3f5fdf2e6da 1001 dn_ipmt_search
jhbr 0:d3f5fdf2e6da 1002 (
jhbr 0:d3f5fdf2e6da 1003 (dn_ipmt_search_rpt*)dn_fsm_vars.replyBuf
jhbr 0:d3f5fdf2e6da 1004 );
jhbr 0:d3f5fdf2e6da 1005
jhbr 0:d3f5fdf2e6da 1006 // Schedule timeout for reply
jhbr 0:d3f5fdf2e6da 1007 dn_fsm_scheduleEvent(DN_SERIAL_RESPONSE_TIMEOUT_MS, dn_event_responseTimeout);
jhbr 0:d3f5fdf2e6da 1008 }
jhbr 0:d3f5fdf2e6da 1009
jhbr 0:d3f5fdf2e6da 1010 static void dn_reply_search(void)
jhbr 0:d3f5fdf2e6da 1011 {
jhbr 0:d3f5fdf2e6da 1012 dn_ipmt_search_rpt* reply;
jhbr 0:d3f5fdf2e6da 1013 debug("Search reply");
jhbr 0:d3f5fdf2e6da 1014
jhbr 0:d3f5fdf2e6da 1015 // Cancel reply timeout
jhbr 0:d3f5fdf2e6da 1016 dn_fsm_cancelEvent();
jhbr 0:d3f5fdf2e6da 1017
jhbr 0:d3f5fdf2e6da 1018 // Parse reply
jhbr 0:d3f5fdf2e6da 1019 reply = (dn_ipmt_search_rpt*)dn_fsm_vars.replyBuf;
jhbr 0:d3f5fdf2e6da 1020
jhbr 0:d3f5fdf2e6da 1021 // Choose next event or state transition
jhbr 0:d3f5fdf2e6da 1022 switch (reply->RC)
jhbr 0:d3f5fdf2e6da 1023 {
jhbr 0:d3f5fdf2e6da 1024 case DN_RC_OK:
jhbr 0:d3f5fdf2e6da 1025 debug("Searching for network advertisements");
jhbr 0:d3f5fdf2e6da 1026 // Will wait for notification of advertisement received
jhbr 0:d3f5fdf2e6da 1027 break;
jhbr 0:d3f5fdf2e6da 1028 case DN_RC_INVALID_STATE:
jhbr 0:d3f5fdf2e6da 1029 debug("The mote is in an invalid state to start searching");
jhbr 0:d3f5fdf2e6da 1030 dn_fsm_enterState(DN_FSM_STATE_RESETTING, 0);
jhbr 0:d3f5fdf2e6da 1031 break;
jhbr 0:d3f5fdf2e6da 1032 default:
jhbr 0:d3f5fdf2e6da 1033 log_warn("Unexpected response code: %#x", reply->RC);
jhbr 0:d3f5fdf2e6da 1034 dn_fsm_enterState(DN_FSM_STATE_DISCONNECTED, 0);
jhbr 0:d3f5fdf2e6da 1035 break;
jhbr 0:d3f5fdf2e6da 1036 }
jhbr 0:d3f5fdf2e6da 1037 }
jhbr 0:d3f5fdf2e6da 1038
jhbr 0:d3f5fdf2e6da 1039 //===== join
jhbr 0:d3f5fdf2e6da 1040
jhbr 0:d3f5fdf2e6da 1041 /**
jhbr 0:d3f5fdf2e6da 1042 Requests that the mote start searching for the previously configured network
jhbr 0:d3f5fdf2e6da 1043 and attempt to join with the configured join key. If the mote is in an invalid
jhbr 0:d3f5fdf2e6da 1044 state to join or lacks configuration to start joining, a reset is scheduled and
jhbr 0:d3f5fdf2e6da 1045 the connect procedure starts over. Otherwise the FSM will wait for the ensuing
jhbr 0:d3f5fdf2e6da 1046 operational event when the mote has finished joining.
jhbr 0:d3f5fdf2e6da 1047 */
jhbr 0:d3f5fdf2e6da 1048 static void dn_event_join(void)
jhbr 0:d3f5fdf2e6da 1049 {
jhbr 0:d3f5fdf2e6da 1050 debug("Join");
jhbr 0:d3f5fdf2e6da 1051
jhbr 0:d3f5fdf2e6da 1052 // Arm reply callback
jhbr 0:d3f5fdf2e6da 1053 dn_fsm_setReplyCallback(dn_reply_join);
jhbr 0:d3f5fdf2e6da 1054
jhbr 0:d3f5fdf2e6da 1055 // Issue mote API command
jhbr 0:d3f5fdf2e6da 1056 dn_ipmt_join
jhbr 0:d3f5fdf2e6da 1057 (
jhbr 0:d3f5fdf2e6da 1058 (dn_ipmt_join_rpt*)dn_fsm_vars.replyBuf
jhbr 0:d3f5fdf2e6da 1059 );
jhbr 0:d3f5fdf2e6da 1060
jhbr 0:d3f5fdf2e6da 1061 // Schedule timeout for reply
jhbr 0:d3f5fdf2e6da 1062 dn_fsm_scheduleEvent(DN_SERIAL_RESPONSE_TIMEOUT_MS, dn_event_responseTimeout);
jhbr 0:d3f5fdf2e6da 1063 }
jhbr 0:d3f5fdf2e6da 1064
jhbr 0:d3f5fdf2e6da 1065 static void dn_reply_join(void)
jhbr 0:d3f5fdf2e6da 1066 {
jhbr 0:d3f5fdf2e6da 1067 dn_ipmt_join_rpt* reply;
jhbr 0:d3f5fdf2e6da 1068 debug("Join reply");
jhbr 0:d3f5fdf2e6da 1069
jhbr 0:d3f5fdf2e6da 1070 // Cancel reply timeout
jhbr 0:d3f5fdf2e6da 1071 dn_fsm_cancelEvent();
jhbr 0:d3f5fdf2e6da 1072
jhbr 0:d3f5fdf2e6da 1073 // Parse reply
jhbr 0:d3f5fdf2e6da 1074 reply = (dn_ipmt_join_rpt*)dn_fsm_vars.replyBuf;
jhbr 0:d3f5fdf2e6da 1075
jhbr 0:d3f5fdf2e6da 1076 // Choose next event or state transition
jhbr 0:d3f5fdf2e6da 1077 switch (reply->RC)
jhbr 0:d3f5fdf2e6da 1078 {
jhbr 0:d3f5fdf2e6da 1079 case DN_RC_OK:
jhbr 0:d3f5fdf2e6da 1080 debug("Join operation started");
jhbr 0:d3f5fdf2e6da 1081 // Will wait for join complete notification (operational event)
jhbr 0:d3f5fdf2e6da 1082 break;
jhbr 0:d3f5fdf2e6da 1083 case DN_RC_INVALID_STATE:
jhbr 0:d3f5fdf2e6da 1084 debug("The mote is in an invalid state to start join operation");
jhbr 0:d3f5fdf2e6da 1085 dn_fsm_enterState(DN_FSM_STATE_RESETTING, 0);
jhbr 0:d3f5fdf2e6da 1086 break;
jhbr 0:d3f5fdf2e6da 1087 case DN_RC_INCOMPLETE_JOIN_INFO:
jhbr 0:d3f5fdf2e6da 1088 debug("Incomplete configuration to start joining");
jhbr 0:d3f5fdf2e6da 1089 dn_fsm_enterState(DN_FSM_STATE_RESETTING, 0);
jhbr 0:d3f5fdf2e6da 1090 break;
jhbr 0:d3f5fdf2e6da 1091 default:
jhbr 0:d3f5fdf2e6da 1092 log_warn("Unexpected response code: %#x", reply->RC);
jhbr 0:d3f5fdf2e6da 1093 dn_fsm_enterState(DN_FSM_STATE_DISCONNECTED, 0);
jhbr 0:d3f5fdf2e6da 1094 break;
jhbr 0:d3f5fdf2e6da 1095 }
jhbr 0:d3f5fdf2e6da 1096 }
jhbr 0:d3f5fdf2e6da 1097
jhbr 0:d3f5fdf2e6da 1098 //===== requestService
jhbr 0:d3f5fdf2e6da 1099
jhbr 0:d3f5fdf2e6da 1100 /**
jhbr 0:d3f5fdf2e6da 1101 The mote is told to request a new service level from the manager. Its reply
jhbr 0:d3f5fdf2e6da 1102 simply checks that the command was accepted, as the FSM will wait for the
jhbr 0:d3f5fdf2e6da 1103 ensuing svcChange event when the service allocation has changed.
jhbr 0:d3f5fdf2e6da 1104 */
jhbr 0:d3f5fdf2e6da 1105 static void dn_event_requestService(void)
jhbr 0:d3f5fdf2e6da 1106 {
jhbr 0:d3f5fdf2e6da 1107 debug("Request service");
jhbr 0:d3f5fdf2e6da 1108
jhbr 0:d3f5fdf2e6da 1109 // Arm reply callback
jhbr 0:d3f5fdf2e6da 1110 dn_fsm_setReplyCallback(dn_reply_requestService);
jhbr 0:d3f5fdf2e6da 1111
jhbr 0:d3f5fdf2e6da 1112 // Issue mote API command
jhbr 0:d3f5fdf2e6da 1113 dn_ipmt_requestService
jhbr 0:d3f5fdf2e6da 1114 (
jhbr 0:d3f5fdf2e6da 1115 DN_SERVICE_ADDRESS,
jhbr 0:d3f5fdf2e6da 1116 DN_SERVICE_TYPE_BW,
jhbr 0:d3f5fdf2e6da 1117 dn_fsm_vars.service_ms,
jhbr 0:d3f5fdf2e6da 1118 (dn_ipmt_requestService_rpt*)dn_fsm_vars.replyBuf
jhbr 0:d3f5fdf2e6da 1119 );
jhbr 0:d3f5fdf2e6da 1120
jhbr 0:d3f5fdf2e6da 1121 // Schedule timeout for reply
jhbr 0:d3f5fdf2e6da 1122 dn_fsm_scheduleEvent(DN_SERIAL_RESPONSE_TIMEOUT_MS, dn_event_responseTimeout);
jhbr 0:d3f5fdf2e6da 1123 }
jhbr 0:d3f5fdf2e6da 1124
jhbr 0:d3f5fdf2e6da 1125 static void dn_reply_requestService(void)
jhbr 0:d3f5fdf2e6da 1126 {
jhbr 0:d3f5fdf2e6da 1127 dn_ipmt_requestService_rpt* reply;
jhbr 0:d3f5fdf2e6da 1128 debug("Request service reply");
jhbr 0:d3f5fdf2e6da 1129
jhbr 0:d3f5fdf2e6da 1130 // Cancel reply timeout
jhbr 0:d3f5fdf2e6da 1131 dn_fsm_cancelEvent();
jhbr 0:d3f5fdf2e6da 1132
jhbr 0:d3f5fdf2e6da 1133 // Parse reply
jhbr 0:d3f5fdf2e6da 1134 reply = (dn_ipmt_requestService_rpt*)dn_fsm_vars.replyBuf;
jhbr 0:d3f5fdf2e6da 1135
jhbr 0:d3f5fdf2e6da 1136 // Choose next event or state transition
jhbr 0:d3f5fdf2e6da 1137 switch (reply->RC)
jhbr 0:d3f5fdf2e6da 1138 {
jhbr 0:d3f5fdf2e6da 1139 case DN_RC_OK:
jhbr 0:d3f5fdf2e6da 1140 debug("Service request accepted");
jhbr 0:d3f5fdf2e6da 1141 // Will wait for svcChanged notification
jhbr 0:d3f5fdf2e6da 1142 break;
jhbr 0:d3f5fdf2e6da 1143 default:
jhbr 0:d3f5fdf2e6da 1144 log_warn("Unexpected response code: %#x", reply->RC);
jhbr 0:d3f5fdf2e6da 1145 dn_fsm_enterState(DN_FSM_STATE_DISCONNECTED, 0);
jhbr 0:d3f5fdf2e6da 1146 break;
jhbr 0:d3f5fdf2e6da 1147 }
jhbr 0:d3f5fdf2e6da 1148 }
jhbr 0:d3f5fdf2e6da 1149
jhbr 0:d3f5fdf2e6da 1150 //===== getServiceInfo
jhbr 0:d3f5fdf2e6da 1151
jhbr 0:d3f5fdf2e6da 1152 /**
jhbr 0:d3f5fdf2e6da 1153 Requests details about the service currently allocated to the mote. Its reply
jhbr 0:d3f5fdf2e6da 1154 checks that we have been granted a service equal to or better than what was
jhbr 0:d3f5fdf2e6da 1155 requested (smaller value equals better).
jhbr 0:d3f5fdf2e6da 1156 */
jhbr 0:d3f5fdf2e6da 1157 static void dn_event_getServiceInfo(void)
jhbr 0:d3f5fdf2e6da 1158 {
jhbr 0:d3f5fdf2e6da 1159 debug("Get service info");
jhbr 0:d3f5fdf2e6da 1160
jhbr 0:d3f5fdf2e6da 1161 // Arm reply callback
jhbr 0:d3f5fdf2e6da 1162 dn_fsm_setReplyCallback(dn_reply_getServiceInfo);
jhbr 0:d3f5fdf2e6da 1163
jhbr 0:d3f5fdf2e6da 1164 // Issue mote API command
jhbr 0:d3f5fdf2e6da 1165 dn_ipmt_getServiceInfo
jhbr 0:d3f5fdf2e6da 1166 (
jhbr 0:d3f5fdf2e6da 1167 DN_SERVICE_ADDRESS,
jhbr 0:d3f5fdf2e6da 1168 DN_SERVICE_TYPE_BW,
jhbr 0:d3f5fdf2e6da 1169 (dn_ipmt_getServiceInfo_rpt*)dn_fsm_vars.replyBuf
jhbr 0:d3f5fdf2e6da 1170 );
jhbr 0:d3f5fdf2e6da 1171
jhbr 0:d3f5fdf2e6da 1172 // Schedule timeout for reply
jhbr 0:d3f5fdf2e6da 1173 dn_fsm_scheduleEvent(DN_SERIAL_RESPONSE_TIMEOUT_MS, dn_event_responseTimeout);
jhbr 0:d3f5fdf2e6da 1174 }
jhbr 0:d3f5fdf2e6da 1175
jhbr 0:d3f5fdf2e6da 1176 static void dn_reply_getServiceInfo(void)
jhbr 0:d3f5fdf2e6da 1177 {
jhbr 0:d3f5fdf2e6da 1178 dn_ipmt_getServiceInfo_rpt* reply;
jhbr 0:d3f5fdf2e6da 1179 debug("Get service info reply");
jhbr 0:d3f5fdf2e6da 1180
jhbr 0:d3f5fdf2e6da 1181 // Cancel reply timeout
jhbr 0:d3f5fdf2e6da 1182 dn_fsm_cancelEvent();
jhbr 0:d3f5fdf2e6da 1183
jhbr 0:d3f5fdf2e6da 1184 // Parse reply
jhbr 0:d3f5fdf2e6da 1185 reply = (dn_ipmt_getServiceInfo_rpt*)dn_fsm_vars.replyBuf;
jhbr 0:d3f5fdf2e6da 1186
jhbr 0:d3f5fdf2e6da 1187 // Choose next event or state transition
jhbr 0:d3f5fdf2e6da 1188 switch (reply->RC)
jhbr 0:d3f5fdf2e6da 1189 {
jhbr 0:d3f5fdf2e6da 1190 case DN_RC_OK:
jhbr 0:d3f5fdf2e6da 1191 if (reply->state == DN_SERVICE_STATE_COMPLETED)
jhbr 0:d3f5fdf2e6da 1192 {
jhbr 0:d3f5fdf2e6da 1193 if (reply->value <= dn_fsm_vars.service_ms)
jhbr 0:d3f5fdf2e6da 1194 {
jhbr 0:d3f5fdf2e6da 1195 debug("Granted service of %u ms (requested %u ms)", reply->value, dn_fsm_vars.service_ms);
jhbr 0:d3f5fdf2e6da 1196 dn_fsm_enterState(DN_FSM_STATE_CONNECTED, 0);
jhbr 0:d3f5fdf2e6da 1197 } else
jhbr 0:d3f5fdf2e6da 1198 {
jhbr 0:d3f5fdf2e6da 1199 log_warn("Only granted service of %u ms (requested %u ms)", reply->value, dn_fsm_vars.service_ms);
jhbr 0:d3f5fdf2e6da 1200 dn_fsm_enterState(DN_FSM_STATE_DISCONNECTED, 0);
jhbr 0:d3f5fdf2e6da 1201 }
jhbr 0:d3f5fdf2e6da 1202
jhbr 0:d3f5fdf2e6da 1203 } else
jhbr 0:d3f5fdf2e6da 1204 {
jhbr 0:d3f5fdf2e6da 1205 debug("Service request still pending");
jhbr 0:d3f5fdf2e6da 1206 dn_fsm_scheduleEvent(DN_CMD_PERIOD_MS, dn_event_getServiceInfo);
jhbr 0:d3f5fdf2e6da 1207 }
jhbr 0:d3f5fdf2e6da 1208 break;
jhbr 0:d3f5fdf2e6da 1209 default:
jhbr 0:d3f5fdf2e6da 1210 log_warn("Unexpected response code: %#x", reply->RC);
jhbr 0:d3f5fdf2e6da 1211 dn_fsm_enterState(DN_FSM_STATE_DISCONNECTED, 0);
jhbr 0:d3f5fdf2e6da 1212 break;
jhbr 0:d3f5fdf2e6da 1213 }
jhbr 0:d3f5fdf2e6da 1214 }
jhbr 0:d3f5fdf2e6da 1215
jhbr 0:d3f5fdf2e6da 1216 //===== sendTo
jhbr 0:d3f5fdf2e6da 1217
jhbr 0:d3f5fdf2e6da 1218 /**
jhbr 0:d3f5fdf2e6da 1219 This event sends a packet into the network, and its reply checks that it was
jhbr 0:d3f5fdf2e6da 1220 accepted and queued up for transmission.
jhbr 0:d3f5fdf2e6da 1221 */
jhbr 0:d3f5fdf2e6da 1222 static void dn_event_sendTo(void)
jhbr 0:d3f5fdf2e6da 1223 {
jhbr 0:d3f5fdf2e6da 1224 dn_err_t err;
jhbr 0:d3f5fdf2e6da 1225 debug("Send");
jhbr 0:d3f5fdf2e6da 1226
jhbr 0:d3f5fdf2e6da 1227 // Arm reply callback
jhbr 0:d3f5fdf2e6da 1228 dn_fsm_setReplyCallback(dn_reply_sendTo);
jhbr 0:d3f5fdf2e6da 1229
jhbr 0:d3f5fdf2e6da 1230 // Issue mote API command
jhbr 0:d3f5fdf2e6da 1231 err = dn_ipmt_sendTo
jhbr 0:d3f5fdf2e6da 1232 (
jhbr 0:d3f5fdf2e6da 1233 dn_fsm_vars.socketId,
jhbr 0:d3f5fdf2e6da 1234 dn_fsm_vars.destIPv6,
jhbr 0:d3f5fdf2e6da 1235 dn_fsm_vars.destPort,
jhbr 0:d3f5fdf2e6da 1236 DN_SERVICE_TYPE_BW,
jhbr 0:d3f5fdf2e6da 1237 DN_PACKET_PRIORITY_MEDIUM,
jhbr 0:d3f5fdf2e6da 1238 DN_PACKET_ID_NO_NOTIF,
jhbr 0:d3f5fdf2e6da 1239 dn_fsm_vars.payloadBuf,
jhbr 0:d3f5fdf2e6da 1240 dn_fsm_vars.payloadSize,
jhbr 0:d3f5fdf2e6da 1241 (dn_ipmt_sendTo_rpt*)dn_fsm_vars.replyBuf
jhbr 0:d3f5fdf2e6da 1242 );
jhbr 0:d3f5fdf2e6da 1243 if (err != DN_ERR_NONE)
jhbr 0:d3f5fdf2e6da 1244 {
jhbr 0:d3f5fdf2e6da 1245 debug("Send error: %u", err);
jhbr 0:d3f5fdf2e6da 1246 dn_fsm_enterState(DN_FSM_STATE_SEND_FAILED, 0);
jhbr 0:d3f5fdf2e6da 1247 }
jhbr 0:d3f5fdf2e6da 1248
jhbr 0:d3f5fdf2e6da 1249 // Schedule timeout for reply
jhbr 0:d3f5fdf2e6da 1250 dn_fsm_scheduleEvent(DN_SERIAL_RESPONSE_TIMEOUT_MS, dn_event_responseTimeout);
jhbr 0:d3f5fdf2e6da 1251 }
jhbr 0:d3f5fdf2e6da 1252
jhbr 0:d3f5fdf2e6da 1253 static void dn_reply_sendTo(void)
jhbr 0:d3f5fdf2e6da 1254 {
jhbr 0:d3f5fdf2e6da 1255 dn_ipmt_sendTo_rpt* reply;
jhbr 0:d3f5fdf2e6da 1256 debug("Send reply");
jhbr 0:d3f5fdf2e6da 1257
jhbr 0:d3f5fdf2e6da 1258 // Cancel reply timeout
jhbr 0:d3f5fdf2e6da 1259 dn_fsm_cancelEvent();
jhbr 0:d3f5fdf2e6da 1260
jhbr 0:d3f5fdf2e6da 1261 // Parse reply
jhbr 0:d3f5fdf2e6da 1262 reply = (dn_ipmt_sendTo_rpt*)dn_fsm_vars.replyBuf;
jhbr 0:d3f5fdf2e6da 1263
jhbr 0:d3f5fdf2e6da 1264 // Choose next event or state transition
jhbr 0:d3f5fdf2e6da 1265 switch (reply->RC)
jhbr 0:d3f5fdf2e6da 1266 {
jhbr 0:d3f5fdf2e6da 1267 case DN_RC_OK:
jhbr 0:d3f5fdf2e6da 1268 debug("Packet was queued up for transmission");
jhbr 0:d3f5fdf2e6da 1269 dn_fsm_enterState(DN_FSM_STATE_CONNECTED, 0);
jhbr 0:d3f5fdf2e6da 1270 break;
jhbr 0:d3f5fdf2e6da 1271 case DN_RC_NO_RESOURCES:
jhbr 0:d3f5fdf2e6da 1272 debug("No queue space to accept the packet");
jhbr 0:d3f5fdf2e6da 1273 dn_fsm_enterState(DN_FSM_STATE_SEND_FAILED, 0);
jhbr 0:d3f5fdf2e6da 1274 break;
jhbr 0:d3f5fdf2e6da 1275 default:
jhbr 0:d3f5fdf2e6da 1276 log_warn("Unexpected response code: %#x", reply->RC);
jhbr 0:d3f5fdf2e6da 1277 dn_fsm_enterState(DN_FSM_STATE_SEND_FAILED, 0);
jhbr 0:d3f5fdf2e6da 1278 break;
jhbr 0:d3f5fdf2e6da 1279 }
jhbr 0:d3f5fdf2e6da 1280 }
jhbr 0:d3f5fdf2e6da 1281
jhbr 0:d3f5fdf2e6da 1282 //=========================== helpers =========================================
jhbr 0:d3f5fdf2e6da 1283
jhbr 0:d3f5fdf2e6da 1284 static dn_err_t checkAndSaveNetConfig(uint16_t netID, const uint8_t* joinKey, uint16_t srcPort, uint32_t req_service_ms)
jhbr 0:d3f5fdf2e6da 1285 {
jhbr 0:d3f5fdf2e6da 1286 if (netID == 0)
jhbr 0:d3f5fdf2e6da 1287 {
jhbr 0:d3f5fdf2e6da 1288 debug("No network ID given; using default");
jhbr 0:d3f5fdf2e6da 1289 dn_fsm_vars.networkId = DN_DEFAULT_NET_ID;
jhbr 0:d3f5fdf2e6da 1290 } else if (netID == DN_PROMISCUOUS_NET_ID)
jhbr 0:d3f5fdf2e6da 1291 {
jhbr 0:d3f5fdf2e6da 1292 debug("Promiscuous network ID given; will search for and join first network advertised");
jhbr 0:d3f5fdf2e6da 1293 dn_fsm_vars.networkId = netID;
jhbr 0:d3f5fdf2e6da 1294 } else
jhbr 0:d3f5fdf2e6da 1295 {
jhbr 0:d3f5fdf2e6da 1296 dn_fsm_vars.networkId = netID;
jhbr 0:d3f5fdf2e6da 1297 }
jhbr 0:d3f5fdf2e6da 1298
jhbr 0:d3f5fdf2e6da 1299 if (joinKey == NULL)
jhbr 0:d3f5fdf2e6da 1300 {
jhbr 0:d3f5fdf2e6da 1301 debug("No join key given; using default");
jhbr 0:d3f5fdf2e6da 1302 memcpy(dn_fsm_vars.joinKey, DN_DEFAULT_JOIN_KEY, DN_JOIN_KEY_LEN);
jhbr 0:d3f5fdf2e6da 1303 } else
jhbr 0:d3f5fdf2e6da 1304 {
jhbr 0:d3f5fdf2e6da 1305 memcpy(dn_fsm_vars.joinKey, joinKey, DN_JOIN_KEY_LEN);
jhbr 0:d3f5fdf2e6da 1306 }
jhbr 0:d3f5fdf2e6da 1307
jhbr 0:d3f5fdf2e6da 1308 if (srcPort == 0)
jhbr 0:d3f5fdf2e6da 1309 {
jhbr 0:d3f5fdf2e6da 1310 debug("No source port given; using default");
jhbr 0:d3f5fdf2e6da 1311 dn_fsm_vars.srcPort = DN_DEFAULT_SRC_PORT;
jhbr 0:d3f5fdf2e6da 1312 } else
jhbr 0:d3f5fdf2e6da 1313 {
jhbr 0:d3f5fdf2e6da 1314 dn_fsm_vars.srcPort = srcPort;
jhbr 0:d3f5fdf2e6da 1315 }
jhbr 0:d3f5fdf2e6da 1316
jhbr 0:d3f5fdf2e6da 1317 if (req_service_ms == 0)
jhbr 0:d3f5fdf2e6da 1318 {
jhbr 0:d3f5fdf2e6da 1319 debug("No service requested; will only be granted base bandwidth");
jhbr 0:d3f5fdf2e6da 1320 }
jhbr 0:d3f5fdf2e6da 1321 dn_fsm_vars.service_ms = req_service_ms;
jhbr 0:d3f5fdf2e6da 1322
jhbr 0:d3f5fdf2e6da 1323 return DN_ERR_NONE;
jhbr 0:d3f5fdf2e6da 1324 }
jhbr 0:d3f5fdf2e6da 1325
jhbr 0:d3f5fdf2e6da 1326 static uint8_t getPayloadLimit(uint16_t destPort)
jhbr 0:d3f5fdf2e6da 1327 {
jhbr 0:d3f5fdf2e6da 1328 bool destIsF0Bx = (destPort >= DN_WELL_KNOWN_PORT_1 && destPort <= DN_WELL_KNOWN_PORT_8);
jhbr 0:d3f5fdf2e6da 1329 bool srcIsF0Bx = (dn_fsm_vars.srcPort >= DN_WELL_KNOWN_PORT_1 && dn_fsm_vars.srcPort <= DN_WELL_KNOWN_PORT_8);
jhbr 0:d3f5fdf2e6da 1330 int8_t destIsMng = memcmp(DN_DEST_IP, DN_DEFAULT_DEST_IP, DN_IPv6ADDR_LEN);
jhbr 0:d3f5fdf2e6da 1331
jhbr 0:d3f5fdf2e6da 1332 if (destIsMng == 0)
jhbr 0:d3f5fdf2e6da 1333 {
jhbr 0:d3f5fdf2e6da 1334 if (destIsF0Bx && srcIsF0Bx)
jhbr 0:d3f5fdf2e6da 1335 return DN_PAYLOAD_SIZE_LIMIT_MNG_HIGH;
jhbr 0:d3f5fdf2e6da 1336 else if (destIsF0Bx || srcIsF0Bx)
jhbr 0:d3f5fdf2e6da 1337 return DN_PAYLOAD_SIZE_LIMIT_MNG_MED;
jhbr 0:d3f5fdf2e6da 1338 else
jhbr 0:d3f5fdf2e6da 1339 return DN_PAYLOAD_SIZE_LIMIT_MNG_LOW;
jhbr 0:d3f5fdf2e6da 1340 } else
jhbr 0:d3f5fdf2e6da 1341 {
jhbr 0:d3f5fdf2e6da 1342 if (destIsF0Bx && srcIsF0Bx)
jhbr 0:d3f5fdf2e6da 1343 return DN_PAYLOAD_SIZE_LIMIT_IP_HIGH;
jhbr 0:d3f5fdf2e6da 1344 else if (destIsF0Bx || srcIsF0Bx)
jhbr 0:d3f5fdf2e6da 1345 return DN_PAYLOAD_SIZE_LIMIT_IP_MED;
jhbr 0:d3f5fdf2e6da 1346 else
jhbr 0:d3f5fdf2e6da 1347 return DN_PAYLOAD_SIZE_LIMIT_IP_LOW;
jhbr 0:d3f5fdf2e6da 1348 }
jhbr 0:d3f5fdf2e6da 1349 }
jhbr 0:d3f5fdf2e6da 1350