The Hiking Pal tracking device firmware. See full description on the detail page: https://www.hackster.io/bowenfeng/hiking-pal-v1-07c02d
Dependencies: FXOS8700CQ MODSERIAL mbed
Fork of Avnet_ATT_Cellular_IOT by
main.cpp@87:ca75c5e785a7, 2016-12-22 (annotated)
- Committer:
- bowenfeng
- Date:
- Thu Dec 22 09:32:33 2016 +0000
- Revision:
- 87:ca75c5e785a7
- Parent:
- 86:5ff234988f53
Join latest hiking activity instead.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
fkellermavnet | 68:6e311c747045 | 1 | /* =================================================================== |
fkellermavnet | 68:6e311c747045 | 2 | Copyright © 2016, AVNET Inc. |
fkellermavnet | 68:6e311c747045 | 3 | |
fkellermavnet | 68:6e311c747045 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); |
fkellermavnet | 68:6e311c747045 | 5 | you may not use this file except in compliance with the License. |
fkellermavnet | 68:6e311c747045 | 6 | You may obtain a copy of the License at |
fkellermavnet | 68:6e311c747045 | 7 | |
fkellermavnet | 68:6e311c747045 | 8 | http://www.apache.org/licenses/LICENSE-2.0 |
fkellermavnet | 68:6e311c747045 | 9 | |
fkellermavnet | 68:6e311c747045 | 10 | Unless required by applicable law or agreed to in writing, |
fkellermavnet | 68:6e311c747045 | 11 | software distributed under the License is distributed on an |
fkellermavnet | 68:6e311c747045 | 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, |
fkellermavnet | 68:6e311c747045 | 13 | either express or implied. See the License for the specific |
fkellermavnet | 68:6e311c747045 | 14 | language governing permissions and limitations under the License. |
fkellermavnet | 68:6e311c747045 | 15 | |
fkellermavnet | 68:6e311c747045 | 16 | ======================================================================== */ |
fkellermavnet | 68:6e311c747045 | 17 | |
stefanrousseau | 55:3abf9e3f42e6 | 18 | #include "mbed.h" |
JMF | 0:9d5134074d84 | 19 | #include <cctype> |
JMF | 0:9d5134074d84 | 20 | #include <string> |
JMF | 2:0e2ef866af95 | 21 | #include "config_me.h" |
stefanrousseau | 4:f83bedd9cab4 | 22 | #include "sensors.h" |
stefanrousseau | 61:f6b93129f954 | 23 | #include "cell_modem.h" |
stefanrousseau | 11:e6602513730f | 24 | #include "hardware.h" |
stefanrousseau | 11:e6602513730f | 25 | |
stefanrousseau | 61:f6b93129f954 | 26 | I2C i2c(PTC11, PTC10); //SDA, SCL -- define the I2C pins being used |
stefanrousseau | 56:cb42ff383dab | 27 | MODSERIAL pc(USBTX, USBRX, 256, 256); // tx, rx with default tx, rx buffer sizes |
stefanrousseau | 63:90d7c69993cd | 28 | MODSERIAL mdm(PTD3, PTD2, 4096, 4096); |
stefanrousseau | 16:17c5916f2d12 | 29 | DigitalOut led_green(LED_GREEN); |
stefanrousseau | 16:17c5916f2d12 | 30 | DigitalOut led_red(LED_RED); |
stefanrousseau | 16:17c5916f2d12 | 31 | DigitalOut led_blue(LED_BLUE); |
JMF | 0:9d5134074d84 | 32 | |
bowenfeng | 85:43d791cd5967 | 33 | #define OK_COLOR 0x2 |
bowenfeng | 85:43d791cd5967 | 34 | #define ERROR_COLOR 0x1 |
bowenfeng | 85:43d791cd5967 | 35 | |
JMF | 0:9d5134074d84 | 36 | |
stefanrousseau | 3:26b3cc155f39 | 37 | //******************************************************************************************************************************************** |
stefanrousseau | 12:7c94ec5069dc | 38 | //* Create string with sensor readings that can be sent to flow as an HTTP get |
stefanrousseau | 3:26b3cc155f39 | 39 | //******************************************************************************************************************************************** |
bowenfeng | 84:0bf8168b690a | 40 | K64F_Sensors_t SENSOR_DATA = { |
stefanrousseau | 12:7c94ec5069dc | 41 | .Temperature = "0", |
stefanrousseau | 12:7c94ec5069dc | 42 | .Humidity = "0", |
stefanrousseau | 12:7c94ec5069dc | 43 | .AccelX = "0", |
stefanrousseau | 12:7c94ec5069dc | 44 | .AccelY = "0", |
stefanrousseau | 12:7c94ec5069dc | 45 | .AccelZ = "0", |
stefanrousseau | 12:7c94ec5069dc | 46 | .MagnetometerX = "0", |
stefanrousseau | 12:7c94ec5069dc | 47 | .MagnetometerY = "0", |
stefanrousseau | 12:7c94ec5069dc | 48 | .MagnetometerZ = "0", |
stefanrousseau | 12:7c94ec5069dc | 49 | .AmbientLightVis = "0", |
stefanrousseau | 12:7c94ec5069dc | 50 | .AmbientLightIr = "0", |
stefanrousseau | 12:7c94ec5069dc | 51 | .UVindex = "0", |
stefanrousseau | 12:7c94ec5069dc | 52 | .Proximity = "0", |
stefanrousseau | 12:7c94ec5069dc | 53 | .Temperature_Si7020 = "0", |
stefanrousseau | 55:3abf9e3f42e6 | 54 | .Humidity_Si7020 = "0", |
stefanrousseau | 55:3abf9e3f42e6 | 55 | .Virtual_Sensor1 = "0", |
stefanrousseau | 55:3abf9e3f42e6 | 56 | .Virtual_Sensor2 = "0", |
stefanrousseau | 55:3abf9e3f42e6 | 57 | .Virtual_Sensor3 = "0", |
stefanrousseau | 55:3abf9e3f42e6 | 58 | .Virtual_Sensor4 = "0", |
stefanrousseau | 55:3abf9e3f42e6 | 59 | .Virtual_Sensor5 = "0", |
stefanrousseau | 55:3abf9e3f42e6 | 60 | .Virtual_Sensor6 = "0", |
stefanrousseau | 55:3abf9e3f42e6 | 61 | .Virtual_Sensor7 = "0", |
stefanrousseau | 71:45a5e426df81 | 62 | .Virtual_Sensor8 = "0", |
stefanrousseau | 72:b500e1507b5f | 63 | .GPS_Satellites = "0", |
stefanrousseau | 71:45a5e426df81 | 64 | .GPS_Latitude = "0", |
stefanrousseau | 71:45a5e426df81 | 65 | .GPS_Longitude = "0", |
stefanrousseau | 71:45a5e426df81 | 66 | .GPS_Altitude = "0", |
stefanrousseau | 71:45a5e426df81 | 67 | .GPS_Speed = "0", |
stefanrousseau | 71:45a5e426df81 | 68 | .GPS_Course = "0" |
stefanrousseau | 3:26b3cc155f39 | 69 | }; |
stefanrousseau | 12:7c94ec5069dc | 70 | |
bowenfeng | 85:43d791cd5967 | 71 | char hid[20] = {0}; |
bowenfeng | 85:43d791cd5967 | 72 | char sid[20] = {0}; |
bowenfeng | 85:43d791cd5967 | 73 | char sessionName[20] = {0}; |
bowenfeng | 85:43d791cd5967 | 74 | |
bowenfeng | 84:0bf8168b690a | 75 | void display_app_firmware_version(void) { |
bowenfeng | 85:43d791cd5967 | 76 | PUTS("\r\n\r\nHiking Pal Firmware: Release 1.0 - built: "__DATE__" "__TIME__"\r\n\r\n"); |
fkellermavnet | 77:c65eae5b9958 | 77 | } |
fkellermavnet | 77:c65eae5b9958 | 78 | |
stefanrousseau | 3:26b3cc155f39 | 79 | //Periodic timer |
stefanrousseau | 3:26b3cc155f39 | 80 | Ticker OneMsTicker; |
stefanrousseau | 3:26b3cc155f39 | 81 | volatile bool bTimerExpiredFlag = false; |
stefanrousseau | 3:26b3cc155f39 | 82 | int OneMsTicks = 0; |
stefanrousseau | 3:26b3cc155f39 | 83 | int iTimer1Interval_ms = 1000; |
stefanrousseau | 3:26b3cc155f39 | 84 | //******************************************************************************************************************************************** |
stefanrousseau | 3:26b3cc155f39 | 85 | //* Periodic 1ms timer tick |
stefanrousseau | 3:26b3cc155f39 | 86 | //******************************************************************************************************************************************** |
bowenfeng | 84:0bf8168b690a | 87 | void OneMsFunction() { |
stefanrousseau | 3:26b3cc155f39 | 88 | OneMsTicks++; |
bowenfeng | 84:0bf8168b690a | 89 | if ((OneMsTicks % iTimer1Interval_ms) == 0) { |
stefanrousseau | 3:26b3cc155f39 | 90 | bTimerExpiredFlag = true; |
stefanrousseau | 3:26b3cc155f39 | 91 | } |
stefanrousseau | 3:26b3cc155f39 | 92 | } //OneMsFunction() |
stefanrousseau | 3:26b3cc155f39 | 93 | |
stefanrousseau | 16:17c5916f2d12 | 94 | //******************************************************************************************************************************************** |
stefanrousseau | 16:17c5916f2d12 | 95 | //* Set the RGB LED's Color |
stefanrousseau | 16:17c5916f2d12 | 96 | //* LED Color 0=Off to 7=White. 3 bits represent BGR (bit0=Red, bit1=Green, bit2=Blue) |
stefanrousseau | 16:17c5916f2d12 | 97 | //******************************************************************************************************************************************** |
bowenfeng | 84:0bf8168b690a | 98 | void SetLedColor(unsigned char ucColor) { |
stefanrousseau | 16:17c5916f2d12 | 99 | //Note that when an LED is on, you write a 0 to it: |
stefanrousseau | 16:17c5916f2d12 | 100 | led_red = !(ucColor & 0x1); //bit 0 |
stefanrousseau | 16:17c5916f2d12 | 101 | led_green = !(ucColor & 0x2); //bit 1 |
stefanrousseau | 16:17c5916f2d12 | 102 | led_blue = !(ucColor & 0x4); //bit 2 |
stefanrousseau | 16:17c5916f2d12 | 103 | } //SetLedColor() |
stefanrousseau | 16:17c5916f2d12 | 104 | |
bowenfeng | 84:0bf8168b690a | 105 | void extract_longlong(const char* s, char v[]) { |
bowenfeng | 84:0bf8168b690a | 106 | long long value = strtoll(s, NULL, 0); |
bowenfeng | 84:0bf8168b690a | 107 | sprintf(v, "%lld", value); |
bowenfeng | 84:0bf8168b690a | 108 | } |
bowenfeng | 84:0bf8168b690a | 109 | |
bowenfeng | 87:ca75c5e785a7 | 110 | long long find_longlong(const char* s, const char* token, const char** end) { |
bowenfeng | 87:ca75c5e785a7 | 111 | const char* tokenBegin = strstr(s, token); |
bowenfeng | 87:ca75c5e785a7 | 112 | if (tokenBegin != 0) { |
bowenfeng | 87:ca75c5e785a7 | 113 | *end = tokenBegin + strlen(token); |
bowenfeng | 87:ca75c5e785a7 | 114 | return strtoll(tokenBegin + strlen(token), NULL, 0); |
bowenfeng | 87:ca75c5e785a7 | 115 | } |
bowenfeng | 87:ca75c5e785a7 | 116 | return 0; |
bowenfeng | 87:ca75c5e785a7 | 117 | } |
bowenfeng | 87:ca75c5e785a7 | 118 | |
bowenfeng | 84:0bf8168b690a | 119 | void find_longlong(const char* s, const char* token, char v[]) { |
bowenfeng | 84:0bf8168b690a | 120 | const char* tokenBegin = strstr(s, token); |
bowenfeng | 84:0bf8168b690a | 121 | if (tokenBegin != 0) { |
bowenfeng | 84:0bf8168b690a | 122 | extract_longlong(tokenBegin + strlen(token), v); |
bowenfeng | 84:0bf8168b690a | 123 | } |
bowenfeng | 84:0bf8168b690a | 124 | } |
bowenfeng | 84:0bf8168b690a | 125 | |
bowenfeng | 87:ca75c5e785a7 | 126 | |
bowenfeng | 85:43d791cd5967 | 127 | int send_receive(char* request, char* response) { |
bowenfeng | 85:43d791cd5967 | 128 | int result = cell_modem_Sendreceive(request, response); |
bowenfeng | 85:43d791cd5967 | 129 | SetLedColor(result ? OK_COLOR : ERROR_COLOR); |
bowenfeng | 85:43d791cd5967 | 130 | return result; |
bowenfeng | 85:43d791cd5967 | 131 | } |
bowenfeng | 85:43d791cd5967 | 132 | |
bowenfeng | 85:43d791cd5967 | 133 | int send_only(char* request) { |
bowenfeng | 85:43d791cd5967 | 134 | char response[512]; |
bowenfeng | 85:43d791cd5967 | 135 | return send_receive(request, response); |
bowenfeng | 85:43d791cd5967 | 136 | } |
bowenfeng | 85:43d791cd5967 | 137 | |
bowenfeng | 87:ca75c5e785a7 | 138 | void find_latest_hiking(char hikingId[]) { |
bowenfeng | 84:0bf8168b690a | 139 | char request[512]; |
bowenfeng | 84:0bf8168b690a | 140 | char response[512]; |
bowenfeng | 84:0bf8168b690a | 141 | sprintf(request, "GET %s/hikings HTTP/1.1\r\nHost: %s\r\n\r\n", FLOW_BASE_URL, MY_SERVER_URL); |
bowenfeng | 85:43d791cd5967 | 142 | if (send_receive(&request[0], &response[0])) { |
bowenfeng | 87:ca75c5e785a7 | 143 | long long llv; |
bowenfeng | 87:ca75c5e785a7 | 144 | long long latestId = 0; |
bowenfeng | 87:ca75c5e785a7 | 145 | const char* begin = response; |
bowenfeng | 87:ca75c5e785a7 | 146 | PRINTF("%s\n\n", begin); |
bowenfeng | 87:ca75c5e785a7 | 147 | |
bowenfeng | 87:ca75c5e785a7 | 148 | char token[] = "\"id\":"; |
bowenfeng | 87:ca75c5e785a7 | 149 | for (;;) { |
bowenfeng | 87:ca75c5e785a7 | 150 | llv = find_longlong(begin, token, &begin); |
bowenfeng | 87:ca75c5e785a7 | 151 | |
bowenfeng | 87:ca75c5e785a7 | 152 | PRINTF("---> %lld\n", llv); |
bowenfeng | 87:ca75c5e785a7 | 153 | PRINTF("%s\n", begin); |
bowenfeng | 87:ca75c5e785a7 | 154 | |
bowenfeng | 87:ca75c5e785a7 | 155 | if (llv == 0) { |
bowenfeng | 87:ca75c5e785a7 | 156 | break; |
bowenfeng | 87:ca75c5e785a7 | 157 | } |
bowenfeng | 87:ca75c5e785a7 | 158 | if (llv > latestId) { |
bowenfeng | 87:ca75c5e785a7 | 159 | latestId = llv; |
bowenfeng | 87:ca75c5e785a7 | 160 | } |
bowenfeng | 87:ca75c5e785a7 | 161 | } |
bowenfeng | 87:ca75c5e785a7 | 162 | sprintf(hikingId, "%lld", latestId); |
bowenfeng | 87:ca75c5e785a7 | 163 | PRINTF("LATEST HIKING ID: %lld", latestId); |
bowenfeng | 84:0bf8168b690a | 164 | } |
bowenfeng | 84:0bf8168b690a | 165 | } |
bowenfeng | 84:0bf8168b690a | 166 | |
bowenfeng | 84:0bf8168b690a | 167 | void join_hiking(const char* hikingId, const char* name, char sessionId[]) { |
bowenfeng | 84:0bf8168b690a | 168 | char request[512]; |
bowenfeng | 84:0bf8168b690a | 169 | char response[512]; |
bowenfeng | 84:0bf8168b690a | 170 | sprintf(request, "GET %s/hikings/%s/sessions?name=%s HTTP/1.1\r\nHost: %s\r\n\r\n", FLOW_BASE_URL, hikingId, name, MY_SERVER_URL); |
bowenfeng | 85:43d791cd5967 | 171 | if (send_receive(&request[0], &response[0])) { |
bowenfeng | 84:0bf8168b690a | 172 | find_longlong(response, "\"id\":", sessionId); |
bowenfeng | 84:0bf8168b690a | 173 | } |
bowenfeng | 84:0bf8168b690a | 174 | } |
bowenfeng | 84:0bf8168b690a | 175 | |
bowenfeng | 85:43d791cd5967 | 176 | void generate_move_request(char request[], const char* hid, const char* sid) { |
bowenfeng | 85:43d791cd5967 | 177 | sprintf( |
bowenfeng | 85:43d791cd5967 | 178 | request, |
bowenfeng | 85:43d791cd5967 | 179 | "GET %s/hikings/%s/sessions/%s/moves?lat=%s&lng=%s HTTP/1.1\r\nHost: %s\r\n\r\n", |
bowenfeng | 85:43d791cd5967 | 180 | FLOW_BASE_URL, |
bowenfeng | 85:43d791cd5967 | 181 | hid, |
bowenfeng | 85:43d791cd5967 | 182 | sid, |
bowenfeng | 85:43d791cd5967 | 183 | SENSOR_DATA.GPS_Latitude, |
bowenfeng | 85:43d791cd5967 | 184 | SENSOR_DATA.GPS_Longitude, |
bowenfeng | 85:43d791cd5967 | 185 | MY_SERVER_URL); |
bowenfeng | 85:43d791cd5967 | 186 | } |
bowenfeng | 85:43d791cd5967 | 187 | void report_move(const char* hid, const char* sid) { |
bowenfeng | 85:43d791cd5967 | 188 | char request[512]; |
bowenfeng | 85:43d791cd5967 | 189 | generate_move_request(request, hid, sid); |
bowenfeng | 85:43d791cd5967 | 190 | send_only(&request[0]); |
bowenfeng | 85:43d791cd5967 | 191 | } |
bowenfeng | 85:43d791cd5967 | 192 | |
JMF | 0:9d5134074d84 | 193 | int main() { |
stefanrousseau | 72:b500e1507b5f | 194 | //delay so that the debug terminal can open after power-on reset: |
fkellermavnet | 77:c65eae5b9958 | 195 | wait (5.0); |
stefanrousseau | 61:f6b93129f954 | 196 | pc.baud(115200); |
fkellermavnet | 77:c65eae5b9958 | 197 | |
fkellermavnet | 77:c65eae5b9958 | 198 | display_app_firmware_version(); |
fkellermavnet | 77:c65eae5b9958 | 199 | |
bowenfeng | 85:43d791cd5967 | 200 | PRINTF(GRN "Hiking Pal tracking device started!\r\n\r\n"); |
JMF | 0:9d5134074d84 | 201 | |
stefanrousseau | 61:f6b93129f954 | 202 | //Initialize the I2C sensors that are present |
stefanrousseau | 11:e6602513730f | 203 | sensors_init(); |
stefanrousseau | 12:7c94ec5069dc | 204 | read_sensors(); |
stefanrousseau | 11:e6602513730f | 205 | |
stefanrousseau | 61:f6b93129f954 | 206 | // Set LED to RED until init finishes |
stefanrousseau | 61:f6b93129f954 | 207 | SetLedColor(0x1); //Red |
JMF | 0:9d5134074d84 | 208 | // Initialize the modem |
stefanrousseau | 64:09004cd610df | 209 | PRINTF("\r\n"); |
stefanrousseau | 61:f6b93129f954 | 210 | cell_modem_init(); |
fkellermavnet | 77:c65eae5b9958 | 211 | display_wnc_firmware_rev(); |
fkellermavnet | 77:c65eae5b9958 | 212 | |
stefanrousseau | 61:f6b93129f954 | 213 | // Set LED BLUE for partial init |
stefanrousseau | 61:f6b93129f954 | 214 | SetLedColor(0x4); //Blue |
JMF | 0:9d5134074d84 | 215 | |
stefanrousseau | 3:26b3cc155f39 | 216 | //Create a 1ms timer tick function: |
stefanrousseau | 61:f6b93129f954 | 217 | iTimer1Interval_ms = SENSOR_UPDATE_INTERVAL_MS; |
stefanrousseau | 3:26b3cc155f39 | 218 | OneMsTicker.attach(OneMsFunction, 0.001f) ; |
bowenfeng | 84:0bf8168b690a | 219 | |
bowenfeng | 84:0bf8168b690a | 220 | sprintf(sessionName, "IoT-kit-%d", rand() % 1000); |
bowenfeng | 84:0bf8168b690a | 221 | |
bowenfeng | 87:ca75c5e785a7 | 222 | find_latest_hiking(hid); |
bowenfeng | 84:0bf8168b690a | 223 | PRINTF("Found Hiking ID: "); |
bowenfeng | 84:0bf8168b690a | 224 | PRINTF(hid); |
bowenfeng | 84:0bf8168b690a | 225 | PRINTF("\r\n"); |
bowenfeng | 84:0bf8168b690a | 226 | |
bowenfeng | 84:0bf8168b690a | 227 | join_hiking(hid, sessionName, sid); |
bowenfeng | 84:0bf8168b690a | 228 | PRINTF("Allocated Session ID: "); |
bowenfeng | 84:0bf8168b690a | 229 | PRINTF(sid); |
bowenfeng | 84:0bf8168b690a | 230 | PRINTF("\r\n"); |
fkellermavnet | 26:8d6e7e7cdcae | 231 | |
JMF | 2:0e2ef866af95 | 232 | // Send and receive data perpetually |
JMF | 2:0e2ef866af95 | 233 | while(1) { |
bowenfeng | 84:0bf8168b690a | 234 | if (bTimerExpiredFlag) { |
stefanrousseau | 3:26b3cc155f39 | 235 | bTimerExpiredFlag = false; |
stefanrousseau | 4:f83bedd9cab4 | 236 | read_sensors(); //read available external sensors from a PMOD and the on-board motion sensor |
bowenfeng | 85:43d791cd5967 | 237 | report_move(hid, sid); |
bowenfeng | 86:5ff234988f53 | 238 | } |
stefanrousseau | 3:26b3cc155f39 | 239 | } //forever loop |
JMF | 0:9d5134074d84 | 240 | } |