Hi There
I am not super familiar with thinger.io and I am having some troubles getting it to work the way I want. I am prototyping with an Arduino MKR NB cellular device which I have managed to get communicating to thinger in a basic sense.
My goal is to create a program with multiple tasks running at different intervals (GPS, main loop, comms etc). I need to do this so that I can optimise the battery usage of the device. In particular I eventually only want the cellular chip to be sending and receiving data ever 3 mins (1 min for now).
For this reason I am using freertos for my task management but running into trouble getting it to work with thinger. When I put the thing.handle function into a thread it just doesn’t work. For now I solved the problem by using the thing.write_bucket functionality, which does work inside a freertos task, to push data to the cloud. Problem is now I want to be able to retrieve some geoJson data from cloud and the only way to do that seems to be to use the thing.handle function.
My questions are:
- is there a function that I could use instead of .handle to directly retrieve json data from the platform?
- what is best practice for retrieving json data from the cloud
- is there maybe actually a better way to control how often thinger pings the backend and therefore save battery life?
- is thinger and freertos actually compatible or should I use a different methodology?
Thanks in advance for your help!
My code is below for reference.
#include <Arduino.h>
#include <Wire.h>
#include <ChainableLED.h>
#define THINGER_SERIAL_DEBUG
#define _DISABLE_TLS_
#include <ThingerMKRNB.h>
#include <MKRNB.h>
#include <arduino_secrets.h>
#include <location.h>
#include <heading.h>
#include <cowtrol.h>
#include <FreeRTOS_SAMD21.h>
TaskHandle_t taskGPSHandle;
TaskHandle_t mainHandle;
TaskHandle_t locationHandle;
TaskHandle_t checkForZoneHandle;
SemaphoreHandle_t mutex;
#define GPS_DELAY_MS 400 // (ms) - 2Hz
#define MAIN_DELAY_MS 200
#define LOCATION_DELAY_MS 60000 // 60 seconds
#define NUM_LEDS 1
// class initilisation
locationServices locationService;
headingServices headingService;
cowtrolServices cowtrolService;
ThingerMKRNB thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL);
ChainableLED leds(5, 6, NUM_LEDS);
// // zone polygon vector - hardcoded for now - TNW
// std::vector<latLonPoint> zonePolygon = {
// {52.36684584896231, 4.892382884038189},
// {52.36653316197476, 4.892287194486286},
// {52.36645977946135, 4.892898433659862},
// {52.36680868093923, 4.893030724121128},
// {52.36684584896231, 4.892382884038189}
// };
// zone polygon vector - hardcoded for now - Leigh and Nisal
std::vector<latLonPoint> zonePolygon = {
{52.35334402186569, 4.846027536843199},
{52.35335365905127, 4.847232301428632},
{52.35448202568118, 4.847126262277273},
{52.35447509518661, 4.846395306438856},
{52.35392988366807, 4.845993872750524},
{52.35334402186569, 4.846027536843199}
};
// Amsterdam location
latLonPoint datum {52.3676, 4.9041};
// global variablesx
int relativeHeading;
latLonPoint location {datum.latitude, datum.longitude}; //set starting location as datum
void taskProcessGPS(void* parameter) {
TickType_t lastWakeTime = xTaskGetTickCount();
while (true) {
// xSemaphoreTake(mutex, portMAX_DELAY);
location = locationService.readGPS();
locationService.checkInZone(location, zonePolygon, datum);
// xSemaphoreGive(mutex);
vTaskDelay(pdMS_TO_TICKS(300));
}
}
void mainLoop(void* parameter) {
TickType_t lastWakeTime = xTaskGetTickCount();
while (1) {
// xSemaphoreTake(mutex, portMAX_DELAY);
if (!locationService.insideZone) {
Serial.println("Cowgorithm Enabled");
leds.setColorRGB(0, 255, 0, 0);
relativeHeading = headingService.getRelativeHeading(headingService.getHeading(), locationService.getCompassHeading());
// cowtrolService.runCowtrol(relativeHeading);
}
else {
cowtrolService.stopPWM();
Serial.println("Cowgorithm Disabled");
leds.setColorRGB(0, 0, 255, 0);
}
// xSemaphoreGive(mutex);
vTaskDelayUntil(&lastWakeTime, pdMS_TO_TICKS(MAIN_DELAY_MS));
}
}
void sendLocation(void* parameter) {
TickType_t lastWakeTime = xTaskGetTickCount();
while (1) {
// xSemaphoreTake(mutex, portMAX_DELAY);
Serial.println("Sending Update");
thing.write_bucket("deviceUpdate", "deviceUpdate");
// xSemaphoreGive(mutex);
vTaskDelayUntil(&lastWakeTime, pdMS_TO_TICKS(LOCATION_DELAY_MS));
}
}
void checkForZone(void* parameter) {
TickType_t lastWakeTime = xTaskGetTickCount();
while (1) {
thing.handle();
vTaskDelayUntil(&lastWakeTime, pdMS_TO_TICKS(LOCATION_DELAY_MS));
}
}
void setup(void)
{
// mutex = xSemaphoreCreateMutex();
// leds.setColorRGB(0, 0, 0, 0);
Serial.begin(9600);
// while (!Serial) delay(10); // wait for serial port to open!
Serial.println("Started");
leds.setColorRGB(0, 255, 0, 0);
headingService.initialise();
// headingService.calibrate();
leds.setColorRGB(0, 0, 255, 0);
delay(1000);
leds.setColorRGB(0, 0, 0, 0);
// optional set pin number
thing.set_pin(SECRET_PINNUMBER);
// set APN
thing.set_apn(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD);
// thing["sendZone"] >> [](pson& in){
// const char* data = in;
// Serial.print("Received GeoJSON data: ");
// Serial.println(data);
// };
thing["deviceUpdate"] >> [](pson& out){
out["lat"] = location.latitude;
out["lon"] = location.longitude;
out["heading"] = relativeHeading;
// out['shockCount'] = cowtrolService.shockCount;
};
while (!thing.is_connected()){
thing.handle();
}
Serial.println("NB Initialized");
// setup services
locationService.setupGPS();
cowtrolService.setupPiezo();
int count = 0;
xTaskCreate(taskProcessGPS, "Process GPS", configMINIMAL_STACK_SIZE, NULL, 1, &taskGPSHandle);
xTaskCreate(sendLocation, "Send Location", configMINIMAL_STACK_SIZE, NULL, 3, &locationHandle);
// xTaskCreate(checkForZone, "Check For Zone", configMINIMAL_STACK_SIZE, NULL, 2, &checkForZoneHandle);
xTaskCreate(mainLoop, "Main Loop", configMINIMAL_STACK_SIZE, NULL, 0, &mainHandle);
vTaskStartScheduler();
}
void loop(void)
{
}