Skip to content

Instantly share code, notes, and snippets.

@rdlauer
Created May 31, 2024 17:23
Show Gist options
  • Save rdlauer/81d222b5a47e63e14f63f77f34793950 to your computer and use it in GitHub Desktop.
Save rdlauer/81d222b5a47e63e14f63f77f34793950 to your computer and use it in GitHub Desktop.
Inbound and Outbound Messaging over Satellite IoT with Blues Starnote
#include <Arduino.h>
#include <Adafruit_GFX.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_ILI9341.h>
#include <Fonts/FreeSans9pt7b.h>
#include <Adafruit_NeoPixel.h>
#include <BBQ10Keyboard.h>
#include <Notecard.h>
#include "base64.hpp"
#define TFT_CS 9
#define TFT_DC 10
#define NEOPIXEL_PIN 11
#define productUID "your-product-uid"
#define serialDebug Serial
HardwareSerial stlinkSerial(PIN_VCP_RX, PIN_VCP_TX); // using optional STLINK
Adafruit_ILI9341 tft(TFT_CS, TFT_DC);
Adafruit_NeoPixel pixels(1, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
BBQ10Keyboard keyboard;
Notecard notecard;
String msg = "";
unsigned long time_now = 0;
unsigned long last_inbound_check = 0;
void setup()
{
#ifdef serialDebug
stlinkSerial.begin(115200);
const size_t usb_timeout_ms = 3000;
for (const size_t start_ms = millis(); !stlinkSerial && (millis() - start_ms) < usb_timeout_ms;)
;
notecard.setDebugOutputStream(stlinkSerial);
#endif
Wire.begin();
// Initialize Notecard
notecard.begin();
// Connect Notecard to your Notehub account (the Product UID)
J *req = notecard.newRequest("hub.set");
if (req != NULL)
{
JAddStringToObject(req, "product", productUID);
JAddStringToObject(req, "mode", "minimum");
notecard.sendRequestWithRetry(req, 5);
}
// Put the Notecard in the relevant NTN mode
req = notecard.newRequest("card.transport");
if (req != NULL)
{
JAddStringToObject(req, "method", "wifi-cell-ntn");
notecard.sendRequestWithRetry(req, 5);
}
// Create a Note template for **OUTBOUND** messages to Notehub/Twilio
req = notecard.newRequest("note.template");
if (req != NULL)
{
JAddStringToObject(req, "file", "outbound_msg.qo");
JAddStringToObject(req, "format", "compact");
JAddNumberToObject(req, "port", 45);
J *body = JCreateObject();
if (body != NULL)
{
JAddStringToObject(body, "message", "x");
JAddItemToObject(req, "body", body);
}
notecard.sendRequestWithRetry(req, 5);
}
// Create a Note template for **INBOUND** messages from Notehub/Twilio
req = notecard.newRequest("note.template");
if (req != NULL)
{
JAddStringToObject(req, "file", "inbound_msg.qi");
JAddStringToObject(req, "format", "compact");
JAddNumberToObject(req, "port", 46);
J *body = JCreateObject();
if (body != NULL)
{
JAddStringToObject(body, "message", "x");
JAddItemToObject(req, "body", body);
}
notecard.sendRequestWithRetry(req, 5);
}
// OPTIONAL: Set a fixed GPS location
req = notecard.newRequest("card.location.mode");
if (req != NULL)
{
JAddStringToObject(req, "mode", "fixed");
JAddNumberToObject(req, "lat", 0); // add your lat/lon!
JAddNumberToObject(req, "lon", 0);
}
notecard.sendRequestWithRetry(req, 5);
// Force a sync between the Notecard and Notehub
req = notecard.newRequest("hub.sync");
if (req != NULL)
{
notecard.sendRequestWithRetry(req, 5);
}
tft.begin();
pixels.begin();
pixels.setBrightness(30);
keyboard.begin();
keyboard.setBacklight(0.5f);
tft.setRotation(1);
tft.fillScreen(ILI9341_BLACK);
tft.setTextSize(1);
tft.setFont(&FreeSans9pt7b);
tft.print("\nWi-Fi/Cell/Satellite SMS with Blues!\n");
}
void theaterChase(uint32_t color, int wait)
{
for (int a = 0; a < 20; a++)
{
for (int b = 0; b < 3; b++)
{
pixels.clear();
for (int c = b; c < pixels.numPixels(); c += 3)
{
pixels.setPixelColor(c, color);
}
pixels.show();
delay(wait);
}
}
}
void loop()
{
if (keyboard.keyCount())
{
const BBQ10Keyboard::KeyEvent key = keyboard.keyEvent();
if (key.state == BBQ10Keyboard::StateRelease)
{
pixels.setPixelColor(0, pixels.Color(0, 255, 0));
pixels.show();
tft.print(key.key);
if (key.key == '\6')
{
// this is the top left "custom" button on the keyboard
J *req = notecard.newRequest("hub.sync");
if (req != NULL)
{
notecard.sendRequestWithRetry(req, 5);
}
tft.print("Manually check for inbound message!\n");
}
else if ((int)key.key == 8)
{
// erase previous character
if (msg.length() > 0)
{
msg = msg.substring(0, msg.length() - 1);
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(0, 10);
tft.print(msg);
}
}
else if ((int)key.key == 10)
{
// carriage return
serialDebug.println("return!");
if (msg.length() > 0)
{
theaterChase(pixels.Color(0, 0, 127), 50); // Blue
// add a note
J *req = notecard.newRequest("note.add");
if (req != NULL)
{
JAddStringToObject(req, "file", "outbound_msg.qo");
J *body = JCreateObject();
if (body != NULL)
{
JAddStringToObject(body, "message", msg.c_str());
JAddItemToObject(req, "body", body);
}
notecard.sendRequestWithRetry(req, 5);
}
req = notecard.newRequest("hub.sync");
if (req != NULL)
{
notecard.sendRequestWithRetry(req, 5);
}
tft.print("Message sent!\n");
msg = "";
}
}
else
{
// any other character
msg += key.key;
}
pixels.clear();
pixels.show();
}
}
// Check to see if there are any inbound messages (Notes) needing processing
time_now = millis();
if (time_now > last_inbound_check + 5000) // every 5 secs
{
last_inbound_check = millis();
J *req = NoteNewRequest("note.get");
if (req != NULL)
{
JAddStringToObject(req, "file", "inbound_msg.qi");
JAddBoolToObject(req, "delete", true);
J *rsp = notecard.requestAndResponse(req);
if (rsp && JGetObject(rsp, "body"))
{
theaterChase(pixels.Color(255, 0, 0), 50); // red notification for inbound msg
J *body = JGetObject(rsp, "body");
String inbound_msg = JGetString(body, "message");
tft.print("New inbound message:\n");
tft.print(inbound_msg);
tft.print("\n");
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment