SmartMesh QSL for STM32F4 version

Fork of COG-AD4050_QSL by APS Lab

Committer:
APS_Lab
Date:
Thu Jul 12 09:19:12 2018 +0000
Revision:
1:b909b8399252
Parent:
0:8ca1e814a851
SmartMesh for STM32F4 version

Who changed what in which revision?

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