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